如何使用GDI+调整带Alpha通道的PNG图像尺寸?

5

在寻找一种方法来调整TPngObject的大小并保持透明度和alpha通道无果后,我尝试使用GDI+。

这是我的代码,看起来似乎工作正常,可以缩放PNG图片。目前已在XP上测试:

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;

我的问题是:使用GetThumbnailImage方法是否是正确的方式?我没有找到其他的方法。
2个回答

7

我认为GetThumbnailImage方法不是一个好的选择,因为我怀疑你能得到高质量的重采样图像。在这篇文章中,你可以找到如何重新调整图像大小。他们使用DrawImage方法来实现,所以我也会这样做。就在那之前,我还会设置高质量的图形模式以获得高质量的输出。以下是一个示例:

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;

我不明白为什么/如何保持透明度/alpha,但它有效 :) 谢谢! - zig
3
不用谢!输出位图格式保留了阿尔法通道(即使由于歧义性重载已经是默认设置,我仍然需要明确指定)。如果您使用例如“PixelFormat32bppRGB”这样的格式,将会失去阿尔法通道。即使在纯GDI中,渲染本身也考虑到透明度。 - TLama
2
是的,你可以省略它们。但是那样的话,你可能会得到与缩略图相同的结果(这只是一个猜测,但我认为它们在内部执行的操作与上面的代码类似,只是没有提高质量)。这里使用的设置是最高质量输出,这需要额外的计算时间。你可以尝试修改它们以使用低于默认质量的设置,但最终可能会得到丑陋的结果。默认模式是 InterpolationModeDefault = ?PixelOffsetModeDefault = PixelOffsetModeNoneSmoothingModeDefault = no smoothing(来源 MSDN)。 - TLama
1
非常感谢您的回答! :) - zig
1
不客气!附言:如果您搜索例如SetInterpolationMode,则可以在网络上找到每个使用的方法的文档,然后您会进入MSDN网站 ,从那里您可以转到枚举InterpolationMode 描述 - TLama
显示剩余3条评论

2
我认为使用GetThumbnailImage方法并不是正确的方法。为什么呢? GetThumbnailImage方法的主要用途是获取缩略图,您可以将其用作某些高分辨率图像的预览。
因此,我认为它背后所使用的算法被开发成尽可能快速,但很可能并不关心最终结果的质量。因此,使用此方法可能会导致具有相当糟糕质量的调整大小的图像。
现在,如果您真正对使用Delphi进行图像处理感兴趣,那么您绝对应该检查Graphics32库(http://graphics32.org/wiki/)。
它支持从Delphi 7及以上的所有Delphi版本。它提供许多先进的图像处理算法。最重要的是,它支持硬件加速,这意味着它实际上可以利用您的GPU处理能力来进行这些图像操作。

你能指出Graphics32中与GPU相关的代码吗?我浏览了源代码,只找到了与CPU硬件加速(MMX / SSE2等)有关的引用。 - bLight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接