Recent

Author Topic: Grayscale  (Read 718 times)

pcurtis

  • Full Member
  • ***
  • Posts: 197
Grayscale
« on: June 09, 2020, 09:18:38 am »
How can I convert a colour image into grayscale?

P.S. I dont want to use external tools.

Thanks in advance.
« Last Edit: June 09, 2020, 09:38:44 am by pcurtis »
Windows 10 / Linux Mint 20
Laz 2.10.0
FPC 3.2.0

eljo

  • Sr. Member
  • ****
  • Posts: 408
Re: Greyscale
« Reply #1 on: June 09, 2020, 09:36:42 am »
Code: Pascal  [Select][+][-]
  1. uses  
  2.   Graphics, GraphUtiuls, .....;
  3.  
  4. procedure ToGrayscale(const aBMP:TBitmap);
  5. var
  6.   X, Y: Integer;
  7. begin
  8.    For X :=0 to aBMP.Width -1 do
  9.     For Y := 0 to aBmp.Height -1 do begin
  10.       aBmp.Canvas.Pixels[X,Y] :=  ColorToGray(aBmp.Canvas.Pixels[X,Y]);
  11.     End;
  12. end;
  13.  

Warning the above code is just a hint. It has never been compiled or checked for errors and of course this is not a recommendation on how to do it. In fact I would suggest to avoid the pixels property at all costs.

pcurtis

  • Full Member
  • ***
  • Posts: 197
Re: Grayscale
« Reply #2 on: June 09, 2020, 09:44:18 am »
Cant it be be done in one operation?
Windows 10 / Linux Mint 20
Laz 2.10.0
FPC 3.2.0

eljo

  • Sr. Member
  • ****
  • Posts: 408
Re: Grayscale
« Reply #3 on: June 09, 2020, 09:55:46 am »
Cant it be be done in one operation?
no. an image is a collection of pixels you need to convert each pixel individually.

circular

  • Hero Member
  • *****
  • Posts: 3440
    • Personal webpage
Re: Grayscale
« Reply #4 on: June 09, 2020, 10:14:15 am »
With BGRABitmap you can with the InplaceGrayscale function.

Code: Pascal  [Select][+][-]
  1. image := TBGRABitmap.Create('image.png');
  2. image.InplaceGrayscale(True); //with gamma correction
Conscience is the debugger of the mind

wp

  • Hero Member
  • *****
  • Posts: 7529
Re: Greyscale
« Reply #5 on: June 09, 2020, 10:29:32 am »
In fact I would suggest to avoid the pixels property at all costs.

Yes, the Pixels property is very slow. This is a faster version using LazIntfImage:

Code: Pascal  [Select][+][-]
  1. uses
  2.   LCLType, FPImage, IntfGraphics;
  3.  
  4. procedure ToGrayscale(const ABitmap: TBitmap);
  5. var
  6.   img: TLazIntfImage;
  7.   i, j: Integer;
  8.   clr: TFPColor;
  9.   gray: Word;
  10.   bmpHandle, maskHandle: HBitmap;
  11. begin
  12.   img := ABitmap.CreateIntfImage;
  13.   for j := 0 to img.Height - 1 do
  14.     for i := 0 to img.Width - 1 do
  15.     begin
  16.       clr := img.Colors[i, j];
  17.       gray := (clr.Red + clr.Green + clr.Blue) div 3;
  18.       clr.Red := gray;
  19.       clr.Green := gray;
  20.       clr.Blue := gray;
  21.       img.Colors[i, j] := clr;
  22.     end;
  23.   img.CreateBitmaps(bmpHandle, maskHandle);
  24.   ABitmap.Handle := bmpHandle;
  25.   ABitmap.MaskHandle := maskHandle;
  26. end;
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

pcurtis

  • Full Member
  • ***
  • Posts: 197
Re: Grayscale
« Reply #6 on: June 09, 2020, 10:43:08 am »
@Circular - Thanks, its simple and works.

@wp, I'll have a look later
Windows 10 / Linux Mint 20
Laz 2.10.0
FPC 3.2.0

PaulRowntree

  • Full Member
  • ***
  • Posts: 132
    • Paul Rowntree
Re: Grayscale
« Reply #7 on: June 09, 2020, 07:43:25 pm »
If you are trying to maintain visual comparisons, the three colour components are usually not equally weighted.

https://en.wikipedia.org/wiki/Grayscale
 
Paul Rowntree
- coding for instrument control, data acquisition & analysis, CNC systems

furious programming

  • Sr. Member
  • ****
  • Posts: 467
  • I click a little.
    • TreeStructInfo — format for text and binary configuration files
Re: Grayscale
« Reply #8 on: June 15, 2020, 08:47:27 pm »
Fastest way, no external libraries needed, no temporary image needed, good final quality:

Code: Pascal  [Select][+][-]
  1. procedure GrayBuffer(ABuffer: TBitmap);
  2. type
  3.   TBitmapPixel = record B, G, R: UInt8 end;
  4. type
  5.   PBitmapLine = ^TBitmapLine;
  6.   TBitmapLine = array [UInt16] of TBitmapPixel;
  7. var
  8.   Line: PBitmapLine;
  9.   LineIndex, PixelIndex: Integer;
  10.   GrayShade: UInt8;
  11. begin
  12.   ABuffer.BeginUpdate();
  13.  
  14.   for LineIndex := 0 to ABuffer.Height - 1 do
  15.   begin
  16.     Line := ABuffer.ScanLine[LineIndex];
  17.  
  18.     for PixelIndex := 0 to ABuffer.Width - 1 do
  19.       with Line^[PixelIndex] do
  20.       begin
  21.         GrayShade := Round(0.299 * R + 0.587 * G + 0.114 * B);
  22.      
  23.         B := GrayShade;
  24.         G := GrayShade;
  25.         R := GrayShade;
  26.       end;
  27.   end;
  28.  
  29.   ABuffer.EndUpdate();
  30. end;
Lazarus 2.0.10 with FPC 3.2.0 (SVN Revision 63526), Windows XP (all 32-bit)

 

TinyPortal © 2005-2018