[fpc-pascal] Performance problems with Image Conversions
Andrew Brunner
atbrunner at aurawin.com
Sun Feb 24 05:58:08 CET 2013
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
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();
if (dstCanvas<>nil) then
dstCanvas.Free();
if (FReader<>nil) then
FReader.Free();
if FWriter<>nil then
FWriter.Free();
if srcImg<>nil then
srcImg.Free();
if dstImg<>nil then
dstImg.Free();
end;
begin
Result:=false;
if SameText(srcKind,Image.Kind.GIF.Name) then begin
sContentType:=hHTTP.ctPNG;
dstKind:=Image.Kind.PNG.Name;
FTransparent:=true;
end else if SameText(srcKind,Image.Kind.PNG.Name) then begin
dstKind:=Image.Kind.PNG.Name;
FTransparent:=true;
end else begin
sContentType:=hHTTP.ctJPG;
dstKind:=Image.Kind.JPG.Name;
FTransparent:=false;
end;
cReader:=FPImage.ImageHandlers.ImageReader[srcKind];
cWriter:=FPImage.ImageHandlers.ImageWriter[dstKind];
dstCanvas:=nil; srcCanvas:=nil; FReader:=nil; FWriter:=nil;
srcImg:=nil; dstImg:=nil;
Result:=(cReader<>nil) and (cWriter<>nil);
if Result then begin
Try
FReader:=cReader.Create();
FWriter:=cWriter.Create();
if SameText(dstKind,Image.Kind.PNG.Name) then begin
TFPWriterPNG(FWriter).Indexed:=false;
TFPWriterPNG(FWriter).UseAlpha:=true;
end;
srcImg:=TFPMemoryImage.Create(0,0);
srcImg.UsePalette:=false;
Stream.Position:=0;
Try
srcImg.LoadFromStream(Stream,FReader);
Stream.Position:=0;
if (srcImg.Width>=srcImg.Height) then begin
Factor:=iX/srcImg.Width;
end else begin
Factor:=iY/srcImg.Height;
end;
if (srcImg.Width>iX) or (srcImg.Height>iY) then begin
if FTransparent then begin
if SameText(srcKind,Image.Kind.GIF.Name) then begin
FTransparent:=TFPReaderGIF(FReader).Transparent;
TFPWriterPNG(FWriter).UseAlpha:=true;
end;
end;
iX:= Round(srcImg.Width * Factor);
iY:= Round(srcImg.Height * Factor);
dstImg:=TFPMemoryImage.Create(iX,iY);
dstImg.UsePalette:=false;
dstCanvas:=TFPImageCanvas.create(dstImg);
dstCanvas.StretchDraw(0,0,iX,iY,srcImg);
Stream.Size:=0;
dstImg.SaveToStream(Stream,FWriter);
Stream.Position:=0;
Result:=true;
end;
Except
Stream.Size:=0;
Stream.Position:=0;
Result:=false;
end;
Finally
FreeImageData();
end;
end;
end;
Further, when a user views images via my preview app, I don't send the
originals, I scale those too using the same methods. The speed is
killing my server's performance.
Does anyone have any idea how to speed up the underlining code?
--
Andrew Brunner
Aurawin LLC
15843 Garrison Circle
Austin, TX 78717
https://aurawin.com
Aurawin is a great new way to store, share, and explore all your content
featuring our innovative cloud social computing platform.
More information about the fpc-pascal
mailing list