How to make a checkerboard grid on a bitmap?

I show transparent images on top of another image "bottom".

In this case, the lower (solid) image is a checkerboard grid, and the upper image is a lion (transparent):

enter image description here

enter image description here = enter image description here

The reason is to show areas of transparency much better, because usually you don’t see which areas are transparent.

The problem is that bitmaps can be any size in size, so the grid must also be the same size as the bitmap.

It seems like a dirty approach is to create a larger version of a chessboard grid up to 2000x2000 in size, then depending on the size of the bitmap images you work with, you can resize the canvas canvas to fit, This is not ideal because it means saving a large raster image of the chess grid with your application, and then it means resizing, which may not give the correct results depending on the aspect ratio, etc.

The correct approach, which I believe, is to make the chessboard grid programmatically, for example:

procedure RenderGrid(Source: TBitmap; Height, Width: Integer; Size: Integer; Color1, Color2: TColor); begin end; 

This will allow you to configure a grid with different sizes and colors, rather than worry about the overhead of storing a large raster image of a chess grid and the need to resize.

However, I'm not sure how you could draw a grid on a bitmap? I thought you need to scroll through each variable line of the bitmap and color it that way? I'm not sure.

This is due to mathematics and calculations, which I feel bad. I would appreciate it if you could enlighten me with the most efficient way to render a grid to a bitmap image.

+4
source share
3 answers
 procedure RenderGrid(Source: TBitmap; Height, Width: Integer; Size: Integer; Color1, Color2: TColor); var y: Integer; x: Integer; begin Source.SetSize(Width, Height); for y := 0 to Height div Size do for x := 0 to Width div Size do begin if Odd(x) xor Odd(y) then Source.Canvas.Brush.Color := Color1 else Source.Canvas.Brush.Color := Color2; Source.Canvas.FillRect(Rect(x*Size, y*Size, (x+1)*Size, (y+1)*Size)); end; end; 
+5
source

Once upon a time, I profiled this particular need . Given your RenderGrid signature, it is likely that the image of the Bitmap parameter will be drawn after drawing the bitmap. Then the best performance is obtained by drawing the entire bitmap in Color1 and draw only the squares for Color2 :

 procedure RenderGrid(Target: TBitmap; Height, Width: Integer; Size: Integer; Color1, Color2: TColor); var Col: Integer; Row: Integer; begin Target.SetSize(Width, Height) Target.Canvas.Brush.Color := Color1; Target.Canvas.FillRect(Rect(0, 0, Width, Height)); Target.Canvas.Brush.Color := Color2; for Col := 0 to Width div Size do for Row := 0 to Height div Size do if Odd(Col + Row) then Target.Canvas.FillRect(Bounds(Col * Size, Row * Size, Size, Size)); end; 

Update

But since you're talking about large raster images, the procedure shown below is 20% faster. It creates a small raster image with only four squares, for example, with a 2 x 2 chessboard, and allows the target property of the brush to distribute it automatically. *)

 procedure RenderGrid(Target: TBitmap; Height, Width: Integer; Size: Integer; Color1, Color2: TColor); var Tmp: TBitmap; begin Tmp := TBitmap.Create; try Tmp.Canvas.Brush.Color := Color1; Tmp.Width := 2 * Size; Tmp.Height := 2 * Size; Tmp.Canvas.Brush.Color := Color2; Tmp.Canvas.FillRect(Rect(0, 0, Size, Size)); Tmp.Canvas.FillRect(Bounds(Size, Size, Size, Size)); Target.Canvas.Brush.Bitmap := Tmp; if Target.Width * Target.Height = 0 then Target.SetSize(Width, Height) else begin Target.SetSize(Width, Height) Target.Canvas.FillRect(Rect(0, 0, Width, Height)); end; finally Tmp.Free; end; end; 

To further optimize this: cache this small bitmap ( Tmp ) and reuse it when its size has not been resized.

*) See also: How to colorize a bitmap without calling FillRect() ? .

+3
source

You will get better performance with this approach. Just don't pass CellSize = 0.

 // Color1, Color2 in RRGGBB format (ie Red = $00FF0000) procedure RenderGrid(Source: TBitmap; CellSize: Integer; Color1, Color2: TColorRef); var I, J: Integer; Pixel: ^TColorRef; UseColor1: Boolean; begin Source.PixelFormat := pf32bit; Pixel := Source.ScanLine[Source.Height - 1]; for I := 0 to Source.Height - 1 do begin UseColor1 := (I div CellSize) mod 2 = 0; for J := 0 to Source.Width - 1 do begin if J mod CellSize = 0 then UseColor1 := not UseColor1; if UseColor1 then Pixel^ := Color1 else Pixel^ := Color2; Inc(Pixel); end; end; end; 
-1
source

All Articles