You are not logged in.
Pages: 1
Fast forward to 2017, Delphi 10.2 Tokyo, Windows 10 x64 Creators Update:
Looks like GDI+ is now faster than JpegDec and JpegTurbo, 12919 x 4719 jpeg:
SynGDIPlus: 692 ms
SynGDIPlus: 689 ms
SynGDIPlus: 692 ms
SynGDIPlus: 681 ms
SynGDIPlus: 701 ms
SynGDIPlus: 686 ms
SynGDIPlus: 687 ms
SynGDIPlus: 693 ms
SynGDIPlus: 686 ms
SynGDIPlus: 681 ms
SSE2 JpegDecoder: 827 ms
SSE2 JpegDecoder: 835 ms
SSE2 JpegDecoder: 842 ms
SSE2 JpegDecoder: 833 ms
SSE2 JpegDecoder: 833 ms
SSE2 JpegDecoder: 848 ms
SSE2 JpegDecoder: 849 ms
SSE2 JpegDecoder: 827 ms
SSE2 JpegDecoder: 833 ms
SSE2 JpegDecoder: 843 ms
libJpeg: 712 ms
libJpeg: 715 ms
libJpeg: 716 ms
libJpeg: 709 ms
libJpeg: 715 ms
libJpeg: 711 ms
libJpeg: 716 ms
libJpeg: 716 ms
Yup, removing packed fixed it, thanks!
There seems to be an issue when using SynGdiPlus.TJpegImage compiled with a 64-bit exe, the CompressionQuality setting is ignored:
Passing a bitmap to the jpeg with CompressionQuality in 32-bit at 100 gives a 280KB jpeg file, while in 64-bit it's 80 KB; setting the value to anything i.e 10 has the same result.
That works. In the case of 2 files I found with this issue, "i" was 1233 and 2714 after the loop (I set 65535 max)
Another issue with some other files:
"Zip error: ZIP format size=0"
In 2 cases I found (working fine with winrar etc), both zzipSize and zfullSize were 0
Reporting a possible issue: I'm getting an exception "ZIP format." with a very specific zip file, after calling
TZipRead.Create(zip)
it triggers here in SynZip.pas
for i := 0 to 127 do begin // resources size may be rounded up to alignment
lhr := @BufZip[Size-sizeof(TLastHeader)];
if lhr^.signature+1=(LASTHEADER_SIGNATURE+1) then
break;
dec(Size);
if Size<=sizeof(lhr^) then
break;
end;
if lhr^.signature+1<>(LASTHEADER_SIGNATURE+1) then begin
UnMap;
raise ESynZipException.Create('ZIP format');
end;
The file opens fine with winrar and 7zip, and if I make a new file with the contents (unpack and repack with winrar), it works fine as well with SynZip
Maybe you could migrate the board to phpbb
That works great, didn't see the overloads somehow, thanks.
ps: does the board support watching threads? it would be nice to be able to receive email notifications of replies.
Congrats, once again your code is the fastest of various I tried:
KAzip (very old component/library, had to update it for unicode/modern delphi)
Delphi's
Synopse
Both for listing and extracting your unit was the fastest after a series of benchmarks (listing the contents of 1000 zips, then extracting 1 a few times over).
Synopse was in both cases some ~10-20% faster than the other 2.
How do you extract a file btw? maybe my proc can be improved someway:
ss: TZipRead;
aa: RawByteString;
ss := TZipRead.Create(zip);
c := ss.NameToIndex(fil);
SetLength(aa,ss.Entry[c].infoLocal.zfullSize);
aa := ss.UnZip(c);
With TFileStream.Create(s,fmCreate) do begin
Write(aa[1],ss.Entry[c].infoLocal.zfullSize);
Free;
end;
Found an ever faster one than all those: the latest libjpeg from this jp guy:
http://cetus.sakura.ne.jp/softlab/jpeg- … html#win32
SynGDIPlus: 981 ms
XE6 jpeg: 5486 ms
Intel JIL: 2912 ms
SSE2 JpegDecoder: 873 ms
JpegTurbo: 766 ms
SSE2 JpegDecoder: 871 ms
SSE2 JpegDecoder: 888 ms
SSE2 JpegDecoder: 889 ms
JpegTurbo: 765 ms
JpegTurbo: 763 ms
JpegTurbo: 761 ms
For smaller files it seems your SSE2 one is still faster though, probably less stuff to init etc.
ps: no way to subscribe to thread replies?
~edit
this is the culprit of the slowdown, the way it converts the jpeg into a bitmap after decompression, slower than the decoding
// reading image
jpeg_start_decompress(@jpeg);
// allocate row
GetMem(prow, jpeg.output_width * 3);
Inherited SetSize(jpeg.output_width, jpeg.output_height);
Inherited PixelFormat := pf24bit;
For y := 0 To jpeg.output_height - 1 Do
Begin
// reading row
jpeg_read_scanlines(@jpeg, @prow, 1);
rowD := scanline[y];
For x := 0 To jpeg.output_width - 1 Do
Begin
rowD[x].RgbtRed := prow[x].rgbtBlue;
rowD[x].rgbtGreen := prow[x].rgbtGreen;
rowD[x].rgbtBlue := prow[x].RgbtRed;
End;
// do anything with the data
End;
// freeing row
FreeMem(prow);
GR32 is very fast for anti-aliased resampling: http://graphics32.org/wiki/Main/Graphics32
I use TKernelResampler + TLanczosKernel for scaling down.
basically,
GR32, GR32_Resamplers,
load jpeg into a TBitmap32 (assign)
R: TKernelResampler;
R := TKernelResampler.Create(Src);
R.Kernel := TLanczosKernel.Create;
Dst.Draw(Dst.BoundsRect, Src.BoundsRect, Src);
Dst = empty bitmap32
Src = bitmap32 containing the jpeg
Thanks that's ok, speedup makes up for larger files. I've started changing all my apps that used jpeg/pngimage to GDIPlus after these tests today (except for 32-bit only apps that mostly load jpeg, will keep using the SSE2 one there)
Interesting fact:
32-bit load:
SynGDIPlus: 1021 ms
XE6 jpeg: 5626 ms
64-bit load:
SynGDIPlus: 867 ms
XE6 jpeg: 2745 ms
--
32-bit save:
GDIPlus PNG: 1561 ms
XE6 PNG: 3293 ms
64-bit save:
GDIPlus PNG: 1736 ms
XE6 PNG: 4059 ms
Windows7 x64
CPU is i5-2500K at 4 Ghz.
Saving PNG seems also much faster, however file size is bigger
1622 x 976
GDIPlus PNG: 123 ms 3.32 MB
GDIPlus PNG: 125 ms
XE6 PNG: 480 ms 2.34 MB
XE6 PNG: 484 ms
GDI
Delphi
12919 x 4719
GDIPlus PNG: 6510 ms
GDIPlus PNG: 6612 ms
XE6 PNG: 44193 ms
XE6 PNG: 44436 ms
GDI 103 MB
Delphi 64 MB
GDI
Delphi
Saving with Jpeg 100%
SynGDIPlus: 1298 ms
SynGDIPlus: 1283 ms
XE6 jpeg: 5576 ms
XE6 jpeg: 5623 ms
GDI 22,4 MB
XE6 25,2 MB oO
Jpeg 85%
SynGDIPlus: 906 ms
SynGDIPlus: 896 ms
XE6 jpeg: 5573 ms
XE6 jpeg: 5639 ms
Oh, now it works with that. Strange I didn't need that for the Jpeg tests before oO
GDIPlus PNG: 1577 ms
GDIPlus PNG: 1547 ms
XE6 PNG: 3450 ms
XE6 PNG: 3449 ms
SynGDIPlus: 987 ms
SynGDIPlus: 967 ms
JpegTurbo: 923 ms
JpegTurbo: 936 ms
SSE2 JpegDecoder: 885 ms
SSE2 JpegDecoder: 892 ms
XE6 jpeg: 5587 ms
XE6 jpeg: 5596 ms
Intel JIL: 2942 ms
Intel JIL: 2934 ms
Same results with SynPicture which is basically the same
k: TSynPicture;
begin
// p := SynGDIPlus.TPNGImage.Create;
k := TSynPicture.Create;
PerfTimerInit;
k.LoadFromFile('z:\bigjpeg.png');
// p.LoadFromFile('z:\bigjpeg.png');
b := k.ToBitmap;
x := PerfTimerStopMS;
k.Free;
b.Free;
Memo1.Lines.Add('GDIPlus PNG: '+IntToStr(x)+' ms');
end;
= 0ms and empty bitmap
Btw is there a special way to load PNG through GDIPlus? I was testing the same for PNG with XE6 vs GDI+, but the image comes out empty
procedure TForm1.Button7Click(Sender: TObject);
Var p: SynGDIPlus.TPNGImage;
x: Int64;
b: TBitmap;
begin
p := SynGDIPlus.TPNGImage.Create;
PerfTimerInit;
p.LoadFromFile('z:\bigjpeg.png');
b := p.ToBitmap;
x := PerfTimerStopMS;
p.Free;
b.Free;
Memo1.Lines.Add('GDIPlus PNG: '+IntToStr(x)+' ms');
end;
Well I guess the GDI one is not THAT much slower than the SSE2, but why use it vs a faster decoder
I always use a failsafe in case the jpeg type isn't supported anyway. Guess I'll change that to use GDI version when it fails (would rather not include the extra DLLs for libjpegturbo).
Seeing that it's so fast, I thought maybe further optimizations are possible with later extensions.
function FastJpegFileToBitmap(fle: string): Graphics.TBitmap;
Var PJ: PJpegDecode;
j: TJpegImage;
m: TMemoryStream;
err: TJpegDecodeError;
begin
Result := nil;
m := TMemoryStream.Create;
With m do begin
Try
LoadFromFile(fle);
Except
m.Free;
Exit;
End;
try
Err := jpegdec.JpegDecode(Memory,Size,PJ);
except
On E:Exception
do ShowMessage('JpegDecode Error: '+fle+' / '+e.Message);
end;
if Err <> JPEG_SUCCESS then begin
m.Free;
PJ^.Free;
// use default
j := TJPEGImage.Create;
j.Performance := jpBestSpeed;
try
Result := Graphics.TBitmap.Create;
j.LoadFromFile(fle);
With Result do begin
Height := j.Height;
Width := j.Width;
Assign(j);
end;
except
FreeAndNil(Result);
FreeAndNil(j);
Exit;
end;
FreeAndNil(j);
Exit;
end;
// SSE Jpeg success
Result := PJ^.ToBitmap;
PJ^.Free;
end;
m.Free;
end;
It seems to be still faster than libJpegTurbo (2012)
https://code.google.com/p/delphi-libjpeg-turbo/
JpegTurbo: 913 ms
JpegTurbo: 929 ms
JpegTurbo: 943 ms
JpegTurbo: 954 ms
SSE2 JpegDecoder: 890 ms
SSE2 JpegDecoder: 897 ms
SSE2 JpegDecoder: 907 ms
SSE2 JpegDecoder: 907 ms
711x400 jpeg
SynGDIPlus: 6 ms
XE6 jpeg: 28 ms
Intel JIL: 12 ms
SSE2 JpegDecoder: 3 ms
SynGDIPlus: 5 ms
XE6 jpeg: 21 ms
Intel JIL: 16 ms
SSE2 JpegDecoder: 3 ms
SynGDIPlus: 6 ms
XE6 jpeg: 35 ms
Intel JIL: 20 ms
SSE2 JpegDecoder: 3 ms
Got any sample code to use that in Delphi?
Did a quick test, your decoder is really impressive
25,2 MB jpeg file of 12919 x 4719 loaded from a RAMdisk:
SynGDIPlus: 976 ms
SynGDIPlus: 1016 ms
SynGDIPlus: 1001 ms
SSE2 JpegDecoder: 914 ms
SSE2 JpegDecoder: 909 ms
SSE2 JpegDecoder: 893 ms
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, jpeg;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
Uses DebugStuff,SynPDF,SynGDIPlus,MyJpeg,MyGraphicsStuff;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
Var j: SynGDIPlus.TJpegImage;
b: TBitmap;
x: Int64;
begin
j := SynGDIPlus.TJpegImage.Create;
PerfTimerInit;
j.LoadFromFile('z:\bigjpeg.jpg');
b := j.ToBitmap;
x := PerfTimerStopMS;
j.Free;
b.Free;
Memo1.Lines.Add('SynGDIPlus: '+IntToStr(x)+' ms');
end;
procedure TForm1.Button2Click(Sender: TObject);
Var j: jpeg.TJpegImage;
x: Int64;
b: TBitmap;
begin
j := jpeg.TJpegImage.Create;
b := TBitmap.Create;
PerfTimerInit;
j.LoadFromFile('z:\bigjpeg.jpg');
//j.DIBNeeded;
b.Assign(j);
x := PerfTimerStopMS;
j.Free;
Memo1.Lines.Add('XE6 jpeg: '+IntToStr(x)+' ms');
end;
procedure TForm1.Button3Click(Sender: TObject);
Var j: MyJpeg.TJpegImage;
x: Int64;
b: TBitmap;
begin
j := MyJpeg.TJpegImage.Create;
b := TBitmap.Create;
PerfTimerInit;
j.LoadFromFile('z:\bigjpeg.jpg');
b.Assign(j);
x := PerfTimerStopMS;
j.Free;
b.Free;
Memo1.Lines.Add('Intel JIL: '+IntToStr(x)+' ms');
end;
procedure TForm1.Button4Click(Sender: TObject);
Var x: Int64;
b: TBitmap;
begin
// jpegdec.JpegDecode(Memory,Size,PJ);
PerfTimerInit;
b := FastJpegFileToBitmap('z:\bigjpeg.jpg');
x := PerfTimerStopMS;
b.Free;
Memo1.Lines.Add('SSE2 JpegDecoder: '+IntToStr(x)+' ms');
end;
end.
Hi, I've been using this for a while and so far it's still the fastest decoder available for Delphi to my knowledge:
5-8 times faster than XE6 TJpegImage
3 times faster than the older Intel's libJpeg (IJL 1.5/2.0)
25-50% faster than libJpeg9a used in FreeImage (http://freeimage.sourceforge.net/features.html)
Maybe you could work on this again some day
Pages: 1