On Sat, 23 Feb 2013, Andrew Brunner wrote:

Hi guys,

I just finished (a beta) of a collage app for Aurawin. I'm seeing a huge load on my servers when scaling images using the Image factory classes for JPEG, and PNG.

Prefix:
6 Core AMD 64 32GB RAM Ubuntu 12.10 x64
8 Core AMD 64 32GB RAM Ubuntu 12.10 x64
FPC/Lazarus daily svn/trunk

Overview:
1.) end-user grabs references to files (stored on my server)
2.) back-end core object scales camera photos to something more net friendly 512px max to scale.
3.) server streams photos back to client over the web and
4.) server assembles XML stream of Mime encoded file data for things like
https://aurawin.com/cb?3

Try to get rid of the XML, it is always going to be slow.
Using XML can slow your applications with a factor 6.
If you are mime-encoding an image, it'll be even more.

Specifics

The pics in this sample take about 30 seconds to go from their originals to 512px. The app waits for the collage to save to the cloud. The problem gets worse for larger collages with more images.

iX,iY are no larger than 512

class function Image.Transform(Stream:TStream; var sContentType,srcKind,dstKind:string; var iX,iY:Integer):boolean;
var
 FReader      : TFPCustomImageReader;
 FWriter      : TFPCustomImageWriter;
 cReader      : TFPCustomImageReaderClass;
 cWriter      : TFPCustomImageWriterClass;
 Factor       : Double;
 FTransparent : boolean;
 dstImg       : TFPMemoryImage;
 srcImg       : TFPMemoryImage;
 srcCanvas    : TFPImageCanvas;
 dstCanvas    : TFPImageCanvas;


 procedure FreeImageData;
 begin
   if (srcCanvas<>nil) then
     srcCanvas.Free();

Do a FreeAndNil(srcCanvas) here. 1. Free already checks if the pointer is not nil.
  You do not need to check again.
2. FreeAndNil will make sure the pointer is Nil

     srcImg:=TFPMemoryImage.Create(0,0);

Do not use TFPMemoryImage. It is a catch-all memory format, not optimized at all, using 64 bits for the images.
Instead, use e.g. TFPCompactImgRGBA8Bit if you need alpha or 
TFPCompactImgRGB8Bit if you do not need Alpha.

         dstImg:=TFPMemoryImage.Create(iX,iY);
         dstImg.UsePalette:=false;
         dstCanvas:=TFPImageCanvas.create(dstImg);
         dstCanvas.StretchDraw(0,0,iX,iY,srcImg);

Phew, this is also a real killer.

Do not draw on a canvas with stretchdraw. That will be slow as well; Rather, attempt to manipulate the image in memory by doing a stretch directly. Choose an algorithm which is fast. The default interpolation will result in quite a lot of calculations.

Michael.
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to