I need to add people's portraits into my app. I'm looking for the most reasonable way to accept as input an image in GIF, BMP, JPG, or PNG, and of (relatively) arbitrary size, then to resize it to my target size (ca. 200x240) and format (JPG). I want a solution which does a good job of scaling, minimizing artifacts. Not in search of a science project, nor a solution which depends on DLLs (other than standard Windows stuff), nor expensive 3rd party image processing tools.
Thanks to all for the suggestions. I have found that the TMS TAdvOfficeImage component works very well for loading from numerous formats. However, how to get from there to a scaled JPEG file is not apparent. Unlike TImage, they do not expose a TBitmap, so I am in murky waters. Moreover, I have found minimal information on how to use it for other than presenting an image on a form. It does provide stream I/O, however, which may be the path I need....
ReplyDeleteGdiPlus has a nice demo showing most topics. Extracts:
ReplyDeleteprocedure TDemoCropAndScaleImages.Run;
var
Image: IGPImage;
Width, Height: Integer;
DestinationRect: TGPRectF;
begin
Image := TGPImage.Create('Apple.gif');
Width := Image.Width;
Height := Image.Height;
// Make the destination rectangle 30 percent wider and
// 30 percent taller than the original image.
// Put the upper-left corner of the destination
// rectangle at (150, 20).
DestinationRect.Initialize(150, 20, 1.3 * Width, 1.3 * Height);
// Draw the image unaltered with its upper-left corner at (0, 0).
Graphics.DrawImage(Image, 0, 0);
// Draw a portion of the image. Scale that portion of the image
// so that it fills the destination rectangle.
Graphics.DrawImage(Image, DestinationRect,
0, 0, // upper-left corner of source rectangle
0.75 * Width, // width of source rectangle
0.75 * Height, // height of source rectangle
UnitPixel);
end;
procedure TDemoTransformJpeg.Run;
var
Image: IGPImage;
Width, Height: Integer;
Params: IGPEncoderParameters;
begin
Image := TGPImage.Create('ImageFile.jpg');
Graphics.DrawImage(Image, 0, 0, Image.Width div 2, Image.Height div 2);
Width := Image.Width;
Height := Image.Height;
TextOutput.Add(Format('The width of the image is %d,', [Width]));
if ((Width mod 16) = 0) then
TextOutput.Add('which is a multiple of 16.')
else
TextOutput.Add('which is not a multiple of 16.');
TextOutput.Add(Format('The height of the image is %d,', [Height]));
if ((Height mod 16) = 0) then
TextOutput.Add('which is a multiple of 16.')
else
TextOutput.Add('which is not a multiple of 16.');
Params := TGPEncoderParameters.Create;
Params.Add(EncoderTransformation, EncoderValueTransformRotate90);
Image.Save('ImageFileR90.jpg', TGPImageFormat.Jpeg, Params);
// Reload rotated image
Image := TGPImage.Create('ImageFileR90.jpg');
Graphics.DrawImage(Image, 330, 0, Image.Width div 2, Image.Height div 2);
end;
procedure TDemoBmpToPng.Run;
var
Image: IGPImage;
begin
Image := TGPImage.Create('Bird.bmp');
Graphics.DrawImage(Image, 10, 10, Image.Width, Image.Height);
try
Image.Save('Bird.png', TGPImageFormat.Png);
TextOutput.Add('Bird.png was saved successfully.');
Image := TGPImage.Create('Bird.png');
Graphics.DrawImage(Image, 130, 10, Image.Width, Image.Height);
except
on E: Exception do
TextOutput.Add('Failure: ' + E.Message);
end;
end;