I have a function that converts TBitmap (which I draw) to TPngImage and then saves it to stream, so other methods can use it. Png is used because it creates smaller images for report output (excel, html). The problem is that SaveToStream seems to take too much time, 15x more than converting TBitmap to TPngImage or using TStream with png. Here is the code:
var
BitmapImage: TBitmap;
PNGImage: TPngImage;
PngStream: TStream;
begin
// draw on BitmapImage
...
PNGImage := TPngImage.Create;
PNGStream := TMemoryStream.Create;
Try
PNGImage.Assign(BitmapPicture.Bitmap); // Step 1: assign TBitmap to PNG
PNGImage.SaveToStream(PNGStream); // Step 2: save PNG to stream
WS.Shapes.AddPicture(PNGStream,PNGImage.Width,PNGImage.Height); // Step 3: Add PNG from Stream to Excel
finally
PNGImage.Free;
PNGStream.Free;
end;
...
This is tested with 70000 images and here are the timings:
Step 1: 7 s
Step 2: 93 s
Step 3: 6 s
Why is saving to Stream so slow? Any suggestion to optimize this?
Using Delphi XE7
EDIT
Here is example (MCVE) with simple bmp that gets converted to PNG and then saved into stream. Just for the sake of another verification I added SaveToFile, which of course takes longer, but it is saving to disk, so I assume acceptable.
The img1.bmp is 49.5KB, saved PNG is 661 bytes. link to img1.bmp = http://www.filedropper.com/img1_1
TMemoryStreamAccess = class(TMemoryStream)
end;
procedure TForm1.Button1Click(Sender: TObject);
var BitmapImage:TBitmap;
PNGImage:TPngImage;
PNGStream:TMemoryStream;//TStream;
i,t1,t2,t3,t4,t5,t6: Integer;
vFileName:string;
begin
BitmapImage:=TBitmap.Create;
BitmapImage.LoadFromFile('c:\tmp\img1.bmp');
t1:=0; t2:=0; t3:=0; t4:=0; t5:=0; t6:=0;
for i := 1 to 70000 do
begin
PNGImage:=TPngImage.Create;
PNGStream:=TMemoryStream.Create;
try
t1:=GetTickCount;
PNGImage.Assign(BitmapImage);
t2:=t2+GetTickCount-t1;
t3:=GetTickCount;
TMemoryStreamAccess(PNGStream).Capacity := 1000;
PNGImage.SaveToStream(PNGStream);
// BitmapImage.SaveToStream(PNGStream); <-- very fast!
t4:=t4+GetTickCount-t3;
finally
PNGImage.Free;
PNGstream.Free
end;
end;
showmessage('Assign = '+inttostr(t2)+' - SaveToStream = '+inttostr(t4));
end;