CILinearGradient not linear?

  • Ok, hopefully this is just me and I'm overlooking some Core Image
    setting. :)

    Create a linear gradient in Core Image Fun House:
    /Developer/Examples/Quartz/Core Image/FunHouse

    and compare it to CTGradient which uses Core Graphics (set the test
    app to the default style):
    http://blog.oofn.net/projects/misc

    Compare with a Photoshop gradient if you like.

    The CTGradient looks almost identical to the Photoshop gradient but
    the Core Image gradient differs quite a bit... showing more lighter
    tones and then dropping to black very quickly at the end. The
    midpoint is 32% black instead of 50%.

    Could this possibly be my machine/video card (ati 9600xt)? A monitor
    color profile affecting core image?

    Actually, I just noticed the example pic in the Core Image
    documentation also exhibits the sharp drop to black:
    http://developer.apple.com/documentation/GraphicsImaging/Conceptual/
    CoreImaging/ci_filters/chapter_5_section_10.html

    And, I created a CIContext that used the CPU rather than GPU and got
    identical results:
    http://developer.apple.com/qa/qa2005/qa1416.html

    Hmmmm.

    George
  • George Orthwein wrote:
    > The CTGradient looks almost identical to the Photoshop gradient but
    > the Core Image gradient differs quite a bit... showing more lighter
    > tones and then dropping to black very quickly at the end. The
    > midpoint is 32% black instead of 50%.

    A wild guess without any knowledge about Core Image whatsoever (and
    without having tried out your suggestions):

    It seems that both gradients are actually "linear", they're just
    linear to different quantities.

    The CT and Photoshop gradients are probably linear in the pixel
    values they send to video hardware - 0 for black, 255 for white, and
    128 for the middle gray in the center. Incidentally, this is also
    approximately linear in perceived brightness.

    The CI gradient is probably linear in actual physical light
    intensity. Try comparing this gradient with a checkerboard pattern of
    white and black pixels (if you're on an LCD, on a CRT use alternating
    white and black horizontal lines), you'll see that it approximately
    matches the brightness in the middle of the gradient.

    On a properly calibrated Mac display, the relationship is that
    light_intensity = pixel_value ^ 1.8, with both quantities measured
    from 0 to 1. In your example: 0.5 = 0.68 ^ 1.8, with 0.68 being the
    complement of your "32% black".

    If this sounds all greek to you, read up on "gamma", especially
    <http://www.poynton.com/notes/colour_and_gamma/GammaFAQ.html>, or on
    colorimetry in general. It's a wide and not completely trivial field,
    but understanding it helps a lot if you're seriously interested in
    computer graphics.

      -Christian
  • I wanted to follow up this thread with the solution, even though I
    also posted to quartz-dev.

    CIContext does indeed default to a colorspace with a linear gamma
    (1.0). The remedy is to create a context with a "normal" gamma using
    kCGColorSpaceGenericRGB:

    CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName
    (kCGColorSpaceGenericRGB);
    NSDictionary *contextOptions = [NSDictionary
    dictionaryWithObjectsAndKeys:(id)colorSpace,
    kCIContextWorkingColorSpace, (id)colorSpace,
    kCIContextOutputColorSpace,nil];
    myCIContext = [CIContext contextWithCGContext:[[NSGraphicsContext
    currentContext] graphicsPort] options:contextOptions];

    I've created a test app showing the differences:
    http://home.comcast.net/~george.o/CITooLinearGradient.html

    I plan to file a doc enhancement request as I don't believe it
    behaves as expected. In fact, I bet most people are unknowingly using
    it as is, effectively creating non-linear gradients, even though
    technically they are linear for a specific colorspace.

    (Also, as far as I can tell, this issue only affects the gradient
    filters.)

    Hope this helps someone!

    George