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