Recent

Author Topic: Scanline Problematic  (Read 2077 times)

loaded

  • Hero Member
  • *****
  • Posts: 825
Scanline Problematic
« on: September 24, 2019, 02:16:24 pm »
Hello to everyone
I have an image object that I draw on.
If I access the pixel data with Scanline, then the drawings I make become colorless.
I would appreciate it if anyone shares the reason and solution.
Respects.
Example Code :
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   p:pointer;
  4. begin
  5.   p:=image1.Picture.Bitmap.ScanLine[0];
  6. end;
  7.  
  8. procedure TForm1.Button2Click(Sender: TObject);
  9. begin
  10.   image1.canvas.Pen.Color:=clblue;
  11.   image1.canvas.Pen.width:=10;
  12.   Image1.Canvas.Line(0,0,image1.Width,image1.Height);
  13. end;  
  14.  
Check out  loaded on Strava
https://www.strava.com/athletes/109391137

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: Scanline Problematic
« Reply #1 on: September 24, 2019, 02:50:57 pm »
To be able to use ScanLine properly, you need to understand pixel format. You can download and learn from the demo I wrote:

https://forum.lazarus.freepascal.org/index.php/topic,37242.msg252828.html#msg252828

loaded

  • Hero Member
  • *****
  • Posts: 825
Re: Scanline Problematic
« Reply #2 on: September 24, 2019, 03:58:54 pm »
Handoko Thank you very much for your answer.
I have no problem using the Scanline method.
My problem;
I cannot draw on canvas after scanline operation.
If you can run the sample code above when available, you will understand me.
Check out  loaded on Strava
https://www.strava.com/athletes/109391137

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: Scanline Problematic
« Reply #3 on: September 24, 2019, 05:01:35 pm »
My problem;
I cannot draw on canvas after scanline operation.
If you can run the sample code above when available, you will understand me.
(1) In Button1Click you are reading the address of the first ScanLine of the bitmap loaded into an Image. The address is stored in a local variable, i.e. it is lost when you exit the procedure.

(2) In Button2Click you draw a line to the Canvas of the image. You should never do it this way. You should only draw to the canvas of a visual component in an OnPaint event. The OnClick handler should only set conditions or parameters and enforce a redraw by calling the Invalidate method of the control you paint on. In its OnPaint method you should execute the drawing itself and take care of the conditions/parameters set in the onClick. The operating system may require a redraw at any time which is out of your control: maybe the user opens another program which overlaps with your image, drags the overlapping window away and the OS repaints the images. But the OnClick is long gone and what was done there cannot be restored.

(3) Why do you paint on a TImage? This component is too complex just for painting. I'd create a TBitmap, load the picture into this bitmap and draw the bitmap on a TPaintBox, a TPanel or a TForm - all these components offer an OnPaint event.

Here is a small example loading the Lazarus cheetah into a bitmap which is painted onto a TPaintBox. And every ButtonClick writes the text "Lazarus" at some random position. This position is reproducible: you can minimize and restore the form without losing the text (although the form is redrawn). For comparison I am also providing a button which paints directly onto the canvas of the Paintbox: Minimize and restore the form and see what is happening...

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Scanline Problematic
« Reply #4 on: September 24, 2019, 05:04:05 pm »
Very simple:

At the end of Button2click there is missing a

Code: Pascal  [Select][+][-]
  1. Image1.refresh

Done.

Winni

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: Scanline Problematic
« Reply #5 on: September 24, 2019, 05:07:46 pm »
Strange... Why is the image persistent this way (even without the Refresh)?

OK, in the sources I see that the Canvas of a TImage is the canvas of a background bitmap. So drawing a line on TImage.Canvas draws the line persistently on the bitmap.

Still, my argument is correct. If you would to the same with a TPaintbox the line would not be persistent because TPaintbox does not have a buffer bitmap. The argument is still valid: Never paint outside an OnPaint event - with the addition: there may be exceptions, though.
« Last Edit: September 24, 2019, 05:15:59 pm by wp »

Handoko

  • Hero Member
  • *****
  • Posts: 5154
  • My goal: build my own game engine using Lazarus
Re: Scanline Problematic
« Reply #6 on: September 24, 2019, 05:10:46 pm »
I can reproduce OP's issue. And calling refresh can't fix the issue.

And I found that, if the TImage has image loaded on design time, that issue won't happen. It seems like a bug, but I don't consider it as a bug. Why? Because if we want to do some painting, we should use TPaintBox not TImage. Correct me if I'm wrong.

~edit~
Oops, I hadn't read wp's posts. He already explained it well.
« Last Edit: September 24, 2019, 05:20:40 pm by Handoko »

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Scanline Problematic
« Reply #7 on: September 24, 2019, 05:23:47 pm »
i!
That  is a bug from Delphi1 times. And Lazarus copied it:

If an TImage does not contain a picture and you draw on it, it does not work.

your have to "initialize" it. Me and some other people do it that way:

Code: Pascal  [Select][+][-]
  1. TForm1.FormCreate (Sender : TObject);
  2. begin
  3. Image1.Canvas.Brush.color := clWhite;
  4. Image1.Canvas.FillRect(0,0,Image1.Width, Image1.HIeight);
  5. Image1.Refresh;
  6. end;
  7.  


Now the image is initialized and the next drawiings can be done without a refresh!

Nearly 20 years old, this bug. And they don't know it. Ts, ts, ,ts ....

Winni
end;



wp

  • Hero Member
  • *****
  • Posts: 11916
Re: Scanline Problematic
« Reply #8 on: September 24, 2019, 05:34:29 pm »
Ah now I see the issue, too...

It looks as if the line drawn onto the Image.Canvas becomes transparent. Well, in fact it is: I loaded the lazarus cheetah.jpg at designtime and it becomes as 32-bit bitmap. The 32-bit value of clBlue is $00FF0000 - the left-most zeros are the alpha channel, alpha=0 means: fully transparent...

I do not see a different behavior between loading the image at designtime and runtime. (Maybe because i am on Windows, and you, Handoko, are not?).

The attached demo loads the Lazarus cheetah into two images, one at designtime, the other one at runtime.
- When I press button (2) the blue line is drawn across both images. BUT: When you do the minimize/restore trick the blue line will be gone.
- When I press button (1) first (which calls ScanLine), then button (2), the line is drawn again, but now it is transparent as I tried to explain. Now the line is persistent, i.e. the minimize/restore trick has no effect.

I must say that I do not understand what TImage is doing here when the ScanLine of the loaded Bitmap is called (I said: TImage is too complex...). And I somehow refrain from trying to understand it more deeply because painting in OnClick is wrong anyway.

« Last Edit: September 24, 2019, 05:54:13 pm by wp »

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Scanline Problematic
« Reply #9 on: September 24, 2019, 05:39:17 pm »
@wp

TBitmap is persistant. And you don't have to care about redraw - it is done by this component.

TBitmap breaks the standard rule only to paint in OnPaint. You can draw on the canvas, whenever you like. In Windows and in Linux. It goes to the persistant Bitmap  and the next time the TBitmap draws itself, the drawing will appear.

For applications like drawing maps or image manipulating a TImage is the real solution and the PaintbBox is a nothing - wont't get rude. PaintBox is good for lines and points that change every second - like measuring stuff. There the Image is too lazy.

So every component has it's applications.

Hope I could help.

Winni


loaded

  • Hero Member
  • *****
  • Posts: 825
Re: Scanline Problematic
« Reply #10 on: September 24, 2019, 07:30:28 pm »
wp and winni and handoku, thank you very much for your precious time and your response.
wp, your Question (3)
My goal;
I'm looking for another image in the image with the scanline method.
If I could find it, I wanted to frame it with the rectangle method.

wp, also, thank you very much for the sample program you have written.

Anyway, we will now investigate other methods. Thanks.
« Last Edit: September 24, 2019, 07:40:27 pm by loaded »
Check out  loaded on Strava
https://www.strava.com/athletes/109391137

 

TinyPortal © 2005-2018