HUE vs 8bit

Upcoming mother of all image editors

HUE vs 8bit

Postby JEL » Sun Feb 08, 2015 8:38 am

So HUE is a circle with 360 distinct values (theoretically)

8-bit color allows a max of 256 values.

Does this mean HUE is twisting (as in; being a dynamically changing value, rather than static) with changes in saturation and/or lightness?


I'm trying to understand the concepts of colorspaces better :)
I imagine that 9-bits is the minimum for the HUE wheel (to cover 360 distinct values), but since Photoreactor is 8-bit I'm guessing it doesn't quite allow that (unless it perhaps uses less bits in one of the other 2 channels; luma and saturation (with saturation probably being the one that would suffer the least from being 7-bit rather then 8, in order to lend an extra bit to the HUE channel))

I came across this in my current work, where I'm trying to make a pass-filter that takes the incoming HUE and sorts (or funnels them) them into a pre-defined list of HUEs. Kind of like the filter that reduces colors, except I'm trying to lock down which HUEs are legal.
It's a continuation of my goal to apply a specific color-palette to an image (like a LUT of sorts)
:)
DAP (AOPs): http://jelstudio.dk/DAP/
PhotoReactor (flows, effects and scripts): http://jelstudio.dk/PhotoReactor/
JEL
 
Posts: 294
Joined: Fri Jan 06, 2012 9:35 pm

Re: HUE vs 8bit

Postby andydansby » Mon Feb 09, 2015 6:08 am

Hi Jel:

It seems that you are mixing up the difference between color depth and color space. 8 bit color does use 256 values and 16 uses 65535 values, however thats not the same as color space which is used for a variety of different functions.

You can still use HSL in 8 bit color as well as the other color spaces (LAB, XYZ, HSV, YUV etc).

Some of the color spaces are used to describe the human eyes and how they perceive colors as we don't see all color equally (XYZ, LAB, Hunter LAB). Some color spaces were meant for use in Television transmission to reduce bandwidth (YUV, YIQ, YCbCr). Others are meant for paint or print (CMYK, Munsel).

Wikipedia has a good article on the color spaces http://en.wikipedia.org/wiki/Color_space.

You can use Photo-Reactor to accurately display all of the color spaces. As for specific code for HSL, there are plenty of places that list conversion formulas. Such as http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/

Andy Dansby
andydansby
 
Posts: 160
Joined: Fri Oct 29, 2010 6:00 am
Location: Syracuse, NY

Re: HUE vs 8bit

Postby JEL » Wed Feb 11, 2015 5:31 am

Hi Andy :)

The color-selector in PR (if you use, for example, the generator-node and choose 'solid color') only allows 256 discrete values for the HUE-input (as well as for SAT and LUMA). It doesn't make its selection in degrees (which would be 360 discrete values)

And if I set up a flow with HSL or HSV, and use channel-split to get to the HUE-channel, followed by a levels-node, I once again only get access to 256 possible values.

I won't say I know how the color-space conversions work in detail, but from my user-point-of-view I'm just wondering how I control the HUE precisely when I can't seem to have more than 256 discrete values.

I am assuming some rounding of the values happen 'under the hood', but all nodes I can use in a flow only allows control-values between 0 and 255.
I assume that if I want more exact precision, then I have to do some more advanced math based on RGB-input? (as in; doing my own conversion from RGB into HSV or HSL space, which I guess is possible in a CPP plugin or via the script-node, but which is also above my skill-level :) )

I read what you say as basically meaning that this is a case of the color-space being 'bit-less' but the 'control-surface' (the adjustments I can do via PR's nodes in a flow) being limited to 8-bit granularity?
DAP (AOPs): http://jelstudio.dk/DAP/
PhotoReactor (flows, effects and scripts): http://jelstudio.dk/PhotoReactor/
JEL
 
Posts: 294
Joined: Fri Jan 06, 2012 9:35 pm

Re: HUE vs 8bit

Postby Oscar » Sun Mar 08, 2015 7:13 pm

Yes, that is exactly right, if you split channels to HSL you will get 8 bit representation of hue and if you put it back to RGB in theory you may feel you are getting hue clamping. But that is not necessary true. The space conversion is calculated from all three components together. The error is not discrete but gradual and itself it would be undetectable by eye.
Reactor can give you a good answer with this test:

reactor.jpg
reactor.jpg (37.12 KiB) Viewed 5099 times


You can add hard clip at the end and discover that the black output is not fully black. There is a median error (depending on the photo) about 1-2%, but again this is not a discrete error (like banding on gradient) it is gradual error and will be completely invisible. It can be detected only by computation, not by eye.

In fact if you save any image to JPG you are creating much bigger error due to the nature JPG create color loss - you can simulate JPEG 4:2:2 subsampling by following (note the Hard clip at the end set to 0-10 to amplify the error):

reactor2.jpg
reactor2.jpg (173.12 KiB) Viewed 5099 times


Even that is undetectable by eye. (The above would be equivalent to JPG quality at 100% - it gets progressively worse as you start removing quality)
Oscar
Site Admin
 
Posts: 863
Images: 2
Joined: Fri Oct 22, 2010 9:54 am

Re: HUE vs 8bit

Postby JEL » Wed Mar 11, 2015 1:04 am

PhotoReactor has taught me more about digital image work than any previous software I've used :)
I really do think it's the best (and most fun to explore possibilities in) image-editor I've ever used :)
(And the launch-time is quicker than anything! From clicking the icon until it's open and ready; just a few seconds. It's just perfect :) )

Thanks for this example. The base-images I'm using for this particular work starts as 8bit 4:2:0 (DSLR video files in H264 compression), so they're already quite dramatically low-res in their color-resolution and fidelity. This ofcourse makes color differences more noticeable, but trying the difference-test you posted it was only visible when pushed to the extreme of extremes (with the hardclip node) so all is good :)
DAP (AOPs): http://jelstudio.dk/DAP/
PhotoReactor (flows, effects and scripts): http://jelstudio.dk/PhotoReactor/
JEL
 
Posts: 294
Joined: Fri Jan 06, 2012 9:35 pm

Re: HUE vs 8bit

Postby Oscar » Fri Mar 13, 2015 3:03 pm

If interested, here is reactor script for RGB2HLS and HSL2RGB conversion in float space.
In this example I am negating hue in the line fhsl.a = 1.0-fhsl.a; but here you can do your calculation in float space (0..1).

Code: Select all
//A sample Reactor Script - desaturates image
//##NAME:Sample Script
//##DESCRIPTION:Just a sample
//##INPUTS:1

/*
 * Converts an RGB color value to HSL. Conversion formula
 * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
 * Assumes r, g, and b are contained in the set [0, 1] and
 * returns h, s, and l in the set [0, 1].
 */
 
 class float3
 {
    float a;
    float b;
    float c;
 }
 
 float3 rgbToHsl(float3 rgb)
 {
    float r = rgb.a;
    float g = rgb.b;
    float b = rgb.c;


    float fmax = max(max(r, g), b);
    float fmin = min(min(r, g), b);
   
    float h, s, l;

    h = s = l = (fmax + fmin) / 2.0;

    if(fmax == fmin)
    {
        h = s = 0; // achromatic
    }
    else
    {
        float d = fmax - fmin;
        s = l > 0.5 ? d / (2 - fmax - fmin) : d / (fmax + fmin);
        if (fmax ==r)
            h = (g - b) / d + (g < b ? 6 : 0);
        if (fmax ==g)
            h = (b - r) / d + 2;
        if (fmax ==b)
            h = (r - g) / d + 4;
       
        h /= 6.0;
    }

    float3 color;//(h,s,l);
   
    color.a = h;
    color.b = s;
    color.c = l;
    return color;
   
}

float hue2rgb(float p, float q, float t)
{
  if(t < 0) t += 1.0;
  if(t > 1) t -= 1.0;
  if(t < 1.0/6.0) return p + (q - p) * 6.0 * t;
  if(t < 1.0/2.0) return q;
  if(t < 2.0/3.0) return p + (q - p) * (2.0/3.0 - t) * 6.0;
  return p;
}

/*
 * Assumes h, s, and l are contained in the set [0, 1] and
 * returns r, g, and b in the set [0, 1].
 */


float3 hslToRgb(float3 hsl)
{
    float r, g, b;

    float h,s,l;
    h = hsl.a;
    s = hsl.b;
    l = hsl.c;
   
    if(s == 0)
    {
        r = g = b = l; // achromatic
    }
    else
    {
       
        float q = l < 0.5 ? l * (1 + s) : l + s - l * s;
        float p = 2 * l - q;
        r = hue2rgb(p, q, h + 1/3.0);
        g = hue2rgb(p, q, h);
        b = hue2rgb(p, q, h - 1/3.0);
    }

    float3 rgb;
    rgb.a = r;
    rgb.b = g;
    rgb.c = b;
   
    return rgb;
}

 
void process(image &img)
{
     int width = img.width;
   int height = img.height;
   
   float3 fcolor;
   float3 fhsl;
   pixel newcolor;
   
   
   for (int y=0; y<height; y++)
   {
      for (int x=0; x<width; x++)
      {
   
         // one way to get color from pixel
         pixel color = img.Pixel(x,y);
         
         fcolor.a = color.r/255.0;
         fcolor.b = color.g/255.0;
         fcolor.c = color.b/255.0;
         
         // convert to HSL
         fhsl = rgbToHsl(fcolor);
         
         // do whatever you want
         fhsl.a = 1.0-fhsl.a;      


         // convert to RGB
         fcolor = hslToRgb(fhsl);
         
         newcolor.r = fcolor.a*255;
         newcolor.g = fcolor.b*255;
         newcolor.b = fcolor.c*255;
         
         
         
         img.SetRGB(x, y,newcolor.r,newcolor.g,newcolor.b);
         
         
      }
   
   }

}



void main()
{
   // get the image from input socket
   image img(INPUT);
   
   
   // sample function call
   process(img);
   
   
   // send the image to output
   img.SetOutput();
   
}
Oscar
Site Admin
 
Posts: 863
Images: 2
Joined: Fri Oct 22, 2010 9:54 am

Re: HUE vs 8bit

Postby JEL » Tue Mar 17, 2015 10:49 am

Thank you very much! :)

I just did some tests with your script, and was able to create a HUE-spread that clamped on to the 6 main colors. VERY nice to be able to do it in a script like this! The previous work I did to do this HUE-control was a massive (and very involved) flow (and I wasn't able to get the precision I can get in your script)

Brilliant new method you've created here Oscar!! :)

I need some more time with the math, to refine it, but I can already see how much more capable this method is than my previous flow-work. Now I can program some spread to the HUE-clamping (to avoid the hard shifts in HUE that I've battled), so that should certainly make it possible to get a much cleaner looking image :)

Thanks again! :)

EDIT: The change I've done to your script in this example is this:
Code: Select all
fhsl.a = (fhsl.a * 6 );
fhsl.a = int(fhsl.a) * 0.2;
Attachments
HUE.jpg
HUE.jpg (128.55 KiB) Viewed 4982 times
DAP (AOPs): http://jelstudio.dk/DAP/
PhotoReactor (flows, effects and scripts): http://jelstudio.dk/PhotoReactor/
JEL
 
Posts: 294
Joined: Fri Jan 06, 2012 9:35 pm


Return to Photo Reactor

Who is online

Users browsing this forum: No registered users and 2 guests