Need a method to calculate the extents of the actual drawing items in a tcanvas

151 Views Asked by At

I am using a paintbox component to draw various shapes using rect, polygon and other canvas methods. After the user has created the drawing, I want to save a bitmap for use in a listbox. The problem is that the drawing may only use a small portion of the canvas and the resulting image in the listbox would be very small unless I adjust its size by selecting only the used portion of the paintbox's original canvas. So the question is how do I determine what portion of the canvas has been used so I can extract only that part of the canvas to load into a bitmap for display in listbox?

(Note:I edited above to clarify the question a bit)

The actual program has a paintbox (200x200) and an image (32 x 32). The image gets its bitmap from the paintbox using Bitmap1.Canvas.CopyRect(Dest, PaintBox1.Canvas, Source);. If the drawing in the paintbox is only 20x20 in the 200x200 paintbox.canvas, then the resulting bitmap in the Image.canvas will be very small in the 32x32 image.canvas. I need it to be enlarged and that means that I must determine the actual size of the used area in the paintbox and change the source size in 'CopyRec'.

1

There are 1 best solutions below

0
On

One approach I have worked out is based on the assumption that the various items that have been drawn such as circles, rectangles, text, etc are all placed on a neutral background. In that case I can read the bitmap using tbitmap.scanline to compare the color of the drawing vs the background color and calculate the extents of the drawing in each row to determine the extents of the drawing in the overall bitmap.

  TRGBTriple = packed record
    rgbtBlue: Byte;
    rgbtGreen: Byte;
    rgbtRed: Byte;
  end;
  TRGBTripleArray = ARRAY[Word] of TRGBTriple;
  pRGBTripleArray = ^TRGBTripleArray; // use a PByteArray for pf8bit color

function findBMPExtents (Bmp : tbitmap; BkgdClr : longint):trect;
// finds the extents of an image in a background or BkgdClr color
//works on 24 bit colors
var
  P : pRGBTripleArray;
  x,y : integer;
  tfound, bfound, done : boolean;
  WorkTrpl : TRGBTriple;
  WorkRect : trect;
begin
  result.top := 0;
  result.bottom := Bmp.height;
  result.left := Bmp.Width;
  result.right := 0;
  tfound := false;
  bfound := false;
  WorkTrpl := getRGB (BkgdClr);

  //find left and top
  y := 0;
  done := false;
  Repeat
    P := Bmp.ScanLine[y];
    x := 0;
    Repeat
      if (p[x].rgbtBlue <> WorkTrpl.rgbtBlue) or
         (p[x].rgbtGreen <> WorkTrpl.rgbtGreen) or
         (p[x].rgbtRed <> WorkTrpl.rgbtRed) then
        begin
          tfound := true;
          if x <= result.left then begin
            result.left := x;
            done := true;
          end;
        end;
      inc (x);
    until (x = bmp.width) or done;
    done := false;
    inc (y);
    if not tfound then
      inc(result.top);
  until (y = bmp.height);

  //find right and bottom
  y := bmp.height - 1;
  done := false;
  Repeat
    P := Bmp.ScanLine[y];
    x := bmp.width-1;
    Repeat
      if (p[x].rgbtBlue <> WorkTrpl.rgbtBlue) or
         (p[x].rgbtGreen <> WorkTrpl.rgbtGreen) or
         (p[x].rgbtRed <> WorkTrpl.rgbtRed) then
        begin
          bfound := true;
          if x >= result.right then begin
            result.right := x;
            done := true;
          end;
        end;
      dec (x);
    Until (x = 0) or done;
    if not bfound then
      dec(result.bottom);
    done := false;
    dec (y);
  Until (y = -1);
  dec(result.bottom);
end;