(SOLVED) Change gamma image lazarus / 39-Graphics ---------------------------------------------------------------------- xinyiman · 2019-10-18 11:51 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. ---------------------------------------------------------------------- xinyiman · 2019-10-20 20:06 No suggestioni?! ---------------------------------------------------------------------- winni · 2019-10-20 20:42 Encoding Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i encoded = ((original / 255) ^ (1 / gamma)) * 255 Decode back Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i original = ((encoded / 255) ^ gamma) * 255 Do that for every channel of RGB. Test it with default gamma = 2.2 Winni ---------------------------------------------------------------------- xinyiman · 2019-10-21 06:07 Quote from: winni on October 20, 2019, 10:42:31 pmEncoding Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i encoded = ((original / 255) ^ (1 / gamma)) * 255 Decode back Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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? ---------------------------------------------------------------------- Thaddy · 2019-10-21 06:59 Basically, uncompress the image, use the above formulae and re-save the image. ---------------------------------------------------------------------- xinyiman · 2019-10-21 07:07 If I understood the concept, I would need a very small example to understand how to do it technically. ---------------------------------------------------------------------- Handoko · 2019-10-21 07:41 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.h tml#msg176665 ---------------------------------------------------------------------- xinyiman · 2019-10-21 08:35 Hi write this example 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 TForm1.EncodeImage;var  p: PBGRAPixel;  ABitmap: TBGRABitmap;  gamma : single;  i     : integer;begin  ABitmap := TBGRABitmap.Create();  ABitmap.LoadFromFile(Self.GetApplicationLocation() + 'abc.jpg');    p := ABitmap.Data;   gamma := 2.2;  for i := ABitmap.NBPixels-1 downto 0 do  begin    p^.red := ((p^.red / 255) ^ (1 / gamma)) * 255;    p^.green := ((p^.green / 255) ^ (1 / gamma)) * 255;    p^.blue := ((p^.blue / 255) ^ (1 / gamma)) * 255;    p^.alpha := ((p^.alpha / 255) ^ (1 / gamma)) * 255;    Inc(p);  end;   ABitmap.SaveToFile(Self.GetApplicationLocation() + 'abc.jpg');  ABitmap.Free;   Self.Image1.picture.LoadFromFile(Self.GetApplicationLocation() + 'abc.jpg'); end;       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? ---------------------------------------------------------------------- xinyiman · 2019-10-21 09:17 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]),co ordToBmp(pts[2])],BGRABlack); and uncomment the line        //bmp.LoadFromFile(GetApplicationLocation() + 'abc.png'); ---------------------------------------------------------------------- circular · 2019-10-21 13:45 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses math; // <- you need to include this unit with uses clause...begin   ...   p^.red := round( power(p^.red / 255, 1 / gamma) * 255);   ...end; ---------------------------------------------------------------------- circular · 2019-10-21 13:51 Quote from: xinyiman on October 21, 2019, 11:17:53 amSo, 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i bmp.PutImage(0,0,myImage,dmDrawWithTransparency); ---------------------------------------------------------------------- xinyiman · 2019-10-21 14:07 Thanks, now run. Look attachment. ---------------------------------------------------------------------- circular · 2019-10-21 14:15 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. ---------------------------------------------------------------------- xinyiman · 2019-10-21 14:24 Quote from: circular on October 21, 2019, 04:15:45 pmWonderful  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 ---------------------------------------------------------------------- wp · 2019-10-21 17:13 Quote from: circular on October 21, 2019, 03:45:34 pmThe 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses  fpimage, fpreadjpeg, fpwritejpeg, math; procedure GammaCorrection(const ASrcFile, ADestFile: String; AGamma: Double);var  img: TFPMemoryImage;  reader: TFPCustomImageReader;  writer: TFPCustomImageWriter;  i, j: Integer;  clr: TFPColor;  invGamma: Double;begin  img := TFPMemoryImage.Create(10, 10);  try    reader := TFPReaderJpeg.Create;    try      img.LoadFromFile(ASrcFile, reader);    finally      reader.Free;    end;     invGamma := 1.0 / AGamma;    for j := 0 to img.Height - 1 do      for i := 0 to img.Width - 1 do      begin        clr := img.Colors[i, j];        clr.Red := round(((clr.Red / 65535)**invGamma)*65535);        clr.Green := round(((clr.Green / 65535)**invGamma)*65535);        clr.Blue := round(((clr.Blue / 65535)**invGamma)*65535);        img.Colors[i, j] := clr;      end;     writer := TFPWriterJpeg.Create;    try      img.SaveToFile(ADestFile, writer);  finally      writer.Free;    end;  finally    img.Free;  end;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). ---------------------------------------------------------------------- circular · 2019-10-21 20:19 That's an elegant solution.  Quote from: wp on October 21, 2019, 07:13:12 pmQuote from: circular on October 21, 2019, 03:45:34 pmThe power operator ^ is not defined in Pascal. True for ^, but there is a ** which can be used instead (requires unit "math")Oh that's true 2**8 = 256  2**16 = 65536