c++有效地在背景图像上绘制线条

c++ efficiently draw line over background image

本文关键字:绘制 图像 有效地 背景 c++      更新时间:2023-10-16

TBitmap* prevImg对象需要一些时间来生成,所以我只生成一次,并希望将其设置为背景:

Image1->Picture->Assign(prevImg); //TImage* Image1

现在我想在鼠标上画一些线和数字,移动到上面:

void __fastcall TTriggerSystemForm::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y){
  if(!prevImg)return;
  Image1->Picture->Assign(prevImg); //reset image
  Image1->Canvas->Pen->Color=clRed; //draw a vertical dotted red line
  Image1->Canvas->Pen->Style=psDot;
  Image1->Canvas->MoveTo(X,0);
  Image1->Canvas->LineTo(X,Image1->Picture->Height);
}

现在这个工作已经很好了。但是,由于图像有时会闪烁,并且任务的CPU占用率高达8%,因此这可能不是很有效。

我正在使用c++ Builder XE2与VCL。

是否有更好的方法在给定的TImage对象上动态地绘制一些东西而不改变原始图像源?

阅读双缓冲,诀窍是你在不同的缓冲区上绘图,一旦你的工作完成,你切换缓冲区。这将防止'闪烁'。

要降低CPU使用率,您可以最小化处理的鼠标事件的数量,例如,如果距离最后处理的事件的时间低于100-200ms,则跳过事件的处理

您可以简单地绘制图像中实际发生变化的部分,而不是绘制整个图像,例如:

int oldX = -1;
void __fastcall TTriggerSystemForm::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
    if (!prevImg) return;
    if (!Image1->Picture->Graphic)
        Image1->Picture->Assign(prevImg); //reset image
    if (oldX == X) return;
    if (oldX != -1)
    {
        TRect r = Rect(oldX, 0, oldX + Image1->Canvas->Pen->Width, Image1->Height);
        Image1->Canvas->CopyRect(r, prevImg->Canvas, r);
    }
    Image1->Canvas->Pen->Color = clRed; //draw a vertical dotted red line
    Image1->Canvas->Pen->Style = psDot;
    Image1->Canvas->MoveTo(X, 0);
    Image1->Canvas->LineTo(X, Image1->Height);
    oldX = X;
}

话虽如此,我建议使用TPaintBox而不是TImage,例如:

int MouseX = -1;
void __fastcall TTriggerSystemForm::PaintBox1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
    MouseX = X;
    PaintBox1->Invalidate();
}
void __fastcall TTriggerSystemForm::PaintBox1MouseMove(TObject *Sender)
{
    if (!prevImg) return;
    PaintBox1->Canvas->Draw(0, 0, prevImg); //reset image
    if (MouseX != -1)
    {
        PaintBox1->Canvas->Pen->Color = clRed; //draw a vertical dotted red line
        PaintBox1->Canvas->Pen->Style = psDot;
        PaintBox1->Canvas->MoveTo(MouseX, 0);
        PaintBox1->Canvas->LineTo(MouseX, PaintBox1->Height);
    }
}