Recent

Author Topic: Load jpg-draw on it-read pixels-SOLVED  (Read 648 times)

Sheepdog

  • New Member
  • *
  • Posts: 39
Load jpg-draw on it-read pixels-SOLVED
« on: February 19, 2024, 02:19:14 pm »
I want to load a jpg from a file into a TImage.

I want to "read" the RGB value of individual pixels of the TImage

... AND draw on the TImage.

--------
I can load the jpg with...

Image1.Picture.LoadFromFile('My.jpg');

--
If I haven't loaded a jpg, I can do...

Image1.Picture.Bitmap.canvas.moveto
                (Image1.canvas.moveto(10,10);
Image1.Picture.Bitmap.canvas.lineto
                (Image1.canvas.moveto(40,40);

(I draw to the bitmap canvas because when I didn't (years ago) the lines drawn would disappear if the image was refreshed.. or something like that.)

I THINK I can read RGB values with...

iRGB:=Image1.Picture.Bitmap.canvas.pixels[15,15];

... That compiles, runs... but I'm not sure the number returned corresponds to what I see at 40,40.

===
Advice welcome! Maybe I need to move the jpg to...
   Image1.Picture.Bitmap.canvas ?
Or maybe do drawing and pixel sampling to/ from
   Image1.Picture ?

===
What I am trying to do...

I have scanned some sheets of paper with grids on them. These sheets are responses to a multiple choice questionnaire... a row for each question, a column for each allowed response. The respondant makes X's on the sheet to indicate response. All very plain vanilla.

The program I'm trying to make will "read" the sheets, "see" where respondents have made marks. (Eventually, the program will then produce a file tabulating what was on the response forms.)

Why do I want to draw on the image? I want to show where the program is scanning for marks, and mark where it sees them.
« Last Edit: February 19, 2024, 08:06:39 pm by Sheepdog »

rvk

  • Hero Member
  • *****
  • Posts: 6199
Re: Load jpg-draw on it-read pixels
« Reply #1 on: February 19, 2024, 02:36:16 pm »
I can load the jpg with...

Image1.Picture.LoadFromFile('My.jpg');
You need to realize that TImage.Picture can hold several types of images. It isn't converted automatically to bitmap.

You can see that in the source.
Code: Pascal  [Select][+][-]
  1.   public
  2.     property Bitmap: TBitmap read GetBitmap write SetBitmap;
  3.     property Icon: TIcon read GetIcon write SetIcon;
  4.     property Jpeg: TJpegImage read GetJpeg write SetJpeg;
  5.     property Pixmap: TPixmap read GetPixmap write SetPixmap;
  6.     property PNG: TPortableNetworkGraphic read GetPNG write SetPNG;
  7.     property PNM: TPortableAnyMapGraphic read GetPNM write SetPNM;
  8.     property Graphic: TGraphic read FGraphic write SetGraphic;

You can also read out Image1.Picture.Graphic.Classname after the LoadFromFile to see WHAT image is loaded exactly.
TJpegImage in your case. So you can't just treat it like a TBitmap.

Now... if you want to force the image to TBitmap you can do something like this:
Code: Pascal  [Select][+][-]
  1. Image1.Picture.Bitmap.Assign(Image1.Picture);
After that you should be able to manipulate the Image1.Picture.Bitmap (TBitmap).

Sheepdog

  • New Member
  • *
  • Posts: 39
Re: Load jpg-draw on it-read pixels
« Reply #2 on: February 19, 2024, 03:19:09 pm »
Many thanks! I  suspected as much, spent (literally) hours trying different permutations before posting!

I THNK I've tried what you suggested. Alas, my attempts to draw on top of the loaded jpg still coming to nothing. Can you spot where I misunderstood your suggestion?...

Code: Pascal  [Select][+][-]
  1. procedure Tomr_for_forum_f1.FormCreate(Sender: TObject);
  2. begin
  3.  
  4. Bitmap:=TBitmap.create;//Create a bitmap object
  5. Bitmap.width:=180;//Assign dimensions
  6. Bitmap.height:=180;
  7.  
  8. Bitmap.canvas.pen.color:=clWhite;
  9. Bitmap.canvas.Rectangle(0,0,180,180);
  10.  
  11. Image1.Picture.Graphic:=Bitmap;
  12. end;//FormCreate
  13.  
  14. procedure Tomr_for_forum_f1.buDoItClick(Sender: TObject);
  15. begin
  16.    DoDoIt;
  17. end;
  18.  
  19. procedure Tomr_for_forum_f1.DoDoIt;
  20. var iLoop:integer;
  21.   iTopOfSample,iLeftOfSample,iExtentOfSample:integer;
  22.  
  23. begin
  24.  
  25.   iLeftOfSample:=35;
  26.   iTopOfSample:=18;
  27.   iExtentOfSample:=60;
  28.  
  29.   Image1.Picture.LoadFromFile('My.jpg');
  30.  
  31.   //https://forum.lazarus.freepascal.org/index.php/topic,66305.0.html
  32.   Image1.Picture.Bitmap.Assign(Image1.Picture);
  33.  
  34.   memo1.lines.clear;
  35.   for iLoop:=0 to 20 do begin
  36.     memo1.lines.add(inttostr(Image1.Picture.Bitmap.canvas.pixels[iLeftOfSample,iTopOfSample+(iLoop*2)]));
  37.     end;//for
  38.  
  39.   Image1.Picture.Bitmap.canvas.pen.color:=clBlack;
  40.   Image1.Picture.Bitmap.canvas.moveto(iLeftOfSample,iTopOfSample);
  41.   Image1.Picture.Bitmap.canvas.lineto(iLeftOfSample,iTopOfSample+iExtentOfSample);
  42. end;//DoLoadJpg                                    

(I've posted a .zip with the whole project that the above was part of as

https://SheepdogGuides.com/lut/lzips/omr_for_forum.zip

cdbc

  • Hero Member
  • *****
  • Posts: 1162
    • http://www.cdbc.dk
Re: Load jpg-draw on it-read pixels
« Reply #3 on: February 19, 2024, 03:38:07 pm »
Hi
Try to call "DoDoIt;" in Tform1.FormPaint(); or TImage1.Image1Paint();
Because you drawing gets erased every time your form repaints itself...
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

rvk

  • Hero Member
  • *****
  • Posts: 6199
Re: Load jpg-draw on it-read pixels
« Reply #4 on: February 19, 2024, 03:47:50 pm »
I THNK I've tried what you suggested. Alas, my attempts to draw on top of the loaded jpg still coming to nothing. Can you spot where I misunderstood your suggestion?...
Actually, you code draws just fine... It's just... it doesn't draw in black.
Set the pen.width to 5 and you see what I mean.

This could be a problem with the color pallet (where clBlack isn't translated to the black color).

You could do it another way. That's to load the jpg separately in a TPicture and then assigning it.

Code: Pascal  [Select][+][-]
  1. var
  2.   jpg: TPicture;
  3. //...
  4.   jpg := TPicture.Create;
  5.   try
  6.     jpg.LoadFromFile('My.jpg');
  7.     Image1.Picture.Bitmap.SetSize(jpg.Width, jpg.Height);
  8.     Image1.Picture.Bitmap.Canvas.Draw(0, 0, jpg.Bitmap);
  9.   finally
  10.     jpg.Free;
  11.   end;
  12.   // ....
After this you can draw to the Image1.Picture.Bitmap like you did and colors are fine.
You might still need to fiddle with width because 1 might be too small to show on the original bitmap.
But setting it to 2 will show it. (That's because your TImage is 320x288 and your jpg is 600x600)

Try to call "DoDoIt;" in Tform1.FormPaint(); or TImage1.Image1Paint();
Because you drawing gets erased every time your form repaints itself...
That's not a problem if you'r drawing to a TBitmap. It's persistent (so everything you draw is stored in that bitmap).
« Last Edit: February 19, 2024, 04:54:02 pm by rvk »

Sheepdog

  • New Member
  • *
  • Posts: 39
Re: Load jpg-draw on it-read pixels
« Reply #5 on: February 19, 2024, 06:26:05 pm »
THANK YOU everyone for the great help, given quickly, so I could press ahead with this and not have to wait, get back up to speed, etc, etc.

I was getting frustrated and beginning to fear I'd be defeated. You've got me "over the hump", and I'm able to move forward... for the moment!

Sheepdog

  • New Member
  • *
  • Posts: 39
Re: Load jpg-draw on it-read pixels
« Reply #6 on: February 19, 2024, 08:06:14 pm »
For people reading this thread, and wanting to do something similar...

It is a dog's dinner... but, as students who wanted to wind me up used to say "but it works!"...

https://SheepdogGuides.com/lut/lzips/omrgoodstart24219.zip

(Holds a Lazarus project, and .exe it produces.)

I would never have reached this stage in the creation of the program I am working towards without the support of the forum members who gave it. The rest of the project... famous last words... is now relatively straightforward. It is something I've wanted to create for YEARS!
« Last Edit: February 19, 2024, 08:07:55 pm by Sheepdog »

 

TinyPortal © 2005-2018