【问题标题】:Scale an image nicely in Delphi?在 Delphi 中很好地缩放图像?
【发布时间】:2010-12-30 20:56:39
【问题描述】:

我使用的是 Delphi 2009,我想缩放图像以适应可用空间。图像始终显示小于原始图像。问题是 TImage Stretch 属性做得不好并且损害了图片的可读性。


(来源:xrw.bc.ca

我希望看到它像这样缩放:


(来源:xrw.bc.ca

任何建议如何最好地做到这一点?试过JVCL,但是好像没有这个能力。一个免费的图书馆会很好,但也许有一个低成本的图书馆“只”这样做也很好。

【问题讨论】:

  • 我建议使用 JanFX 库(现在已合并到胖 Jedi 发行版中,但幸运的是,您可以从 Jedi 中提取此文件)。在 JanFX 中,请参阅 Stretch(我认为)功能。它提供了非常好的平滑效果(不如 Graphics32 但足够好),但速度要快得多。

标签: delphi graphics image-scaling timage


【解决方案1】:

真的非常想使用Graphics32

procedure DrawSrcToDst(Src, Dst: TBitmap32);
var
  R: TKernelResampler;  
begin
  R := TKernelResampler.Create(Src);
  R.Kernel := TLanczosKernel.Create;
  Dst.Draw(Dst.BoundsRect, Src.BoundsRect, Src);
end;

在重新采样图像时,您可以选择多种方法和过滤器。上面的例子使用了一个内核重采样器(有点慢,但效果很好)和一个Lanczos 过滤器作为重建内核。上面的例子应该适合你。

【讨论】:

  • 这是一个很酷的工具,但我发现它对于我需要的东西来说太慢了。现在我有了它,我相信我会用它来做其他事情。谢谢!
  • 很好——但是,如果你发现它很慢,我通常倾向于认为其他地方有问题。无论如何,很高兴您找到了解决问题的好方法!
  • 也许对他来说很慢,因为他每秒都在快速更新?我遇到了同样的性能问题,这是在具有大量内存的 Intel Quad Core I5 上。我从内核重采样器切换到草稿重采样器 (TDraftResampler),性能问题就消失了。在我的应用程序的情况下,我每秒更新 20 次 1100w x 1100h 图像,然后进行下采样,Lanczos 内核太慢而无法跟上。感谢您提供有关 Graphics32 库的提示。这是一个真正的祝福,它确实有助于改善我的下采样图像的外观。
  • 你真的很想避免 Graphics32。 Graphics32 不错。但是过于复杂。仅仅因为你需要一个函数就使用这么大的库完全是矫枉过正。我推荐 JanFX(现在可以在 Jedi 中找到)。您可以从那里复制/粘贴您需要的一个功能。
  • “所以你推荐安装 Jedi,因为你不喜欢复杂” - 不不不。 janfx 重新采样器只是一个功能,在一个文件中。完全独立于图书馆。您只需提取该文件即可。您也可以在互联网上查找 janfx。在该库被集成到绝地之前,有些网站会列出该库。
【解决方案2】:

如果您恢复使用 Win32 API 调用,您可以使用 SetStretchBltMode 到 HALFTONE 并使用 StretchBlt。我不确定这是否是使用默认的 Delphi 调用提供的,但这是我通常解决此问题的方式。

更新(2014 年 9 月) 刚才我(再次)处于类似情况,并且在 TScrollBox 中有一个 TImage,表单上还有更多内容,我真的很想 Image1.Stretch:=true;做半色调。正如 Rob 指出的那样,TBitmap.Draw 仅在目标画布为每像素 8 位或更低且源画布具有更多比特时使用 HALFTONE @ 改为其中之一:

TBitmapForceHalftone=class(TBitmap)
protected
  procedure Draw(ACanvas: TCanvas; const Rect: TRect); override;
end;

{ TBitmapForceHalftone }

procedure TBitmapForceHalftone.Draw(ACanvas: TCanvas; const Rect: TRect);
var
  p:TPoint;
  dc:HDC;
begin
  //not calling inherited; here!
  dc:=ACanvas.Handle;
  GetBrushOrgEx(dc,p);
  SetStretchBltMode(dc,HALFTONE);
  SetBrushOrgEx(dc,p.x,p.y,@p);
  StretchBlt(dc,
    Rect.Left,Rect.Top,
    Rect.Right-Rect.Left,Rect.Bottom-Rect.Top,
    Canvas.Handle,0,0,Width,Height,ACanvas.CopyMode);
end;

【讨论】:

  • 谢谢;这提供了速度和质量的良好平衡。
  • 如果目标画布的每像素位数小于或等于 8 并且源位图的每像素位数大于目标,Delphi 会自动将拉伸模式设置为半色调。否则,它将 Stretch_DeleteScans 用于彩色位图。
  • 谢谢你抢。我需要它始终使用 HALFTONE。顺便说一句,感谢您在堆栈溢出方面做了这么多好事。
  • 奇怪,我错过了 Rob 的帖子吗?无论如何,请注意我添加了一些关于 TBitmapForceHalftone 的内容。
  • 非常非常非常非常非常非常非常好!谢谢。
【解决方案3】:

你可以试试GraphUtil内置的Delphi ScaleImage

【讨论】:

  • 最佳答案:)
【解决方案4】:

我使用 GDIPOB.pas 的 TGPGraphics 类

如果 Canvas 是 TGPGraphics,Bounds 是 TGPRectF,NewImage 是 TGPImage 实例:

Canvas.SetInterpolationMode(InterpolationModeHighQualityBicubic);
Canvas.SetSmoothingMode(SmoothingModeHighQuality);
Canvas.DrawImage(NewImage, Bounds, 0, 0, NewImage.GetWidth, NewImage.GetHeight, UnitPixel);

你可以通过改变插值模式来选择质量VS速度因子

InterpolationModeDefault             = QualityModeDefault;
InterpolationModeLowQuality          = QualityModeLow;
InterpolationModeHighQuality         = QualityModeHigh;
InterpolationModeBilinear            = 3;
InterpolationModeBicubic             = 4;
InterpolationModeNearestNeighbor     = 5;
InterpolationModeHighQualityBilinear = 6;
InterpolationModeHighQualityBicubic  = 7;

和smooting模式:

SmoothingModeDefault     = QualityModeDefault;
SmoothingModeHighSpeed   = QualityModeLow;
SmoothingModeHighQuality = QualityModeHigh;
SmoothingModeNone        = 3;
SmoothingModeAntiAlias   = 4;

注意:这需要 XP 或更高版本,或者在安装程序中捆绑 gdiplus.dll。

【讨论】:

    猜你喜欢
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    • 2021-05-08
    相关资源
    最近更新 更多