奇怪的CGImage创建问题

发布于 2024-11-16 16:38:09 字数 2353 浏览 3 评论 0原文

在 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,我会得到以下结果...

从数据创建的CGImageRef

水平伪影是由我的屏幕截图创建的(不在实际图像中),但是分割的那两条垂直线将图像分成 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...

CGImageRef created from data

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...

Drawing noise manually

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谈情不如逗狗 2024-11-23 16:38:09

由于 CGBitmapContextCreate 假设您的图像缓冲区是按行索引而不是按列索引,因此您需要交换 x 和 y 循环。

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++;
    }
}

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++;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文