Good find and great sleuth work.

It is possible that the original reason for switching R and B channels was to make the agg color object more compatible with LCL which seems to prefer BGR, order, but who knows... One obvious problem seems to be

function AggToLCLColor(const c: TAggColor): TColor;

in Agg_LCL, that relies for conversion on RGBToColor in the Graphics unit.

function RGBToColor(R, G, B: Byte): TColor;
begin
  Result := (B shl 16) or (G shl 8) or R;
end;

Anyway, a quick search of the agg source code shows that the rgba8 object is used only by a handful of units directly. Most agg units and demos use the more complicated aggclr object to represent color. I tried a few demos and seem unaffected by your fix. This explains why the bug was only clearly visible in your case, most of the other agg demos seem indiferent to the bug. On the other hand, besides agg_2D there are agg_fpimage, Agg2D (the one that integrates with LCL) that also use the rgba8 (through the TAggColor alias) and are clearly affected by the R and B swap when using canvas methods that involve the TAggColor object (e.g., AggClearAll, AggClearClipBox, etc). These would need to be updated as well. As an example, after your fix, the call canvas.AggClearAll(255,0,0) to TAggFPCanvas.AggClearAll(const r ,g ,b : byte; a : byte = 255 ) produces a blue background, which is clearly wrong.

On 06/18/2017 08:35 PM, James Richters wrote:


I finally partially figured out the red / blue color problem.
After single stepping through tons of the aggpas code for hours (it's quite 
complicated even to draw a line) with a sample program that just made a red 
line at the top, I discovered that it's actually doing everything exactly 
correct!   The problem is not with rendering with rgb565,  the problem is 
something in the original that was patched with the setcolor function:

Line 122 of agg_color pas has:
constructor rgba8.Construct;
begin
 b{*}:=int8u(r_ );
 g:=int8u(g_ );
 r:=int8u(b_ );
 a:=int8u(a_ );

end;

This switches red and blue... if I correct it to:
constructor rgba8.Construct;
begin
 b{*}:=int8u(b_ );
 g:=int8u(g_ );
 r:=int8u(r_ );
 a:=int8u(a_ );

end;

now my colors with rgb565 are correct.     Since this is no logical reason to 
make b:=R_ and r:=B_ it seems more likely that with the rgba format somewhere 
along the way someone got lazy and just switched red and blue instead of fixing 
the pixelformat.

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to