Page 1 of 1

draw and move a rectangle over a bitmap

PostPosted: Mon Sep 17, 2018 7:18 am
by mark_c
Hello,
I can not find an example to draw and move a rectangle over a bitmap.
I have to have an Image1 that contains the bitmap and an Image2 that contains the fixed rectangle, even when the bitmap changes in the Image1; in short, a kind of sumulation of layers

example: Image

Code: Select all
void __fastcall TForm1::Button5Click(TObject *Sender)
{
        Image1->Picture->LoadFromFile("mypicture.jpg");
        bmp1= new Graphics::TBitmap;
        bmp1->Assign(Form1->Image1->Picture->Graphic);

        Image1->Picture->Bitmap->Assign(bmp1);
        delete bmp1;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
        if(Shift.Contains(ssLeft))
        {
                Label7->Caption=X;
                Label8->Caption=Y;
        }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
        Label4->Caption=X;
        Label5->Caption=Y;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
        int x1, y1, x2, y2;
        x1=StrToInt(Label4->Caption);
        y1=StrToInt(Label5->Caption);
        x2=StrToInt(Label7->Caption);
        y2=StrToInt(Label8->Caption);

        Image2->Transparent=true;
        Image2->Canvas->Pen->Color=clBlack;
        Image2->Picture->Bitmap->Canvas->Rectangle(x1,y1,x2,y2);
}
//---------------------------------------------------------------------------

Re: draw and move a rectangle over a bitmap

PostPosted: Mon Sep 17, 2018 2:28 pm
by HsiaLin
You probably want to look into the LineDDA function.
It can draw the "marching ants" type selection rectangle that most image editing
programs use, but it is a little complicated.

Re: draw and move a rectangle over a bitmap

PostPosted: Mon Sep 17, 2018 4:00 pm
by rlebeau
mark_c wrote:Hello,
I can not find an example to draw and move a rectangle over a bitmap.
I have to have an Image1 that contains the bitmap and an Image2 that contains the fixed rectangle, even when the bitmap changes in the Image1; in short, a kind of sumulation of layers


I would not use TImage for this, especially when moving pieces around is involved. Use TPaintBox instead, and draw everything you need in its OnPaint event. Draw the bitmap first, and then draw the box on top of it. When you need to move things around, calculate what you need and then call the TPaintBox::Invalidate() method to trigger the OnPaint event, when can then redraw everything using the updated values as needed.

For example:

Code: Select all
private
    TJPEGImage *jpg;
    TPoint anchorPt;
    TRect box;

__fastcall TForm1::TForm1(TComponent *Owner)
    : TForm(Owner)
{
    anchorPt = Point(-1, -1);
    jpg = new TJPEGImage;
}

__fastcall TForm1::~TForm1()
{
    delete jpg;
}

void __fastcall TForm1::Button5Click(TObject *Sender)
{
    jpg->LoadFromFile("mypicture.jpg");
    PaintBox1->Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
    if (Shift.Contains(ssLeft))
    {
        if (X < anchorPt.X)
        {
            box.Left = X;
            box.Right = anchorPt.X;
        }
        else
        {
            box.Left = anchorPt.X;
            box.Right = X;
        }

        if (Y < anchorPt.Y)
        {
            box.Top = Y;
            box.Bottom = anchorPt.Y;
        }
        else
        {
            box.Top = anchorPt.Y;
            box.Bottom = Y;
        }

        PaintBox1->Invalidate();
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    if (Button == mbLeft)
    {
        anchorPt = Point(X, Y);
        box = Rect(X, Y, X, Y);
        PaintBox1->Invalidate();
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    if (Button == mbLeft)
    {
        anchorPt = Point(-1, -1);
        PaintBox1->Invalidate();
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
    PaintBox1->Canvas->FillRect(PaintBox1->ClientRect);

    if (!jpg->Empty)
        PaintBox1->Canvas->Draw(0, 0, jpg);

    if (!box.IsEmpty())
    {
        PaintBox1->Canvas->Pen->Color = clBlack;
        PaintBox1->Canvas->Brush->Style = bsClear;
        PaintBox1->Canvas->Rectangle(box);
    }
}
//---------------------------------------------------------------------------

Re: draw and move a rectangle over a bitmap

PostPosted: Tue Sep 18, 2018 8:30 am
by mark_c
thanks for now

Re: draw and move a rectangle over a bitmap

PostPosted: Fri Sep 21, 2018 9:19 am
by mark_c
this is my modified version that I leave to thank the staff. It basically restores the bitmap through bmp2 to every redraw of the rectangle. I hope it can serve others.

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <Jpeg.hpp>

Graphics::TBitmap *bmp1, *bmp2;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        DoubleBuffered=true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        Image1->Picture->LoadFromFile("mypicture.jpg");
        bmp1= new Graphics::TBitmap;
        bmp2= new Graphics::TBitmap;
        bmp1->Assign(Form1->Image1->Picture->Graphic);

        Image1->Picture->Bitmap->Assign(bmp1);
        bmp2->Assign(bmp1);
        delete bmp1;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
        Label1->Caption=X;
        Label2->Caption=Y;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
        if(Shift.Contains(ssLeft))
        {
                Label3->Caption=X;
                Label4->Caption=Y;


                int x1, y1, x2, y2;
                x1=StrToInt(Label1->Caption);
                y1=StrToInt(Label2->Caption);
                x2=StrToInt(Label3->Caption);
                y2=StrToInt(Label4->Caption);

                if(x1 > x2 || y1 > y2) return;

                Image1->Picture->Bitmap->Assign(bmp2);

                Image1->Picture->Bitmap->Canvas->Brush->Style = bsClear;
                Image1->Picture->Bitmap->Canvas->Rectangle(x1,y1,x2,y2);
        }
}
//---------------------------------------------------------------------------