# Bizarre color issue in Obj-C



## Iritscen (Oct 5, 2006)

Hi guys.  I have a really weird history in programming, where I am fairly skilled in some ways but blasted ignorant in others.  I am still getting the hang of drawing in OS X.  I've made some great progress in things like loading and displaying images with color masks, and yet some of the simpler things stymie me.

All I'm trying to do at the moment is get reliable color in OS X.  Apparently I'm missing something.  I'm using the function CGContextSetStrokeColor (and related functions like -SetFillColor()), and passing it the current CGContext and a float array with four elements.  Then I use something like a FillRect() command to draw onscreen.

According to the documentation I'm reading, colors in OS X are handled initially as floats from 0.0 to 1.0, with a value for R, G, B, and alpha, so black would be {1, 1, 1, 1}.  Right?

I am getting very inconsistent results.  Most sets of values that I'm using yield nothing.  Invisible lines.  Despite the fact that the alpha value is always 1.0.  When {1, 1, 1, 1} failed to yield black, I found through trial and error that {.25, .25, .25, 1} yields a somewhat acceptable gray.

{0, 0, 1, 1} should yield blue but it's also invisible or gray.  {.25, .25, 1, 1} yields a mid-bright blue, however, exactly as you'd expect.  What is going on?  Am I in the wrong drawing mode or something?  I'm not setting any drawing mode in particular, so presumably Quartz is using the default mode, which should be fine.  Incidentally, I always use 1.0 for 1 and 0.0 for 0 in the actual code, I just didn't type out the decimal places in this post because I'm lazy 

If no one understands the problem, I will bring in the actual code snippet to post tomorrow.


----------



## HateEternal (Oct 5, 2006)

0,0,0,1 should be black. All ones is white. Remember, black is the absense of light and white light is the combination of all colors. It's opposite of the way print works -- the more colors you put in the darker it is.


----------



## Mikuro (Oct 5, 2006)

I had this same problem myself. The problem is that the default color space is not RGB! (Blasphemy!) You need to either specify the color space yourself, or use the CGContextSet*RGB*FillColor function instead, which will work no matter what color space is currently set.

Here's how to set an RGB color space:

```
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
CGContextSetFillColorSpace(myContext,colorSpace);
CGColorSpaceRelease(colorSpace);
```
I hope I just saved you from pulling out as much hair as I did.


----------



## Iritscen (Oct 6, 2006)

OK, I was a little mixed-up when I posted yesterday -- as HateEternal pointed out, {0, 0, 0, 1} is black.  When that didn't work for me, I ended up trying {1, 1, 1, 1} and everything in-between until I got my wires crossed as to whether color in the Mac was additive or subtractive.  I'm back with it now, although it doesn't solve my problem.

I appreciate the response, Mikuro, but guess what?  I'm already using that function.  I said yesterday that I wasn't changing drawing modes, but I was setting the color space.  Here, let me post the abridged version of my code:


```
#import "MyView.h"

#define	WIN_WDTH	750
#define	WIN_HGHT	550

@implementation MyView

- (id)initWithFrame:(NSRect)frameRect
{
	if ((self = [super initWithFrame:frameRect]) != nil)
	{
		black[0] = 0.25, black[1] = 0.25, black[2] = 0.25, black[3] = 1.0;
		blue[0] = 0.5, blue[1] = 0.5, blue[2] = 1.0, blue[3] = 1.0;
	}
	
	return self;
}

- (BOOL)acceptsFirstResponder
{
    return YES;
}

- (void)drawRect:(NSRect)rect
{
	contextcg = [[NSGraphicsContext currentContext] graphicsPort];
	CGContextSetFillColorSpace(contextcg, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
	CGRect gaugeframe = CGRectMake(WIN_WDTH / 2 - 200, WIN_HGHT - 100, WIN_WDTH / 2, 100);
	CGContextSetStrokeColor(contextcg, black);
	CGContextStrokeRect(contextcg, gaugeframe);
}

- (void)dealloc
{
	[super dealloc];
}

@end
```

I was using CGColorSpaceCreateDeviceRGB() to set the space up until recently, when I read in the documentation something about it being replaced in OS 10.4, or not recommended, and decided to use the CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) bit.  But they both work the same.

Anyone who creates a new Cocoa project, sub-classes NSView for their own custom class, say, MyView, and who puts this code in the MyView.m file should get the same buggy results with color codes that I do.

The variables black[] and blue[] are declared in MyView.h as 
	
	



```
float black[4], blue[4];
```
  The values I provide for the two variables in the init method should yield a gray frame, or, if you switch "blue" in for "black" in the drawing function, should yield a light-ish blue frame.  But if you then make blue[] equal to {0, 0, 1, 1}, you won't get blue at all.  If they don't work that way for you, that will only add to my confusion.


----------



## Iritscen (Oct 11, 2006)

Wow, I stumped the board.  83 views, no answers.  I hate to bump my own thread, and I won't do it again, but I can't help but express my surprise at the lack of responses.

Does that mean that the code I listed works fine for other people, or what?  Or does it mean that no one even understands what this topic is asking?  As I said, simply make a new Cocoa project, sub-class NSView to create MyView.m and .h, and paste the above code into MyView.m.  Then try setting blue to {0, 0, 1, 1} and seeing if you actually get blue (and obviously change the SetStrokeColor function to use blue, not black).

I would think the solution to this must be simple for an experienced Cocoa programmer.


----------



## KenDRhyD (Oct 11, 2006)

Iritscen said:


> Wow, I stumped the board.  83 views, no answers.  I hate to bump my own thread, and I won't do it again, but I can't help but express my surprise at the lack of responses.
> 
> Does that mean that the code I listed works fine for other people, or what?  Or does it mean that no one even understands what this topic is asking?  As I said, simply make a new Cocoa project, sub-class NSView to create MyView.m and .h, and paste the above code into MyView.m.  Then try setting blue to {0, 0, 1, 1} and seeing if you actually get blue (and obviously change the SetStrokeColor function to use blue, not black).
> 
> I would think the solution to this must be simple for an experienced Cocoa programmer.



I have not used the Core Graphics calls directly, as they have not been needed in my code. Instead, I have used the colorWithDeviceRed:green:blue:alpha: call to return an NSColor object, and then a call like [NSBezierPath fillRect:[self bounds]]; to set the background color in a view. The following lines of code paced in the -drawRect() method of a derived view class result in the background color of the view being set to full blue.

```
NSRect	bounds = [self bounds];
	
	[[NSColor colorWithDeviceRed:0.0
						   green:0.0
							blue:1.0
						   alpha:1.0] set];
	[NSBezierPath fillRect:bounds];
```


----------



## Iritscen (Oct 11, 2006)

That's a perfectly good alternative to my code.  I'll try that.  Thanks.


----------

