合并螺纹位图绘画颜料结果 [英] merge paint results in thread bitmap painting

查看:225
本文介绍了合并螺纹位图绘画颜料结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想加快画一个位图,因此我设计像一个类<一href=\"http://stackoverflow.com/questions/24274279/how-to-paint-by-multi-threading-into-a-tbitmap\">BITMAP线程类。一旦局部图像的个人绘画完成后我要合并的Thread.done过程中的所有图像
我的code是这样的

 键入
      TbmpthreadForm =类(TForm的)
        .....
        THreadImage:TImage中;
        程序Button_threadstartClick(发件人:TObject的);
        程序FORMCREATE(发件人:TObject的);
        程序FormClose(发件人:TObject的; VAR行动:TCloseAction);
      私人的
        {私营Deklarationen}
        程序ThreadDone(发件人:TObject的);
      上市
        {公Deklarationen}
        fserver,fdatabasename,ftablename:字符串;
        global_thread_counter:整数;
        XPixel,YPixel:整数;
        Masterbitmap:TBitmap;
      结束;    VAR
      bmpthreadForm:TbmpthreadForm;    履行    {$ R * .DFM}    程序TbmpthreadForm.ThreadDone(发件人:TObject的);
    开始
      DEC(global_thread_counter);
      MyStatusBar.SimpleText:='线程计数 - &GT;' + IntToStr(global_thread_counter);      Masterbitmap.Canvas.Lock;
      与(发件人为TPaintBitmapThread)做
      开始
        的bitblt(Masterbitmap.Canvas.handle,0,0,XPixel,YPixel,
          bitmap.Canvas.handle,0,0,SRCAND);
        THreadImage.Picture.Bitmap.Assign(Masterbitmap);
        //让我们看看当地的TThread中间结果,并将其保存到高清
        THreadImage.Picture.Bitmap.SaveToFile('C:\\ TEMP \\ MYIMAGE'+ IntToStr(索引)
  +'的.bmp');
      结束;
      Masterbitmap.Canvas.UnLock;      如果(global_thread_counter = 0),那么
      开始
         ...
      结束;
    结束;
程序TbmpthreadForm.Button_threadstartClick(发件人:TObject的);
VAR
     .....
开始  index_max:= 2000000;
  threadCounter:= 10;
  Indexdelta:= ROUND(index_max / threadCounter);  ///
  ///
  ....
  Masterbitmap.Width:= XPixel;
  Masterbitmap.Height:= YPixel;  对于i:= 0 threadCounter - 1做
  开始
    N:= I * Indexdelta;
    L:=第(​​i + 1)* Indexdelta;
    //只是一个测试SQL字符串....
    sqlstr:='SELECT * FROM MYTABLE其中,objectindex&LT;' + IntToStr(M)+
      和Objectindex&GT;' + IntToStr(N);    aPaintBitmapThread:= TPaintBitmapThread.Create(XPixel,YPixel,......,fserver,fdatabasename,ftablename,
      sqlstr,I);
    aPaintBitmapThread.OnTerminate:= ThreadDone;
    Memo1.Lines.Add('开始线程&GT;'+ IntToStr(I));
    INC(global_thread_counter);
  结束;结束;

该Thread.done设计遵循previous话题在这里SO(<一个href=\"http://stackoverflow.com/questions/14171485/asynchronous-threads-drawing-in-bitmaps-delphi\">reference问题
由于生成的图像/ Masterbitmap看起来有点不同从RUN跑,我想我的方法不是线程安全设计副本螺纹BMP内容放到masterbitmap在VCL的MainForm,
我看不到任何错误在我的code,什么是错的????

另一个问题

Q1:内部TPaintBitmapThread fbitmap是Thread.create过程内创建的,TAdoconnection我找到了评论,它应该在thread.execute内创建。必须在此也可以做的位图?

Q2:附带的图像显示用螺纹和实际图像效果(按的THreadImage.Picture.Bitmap.SaveToFile命令)


解决方案

 的bitblt(Masterbitmap.Canvas.handle,0,0,XPixel,YPixel,
      bitmap.Canvas.handle,0,0,SRCAND);

您明确要求Masterbitmap.Canvas.Lock,但是你也没有告诉bitmap.Canvas.Lock(这样你就可以松画布此调用内随时办理...)

此外,你需要考虑在自己的GDI线程安全性:任何GDI共享应该不惜一切代价避免不同的线程之间的对象。例如,如果你选择一个位图到两个不同的设备上下文在同一时间(但在不同的线程),你可能会遇到在GDI本身的问题...

请注意,旧版本的Delphi不能防止缓存的句柄共享(字体,刷子和笔句柄全局列表中的缓存。这是一种固定的XE3服务包,如果我没记错的话)。

总之:我会考虑避免的TCanvas和TBitmap完全如果你真的需要多线程。 (这是很容易成为多线程安全的这种方式)

I want to speed up painting a bitmap, therefore I designed a class like BITMAP THREAD CLASS. Once the individual painting of a partial image is finished I want to merge all image in the Thread.done procedure My code goes like this

    type
      TbmpthreadForm = class(TForm)
        .....
        THreadImage: TImage;
        procedure Button_threadstartClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private-Deklarationen }
        procedure ThreadDone(Sender: TObject);
      public
        { Public-Deklarationen }
        fserver, fdatabasename, ftablename: String;
        global_thread_counter: Integer;
        XPixel, YPixel: Integer;
        Masterbitmap: TBitmap;
      end;

    var
      bmpthreadForm: TbmpthreadForm;

    implementation

    {$R *.dfm}

    procedure TbmpthreadForm.ThreadDone(Sender: TObject);
    begin
      dec(global_thread_counter);
      MyStatusBar.SimpleText := 'Thread Count ->' + IntToStr(global_thread_counter);

      Masterbitmap.Canvas.Lock;
      with (Sender as TPaintBitmapThread) do
      begin
        bitblt(Masterbitmap.Canvas.handle, 0, 0, XPixel, YPixel,
          bitmap.Canvas.handle, 0, 0, srcand);
        THreadImage.Picture.Bitmap.Assign(Masterbitmap);
        // lets see local tthread intermediate results  and save it to HD
        THreadImage.Picture.Bitmap.SaveToFile('c:\temp\myimage' + IntToStr(Index)
  + '.bmp');
      end;
      Masterbitmap.Canvas.UnLock;

      if (global_thread_counter = 0) then
      begin
         ...
      end;
    end;
procedure TbmpthreadForm.Button_threadstartClick(Sender: TObject);
var
     ..... 
begin

  index_max := 2000000;
  threadCounter := 10;
  Indexdelta := round(index_max / threadCounter);

  ///
  ///
  ....
  Masterbitmap.Width := XPixel;
  Masterbitmap.Height := YPixel;

  for i := 0 to threadCounter - 1 do
  begin
    n := i * Indexdelta;
    m := (i + 1) * Indexdelta;
    //  just a test sql string .... 
    sqlstr := 'select * from  Mytable  where objectindex <' + IntToStr(m) +
      ' and Objectindex >' + IntToStr(n);

    aPaintBitmapThread := TPaintBitmapThread.Create(XPixel, YPixel, ......   , fserver, fdatabasename, ftablename,
      sqlstr, i);
    aPaintBitmapThread.OnTerminate := ThreadDone;
    Memo1.Lines.Add('start thread->' + IntToStr(i));
    inc(global_thread_counter);
  end;

end;

The Thread.done design follows a previous topic here on SO ( reference question As the resulting image/Masterbitmap looks a bit different from run to run , I guess my approach is not thread safe design for copy Thread bmp content into the masterbitmap in the VCL mainform, I can not see any error in my code, what is wrong ????

additional question

Q1 : fbitmap inside TPaintBitmapThread is created inside the Thread.create procedure, for TAdoconnection I found the comment, it should be created inside the thread.execute. Must this also be done the the bitmap ?

Q2 : the attached image shows the expected result of an image(Bitmap) by an Thread and the actual image results (as seen by the THreadImage.Picture.Bitmap.SaveToFile command)

解决方案

    bitblt(Masterbitmap.Canvas.handle, 0, 0, XPixel, YPixel,
      bitmap.Canvas.handle, 0, 0, srcand);

you explicitly called Masterbitmap.Canvas.Lock, however you didn't call bitmap.Canvas.Lock (so you can loose the canvas handle anytime within this call...)

Additionally, you need to consider thread safety within GDI itself: Sharing of any GDI objects between different threads should be avoided at all cost. For example if you select a bitmap into two different device contexts at the same time (but in different threads) you may run into problems within GDI itself...

Please note that older versions of delphi don't protect against sharing of cached handles (Font, Brush and Pen handles are cached within a global list. This was fixed in an XE3 service pack if I remember correctly).

In short: I'd consider to avoid TCanvas and TBitmap completely if you really need multi-threading. (It's much easier to be multi-threading safe that way)

这篇关于合并螺纹位图绘画颜料结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆