views:

935

answers:

5

I'm using Delphi 2009 and I'd like to scale an image to fit the available space. the image is always displayed smaller than the original. the problem is TImage Stretch property doesn't do a nice job and harms the picture's readability.

ugly way

I'd like to see it scaled like this instead:

nicer way

Any suggestions how best to do this? Tried JVCL, but it doesn't seem to have this ability. A free library would be nice but maybe there's a low cost library that does "only" this would be good as well.

+14  A: 

You really, really want to use 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;

You have several methods and filters to choose when resampling an image. The example above uses a kernel resampler (kinda low, but with great results) and a Lanczos filter as reconstruction kernel. The above example should work for you.

Leonardo Herrera
it's a cool tool but i found it to be too slow for exactly what i needed. now that i have it, i'm sure i'll use it for something else. thank you!
X-Ray
Great -- however, if you find it slow I'm mostly inclined to think that something was wrong somewhere else. Anyways, glad you found a good solution for your problem!
Leonardo Herrera
@Leonardo. Perhaps it was slow for him because he was doing fast updates each second? I had the same performance problem and this was on an Intel Quad Core I5 with plenty of memory. I switched from a kernel resampler to a draft resampler (TDraftResampler) and the performance problem went away. In my application's case I was updating a 1100w x 1100h image 20 times a second and then downsampling and the Lanczos kernel was too slow to keep up. Thanks for the tip about the Graphics32 library though. It's a real blessing and it really helped improve the look of my downsampled image.
Robert Oschler
+1  A: 

The MadExcept library also has an image resize routine - see this topic. It is "free for non-commercial usage".

devstopfix
good to know--thank you!
X-Ray
+4  A: 

If you revert to using Win32 API calls, you can use SetStretchBltMode to HALFTONE and use StretchBlt. I'm not sure if this is provided using default Delphi calls, but that's the way I generally solve this issue.

Stijn Sanders
thank you; this provided a good balance btwn speed and quality.
X-Ray
Delphi sets the stretch mode to Halftone automatically if the destination canvas's bits-per-pixel count is less than or equal to 8 and the source bitmap's bits-per-pixel count is greater than the destination's. Otherwise, it uses Stretch_DeleteScans for color bitmaps.
Rob Kennedy
thank you rob. i needed it to use HALFTONE always.btw, thank you for doing so much good stuff on stack overflow.
X-Ray
+1  A: 

You could try the built-in Delphi ScaleImage from GraphUtil

David
thank you for the tip--i didn't know about ScaleImage!
X-Ray
A: 

I use GDIPOB.pas's TGPGraphics class

if Canvas is TGPGraphics, Bounds is TGPRectF and NewImage is TGPImage instance:

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

You can choose the quality VS speed factor by changing the interpolation mode

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

and smooting mode:

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

NOTE: This would require XP or later or bundeling the gdiplus.dll in your installer.

Gad D Lord