Sign in Join
Wiki copytemporary

BGRABitmap tutorial 13: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11This tutorial talks about the coordinate system of BGRABitmap. A sample project showing how gamma factor affects antialiasing can be found in [[BGRABitmap AggPas]].
22
33### Pixel coordinates
44
55Standard canvas routines use integer coordinates. This is also the case with the CanvasBGRA property, which emulates standard canvas functions, but with antialiasing (AntialiasingMode), alphablending (Opacity property of Pen, Brush and Font) and gamma correction.
66
77When using pure integer coordinates without antialiasing, the coordinates specify a pixel position, i.e. a square. So when drawing a line from (0,0) to (5,5), the top-left pixel is the first painted pixel. In standard canvas, the last pixel is not painted, so the end of the line will be at (4,4).
88
9-<figure>
10-<img src="BGRATutorial13a.png" title="BGRATutorial13a.png" />
11-<figcaption>BGRATutorial13a.png</figcaption>
12-</figure>
9+![](/wiki-images/a/a3/BGRATutorial13a.png)
1310
1411When drawing an ellipse, the bounding rectangle specifies the pixels that will be used to render the ellipse. Once again, in standard canvas, the lower-right coordinates are excluded from the drawing, so filling the rectangle (0,0)-(5,5) will in fact fill pixels having coordinates from 0 to 4.
1512
1613### Floating coordinates
1714
1815Now, when working with floating point values, the coordinates specify a position that can be anywhere on the pixels. The width value of the pen really means a distance, and not a number of pixels. So what does (0.0,0.0) mean ?
1916
2017#### Top-left distance floating point coordinates
2118
2219It can, for example, be the distance from the top-left corner (this is not the case with BGRABitmap). In this case, this coordinate would be the upper-left corner of the first pixel. But if we do this, the behavior is slightely different between integer coordinates and floating point coordinates. Indeed, imagine we draw an horizontal segment on pixels (0,1) to (4,1). In pixel coordinates it would be the line (0,1)-(5,1) and the width would be 1 pixel. Now if we want to define this segment with floating point coordinates: the left side would be at 0.0, the right at 5.0, that's ok. The top side would be at 1.0 and the bottom at 2.0. Here is the problem. The center of the line is at a vertical coordinate of 1.5. So to draw this line, we should supply coordinates (0.0,1.5)-(5.0,1.5).
2320
24-<figure>
25-<img src="BGRATutorial13b.png" title="BGRATutorial13b.png" />
26-<figcaption>BGRATutorial13b.png</figcaption>
27-</figure>
21+![](/wiki-images/1/18/BGRATutorial13b.png)
2822
2923In fact every 1-pixel wide line with integer coordinates would be drawn between pixels, and with antialiasing, this leads to blurred lines. What appeared to be ok with horizontal coordinates is in fact an illusion, because if the line has caps, the correct coordinates are (0.5,1.5)-(4.5,1.5). If we ignore the last pixel issue, we see that these coordinates are simply 0.5 greater.
3024
3125#### Pixel-center floating point coordinates
3226
3327The coordinates can be the distance from the center of the top-left pixel. In other words, integer values are at the center of the pixels. This is the case with BGRABitmap functions. Using these coordinates, the line that fills pixels (0,1) to (4,1) is simply (0.0,1.0)-(4.0,1.0).
3428
35-<figure>
36-<img src="BGRATutorial13c.png" title="BGRATutorial13c.png" />
37-<figcaption>BGRATutorial13c.png</figcaption>
38-</figure>
29+![](/wiki-images/6/6c/BGRATutorial13c.png)
3930
4031This is strange from a mathematical point of view, but very convenient, because you can use integer coordinates to draw normal 1-pixel wide lines. This way, there is little difference between calls to CanvasBGRA functions and BGRABitmap normal floating point functions.
4132
4233### Create a new project
4334
4435Create a new project and add a reference to [[BGRABitmap]], the same way as in [[BGRABitmap tutorial|the first tutorial]].
4536
4637### Canvas and BGRACanvas
4738
4839Let's try to show what happens at the pixel level.
4940
5041First, we'll use the standard Canvas:
5142
5243``` pascal
5344procedure TForm1.FormPaint(Sender: TObject);
5445var image: TBGRABitmap;
5546begin
5647 image := TBGRABitmap.Create(10,10);
5748 with image.Canvas do
5849 begin
5950 //clear with white
6051 brush.color := clWhite;
6152 FillRect(0,0,image.width,image.height);
6253 //blue ellipse with black border
6354 brush.style := bsClear;
6455 pen.color := clBlack;
6556 Ellipse(0,0,9,9);
6657 end;
6758 /stretch the image so we can see the pixels
6859 BGRAReplace(image,image.Resample(image.Width*10,image.Height*10,rmSimpleStretch));
6960 image.Draw(Canvas,0,0,True);
7061 image.free;
7162end;
7263```
7364
7465The resample option rmSimpleStretch prevents the use of interpolation filters.
7566
7667You should get this:
7768
78-<figure>
79-<img src="BGRATutorial13d.png" title="BGRATutorial13d.png" />
80-<figcaption>BGRATutorial13d.png</figcaption>
81-</figure>
69+![](/wiki-images/7/75/BGRATutorial13d.png)
8270
8371The pixels of coordinate 9 are not filled as explained above about rectangle bounds. Now, let's draw this BGRACanvas. Just change the 'with' line:
8472
8573``` pascal
8674with image.CanvasBGRA do
8775```
8876
8977Now you should get this:
9078
91-<figure>
92-<img src="BGRATutorial13e.png" title="BGRATutorial13e.png" />
93-<figcaption>BGRATutorial13e.png</figcaption>
94-</figure>
79+![](/wiki-images/b/b0/BGRATutorial13e.png)
9580
9681The result is very similar except with antialiasing.
9782
9883### Subtle considerations
9984
10085Suppose we want to fill an antialiased ellipse that fit exactly in a 9x9 bitmap. We could try with this code:
10186
10287``` pascal
10388procedure TForm1.FormPaint(Sender: TObject);
10489var image: TBGRABitmap;
10590begin
10691 image := TBGRABitmap.Create(9,9,BGRAWhite);
10792 image.FillEllipseAntialias(4,4, 4,4, BGRABlack);
10893 BGRAReplace(image,image.Resample(image.Width*10,image.Height*10,rmSimpleStretch));
10994 image.Draw(Canvas,0,0,True);
11095 image.free;
11196end;
11297```
11398
11499We get:
115100
116-<figure>
117-<img src="BGRATutorial13f.png" title="BGRATutorial13f.png" />
118-<figcaption>BGRATutorial13f.png</figcaption>
119-</figure>
101+![](/wiki-images/2/25/BGRATutorial13f.png)
120102
121103As you can see, the border is not completely filled. The ellipse is smaller than expected. In fact, the center of the ellipse is (4,4) so the left border is at (0,4). But remember it is the center of the pixel. So if we want the ellipse to go to the border of the pixel, we need to add 0.5 to the radius:
122104
123105``` pascal
124106 image.FillEllipseAntialias(4,4, 4.5,4.5, BGRABlack);
125107```
126108
127-<figure>
128-<img src="BGRATutorial13g.png" title="BGRATutorial13g.png" />
129-<figcaption>BGRATutorial13g.png</figcaption>
130-</figure>
109+![](/wiki-images/4/46/BGRATutorial13g.png)
131110
132111#### Filled shapes with canvas
133112
134113Note that with standard canvas, the result is very surprising. Suppose we want to do the same thing. We could try this:
135114
136115``` pascal
137116 brush.color := clWhite;
138117 FillRect(0,0,image.width,image.height);
139118 brush.color := clBlue;
140119 pen.style := psClear;
141120 Ellipse(0,0,9,9);
142121```
143122
144123We get this:
145124
146-<figure>
147-<img src="BGRATutorial13h.png" title="BGRATutorial13h.png" />
148-<figcaption>BGRATutorial13h.png</figcaption>
149-</figure>
125+![](/wiki-images/e/eb/BGRATutorial13h.png)
150126
151127So in this case, there is yet another pixel substracted. The ellipse is 8 pixels wide whereas the supplied rectangle is 9 pixels wide.
152128
153129[[BGRABitmap tutorial 12|Previous tutorial (text functions)]] [[BGRABitmap tutorial 14|Next tutorial (canvas2D)]]
154130
155131---
156132*From the Free Pascal wiki, page "BGRABitmap tutorial 13", as it stood on 2023-05-20 after a change by Circular, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
157133Category: BGRABitmap
158134Category: Graphics

Back to history