Skip navigation.
 
mlRe: Problem with setting color in NSBitmapImageRep
FROM : Christian Kaiser
DATE : Thu Apr 03 21:14:15 2008

Thank to all those who tried to help me with my problem.

My gradient color problem is just a simplified version of what I have to
do. I need to do a scientific simulation where I have to set the color
of random pixels to a given color which corresponds to a value inside a
given range. So I really need to compute the gradient color and set each
pixel separately.

Thanks to Eddie Herbert, I was not aware of the existence of the blend
function in the NSColor class.

Finally, I could locate the problem to reside in the NSBitmapImageRep
setColor:atX:y: method. If I understand this method correctly, it is
supposed to do something like this (if the color space of the image rep
and the provided color are the same):

-(void)setColor:(NSColor*)color atX:(NSInteger)x y:(NSInteger)y
{
    CGFloat comps[5];
    [color getComponents:comps];
 
    NSInteger i;
    NSUInteger intComps[5];
    for (i = 0; i < [self samplesPerPixel]; i++)
    {
        intComps[i] = comps[i] * 255;
    }
 
    [self setPixel:intComps atX:x y:y];

}


Using this method instead of the one provided by the original
NSBitmapImageRep, the image gets rendered as expected.

I am not understanding correctly the setColor:atX:y: class or it is a
bug... I would be glad to have an advise whether to file a bug report or
not (I have never done this).

Thanks again for your help !


Cheers,
Christian Kaiser








Jean-Daniel Dupas wrote:
> Don't know why you got this problem, but if I had to fill a bitmap
> using a simple gradient, i would probably use either CGGradient
> (Leopard required) or CGShading (if you want a greater control of the
> shading function, etc...).
>
> It can be done like this:
>
> NSGraphicsContext *ctxt = [NSGraphicsContext
>  graphicsContextWithBitmapImageRep:imageRep]; /* see doc for details
> about bitmap format supported */
> CGContextRef cgctxt = [ctxt graphicPort];
> CGShadingRef shading = CGShadingCreate(...); /* see Quartz 2D
> programming guide */
> CGContextDrawShading(cgctxt, shading);
> CGShadingRelease(shading);
>
> This will be really faster than creating a NSColor object for each pixel.
>
> In the same way, you can fill it with an uniform color using
> CGContextFillRect() function.
>
> And is you want to use Cocoa drawing function instead, set your new
> context as the current context using -[NSGraphicsContext
> setCurrentContext:] and the you will be able to call NSBezierPath
> function for example.
>
>
> Le 31 mars 08 à 21:30, Christian Kaiser a écrit :

>> I'm struggling with setting color in a NSBitmapImageRep. I'm
>> computing the components of a NSColor according to a numeric value;
>> its basically a linear interpolation between all components of two
>> NSColors. I've got a function which is computing the new NSColor
>> based on a given value. If I call this function repeatedly using the
>> same value and setting the color using NSBitmapImageRep
>> setColor:atX:y:, I expect to have a uniform image if applying to all
>> pixels. But this is not the case...! What am I missing ?
>>
>> As I'm probably a little bit confusing, here the code producing my
>> strange image :
>>
>>
>>
>>  // Creating two colors which define a gradient. The color for our image
>>  // will be computed using this gradient.
>>
>>  NSColor *lightYellow =
>>      [NSColor colorWithCalibratedRed:0.97 green:0.93 blue:0.65
>> alpha:1.0];
>>    NSColor *darkRed =
>>      [NSColor colorWithCalibratedRed:0.69 green:0.09 blue:0.11
>> alpha:1.0];
>>
>>
>>  // Creating an empty image with the same color space.
>>
>>  NSBitmapImageRep *img = [[NSBitmapImageRep alloc]
>>      initWithBitmapDataPlanes:NULL
>>      pixelsWide:10
>>      pixelsHigh:10
>>      bitsPerSample:8
>>      samplesPerPixel:3
>>      hasAlpha:NO
>>      isPlanar:YES
>>      colorSpaceName:[lightYellow colorSpaceName]
>>      bitmapFormat:0
>>      bytesPerRow:0
>>      bitsPerPixel:0];
>> 
>>  // Assigning the same (???) color to all pixels.
>>  int x, y;
>>  for (y = 0; y < 10; y++)
>>  {
>>      for (x = 0; x < 10; x++)
>>      {
>>          NSColor *imgColor = [GradientColor gradientColorWithValue:40.0
>>              minColor:lightYellow maxColor:darkRed
>>              minValue:30.0 maxValue:60.0];
>>                    [img setColor:imgColor atX:x y:y];
>>      }
>>  }
>>      [[img TIFFRepresentation]
>>      writeToFile:@"/Users/chkaiser/Desktop/img.tif" atomically:YES];
>>
>>
>> And the function computing the gradient color based on our values:
>>
>> +(NSColor*)gradientColorWithValue:(double)value minColor:(NSColor*)c1
>>  maxColor:(NSColor*)c2 minValue:(double)v1 maxValue:(double)v2
>> {
>>    // Color components.
>>  CGFloat comps1[5];
>>  [c1 getComponents:comps1];
>>  CGFloat comps2[5];
>>  [c2 getComponents:comps2];
>>    // Compute the multiplication factor for the value. This factor has
>>  // a value between 0 and 1.
>>  double factor = (value - v1) / (v2 - v1);
>>    // Compute the new components.
>>  int i;
>>  CGFloat newComps[5];
>>  for (i = 0; i < [c1 numberOfComponents]; i++)
>>  {
>>      newComps[i] =
>>          (factor * (comps2[i] - comps1[i])) +
>>              comps1[i];
>>  }
>>    // Create the new color with the computed components.
>>  NSColor *newColor = [NSColor colorWithColorSpace:[c1 colorSpace]
>>      components:newComps count:[c1 numberOfComponents]];
>>    return newColor;
>>  }
>>
>>
>> What is going wrong here ?
>>
>> I have not found any similar topic on this list until now, even if it
>> seems to me quite strange. Is there something obvious I am missing ?
>>
>> --Christian Kaiser
>>

Related mailsAuthorDate
mlProblem with setting color in NSBitmapImageRep Christian Kaiser Mar 31, 21:30
mlRe: Problem with setting color in NSBitmapImageRep Jean-Daniel Dupas Mar 31, 23:39
mlRe: Problem with setting color in NSBitmapImageRep Christian Kaiser Apr 3, 21:14