Recent

Author Topic: (SOLVED) Change gamma image  (Read 1353 times)

xinyiman

  • Hero Member
  • *****
  • Posts: 1990
    • Lazarus and Free Pascal italian community
(SOLVED) Change gamma image
« on: October 18, 2019, 01:51:28 pm »
Hi guys, I was wondering if there is a library for manipulating the gamma value of an image. It must be disconnected from LCL because I then have to use it in a program for android. Some examples of how to use it would be very welcome. Because I am not very grasped in the manipulation of images.
« Last Edit: October 21, 2019, 04:07:50 pm by xinyiman »
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

xinyiman

  • Hero Member
  • *****
  • Posts: 1990
    • Lazarus and Free Pascal italian community
Re: Change gamma image
« Reply #1 on: October 20, 2019, 10:06:06 pm »
No suggestioni?!
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

winni

  • Hero Member
  • *****
  • Posts: 546
Re: Change gamma image
« Reply #2 on: October 20, 2019, 10:42:31 pm »
Encoding

Code: Text  [Select]
  1. encoded = ((original / 255) ^ (1 / gamma)) * 255

Decode back

Code: Text  [Select]
  1. original = ((encoded / 255) ^ gamma) * 255

Do that for every channel of RGB.

Test it with default gamma = 2.2

Winni

xinyiman

  • Hero Member
  • *****
  • Posts: 1990
    • Lazarus and Free Pascal italian community
Re: Change gamma image
« Reply #3 on: October 21, 2019, 08:07:55 am »
Encoding

Code: Text  [Select]
  1. encoded = ((original / 255) ^ (1 / gamma)) * 255

Decode back

Code: Text  [Select]
  1. original = ((encoded / 255) ^ gamma) * 255

Do that for every channel of RGB.

Test it with default gamma = 2.2

Winni

Thank you so much winni. But as I have already said I am not very practical with image manipulation. That's why I still ask you a very trivial question. How do I read and set the gamma value of a jpg image?

Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

Thaddy

  • Hero Member
  • *****
  • Posts: 9273
Re: Change gamma image
« Reply #4 on: October 21, 2019, 08:59:21 am »
Basically, uncompress the image, use the above formulae and re-save the image.
also related to equus asinus.

xinyiman

  • Hero Member
  • *****
  • Posts: 1990
    • Lazarus and Free Pascal italian community
Re: Change gamma image
« Reply #5 on: October 21, 2019, 09:07:08 am »
If I understood the concept, I would need a very small example to understand how to do it technically.
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

Handoko

  • Hero Member
  • *****
  • Posts: 3221
  • My goal: build my own game engine using Lazarus
Re: Change gamma image
« Reply #6 on: October 21, 2019, 09:41:49 am »
Not sure will it give the result you want, but I found an interesting code ChangeLightness posted by Circular:

https://forum.lazarus.freepascal.org/index.php/topic,12390.msg176665.html#msg176665

xinyiman

  • Hero Member
  • *****
  • Posts: 1990
    • Lazarus and Free Pascal italian community
Re: Change gamma image
« Reply #7 on: October 21, 2019, 10:35:23 am »
Hi write this example

Code: Pascal  [Select]
  1.  
  2. procedure TForm1.EncodeImage;
  3. var
  4.   p: PBGRAPixel;
  5.   ABitmap: TBGRABitmap;
  6.   gamma : single;
  7.   i     : integer;
  8. begin
  9.   ABitmap := TBGRABitmap.Create();
  10.   ABitmap.LoadFromFile(Self.GetApplicationLocation() + 'abc.jpg');
  11.  
  12.  
  13.   p := ABitmap.Data;
  14.  
  15.   gamma := 2.2;
  16.   for i := ABitmap.NBPixels-1 downto 0 do
  17.   begin
  18.     p^.red := ((p^.red / 255) ^ (1 / gamma)) * 255;
  19.     p^.green := ((p^.green / 255) ^ (1 / gamma)) * 255;
  20.     p^.blue := ((p^.blue / 255) ^ (1 / gamma)) * 255;
  21.     p^.alpha := ((p^.alpha / 255) ^ (1 / gamma)) * 255;
  22.     Inc(p);
  23.   end;
  24.  
  25.   ABitmap.SaveToFile(Self.GetApplicationLocation() + 'abc.jpg');
  26.   ABitmap.Free;
  27.  
  28.   Self.Image1.picture.LoadFromFile(Self.GetApplicationLocation() + 'abc.jpg');
  29.  
  30. end;        
  31.  
  32.  

But when build return this error

unit1.pas(72,33) Error: Illegal qualifier

line error is: p^.red := ((p^.red / 255) ^ (1 / gamma)) * 255;

Why?
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

xinyiman

  • Hero Member
  • *****
  • Posts: 1990
    • Lazarus and Free Pascal italian community
Re: Change gamma image
« Reply #8 on: October 21, 2019, 11:17:53 am »
So, I found an example in the BGRABitmap library. It's called aa_demo. The original example works, but if you want to replace the triangle that draws the original example with a photo, the program stops working. Who explains to me what the mistake is?

To reproduce the error just comment on the line
       bmp.FillPolyAntialias([coordToBmp(pts[0]),coordToBmp(pts[1]),coordToBmp(pts[2])],BGRABlack);
and uncomment the line
       //bmp.LoadFromFile(GetApplicationLocation() + 'abc.png');
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

circular

  • Hero Member
  • *****
  • Posts: 3045
    • Personal webpage
Re: Change gamma image
« Reply #9 on: October 21, 2019, 03:45:34 pm »
The power operator ^ is not defined in Pascal. Instead you need to use Power function of math unit.

Also you need to round the result, because division and power returns floating point values, but channel values are integers (byte to be specific).

Code: Delphi  [Select]
  1. uses math; // <- you need to include this unit with uses clause
  2. ...
  3. begin
  4.    ...
  5.    p^.red := round( power(p^.red / 255, 1 / gamma) * 255);
  6.    ...
  7. end;
Conscience is the debugger of the mind

circular

  • Hero Member
  • *****
  • Posts: 3045
    • Personal webpage
Re: Change gamma image
« Reply #10 on: October 21, 2019, 03:51:49 pm »
So, I found an example in the BGRABitmap library. It's called aa_demo. The original example works, but if you want to replace the triangle that draws the original example with a photo, the program stops working. Who explains to me what the mistake is?[/code]
Ok so the bitmap is expected to have a certain size, in this case very small. When calling load function, it resizes the bitmap. In this case, the problem is that it is then upscaled a lot and it may become too big.

Also you would not load the image each time the screen is rendered so rather load it when the form is created and free it on destroy. Then draw it by calling
Code: Delphi  [Select]
  1. bmp.PutImage(0,0,myImage,dmDrawWithTransparency);
Conscience is the debugger of the mind

xinyiman

  • Hero Member
  • *****
  • Posts: 1990
    • Lazarus and Free Pascal italian community
Re: Change gamma image
« Reply #11 on: October 21, 2019, 04:07:38 pm »
Thanks, now run. Look attachment.
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

circular

  • Hero Member
  • *****
  • Posts: 3045
    • Personal webpage
Re: (SOLVED) Change gamma image
« Reply #12 on: October 21, 2019, 04:15:45 pm »
Wonderful  :)

Note that this may be a bit slow, especially if the image is big. You can speed up things by precomputing an array[0..255] of byte with the formula used.

Then instead of applying the formula for each component and pixel, simply access the array for that value.
Conscience is the debugger of the mind

xinyiman

  • Hero Member
  • *****
  • Posts: 1990
    • Lazarus and Free Pascal italian community
Re: (SOLVED) Change gamma image
« Reply #13 on: October 21, 2019, 04:24:13 pm »
Wonderful  :)

Note that this may be a bit slow, especially if the image is big. You can speed up things by precomputing an array[0..255] of byte with the formula used.

Then instead of applying the formula for each component and pixel, simply access the array for that value.

Ok, is a great idea. Thanks a lot
Win10, Ubuntu and Mac
Lazarus: 2.1.0
FPC: 3.3.1

wp

  • Hero Member
  • *****
  • Posts: 6444
Re: Change gamma image
« Reply #14 on: October 21, 2019, 07:13:12 pm »
The power operator ^ is not defined in Pascal.
True for ^, but there is a ** which can be used instead (requires unit "math").

@xinyiman:
Here is another version for gamma correction based on winni's post, but which does not require neither LCL nor BGRABitmap, and is satisfied with the built-in FCL-Image machinery (https://wiki.freepascal.org/fcl-image).  It works on files directly. I double-checked with GIMP's gamma correction and found good agreement.

Code: Pascal  [Select]
  1. uses
  2.   fpimage, fpreadjpeg, fpwritejpeg, math;
  3.  
  4. procedure GammaCorrection(const ASrcFile, ADestFile: String; AGamma: Double);
  5. var
  6.   img: TFPMemoryImage;
  7.   reader: TFPCustomImageReader;
  8.   writer: TFPCustomImageWriter;
  9.   i, j: Integer;
  10.   clr: TFPColor;
  11.   invGamma: Double;
  12. begin
  13.   img := TFPMemoryImage.Create(10, 10);
  14.   try
  15.     reader := TFPReaderJpeg.Create;
  16.     try
  17.       img.LoadFromFile(ASrcFile, reader);
  18.     finally
  19.       reader.Free;
  20.     end;
  21.  
  22.     invGamma := 1.0 / AGamma;
  23.     for j := 0 to img.Height - 1 do
  24.       for i := 0 to img.Width - 1 do
  25.       begin
  26.         clr := img.Colors[i, j];
  27.         clr.Red := round(((clr.Red / 65535)**invGamma)*65535);
  28.         clr.Green := round(((clr.Green / 65535)**invGamma)*65535);
  29.         clr.Blue := round(((clr.Blue / 65535)**invGamma)*65535);
  30.         img.Colors[i, j] := clr;
  31.       end;
  32.  
  33.     writer := TFPWriterJpeg.Create;
  34.     try
  35.       img.SaveToFile(ADestFile, writer);
  36.     finally
  37.       writer.Free;
  38.     end;
  39.   finally
  40.     img.Free;
  41.   end;
  42. end;
Note that we must use the factor 65535 here because FPImage has 16-bit color channels.

I added the (slightly modified) code to the wiki article (https://wiki.freepascal.org/fcl-image#Gamma_correction).
« Last Edit: October 21, 2019, 07:49:08 pm by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10