I'm encountering a pretty strange problem when creating a CGImageRef from raw data on iphone. I'm trying to create a CGImageRef from a perlin noise generating function that takes x, y, z, and t and returns a value between -1 and 1. For each pixel, I get the noise value between -1 and 1, convert this to a char between 0 and 255, and create a CGImageRef out of the data in the following way...
int width = (int)frame.size.width;
int height = (int)frame.size.height;
char* rgba = (char*)malloc(width * height * 4);
//set pixel data
int i = 0;
for(float x = 0.0; x < width; x+=1.0) {
for (float y = 0.0; y < height; y+=1.0) {
float perlinF = ABS([perlinGenerator perlinNoiseX:x y:y z:0.0 t:0.0]);
char perlin = (char)( perlinF * 255.0 );
rgba[4*i] = perlin;
rgba[4*i+1] = perlin;
rgba[4*i+2] = perlin;
rgba[4*i+3] = 255;
i++;
}
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext = CGBitmapContextCreate(
rgba,
width,
height,
8, // bitsPerComponent
4*width, // bytesPerRow
colorSpace,
kCGImageAlphaNoneSkipLast);
CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
If I then draw this CGImageRef to a CALayer, I get the following result...
The horizontal artifacts were created by my screen capture (not in the actual image), however those 2 vertical lines that split the image into 3 identical sections are the problem! What could cause the image to repeat 3 times at and have those 2 vertical discontinuities?! Even stranger is that if I render the perlin noise manually without creating a CGImageRef, like this...
for (CGFloat x = 0.0; x<size.width; x+=1.0) {
for (CGFloat y=0.0; y< size.height; y+=1.0) {
float perlinF = ABS([perlinGenerator perlinNoiseX:x y:y z:0.0 t:0.0]);
char perlin = (char)( perlinF * 255.0 );
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, (float)perlin / 255.0);
CGContextFillRect(context, CGRectMake(x, y, 1.0, 1.0));
}
}
Note, I purposely casted to char and then divided by 255.0 to make sure that the cast to char wasn't causing the problem. Anyway, I get the following result...
So you seem I'm creating the noise exactly the same in both of the above approaches, and I've even printed the values from each method side by side to confirm that they are identical! So Somehow creating a CGImageRef out of the data rather than drawing it straight to a context is create weird visual problems that destroy the image. I need to be able to generate a series of these images at application start and cannot manually draw them to get the good results. Anyone have any idea what could cause such problems???
Since CGBitmapContextCreate assumes that your image buffer is indexed by row instead of by column you will need to swap the x and y for loops.
int i = 0;
for (float y = 0.0; y < height; y+=1.0) {
for(float x = 0.0; x < width; x+=1.0) {
float perlinF = ABS([perlinGenerator perlinNoiseX:x y:y z:0.0 t:0.0]);
char perlin = (char)( perlinF * 255.0 );
rgba[4*i] = perlin;
rgba[4*i+1] = perlin;
rgba[4*i+2] = perlin;
rgba[4*i+3] = 255;
i++;
}
}