Recent

Author Topic: Convert a picture to Gray  (Read 5179 times)

winni

  • Hero Member
  • *****
  • Posts: 2806
Re: Convert a picture to Gray
« Reply #15 on: December 23, 2019, 06:25:52 pm »
Hi!

Before you resize Image7 you have to initialize the internal bitmap.

The easiest way is to fill it white
Code: Pascal  [Select][+][-]
  1. image7.canvas.brush.color := clWhite;
  2. image7.Canvas.fillrect(0,0,image7.width,image7.height);
  3.  
Now you can resize the bitmap of image7 without crash.

Winni

fpauw

  • New Member
  • *
  • Posts: 11
Re: Convert a picture to Gray
« Reply #16 on: December 24, 2019, 08:35:21 am »
I add the code but now the same error is now on closing the program. The gray image is just a white surface...

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. Var
  3.   ScanData, ResultData: PRGBQuad;
  4.   ValR, ValG, ValB, monoByte : Byte;
  5.   X, Y: Integer;
  6. begin
  7.   if openpicturedialog1.Execute then
  8.      Begin
  9.        Image1.Picture.LoadFromFile(openpicturedialog1.FileName);
  10.      end;
  11.  
  12.   Image7.Picture.Bitmap.Width := Image1.Picture.Width;
  13.   Image7.Picture.Bitmap.Height := Image1.Picture.Height;
  14.   image7.canvas.brush.color := clWhite;
  15.   image7.Canvas.fillrect(0,0,image7.width,image7.height);
  16.  
  17.   For Y:=0 To Image1.Height-1 Do
  18.   Begin
  19.     ScanData := Image1.Picture.Bitmap.ScanLine[Y];
  20.     ResultData := Image7.Picture.Bitmap.ScanLine[Y];
  21.     For X:=0 To Image1.Width-1 Do
  22.     Begin
  23.       ValR := ScanData^.rgbRed;
  24.       ValG := ScanData^.rgbGreen;
  25.       ValB := ScanData^.rgbBlue;
  26.  
  27.       MonoByte := round(0.2125 * ValR + 0.7154 * ValG + 0.0721 * ValB);
  28.  
  29.       ResultData^.rgbRed:=MonoByte;
  30.       ResultData^.rgbGreen:=MonoByte;
  31.       ResultData^.rgbBlue:=MonoByte;
  32.  
  33.       Inc(ScanData);
  34.       Inc(ResultData);
  35.     end;
  36.   end;
  37. end;    
  38.  
« Last Edit: December 24, 2019, 09:19:36 am by fpauw »

martijnn

  • New Member
  • *
  • Posts: 16
Re: Convert a picture to Gray
« Reply #17 on: December 24, 2019, 09:16:20 am »
Have a look at comment on the ScanLine property:

Code: Pascal  [Select][+][-]
  1. property ScanLine[Row: Integer]: Pointer read GetScanLine; platform; // Use only when wrpped by a begin/endupdate

Adding the following...
Code: Pascal  [Select][+][-]
  1. Image7.Picture.Bitmap.BeginUpdate;
  2. // Double loop here
  3. Image7.Picture.Bitmap.EndUpdate;
  4.  
... at least starts to show a grayscale picture (still with some issues left)

fpauw

  • New Member
  • *
  • Posts: 11
Re: Convert a picture to Gray
« Reply #18 on: December 24, 2019, 09:29:35 am »
Thanks I have output now! :)

And yes there are still errors now I have vertical white lines. :o

martijnn

  • New Member
  • *
  • Posts: 16
Re: Convert a picture to Gray
« Reply #19 on: December 24, 2019, 09:50:46 am »
As a next step it will probably help to match the number of bits per pixel of the input image. For example:

Code: Pascal  [Select][+][-]
  1. image7.Picture.Bitmap.PixelFormat := image1.Picture.Bitmap.PixelFormat;

fpauw

  • New Member
  • *
  • Posts: 11
Re: Convert a picture to Gray
« Reply #20 on: December 24, 2019, 10:28:10 am »
Thanks a Lot!

Now it works without errors! :D

This is the result
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. Var
  3.   ScanData, ResultData: PRGBQuad;
  4.   ValR, ValG, ValB, monoByte : Byte;
  5.   X, Y: Integer;
  6. begin
  7.   if openpicturedialog1.Execute then
  8.      Begin
  9.        Image1.Picture.LoadFromFile(openpicturedialog1.FileName);
  10.      end;
  11.   Image7.Picture.Bitmap.Width := Image1.Picture.Width;
  12.   Image7.Picture.Bitmap.Height := Image1.Picture.Height;
  13.   image7.Picture.Bitmap.PixelFormat := image1.Picture.Bitmap.PixelFormat;
  14.   Image7.Picture.Bitmap.BeginUpdate;
  15.  
  16.   For Y:=0 To Image1.Height-1 Do
  17.   Begin
  18.     ScanData := Image1.Picture.Bitmap.ScanLine[Y];
  19.     ResultData := Image7.Picture.Bitmap.ScanLine[Y];
  20.     For X:=0 To Image1.Width-1 Do
  21.     Begin
  22.       //   X, Y, TotalTime, DistCurve: Integer;Point to the pixel location
  23.       // Get RGB value of the pixel
  24.       ValR := ScanData^.rgbRed;
  25.       ValG := ScanData^.rgbGreen;
  26.       ValB := ScanData^.rgbBlue;
  27.  
  28.       MonoByte := round(0.2125 * ValR + 0.7154 * ValG + 0.0721 * ValB);
  29.  
  30.       ResultData^.rgbRed:=MonoByte;
  31.       ResultData^.rgbGreen:=MonoByte;
  32.       ResultData^.rgbBlue:=MonoByte;
  33.  
  34.       Inc(ScanData);
  35.       Inc(ResultData);
  36.     end;
  37.   end;
  38.   Image7.Picture.Bitmap.EndUpdate;
  39. end;  
  40.  
« Last Edit: December 24, 2019, 10:45:29 am by fpauw »

trheo

  • Newbie
  • Posts: 2
Re: Convert a picture to Gray
« Reply #21 on: October 21, 2021, 09:23:38 am »
Please, does anyone have an idea on how to convert directly Image1 to grey (without creating a new Image) ?

Thank you !!

Ally

  • New Member
  • *
  • Posts: 22
Re: Convert a picture to Gray
« Reply #22 on: October 21, 2021, 10:20:41 am »
Hallo trheo,

rhsBitmapGrayscale uses TLazIntfImage, which speeds up processing significantly.

Code: Pascal  [Select][+][-]
  1. // rhsBitmapGrayscale
  2. // ----------------------------------------------------------------------------
  3.  
  4. unit rhsBitmapGrayscale;
  5.  
  6. {$mode objfpc}{$H+}
  7.  
  8. interface
  9.  
  10. uses
  11.   SysUtils, Classes, Graphics, IntfGraphics, FPImage;
  12.  
  13.   procedure BitmapGrayscale(BM: TCustomBitmap; R, G, B: Single);
  14.  
  15. implementation
  16.  
  17. procedure BitmapGrayscale(BM: TCustomBitmap; R, G, B: Single);
  18. var
  19.   IntfImg: TLazIntfImage = nil;
  20.   x, y: Integer;
  21.   TempColor: TFPColor;
  22.   Gray: Word;
  23. begin
  24.   try
  25.     IntfImg := BM.CreateIntfImage;
  26.  
  27.     IntfImg.BeginUpdate;
  28.     for y := 0 to IntfImg.Height - 1 do
  29.       for x := 0 to IntfImg.Width - 1 do
  30.       begin
  31.         TempColor := IntfImg.Colors[x, y];
  32.         Gray := Round(TempColor.Red * R + TempColor.Green * G + TempColor.Blue * B);
  33.         TempColor.Red := Gray;
  34.         TempColor.Green := Gray;
  35.         TempColor.Blue := Gray;
  36.         IntfImg.Colors[x, y] := TempColor;
  37.       end;
  38.     IntfImg.EndUpdate;
  39.  
  40.     BM.LoadFromIntfImage(IntfImg);
  41.   finally
  42.     IntfImg.Free;
  43.   end;
  44. end;
  45.  
  46. end.

Here is another example for the use of rhsBitmapGrayscale.

Code: Pascal  [Select][+][-]
  1. BitmapGrayscale(Image1.Picture.Bitmap, 0.30, 0.59, 0.11);  // Neutral filter
  2. BitmapGrayscale(Image1.Picture.Bitmap, 1.00, 0.00, 0.00);  // Red filter
  3. BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 1.00, 0.00);  // Green filter
  4. BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 0.00, 1.00);  // Blue filter
  5. BitmapGrayscale(Image1.Picture.Bitmap, 0.00, 0.50, 0.50);  // Cyan filter
  6. BitmapGrayscale(Image1.Picture.Bitmap, 0.50, 0.00, 0.50);  // Magenta filter
  7. BitmapGrayscale(Image1.Picture.Bitmap, 0.50, 0.50, 0.00);  // Yellow filter

« Last Edit: October 21, 2021, 10:33:43 am by Ally »

trheo

  • Newbie
  • Posts: 2
Re: Convert a picture to Gray
« Reply #23 on: October 21, 2021, 10:45:39 am »
Thank you very much Ally

wp

  • Hero Member
  • *****
  • Posts: 9030
Re: Convert a picture to Gray
« Reply #24 on: October 21, 2021, 11:46:46 am »
If the input bitmap is in pf24Bit pixelformat every r,g,b component is stored as 1 byte. After converting to grayscale by Ally's code, the 24Bit pixelformat stays the same, but r,g,b have the same value. Even worse, if the input bitmap is pf32Bit. It would be more memory-efficient to store the gray value only once, like in pf8bit.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

Ally

  • New Member
  • *
  • Posts: 22
Re: Convert a picture to Gray
« Reply #25 on: October 21, 2021, 12:28:17 pm »
Hello wp,

that's true, of course.
But in the case of images with an alpha channel, the transparency would be lost.

 

TinyPortal © 2005-2018