gpt4 book ai didi

delphi - 如何在后台从磁盘加载图像(多线程)[AKA : TBitmap is not thread-safe]

转载 作者:行者123 更新时间:2023-12-03 15:25:26 27 4
gpt4 key购买 nike

我想快速显示一些图像(jpg、png 等)作为缩略图。因为解码和调整大小的过程很慢,所以我在一个或多个线程中完成它。

但是,it looks like使用 TBitmap 和 TJpeg 的 Canvas 不是多线程安全的。

在这种情况下,我的问题是:
1. 如何在不完全重写GIF/PNG/BMP/JPG库的情况下完成此操作?
2. 有人知道 Embarcadero 的 Gif 和 Png 库是否也不安全吗?
3. 如果我使用 Lock 锁定 Canvas ,会不会因为调整大小部分访问 Canvas 并占用大部分 CPU 周期而破坏性能?

<小时/>

我发现这个问题困扰着我:

David HAROUCHE wrote: That is not correct. The really confusing part is that even local TBitmap are not thread safe unless you lock them. This is because every TBitmap registers itself to the global BitmapCanvasList list in graphics.pas. And when the DC garbage collection FreeMemoryContexts()

http://www.codenewsfast.com/cnf/thread/0/permalink.thr-ng1908q2024

最佳答案

将 GDI+ 与 CreateCompatibleDC 和 CreateBitmap 结合使用将覆盖许多图像格式并避免 Canvas 线程问题。
这只是一个示例实现,可能会被修改。GDI+ API 需要三个单元,无需安装,可以从 http://www.progdigy.com/ 获取。

unit ScaleImageThread;
// 2013 Thomas Wassermann
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls
,GDIPAPI, GDIPOBJ, StdCtrls;
Type
TScaleImageThread=Class(TThread)
FBMP:TBitMap;
FMemDC:HDC;
FMemBMP:HBitmap;
Procedure Execute;Override;
private
Ffn:String;
FDestWidth,FDestHeight:Integer;
procedure SyncFinished;
Public
Constructor Create(aBitMap:TBitmap;const fn:String);overload;
property BMP:TBitmap read FBMP;
Property FileName:String read Ffn;
End;
implementation
{ TGDIThread }
Procedure ScaleOneImage(Const source:String;aHDC:HDC;DestWidth,DestHeight:Integer;Qual:Integer=92;WithOutMargins:Boolean=false;BgColor:TColor=ClWhite;DoNotUpScale:Boolean=false);
var
graphics : TGPGraphics;
image: TGPImage;
width, height: UINT;
faktor:Double;
destx,desty:Double;
rct:TGPRectF;
Ext:String;
begin

image:= TGPImage.Create(source);
width := image.GetWidth;
height := image.GetHeight;


if (DestWidth / width) < (DestHeight/Height) then faktor := (DestWidth / width) else faktor:= (DestHeight/Height);
destx := (DestWidth - faktor * width) / 2;
desty := (DestHeight - faktor * Height) / 2;
graphics := TGPGraphics.Create(aHDC);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);

graphics.DrawImage(
image,
MakeRect(destx, desty , faktor * width, faktor * height), // destination rectangle
0, 0, // upper-left corner of source rectangle
width, // width of source rectangle
height, // height of source rectangle
UnitPixel);
image.Free;
graphics.Free;
end;

constructor TScaleImageThread.Create(aBitMap: TBitmap;const fn:String);
begin
inherited create(False);
Ffn :=fn;
FreeOnTerminate := true;
FBmp := aBitMap;
FMemDC := CreateCompatibleDC(FBmp.Canvas.Handle);
FMemBMP := CreateBitmap(FBmp.Width ,FBmp.Height ,1,GetDeviceCaps(FBmp.Canvas.Handle, BITSPIXEL),nil);
SelectObject(FMemDC, FMemBMP);
FDestWidth :=FBMP.Width;
FDestHeight:=FBMP.Height;
end;


procedure TScaleImageThread.Execute;
begin
inherited;
ScaleOneImage(Ffn,FMemDC,FDestWidth,FDestHeight);
Synchronize(SyncFinished);
end;

procedure TScaleImageThread.SyncFinished;
begin
BitBlt(FBmp.Canvas.Handle, 0, 0, FBmp.Width, FBmp.Height, FMemDC, 0, 0, SRCCOPY);
DeleteObject(FMemBMP);
DeleteDC (FMemDC);
end;

end.

实现测试

uses ScaleImageThread;
{$R *.dfm}

procedure TForm1.ThreadTerminate(Sender: TObject);
begin
Canvas.Draw(FX, FY, TGDIThread(Sender).BMP);
TGDIThread(Sender).BMP.Free;
FX := FX + 70;
if FX > 500 then
begin
FX := 0;
FY := FY + 70;
end;

end;

procedure TForm1.Button1Click(Sender: TObject);
const
C_DIM = 64;
var
i: Integer;
Function GetNewBitMap: TBitMap;
begin
Result := TBitMap.Create;
Result.Width := C_DIM;
Result.Height := C_DIM;
end;

begin
ReportMemoryLeaksOnShutDown := true;
for i := 1 to 10 do
With TGDIThread.Create(GetNewBitMap,
'C:\temp\bild ' + intToStr(i) + '.png') do
OnTerminate := ThreadTerminate;

for i := 1 to 10 do
With TGDIThread.Create(GetNewBitMap,
'C:\Bilder\Kids' + intToStr(i) + '.jpg') do
OnTerminate := ThreadTerminate;


end;

关于delphi - 如何在后台从磁盘加载图像(多线程)[AKA : TBitmap is not thread-safe],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14802531/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com