Странная проблема создания CGImage - PullRequest
0 голосов
/ 22 июня 2011

Я сталкиваюсь с довольно странной проблемой при создании CGImageRef из необработанных данных на iphone.Я пытаюсь создать CGImageRef из функции генерации шума perlin, которая принимает 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 created from data

Горизонтальные артефакты были созданы моим снимком экрана (не на самом изображении), однако эти 2 вертикальные линии, которые разделяют изображение на 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не вызывает проблемы.Во всяком случае, я получаю следующий результат ...

Drawing noise manually

Так что вы, кажется, я создаю шум одинаково в обоих вышеупомянутых подходах, и я даже напечаталзначения от каждого метода рядом, чтобы подтвердить, что они идентичны!Так что создание CGImageRef из данных, а не рисование их непосредственно в контексте, создает странные визуальные проблемы, которые разрушают изображение.Мне нужно иметь возможность генерировать серию этих изображений при запуске приложения и не могу нарисовать их вручную, чтобы получить хорошие результаты.Кто-нибудь есть идеи, что может вызвать такие проблемы ???

1 Ответ

0 голосов
/ 22 июня 2011

Поскольку 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++;
    }
}
...