我有此功能需要4.2秒才能将jpg转换为bmp。
为什么要花这么长时间?我可以更快吗?
IrfanView只需一小部分时间即可加载和转换文件。
我认为大部分时间都花在JPG.LoadFromFile中。但是当我测量时间时,我惊讶地发现它花费了大部分时间在BMP.Assing(JPG)中。
function ConvertJPG2BMP(CONST FileName: string): TBitmap;
VAR JPG: TJpegImage;
begin
Result:= NIL;
JPG:= TJpegImage.Create;
TRY
JPG.LoadFromFile(FileName);
if (JPG.Width > 0) AND (JPG.Width < 32768)
AND (JPG.Height> 0) AND (JPG.Height < 32768) then
begin
Result:= TBitmap.Create;
TRY
Result.HandleType:= bmDIB;
// Fuji_FinePix_F550.JPG [3200x1800] [1.44MB]
Result.Assign(JPG); <--- 4 seconds!!
EXCEPT
FreeAndNil(Result);
END;
end;
FINALLY
FreeAndNil(JPG);
end;
end;
答案 0 :(得分:4)
由于我只想测试稍旧一些的功能,所以现在是个很好的机会。
这些在下面的代码中做了些改动。
OP的function ConvertJPG2BMP()
(2512:ms)经过某种调整的源代码
function ConvertJPG2BMP(CONST FileName: string): TBitmap;
VAR
JPG: TJpegImage;
begin
Result:= NIL;
JPG:= TJpegImage.Create;
TRY
JPG.LoadFromFile(FileName);
if (JPG.Width > 0) AND (JPG.Width < 32768)
AND (JPG.Height> 0) AND (JPG.Height < 32768) then
begin
Result:= TBitmap.Create;
TRY
Result.PixelFormat := pf24bit;
Result.Width := JPG.Width;
Result.Height := JPG.Height;
Result.HandleType:= bmDIB;
// 2018-10-17 14.04.23.jpg [2560x1920] [1.66MB]
Result.Assign(JPG);
Result.SaveToFile('F:\ProgramFiles\Embarcadero\dtx\Projects\Bmp-DIB\JPG2BMP.bmp');
EXCEPT
FreeAndNil(Result);
END;
end;
FINALLY
FreeAndNil(JPG);
end;
end;
TWICImage用法的来源(296:毫秒)
Vcl.Graphics?
中还有一个名为TWICImage
的类,用于处理Microsoft Imaging Component支持的图像
包括BMP,GIF,ICO,JPEG,PNG,TIF和Windows Media Photo
procedure LoadImageFromStream(Stream: TStream; Image: TImage);
var
wic: TWICImage;
Bitmap: TBitmap;
begin
Stream.Position := 0;
wic := TWICImage.Create;
try
wic.LoadFromStream(Stream);
Image.Picture.Assign(wic);
Bitmap := TBitmap.Create;
try
Bitmap.PixelFormat := pf24bit;
Bitmap.Width := Image.Picture.Width;
Bitmap.Height := Image.Picture.Height;
Bitmap.Canvas.Draw(0, 0, Image.Picture.Graphic);
Bitmap.SaveToFile('F:\ProgramFiles\Embarcadero\dtx\Projects\Bmp-DIB\TWICImage.bmp');
finally
Bitmap.Free;
end;
finally
wic.Free;
end;
end;
procedure RenderImage(const Filename: string);
var
fs: TFileStream;
begin
fs := TFileStream.Create(Filename, fmOpenRead);
try
LoadImageFromStream(fs, Form1.Image1);
finally
fs.Free;
end;
end;
所有已测试例程的GetTickCount。
procedure TForm1.Button1Click(Sender: TObject);
var
MyDIB : TBitmap;
loadStr : string;
XStart,Xend : LongWord;
begin
loadStr := 'F:\ProgramFiles\Embarcadero\dtx\Projects\Bmp-DIB\2018-10-17 14.04.23.jpg';
XStart := GetTickCount;
if RadioGroup1.ItemIndex = 0 then MyDIB := ConvertJPG2BMP(loadStr);// ConvertJPG2BMP()
if RadioGroup1.ItemIndex = 1 then TestBmp(loadStr);
if RadioGroup1.ItemIndex = 2 then RenderImage(loadStr);// TWICImage
if RadioGroup1.ItemIndex = 3 then GetOleGraphic(loadStr);
Xend := GetTickCount;
Label1.Caption := IntToStr(xEnd-XStart) + ' : MS' ;
end;
生成的图像仅与函数GetOleGraphic()
的文件大小相同吗?是生成的较小文件,分辨率较差吗?
答案 1 :(得分:1)
这是上面的moskito-x发布的WIC图像加载器的精简版。
请投票他的答案不是我的。我在这里的答案仅是提供精简版本和一些细节。
{ Uses TWICImage
>8 times faster than Delphi's JPG function
Tested with:
Animated GIF, PNG, JPG
Drawbacks:
Fails with JPEG2K
No EXIF support.}
function LoadImageWic(CONST FileName: string): TBitmap;
VAR
wic: TWICImage;
begin
wic := TWICImage.Create;
TRY
wic.LoadFromFile(FileName);
Result := TBitmap.Create;
TRY
Result.Assign(wic);
EXCEPT
FreeAndNil(Result);
END;
FINALLY
FreeAndNil(wic);
END;
end;
答案 2 :(得分:0)
只需尝试使用我们的Open Source SynGDIPlus unit解压缩jpeg。
我们发现它比Delphi内置的jpeg.pas单元快得多。
最新修订版can be retrieved from github。
作为替代方案,您可以尝试使用我们的fast Jpeg decoder using SSE2,但它不能处理所有类型的Jpeg,并且仅适用于Win32。