# JPG image resizing

This Delphi (Seattle 10) routine resizes a JPG image if one of its sizes is larger than AMaxDimension pixels, and gives it a compression factor of ACompressionQuality. Images smaller than 128x128 pixels are left alone. As the name says, it ignores alpha channel.

I'm not an expert in image manipulation and wonder if this can be (substantially) optimized. We see that it takes a long time for larger pictures.

procedure ResizeJPGImageWithoutAlpha(var AJPGImage: TJPegImage; AMaxDimension, ACompressionQuality: Integer);
var
lBitmap   : TBitmap;
lFactor   : Real;
lNewWidth,
lNewHeight: Integer;
begin
if (AJPGImage.Width <= 128) and (AJPGImage.Height <= 128) then Exit;

if AJPGImage.Width > AJPGImage.Height then
if AJPGImage.Width > AMaxDimension then
lFactor := AJPGImage.Width
else
lFactor := 0
else
if AJPGImage.Height > AMaxDimension then
lFactor := AJPGImage.Height
else
lFactor := 0;
if lFactor <> 0 then
begin
lFactor    := lFactor / AMaxDimension;
lNewWidth  := Trunc(AJPGImage.Width  / lFactor);
lNewHeight := Trunc(AJPGImage.Height / lFactor);
lBitmap    := TBitmap.Create;
try
lBitmap.Width := lNewWidth;
lBitmap.Height:= lNewHeight;
lBitmap.Canvas.StretchDraw(lBitmap.Canvas.Cliprect, AJPGImage);
// Convert back to JPEG
AJPGImage.Assign(lBitmap);
finally
lBitmap.free;
end;
end
else
AJPGImage.DIBNeeded;
// Decompress the jpeg image into a bitmap.
// DIBNeeded is used when the jpeg image needs a bitmap representation of its image.
// Compress will not work without that (width/height become 0). The resize code already caused a bitmap.
AJPGImage.CompressionQuality := ACompressionQuality;
AJPGImage.Compress;
end;


Notes:

• Input JPG or PNG types can be anything.
• We resize to images that have as their largest dimension 128, 1024, 2048 or 4096.
• On my local machine, if I have large images with dimensions like 7000 or 10000 pixels, it takes 10-11 seconds on the stretchdraw, 0,3 sec for the assignment to the JPG, 0.1 sec on the compression. This code has to run in a web service, so speed is important.
• I notice that newly created TJPEGImages have these defaults. Maybe there's something to be done with that?

var   // Default settings for all new TJPEGImage instances
JPEGDefaults: TJPEGDefaults = (
CompressionQuality: 90;
Grayscale: False;
Performance: jpBestQuality;
PixelFormat: jf24Bit;         // initialized to match video mode
ProgressiveDisplay: False;
ProgressiveEncoding: False;
Scale: jsFullSize;
Smoothing: True;
);


I have no particular expertise with this, but here are some random thoughts:

First, you could try resizing the the images in some other application just to get some benchmarks so you can get an idea how slow your code is. I'm thinking of things like Windows Paint, Irfan View, Paint.Net.

Do you have enough ram? I imagine that the images would be expanded out in raw form into a buffer at some stage. If the buffer used 32 bits or 4 bytes per pixel, then a 10,000 * 10,000 image would require 10000 * 10000 * 4 / 1024 / 1024 = 381 MB.

I don't know if StretchDraw will use the graphics hardware on your video card to do the jpeg compression/decompression and resizing. Your video card may (or may not) be a factor.

I think your best bet might be to try some other image manipulation tools or libraries. I'm thinking of things like ImageEn, Envision, Vampyre, ffmpeg, ImageMagick (or PascalMagick).