How do I generate a random color hexadecimal in Objective-C ?
I need a color hexdecimal , I don't need a random color. It is complicated ...
I think should work for you. Arc4random() is far better in the way of performance & ... accuracy than rand(). Rand() also needs to be seeded before use.
// 16777215 is FFFFFF
NSInteger *baseInt = arc4random() % 16777216;
NSString *hex = [NSString stringWithFormat:#"%06X", baseInt];
Edit: Edited based on comment regarding formatting.
You can use the standard C library routine rand() in your Objective-C application. From there, then, you'll want to call it three times to get random values for each of the red, green, and blue channels of your random color. You'll want to mod (%) the value by the maximum value the channel can have- typically 256. From there you can construct your NSColor appropriately. So your code might look something like:
int red = rand() % 255;
int green = rand() % 255;
int blue = rand() % 255;
NSColor* myColor = [NSColor colorWithCalibratedRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1.0];
Because NSColor takes floats instead of integers a better approach would be to divide the random values by RAND_MAX right from the start:
float rand_max = RAND_MAX;
float red = rand() / rand_max;
float green = rand() / rand_max;
float blue = rand() / rand_max;
NSColor* myColor = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:1.0];
This latter code will not limit the number of colors to a 24-bit spectrum.
There is an article on cocoadev (including code examples) on writing a screensaver - with random colors:
http://cocoadevcentral.com/articles/000088.php
Just for a short note:
Depending on your needs, it's possible that you should consider to write a not-so-random color generator. (For example when want to set up "rules" for the visibility of the generated colors.) So it's possible that you need to get the color code by limiting the random-generated values in HSB.
Related
I need to assign user profiles colors in a pseudo random consistent way based on their username/name/any string.
How do I do this in objective C iOS 7?
Java based example is here
Compute hex color code for an arbitrary string
There are probably many ways. Here's one:
NSString *someString = ... // some string to "convert" to a color
NSInteger hash = someString.hash;
int red = (hash >> 16) & 0xFF;
int green = (hash >> 8) & 0xFF;
int blue = hash & 0xFF;
UIColor *someColor = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:1.0];
The same string will always give the same color. Different strings will generally give different colors but it is possible that two different strings could give the same color.
My version:
+ (UIColor *)colorForString:(NSString *)string
{
NSUInteger hash = string.hash;
CGFloat hue = ( hash % 256 / 256.0 ); // 0.0 to 1.0
CGFloat saturation = ( hash % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white
CGFloat brightness = ( hash % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black
return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1];
}
It creates more saturated but bright enough and beautiful colors.
I am working on an application which needs to compare two images, in order to see how different they are and the application does this repeatedly for different images. So the way I currently do this is by having both the images as NSBitmapImageRep, then using the colorAtX: y: function in order to get a NSColor object, and then examining the RGB components. But this approach is extremely slow. So researching around the internet I found posts saying that a better way would be to get the bitmap data, using the function bitmapData, which returns an unsigned char. Unfortunately for me I don't know how to progress further from here, and none of the posts I've found show you how to actually get the RGB components for each pixel from this bitmapData. So currently I have :
NSBitmapImageRep* imageRep = [self screenShot]; //Takes a screenshot of the content displayed in the nswindow
unsigned char *data = [imageRep bitmapData]; //Get the bitmap data
//What do I do here in order to get the RGB components?
Thanks
The pointer you get back from -bitmapData points to the RGB pixel data. You have to query the image rep to see what format it's in. You can use the -bitmapFormat method which will tell you whether the data is alpha first or last (RGBA or ARGB), and whether the pixels are ints or floats. You need to check how many samples per pixel, etc. Here are the docs. If you have more specific questions about the data format, post those questions and we can try to help answer them.
Usually the data will be non-planar, which means it's just interleaved RGBA (or ARGB) data. You can loop over it like this (assuming 8-bit per channel, 4 channels of data) :
int width = [imageRep pixelsWide];
int height = [imageRep pixelsHight];
int rowBytes = [imageRep bytesPerRow];
char* pixels = [imageRep bitmapData];
int row, col;
for (row = 0; row < height; row++)
{
unsigned char* rowStart = (unsigned char*)(pixels + (row * rowBytes));
unsigned char* nextChannel = rowStart;
for (col = 0; col < width; col++)
{
unsigned char red, green, blue, alpha;
red = *nextChannel;
nextChannel++;
green = *nextChannel;
nextChannel++;
// ...etc...
}
}
I'm trying to find out a way to calculate the average color of the screen using objective-c.
So far I use this code to get a screen shot, which works great:
CGImageRef image1 = CGDisplayCreateImage(kCGDirectMainDisplay);
NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage:image1];
// Create an NSImage and add the bitmap rep to it...
NSImage *image = [[NSImage alloc] init];
[image addRepresentation:bitmapRep];
Now my problem is to calculate the average RGB color of this image.
I've found one solution, but the R G and B color components were always calculated to be the same (equal):
NSInteger i = 0;
NSInteger components[3] = {0,0,0};
unsigned char *data = [bitmapRep bitmapData];
NSInteger pixels = ([bitmapRep size].width *[bitmapRep size].height);
do {
components[0] += *data++;
components[1] += *data++;
components[2] += *data++;
} while (++i < pixels);
int red = (CGFloat)components[0] / pixels;
int green = (CGFloat)components[1] / pixels;
int blue = (CGFloat)components[2] / pixels;
A short analysis of bitmapRep shows that each pixel has 32 bits (4 bytes) where the first byte is unused, it is a padding byte, in other words the format is XRGB and X is not used. (There are no padding bytes at the end of a pixel row).
Another remark: for counting the number of pixels you use the method -(NSSize)size.
You should never do this! size has nothing to do with pixels. It only says how big the image should be depicted (expressed in inch or cm or mm) on the screen or the printer. For counting (or using otherwise) the pixels you should use -(NSInteger)pixelsWide and -(NSInteger)pixelsHigh. But the (wrong) using of -size works if and only if the resolution of the imageRep is 72 dots per inch.
Finally: there is a similar question at Average Color of Mac Screen
Your data is probably aligned as 4 bytes per pixel (and not 3 bytes, like you assume). That would (statistically) explain the near-equal values that you get.
I am trying to get a random color. I have done it using brute force but this method seems overly laborious (though the distribution is pretty even):
- (UIColor *) getRandomColor {
// GOAL: reject colors that are too dark
float total = 3;
float one = arc4random() % 256 / 256.0;
total -= one;
float two = arc4random() % 256 / 256.0;
total -= two;
float three = total; // UIColor will chop out-of-range nums
NSMutableArray *threeFloats = [[[NSMutableArray alloc] initWithObjects:[NSNumber numberWithFloat:one], [NSNumber numberWithFloat:two], [NSNumber numberWithFloat:three], nil] autorelease];
NSNumber *red, *green, *blue;
red = [threeFloats objectAtIndex:arc4random() % [threeFloats count]];
[threeFloats removeObject:red];
green = [threeFloats objectAtIndex:arc4random() % [threeFloats count]];
[threeFloats removeObject:green];
blue = [threeFloats lastObject];
return [UIColor colorWithRed:[red floatValue] green:[green floatValue] blue:[blue floatValue] alpha:1];
}
How can it be bettered? I want an even distribution of red, green and blue and nothing too dark (otherwise I'd grab three random numbers and be done with it).
+ (UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha;
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black
If white is ok then do saturation like hue instead of brightness.
I'd probably generate (pseudo-)random numbers for hue, saturation and lightness (or HSB), with the lightness (or brightness) limited to whatever range you find reasonable, then convert that to RGB.
This method might help you quickly generate bright colors randomly:
1 - Pick a random integer between 0-2
2 - If it is 0, set Red to Random(0.75-1.0), Green and Blue to Random(0.0-1.0)
2 - If it is 1, set Green to Random(0.75-1.0), Red and Blue to Random(0.0-1.0)
2 - If it is 2, set Blue to Random(0.75-1.0), Green and Red to Random(0.0-1.0)
I'm attempting to define an extremely simple utility method that will save me from having to use a calculator to define RGB values as percentages. When I look into Apple's sample code called "QuartzCache", in the DrawView.m file, line 96, I see this:
float whiteColor[4] = {1, 1, 1, 1};
However, when I attempt to created a method like the following, the compiler hates me. A half-hour of intensive Googling has not produced any help.
+(float[])percentagesRGBArray:(float[])rgbArray{
float red = rgbArray[0];
float green = rgbArray[1];
float blue = rgbArray[2];
float alpha = rgbArray[3];
red = red/255;
green = green/255;
blue = blue/255;
alpha = alpha;
float percentagesRGBArray[4] = {red, green, blue, alpha};
return percentagesRGBArray;
}
What is the proper way to define such a method? What am I doing wrong here?
Define a struct that contains all of the components, or wrap up each individual component in an NSNumber. Alternatively, use an NSColor instance to contain your colour components.
struct way:
typedef struct
{
float red;
float green;
float blue;
float alpha;
} MyColor;
- (MyColor) percentagesRGBArray:(MyColor) incoming
{
MyColor result;
result.red = incoming.red / 255;
result.green = incoming.green / 255;
result.blue = incoming.blue / 255;
result.alpha = incoming.alpha;
return result;
}
NSNumber way:
- (NSArray *) percentagesRGBArray:(float[]) rgbArray
{
NSNumber *red = [NSNumber numberWithFloat:rgbArray[0] / 255];
NSNumber *green = [NSNumber numberWithFloat:rgbArray[1] / 255];
NSNumber *blue = [NSNumber numberWithFloat:rgbArray[2] / 255];
NSNumber *alpha = [NSNumber numberWithFloat:rgbArray[3]];
return [NSArray arrayWithObjects:red, green, blue, alpha, nil];
}
NSColor way:
- (NSColor *) percentagesRGBArray:(float[]) rgbArray
{
CGFloat red = rgbArray[0] / 255;
CGFloat green = rgbArray[1] / 255;
CGFloat blue = rgbArray[2] / 255;
CGFloat alpha = rgbArray[3];
return [NSColor colorWithDeviceRed:red
green:green
blue:blue
alpha:alpha];
}
Normally, you would use Cocoa's NSColor class to handle this sort of thing, but it looks like you are doing something a little more low-level.
In that case, I would do the following:
typedef struct
{
float red;
float green;
float blue;
float alpha;
}
RGBAData;
RGBAData ConvertRGBAToPercentages(const RGBAData source)
{
RGBAData percentages;
percentages.red = source.red/255;
percentages.green = source.green/255;
percentages.blue = source.blue/255;
percentages.alpha = source.alpha/255;
return percentages;
}
To be used as follows:
RGBAData original = { 0xFF, 0xFF, 0x00, 0x80 }; // 50% transparent yellow
RGBAData percents = ConvertRGBAToPercentages(original);
Both e.James and dreamlax's answers give good approaches for doing this. But to answer what was wrong with your original code:
Basically, it has to do with how C arrays work. An array is essentially equivalent to a pointer to its first element. In fact, when you pass an array to a function, it decays into a pointer. You're still allowed to name the argument float myArray[4] (you have to declare the number of elements) just to make it clear that the pointer is supposed to be to an array of 4 elements — but you're still getting a pointer. Now consider the return value. What are you returning? We already established that you can't return an array by value, because it decays into a pointer. But even if you change the return type to be a pointer, it still won't work, because the array will have gone out of scope once the function returns. In order to return an array, you have to malloc the memory, and then you're responsible for freeing it later.
This is why you should avoid working with C arrays when at all possible. They're really low-level and fiddly. Even when you do use them, it's usually a good idea to hide them behind an API that takes care of the low-level details for you.
I think i'm late) but i have just found this thread.
the C way to do this is to create an array before invoking a function;
+(void) percentagesRGBArray:(float[])inArray toArray:(float*)outArray {
...
}
float array1[4];
float array2[4];
[MyClass percentagesRGBArray:array1 toArray:array2];