ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Using TImageEnProc.GammaCorrect with a scrollbar
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

Patrick Quinn

United Kingdom
81 Posts

Posted - Nov 27 2016 :  12:18:42  Show Profile  Reply
I'm trying to use the TImageEnProc.GammaCorrect with a TScrollbar.

I've tried to build a constant array(1..200) of single numbers to make a look up table to convert the position of the scrollbar to a value to use for ImageEnProc.GammaCorrect.

For the scrollbar fully left, Scrollbar.Position := 1 the value would be about 7.0 - 8.0, central (Position 100) exactly 1.00 and fully right (Position 200) approximately 0.01.
(Photoshop's range is 9.99 to 0.01)

My problem is my maths isn't very good. I've been trying to use the function Power(i, 2.2) in some test code to make the array, but haven't managed successfully yet.

Does anyone know which algorithm I should be using? (I'm not asking for you to write the code, just steer me in the right direction).

There's not much information on the internet, most search results are about monitor gamma.

Any help would be much appreciated

Thanks

Patrick

nwscomps

185 Posts

Posted - Nov 29 2016 :  12:51:06  Show Profile  Reply
Hello Patrick,

the code below should give you the values (I have tested it quickly), but they are calculated only in a linear way. Possibly you can change the algorithm to fit your need use non-linear functions.


function GetGammaValue(scrPos, scrMin, scrCenter, scrMax: integer):double;
begin
  if scrPos = scrCenter then
    result := 1.00
  else if scrPos < scrCenter then
    result := 1.00 + (8.00 - 1.00) * (1 - (scrPos - scrMin) / (scrCenter - scrMin))  //gives 8 for position = min
  else
    result := 0.01 + (1.00 - 0.01) * (1 - (scrPos - scrCenter) / (scrMax - scrCenter));  //gives 0.01 for position = max
end;


I use 8 as value for minimum position, and 0.01 for max position, as you have requested.

Example of use:


  ShowMessage(FloatToStr(GetGammaValue(1, 1, 100, 200)));
  ShowMessage(FloatToStr(GetGammaValue(100, 1, 100, 200)));
  ShowMessage(FloatToStr(GetGammaValue(200, 1, 100, 200)));

  ShowMessage(FloatToStr(GetGammaValue(25, 1, 100, 200)));
  ShowMessage(FloatToStr(GetGammaValue(50, 1, 100, 200)));
  ShowMessage(FloatToStr(GetGammaValue(125, 1, 100, 200)));
  ShowMessage(FloatToStr(GetGammaValue(150, 1, 100, 200)));
  ShowMessage(FloatToStr(GetGammaValue(175, 1, 100, 200)));


Francesco Savastano
Nwscomps.com
Add-ons for the ImageEn Library
Go to Top of Page

Patrick Quinn

United Kingdom
81 Posts

Posted - Nov 29 2016 :  16:14:32  Show Profile  Reply
Hi Francesco. Thanks for looking at this. This does need to be non-linear. I've been experimenting and Photoshop (Image/Adjustments/Exposure/Gamma) seems to be using a power law with an exponent of around 3.

I made a test program and coded a for next loop to get the values, then another for next loop to make the middle value = 1.

I've got the test app drawing a graph as a check that I'm doing it right.



The code is pretty scrappy...
procedure TForm1.btnGetValuesClick(Sender: TObject);
const
  offset: Single = 0.0005;
var
  i, j: integer;
  Correction: Single;
begin
  Memo1.Clear;
  {The ScrollBar1.Position changes the exponent
  An exponent of 3 seems to give the best results }
  // Get values
  for i := Low(GammaLUT) to High(GammaLUT) do
    GammaLut[i] := Power(9 + High(GammaLUT) - i, ScrollBar1.Position / 10);

  // Go through again, apply correction so middle value in array = 1
  Correction :=  1 / GammaLUT[High(GammaLUT) div 2];
  for i := Low(GammaLUT) to High(GammaLUT) do
    begin
      GammaLUT[i] := Correction * GammaLUT[i];
      GammaLUT[i] := GammaLUT[i] + offset;
    end;
    Correction :=  1 / GammaLUT[High(GammaLUT) div 2];
    for i := Low(GammaLUT) to High(GammaLUT) do
    begin
      GammaLUT[i] := Correction * GammaLUT[i];
      Memo1.Lines.Add(IntToStr(i) + ' = ' + FloatToStr(GammaLut[i]));
    end;
  // Draw the graph
  PaintBox1.Invalidate;
end;
This gives values of 6.95 to 0.001 so I'm nearly there. I'll tweak it a bit more to try and get about 7.5 to 0.01. Then I'll add code to write the Delphi array constant declaration.

Most importantly the middle value is always 1.

Thanks

Patrick



Go to Top of Page

nwscomps

185 Posts

Posted - Dec 03 2016 :  07:15:57  Show Profile  Reply
Hi Patrick,
mathematically this kind of interpolation (3 arbitrary points - keeping the slope constantly decreasing) can be only achieved using B-spline (https://en.wikipedia.org/wiki/B-spline) with a (pseudo-continuous curve)
In TRGBCurves component, I use the math for that to build the curve and their LUTs.
The simple solution I posted earlier uses two separate line segments to interpolate the points, which means you will have a "discontinuity" in the slope at the middle point.
The exponential function posted from you can never exactly fit all 3 points you have given, although if you are content to fit exactly only 1 of them, it can be satisfactory enough for you.


Francesco Savastano
Nwscomps.com
Add-ons for the ImageEn Library
Go to Top of Page

Patrick Quinn

United Kingdom
81 Posts

Posted - Dec 08 2016 :  16:00:48  Show Profile  Reply
Thanks, Fransesco. I've got it working by playing around with my algorithm, and got it to generate the code for the constant array. It goes from 0.01 to 9.72, which is close to Photoshop

In Photoshop you move the slider to the right and the image gets darker, which feels wrong to me, so I reversed the curve. Now, moving it to the left makes it darker and right makes it lighter.

The Proc.GammaCorrect works very well. I've compiled a simple demo with .exe and source code (includes the look up table array values).

[Edit] I tried to put the demo in 'User Demos and Applications' but for some reason it didn't go up. I'll try again tomorrow
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: