Recent

Author Topic: Incorrect behavior writing pixels[x,y] to a TImage (Bitmap.Assign bug)  (Read 4316 times)

QuinnMartin

  • Jr. Member
  • **
  • Posts: 56
I started writing code for making a rubber band on a TImage using pixels[].  No matter what I did it wanted to draw only light gray lines.  So I created a very simple piece of test code on a pre-existing image (so it's initialized already):

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.TestButtonClick(Sender: TObject);
  2. var
  3.   x, y : integer;
  4. begin  
  5.   for x := 20 to 100 do
  6.      for y := 20 to 100 do
  7.       Image1.Picture.Bitmap.Canvas.Pixels[x, y] := RGB(0, 0, 0);
  8. end;
  9.  

This draws a light gray box!  Why?  I sampled the color in a paint program and get rgb=240,240,240.  It should be drawing a black box.

I don't know what I am doing wrong.  Is there some other method for setting color in Lazarus I am missing?  I did try setting PixelFormat to pf24bit and pf32bit in the FormCreate event and it doesn't make any difference.
« Last Edit: May 31, 2024, 04:15:27 am by QuinnMartin »

RayoGlauco

  • Full Member
  • ***
  • Posts: 193
  • Beers: 1567
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #1 on: May 28, 2024, 10:40:46 am »
Maybe RGB doesn't do what you want. Have you tried Graphics.RGBtoColor(0,0,0) ?

Or just Image1.Picture.Bitmap.Canvas.Pixels[x, y] := clBlack
« Last Edit: May 28, 2024, 10:44:08 am by RayoGlauco »
To err is human, but to really mess things up, you need a computer.

Zvoni

  • Hero Member
  • *****
  • Posts: 2738
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #2 on: May 28, 2024, 10:41:26 am »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 16157
  • Censorship about opinions does not belong here.
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #3 on: May 28, 2024, 10:44:11 am »
Why are you trying to draw using direct pixel access? Use LineTo. Must faster.
If I smell bad code it usually is bad code and that includes my own code.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #4 on: May 28, 2024, 11:58:37 am »
I don't know what I am doing wrong.
You do many things wrong in my opinion.
Is there some other method for setting color in Lazarus I am missing?
Yes.
Use TImage as display container and not draw direct inside.
Always do it like:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   LBitmap: TBitmap;
  4. begin
  5.   // create class
  6.   LBitmap := TBitmap.Create;
  7.   try
  8.     // step 1: set size
  9.     LBitmap.SetSize(Image1.Width, Image1.Height);
  10.     // step 2: fill background
  11.     LBitmap.Canvas.Brush.Style := bsSolid;
  12.     LBitmap.Canvas.Brush.Color := clBlack;
  13.     LBitmap.Canvas.FillRect(LBitmap.Canvas.ClipRect);
  14.     // step 3: create band
  15.     LBitmap.Canvas.Brush.Color := RGBToColor($A4, $A0, $A0); // <- clMedGray
  16.     // X1 = x axis start
  17.     // Y1 = y axis start
  18.     // X2 = x axis end
  19.     // Y2 = y axis end
  20.     LBitmap.Canvas.FillRect(20, 0, 40, LBitmap.Canvas.ClipRect.Height);
  21.     // step 4: transport image to display container
  22.     Image1.Picture.Assign(LBitmap);
  23.   finally
  24.     // Free class
  25.     LBitmap.Free;
  26.   end;
  27. end;
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

jamie

  • Hero Member
  • *****
  • Posts: 6734
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #5 on: May 28, 2024, 01:01:52 pm »
I started writing code for making a rubber band on a TImage using pixels[].  No matter what I did it wanted to draw only light gray lines.  So I created a very simple piece of test code on a pre-existing image (so it's initialized already):

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.TestButtonClick(Sender: TObject);
  2. var
  3.   x, y : integer;
  4. begin  
  5.   for x := 20 to 100 do
  6.      for y := 20 to 100 do
  7.       Image1.Picture.Bitmap.Canvas.Pixels[x, y] := RGB(0, 0, 0);
  8. end;
  9.  

This draws a light gray box!  Why?  I sampled the color in a paint program and get rgb=240,240,240.  It should be drawing a black box.

I don't know what I am doing wrong.  Is there some other method for setting color in Lazarus I am missing?  I did try setting PixelFormat to pf24bit and pf32bit in the FormCreate event and it doesn't make any difference.

When I attempt to use "RGB(....)" with standard graphic units, there does not seem to be an existing function of that name?

Where did you get it and did you confirm the return results of that function by simply sampling a value returned ?

EDIT:
  Yes, I found it, it's in the windows unit and I tested it. it returns DWORD of 0 value.

  is your format in the image a 24bit or better?

« Last Edit: May 28, 2024, 01:04:55 pm by jamie »
The only true wisdom is knowing you know nothing

QuinnMartin

  • Jr. Member
  • **
  • Posts: 56
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #6 on: May 29, 2024, 08:29:51 am »
Yes.
Use TImage as display container and not draw direct inside.
Always do it like:

I think you are getting ahead of me... my Pixel draw routine was just a test function to see what was wrong.  I was originally trying to draw a rubber band (as stated in the original message) but this wasn't working and it led me down a series of tests trying to find out what is wrong with Pixels[].

I did try addressing the container as Image1.Canvas.Pixels[x, y] := RGB(0, 0, 0);  but it makes no difference, it still draws the exact same light gray box.  I will look into the other comments about the RGB function.

QuinnMartin

  • Jr. Member
  • **
  • Posts: 56
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #7 on: May 29, 2024, 08:31:52 am »
Yes, I found it, it's in the windows unit and I tested it. it returns DWORD of 0 value.

  is your format in the image a 24bit or better?

Yes, my RGB function is from the Windows unit.  I do have the 24bit mode set and tried 32bit with no difference.

Code: Pascal  [Select][+][-]
  1. Image1.Picture.Bitmap.PixelFormat := pf24bit;

QuinnMartin

  • Jr. Member
  • **
  • Posts: 56
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #8 on: May 29, 2024, 08:33:44 am »
https://lazarus-ccr.sourceforge.io/docs/lcl/graphics/tcolor.html
Try RGBToColor instead of RGB-Function?

I tried it this way and it still draws the box as light gray.

Code: Pascal  [Select][+][-]
  1.   for x := 20 to 100 do
  2.      for y := 20 to 100 do
  3.        Image1.Picture.Bitmap.Canvas.Pixels[x, y] := RGBToColor(0, 0, 0);

I did create a standalone program and pixels is working correctly, painting black like it should, so evidently this is a problem specific to that project and not a Lazarus bug.  I also notice in the faulty program, MoveTo/LineTo is also drawing gray even though I set Pen.Color to clBlack.  I am working to figure out why that particular TImage is not rendering correctly.
« Last Edit: May 29, 2024, 08:47:15 am by QuinnMartin »

Zvoni

  • Hero Member
  • *****
  • Posts: 2738
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #9 on: May 29, 2024, 08:40:08 am »
What about:
Code: Pascal  [Select][+][-]
  1. Image1.Picture.Bitmap.Canvas.Pixels[x, y] := clBlack;
Still gray?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 16157
  • Censorship about opinions does not belong here.
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #10 on: May 29, 2024, 08:40:18 am »
As I wrote: that is the wrong approach, use canvas lineto etc.
Will add example later.
If I smell bad code it usually is bad code and that includes my own code.

QuinnMartin

  • Jr. Member
  • **
  • Posts: 56
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #11 on: May 29, 2024, 08:49:29 am »
As I wrote: that is the wrong approach, use canvas lineto etc.
Will add example later.

OK thanks, appreciate the quick response.  I will remember to start doing it that way.

I do notice all the Canvas line draw operations draw the same light gray color on TImage in the faulty program even when pen.color is set to clBlack.  I am continuing to look around to see what the problem is.

Zvoni

  • Hero Member
  • *****
  • Posts: 2738
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #12 on: May 29, 2024, 09:07:13 am »
As I wrote: that is the wrong approach, use canvas lineto etc.
Will add example later.

OK thanks, appreciate the quick response.  I will remember to start doing it that way.

I do notice all the Canvas line draw operations draw the same light gray color on TImage in the faulty program even when pen.color is set to clBlack.  I am continuing to look around to see what the problem is.
If you use Black as the Color, and you get gray as a result, it probably has to do with the opacity-factor (Alpha-Channel?)

EDIT: If it is the Alpha-Channel, maybe this?
https://www.freepascal.org/daily/packages/fcl-image/fpimage/tfpcolor.html
https://lazarus-ccr.sourceforge.io/docs/lcl/graphics/fpcolortotcolor.html

untested
Code: Pascal  [Select][+][-]
  1. Image1.Picture.Bitmap.Canvas.Pixels[x, y] := FPColorToColor(TFPColor(0,0,0,0));
« Last Edit: May 29, 2024, 09:12:59 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

rvk

  • Hero Member
  • *****
  • Posts: 6575
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #13 on: May 29, 2024, 09:20:04 am »
I started writing code for making a rubber band on a TImage using pixels[].  No matter what I did it wanted to draw only light gray lines.  So I created a very simple piece of test code on a pre-existing image (so it's initialized already):
Can you post that pre-existing image here?
It could be the cause of the problems.
For example if it has a weird color palet then the pixels need to be in that palet.

As I wrote: that is the wrong approach, use canvas lineto etc.
Will add example later.
Using lineto would be more appropriate for drawing a box... but isn't the issue here.
If you want to manipulate direct pixels on the canvas, the coloring should work too, and it doesn't in this case... that's the issue.

Could you create your example where you manipulate pixels directly, setting a certain color for a pixel?


Zvoni

  • Hero Member
  • *****
  • Posts: 2738
Re: Incorrect behavior writing pixels[x,y] to a TImage
« Reply #14 on: May 29, 2024, 09:23:43 am »
I started writing code for making a rubber band on a TImage using pixels[].  No matter what I did it wanted to draw only light gray lines.  So I created a very simple piece of test code on a pre-existing image (so it's initialized already):
Can you post that pre-existing image here?
It could be the cause of the problems.
For example if it has a weird color palet then the pixels need to be in that palet.
Maybe that pre-existing Picture has a set Alpha-Channel?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

 

TinyPortal © 2005-2018