Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resize PNG image with Alpha channels using GDI+?

After looking for a way to resize TPngObject and maintain the transparency + alpha channels to no avail, I'm trying to use GDI+

Here is my code, and it seems to work fine. it will down/up scale a PNG. Tested on XP so far:

uses GDIPAPI, GDIPOBJ, GDIPUTIL; 

procedure TForm1.Button1Click(Sender: TObject);
var
  encoderClsid: TGUID;
  stat: TStatus;
  img, img_out: TGPImage;
begin
  img := TGPImage.Create('in.png'); // 200 x 200  
  img_out := img.GetThumbnailImage(100, 100, nil, nil);
  GetEncoderClsid('image/png', encoderClsid);
  img_out.Save('out.png', encoderClsid);
  img_out.free;
  img.Free;
end;

My question: is using GetThumbnailImage the correct way of doing this? I did not find any other method.

like image 497
zig Avatar asked Jul 07 '15 14:07

zig


2 Answers

I don't think that GetThumbnailImage method is a good way to go because I doubt that you will get a high quality resampled image. In this article you can find how to rescale the image. They're using the DrawImage method for that, so I would do the same. Just before that I would set also the high quality graphics modes to get high quality output. Here is an example:

procedure TForm1.Button1Click(Sender: TObject);
var
  Input: TGPImage;
  Output: TGPBitmap;
  Encoder: TGUID;
  Graphics: TGPGraphics;
begin
  Input := TGPImage.Create('C:\InputImage.png');
  try
    // create the output bitmap in desired size
    Output := TGPBitmap.Create(100, 100, PixelFormat32bppARGB);
    try
      // create graphics object for output image
      Graphics := TGPGraphics.Create(Output);
      try
        // set the composition mode to copy
        Graphics.SetCompositingMode(CompositingModeSourceCopy);
        // set high quality rendering modes
        Graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
        Graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality);
        Graphics.SetSmoothingMode(SmoothingModeHighQuality);
        // draw the input image on the output in modified size
        Graphics.DrawImage(Input, 0, 0, Output.GetWidth, Output.GetHeight);
      finally
        Graphics.Free;
      end;
      // get encoder and encode the output image
      if GetEncoderClsid('image/png', Encoder) <> -1 then
        Output.Save('C:\OutputImage.png', Encoder)
      else
        raise Exception.Create('Failed to get encoder.');
    finally
      Output.Free;
    end;
  finally
    Input.Free;
  end;
end;
like image 82
TLama Avatar answered Nov 05 '22 06:11

TLama


I don't think using of GetThumbnailImage method is the correct approach. Why?

The main use of GetThumbnailImage method is getting a thumbnail that you can use as a preview of some higher resolution image.

Therefore I assume the algorithm that is used behind is developed to be as fast as possible but it probably doesn't care about end result quality much. So using of this method can lead to resized images with pretty bad quality.


Now if you are realy interested in image manipulation using Delphi then you should definitely check the Graphics32 library (http://graphics32.org/wiki/).

It supports all Delphi versions from Delphi 7 and up. It provides many advanced image manipulation algorithms. And best of all it does support hardware acceleration meaning that it can actually make use of your GPU processing power to make those image manipulations.

like image 30
SilverWarior Avatar answered Nov 05 '22 07:11

SilverWarior