- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想快速显示一些图像(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/
我偶然发现了 Wikipedia 上的线程安全文章;它区分了几个安全级别,尤其是: Thread safe: Implementation is guaranteed to be free of ra
当我启动 Rails 时,如何摆脱这个警告/错误。 在没有 :safe 选项的情况下调用“加载”——默认为安全模式。 => Booting Thin => Rails 3.2.13 applicati
当我启动 Rails 时,如何摆脱这个警告/错误。 在没有 :safe 选项的情况下调用“加载”——默认为安全模式。 => Booting Thin => Rails 3.2.13 applicati
我正在尝试使用 FCM 和 https://www.simplifiedcoding.net/firebase-cloud-messaging-android/ 上提供的教程向我的应用程序添加通知服务
我正在 VB.net 中寻找“安全”点符号。这样的事情是否存在——在 VB.NET 或任何语言中?我希望能够做的是,在使用 non-nullable 遗留对象时,解决如下问题: “如果有计划,如果有案
我在我的机器上使用 Windows 10 家庭单语言版,这是一个 64 位操作系统。 我已经安装了最新版本的 XAMPP,它在我的机器上安装了 PHP 7.2.7。 我是根据摘自 PHP Manual
我在 XmlDocument class documentation 中看到在 MSDN 上 Any public static ( Shared in Visual Basic) members o
例如,我经常想用 SELECT whatever FROM questions WHERE views * N + votes * M > answers AND NOT(answered) O
在DataStax收购Aurelius之后,自从Titan 1.0.0在2015年9月发布以来,自那时以来几乎没有提交过,所以我想知道在生产中使用TitanDB是否安全。谁能给我一些见识? 最佳答案
给定一个文件: dept4.abc.edu dept3.abc.edu dept2.abc.edu dept1.abc.edu 我知道如何使用以下命令获取从底部开始的第三行: tail -3 file
SELECT TO_NUMBER('*') FROM DUAL 这显然给了我一个异常(exception): ORA-01722: invalid number 有没有办法“跳过”它并获取 0 或 N
我不是在问这些是否真的是随机的。我只是想知道如果两个用户同时点击一个页面他们可以获得相同的随机数吗?我在想,如果我在多核服务器上运行它,我会因为同步或其他原因在很长一段时间内生成相同的随机数吗? pu
我有一个服务器存储来自客户端的数据。每个客户端都在自己的线程中工作,并且拥有一个数据对象。 这个数据对象是一个自定义类,让我们调用包含非特定数据的 Data.java,这可能是一些字节,但通常约为 1
我正在开发一个应用程序,其中我有一个包含 5000 行和 4 列的数据库。 problem_id (int) problem_no (string) problem_title (string) da
我有一个表,其中每行的字段数据都不完整,我想要修复。 这就是我的意思: mysql> CREATE TABLE test ( key INT a CHAR(1),
这个问题已经有答案了: How do JavaScript closures work? (86 个回答) 已关闭 6 年前。 所以,这个代码片段工作起来非常方便,但我对它的工作方式感到有点惊讶。 v
我想 compile C++ extensions to SQL Server , 来自文档 Safe mode: Run verifiably typesafe code; compiled wit
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。为了帮助澄清这个问题以便它可以重新打开,visit the help center。 关
这种互斥模式是否像我认为的那样安全?如果是这样,你怎么调用它? lock (_lock) { if (_flag) return; else _flag = true; } try {
假设您使用 EntityFramework 作为 ORM,所有这些都封装在一个单独的 DAL 类库中。 您在另一个“公共(public)”类库中有以下 POCO 对象,它在您的 DAL、SL 和表示层
我是一名优秀的程序员,十分优秀!