Load jpg-draw on it-read pixels-SOLVED lazarus / 39-Graphics ---------------------------------------------------------------------- Sheepdog · 2024-02-19 13:19 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. ---------------------------------------------------------------------- rvk · 2024-02-19 13:36 Quote from: Sheepdog on February 19, 2024, 02:19:14 pmI 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   public  property Bitmap: TBitmap read GetBitmap write SetBitmap;    property Icon: TIcon read GetIcon write SetIcon;    property Jpeg: TJpegImage read GetJpeg write SetJpeg;    property Pixmap: TPixmap read GetPixmap write SetPixmap;    property PNG: TPortableNetworkGraphic read GetPNG write SetPNG;    property PNM: TPortableAnyMapGraphic read GetPNM write SetPNM;    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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Image1.Picture.Bitmap.Assign(Image1.Picture);After that you should be able to manipulate the Image1.Picture.Bitmap (TBitmap). ---------------------------------------------------------------------- Sheepdog · 2024-02-19 14:19 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure Tomr_for_forum_f1.FormCreate(Sender: TObject);begin Bitmap:=TBitmap.create;//Create a bitmap objectBitmap.width:=180;//Assign dimensionsBitmap.height:=180; Bitmap. canvas.pen.color:=clWhite;Bitmap.canvas.Rectangle(0,0,180,180); Image1 .Picture.Graphic:=Bitmap;end;//FormCreate procedure Tomr_for_forum_f1.buDoItClick(Sender: TObject);begin   DoDoIt;end; procedure Tomr_for_forum_f1.DoDoIt;var iLoop:integer;  iTopOfSample,iLeftOfSample,iExtentOfSample:integer; begin   iLeftOfSample:=35;  iTopOfSample:=18;  iExtentOfSample:=60;   Image1.Picture.LoadFromFile('My.jpg');   //https://forum.lazarus.freepascal.org/index.php/topic,66305.0.html  Image1.Picture.Bitmap.Assign(Image1.Picture);   memo1.lines.clear;  for iLoop:=0 to 20 do begin    memo1.lines.add(inttostr(Image1.Picture .Bitmap.canvas.pixels[iLeftOfSample,iTopOfSample+(iLoop*2)]));    end;//for   Image1.Picture.Bitmap.canvas.pen.color:=clBlack;  Image1.Picture.Bitmap.canvas.moveto(iLeftOfSample,iTopOfSample);  Imag e1.Picture.Bitmap.canvas.lineto(iLeftOfSample,iTopOfSample+iExtentOfSa mple);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 · 2024-02-19 14:38 Hi Try to call "DoDoIt;" in Tform1.FormPaint(); or TImage1.Image1Paint(); Because you drawing gets erased every time your form repaints itself... Regards Benny ---------------------------------------------------------------------- rvk · 2024-02-19 14:47 Quote from: Sheepdog on February 19, 2024, 03:19:09 pmI 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  jpg: TPicture;//...  jpg := TPicture.Create;  try    jpg.LoadFromFile('My.jpg');    Image1.Picture.Bitmap.SetSize(jpg.Width, jpg.Height);    Image1.Picture.Bitmap.Canvas.Draw(0, 0, jpg.Bitmap);  finally    jpg.Free;  end;  // ....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) Quote from: cdbc on February 19, 2024, 03:38:07 pmTry 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). ---------------------------------------------------------------------- Sheepdog · 2024-02-19 17:26 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 · 2024-02-19 19:06 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!