奇怪的CGImage创建问题
在 iPhone 上从原始数据创建 CGImageRef 时,我遇到了一个非常奇怪的问题。我正在尝试从 perlin 噪声生成函数创建 CGImageRef,该函数采用 x、y、z 和 t 并返回 -1 和 1 之间的值。对于每个像素,我得到 -1 和 1 之间的噪声值,转换将其设置为 0 到 255 之间的字符,并按以下方式从数据中创建 CGImageRef...
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);
如果我随后将此 CGImageRef 绘制到 CALayer,我会得到以下结果...
水平伪影是由我的屏幕截图创建的(不在实际图像中),但是分割的那两条垂直线将图像分成 3 个相同的部分就是问题所在!什么会导致图像重复 3 次并出现 2 个垂直不连续点?!更奇怪的是,如果我手动渲染柏林噪声而不创建 CGImageRef,就像这样......
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));
}
}
注意,我故意转换为 char,然后除以 255.0 以确保转换为 char 不会导致问题。无论如何,我得到以下结果...
所以你看起来我正在创建完全相同的噪声上述两种方法,我什至并排打印了每种方法的值,以确认它们是相同的!因此,以某种方式从数据中创建 CGImageRef 而不是直接将其绘制到上下文会产生奇怪的视觉问题,从而破坏图像。我需要能够在应用程序启动时生成一系列这些图像,并且无法手动绘制它们以获得良好的结果。任何人都知道什么可能会导致此类问题???
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???
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于 CGBitmapContextCreate 假设您的图像缓冲区是按行索引而不是按列索引,因此您需要交换 x 和 y 循环。
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.