Page 1 of 1

equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-04T13:04:54-07:00
by m31
hi,

I trying to simulate "pick grey point" from gimp "levels" dialog with convert.
for "black point" and "white point" I use:

$ convert -level-colors 'rgb(0,0,0),rgb($RED,$GREEN,$BLUE)' in.jpg out.jpg
and
$ convert -level-colors 'rgb($RED,$GREEN,$BLUE),rgb(255,255,255)' in.jpg out.jpg

any idea what can I use for "grey point" ?

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-04T13:09:52-07:00
by Bonzo
Looking around RGB value (119,119,119) looks a good value. See this wiki post.

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-04T13:27:59-07:00
by snibgo
I don't know what method Gimp uses. Some experimentation might nail it.

Gimp probably multiplies each of the RGB channels by a certain factor. The factors are chosen so that the user-selected pixel rgb(a,b,c) becomes rgb(d,d,d). Simple arithmetic says the three factors will be (a/d, b/d, c/d). The value chosen for d will be a grayscale value of rgb(a,b,c). However, this can result in clipping, so d may be adjusted to be max(a,b,c) so that clipping cannot occur. It may be intelligent and adjust d sufficiently to ensure that clipping doesn't actually occur.

EDIT: In ImageMagick, HDRI can be used, so pixel values can exceed 100% after the multiplication then brought back into range with "-auto-level". This would greatly simplify the calculation of d. I think Gimp always works with 8-bit integers, so that trick won't be used by Gimp.

See also my Colour Temperature page.

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-04T13:40:51-07:00
by fmw42
gray point is the IM gamma value in -level. See ://www.imagemagick.org/script/command-line ... .php#level. Process each channel separately if that is what you want to modify colors and not just intensity. In GIMP levels you would select each channel and modify in a similar manner.

convert image \
-channel r -level bp,wp,gamma +channel \
-channel g -level bp,wp,gamma +channel \
-channel b -level bp,wp,gamma +channel \
result

Alternately, you can create a PNG Hald image in IM. Then take it to GIMP and process it the same as you processed your image there. Save as PNG. Then bring the modified Hald image back to IM and use -hald-clut to process your original image in IM to duplicate what you did in GIMP. see http://www.imagemagick.org/Usage/color_mods/#hald-clut

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-04T14:10:09-07:00
by m31
thank you all of you for replies!

@fmw42: nice tip the one with hald image. but I'm not sure I understand first part. so I have an image and a picked rgb value.
how this rgb values fits in the convert example. AFAIK gamma value is between 0.1 ant 10. do I miss something ?

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-04T19:00:07-07:00
by fmw42
m31 wrote:thank you all of you for replies!

@fmw42: nice tip the one with hald image. but I'm not sure I understand first part. so I have an image and a picked rgb value.
how this rgb values fits in the convert example. AFAIK gamma value is between 0.1 ant 10. do I miss something ?

1) You create the hald image such as

Code: Select all

convert hald:8 hald.png
2)Then you move the hald.png image over to GIMP and apply any color processing you want to it, but no geometry and no blurring or sharpening, only color or brightness contrast changes. Then save to a new PNG image such as hald_processed.png

3) Now bring that image back to IM and apply it to your original image as follows:

Code: Select all

convert yourimage hald_processed.png -hald-clut result.png

Gamma and graypoint are generally between 0.1 and 10 in both IM -level and GIMP level

There is no graypoint or gamma associated with -level-color only -level, which is the counterpart to GIMP level

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-05T09:22:48-07:00
by m31
i'm getting close.

so for value (r,g,b) picked by user I'll calculate the gamma for each channel:

Code: Select all


static double sRGB_to_linear(double x) {
    if (x < 0.04045) return x/12.92;
    return Math.pow((x+0.055)/1.055, 2.4);
 }

double R_linear = sRGB_to_linear(r/255.0);
double G_linear = sRGB_to_linear(g/255.0);
double B_linear = sRGB_to_linear(b/255.0);
double gray_linear = 0.2126 * R_linear + 0.7152 * G_linear + 0.0722 * B_linear;

Code: Select all

double gammaRed=Math.log(R_linear)/Math.log(gray_linear);
double gammaGreen=Math.log(G_linear)/Math.log(gray_linear);
double gammaBlue=Math.log(B_linear)/Math.log(gray_linear);

Code: Select all

$ convert in.jpg -gamma gammaRed,gammaGreen,gammaBlue out.jpg

http://stackoverflow.com/questions/1568 ... scale-in-c
https://en.wikipedia.org/wiki/Grayscale ... _grayscale

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-05T09:57:53-07:00
by fmw42
I do not understand what you want to achieve. You originally seemed to want to know about the IM equivalent to GIMP level. But you can do that with IM -level. In both, the user specifies the blackpt, whitepoint and graypoint (gamma). Each is up to the user to choose independently. If you want an autolevel. Then use IM -auto-level and -auto-gamma for each channel using the -channel operator to work on each of r,g,b separately.

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-05T10:31:00-07:00
by m31
ok maybe I wasn't clear enough.

in gimp the user clicks on "pick grey point" from "levels" dialog and picks a color.
gimp magically transforms that color in some gamma values for each channel and applies them, resulting a new image.

now what I want is to simulate this behavior with imagemagick. so let's say there is an interface where the user picks a color (as grey point) from the input image. this color is (r,g,b). using this color (r,g,b) and the input image and the "convert" command I want to produce the same result as gimp.

- with "auto-gamma" and "-auto-level" I can not use (r,g,b) color picked by the user.
-it seems that I can achieve what I want with "-level" like you suggested or, since I don't touch black_point and white_point", I can use "-gamma"

now the problem is reduced to:

how do I transform a color selected by the user (r,g,b) in some gamma values that will be applied with "-gamma" or "-level" ?

the solution i posted in the previous post seems to produce something like gimp, but I think there are better ways to do it.

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-05T10:44:27-07:00
by snibgo
m31 wrote:gimp magically transforms that color in some gamma values for each channel and applies them, resulting a new image
Gimp changes the image such that the chosen pixel become grayscale but at the same lightness (or brightness or something) as before. Hence m31's code to find the lightness.

I haven't investigated but I doubt that Gimp uses gamma for this. It is more likely it merely multiples each channel. But I could be wrong.

Re: equivalent of "pick grey point" from gimp "levels" dialog

Posted: 2015-08-05T10:53:25-07:00
by m31
from app/operations/gimplevelsconfig.c

Code: Select all

gimp_levels_config_adjust_by_colors (GimpLevelsConfig     *config,
                                     GimpHistogramChannel  channel,
                                     const GimpRGB        *black,
                                     const GimpRGB        *gray,
                                     const GimpRGB        *white)
{
[...]
  if (gray)
    {
      gdouble input;
      gdouble range;
      gdouble inten;
      gdouble out_light;
      gdouble lightness;

      /* Calculate lightness value */
      lightness = GIMP_RGB_LUMINANCE (gray->r, gray->g, gray->b);

      input = gimp_levels_config_input_from_color (channel, gray);

      range = config->high_input[channel] - config->low_input[channel];
      if (range <= 0)
        goto out;

      input -= config->low_input[channel];
      if (input < 0)
        goto out;

      /* Normalize input and lightness */
      inten = input / range;
      out_light = lightness / range;
[...]
      if (out_light <= 0.0001 || out_light >= 0.9999)
        goto out;

      /* Map selected color to corresponding lightness */
      config->gamma[channel] = log (inten) / log (out_light);
      config->gamma[channel] = CLAMP (config->gamma[channel], 0.1, 10.0);
      g_object_notify (G_OBJECT (config), "gamma");
    }

 out:
  g_object_thaw_notify (G_OBJECT (config));
}