Использование изображения, созданного с помощью CGBitmapContextCreate, в качестве текстуры opengl - PullRequest
10 голосов
/ 02 августа 2010

Я генерирую изображение, используя quartz2d, и я хочу использовать его в качестве opengl текстуры.Сложность в том, что я хочу использовать как можно меньше бит на пиксель, поэтому я создаю cgContext следующим образом:

int bitsPerComponent = 5;
int bytesPerPixel = 2;
int width = 1024;
int height = 1024;
void* imageData = malloc(width * height * bytesPerPixel);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageContext context = CGBitmapContextCreate(imageData, width, height, bitsPerComponent, width * bytesPerPixel, colorSpace, kCGImageAlphaNoneSkipFirst);
//draw things into context, release memory, etc.

Как указано в документации здесь ,это единственный поддерживаемый формат RGB пикселей для CGBitmapContextCreate, который использует 16 бит на пиксель.Итак, теперь я хочу загрузить данные imageData, которые выглядят как «1 бит пропущен - 5 бит красного цвета - 5 бит зеленого цвета - 5 бит синего» в текстуру opengl.Поэтому я должен сделать что-то вроде этого:

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, imageData); 

Это не сработает, потому что в этом вызове я указал пиксельный формат как 5 red - 5 green - 5 blue - 1 alpha.Это неправильно, но похоже, что нет формата, который соответствовал бы основному графическому выводу.
Есть некоторые другие опции, такие как GL_UNSIGNED_SHORT_1_5_5_5_REV, но они не будут работать на iphone.

Мне нужнокакой-то способ использовать это imageData в качестве текстуры, но я действительно не хочу обменивать байты вручную, используя memset или тому подобное, потому что это кажется ужасно неэффективным.

Ответы [ 2 ]

2 голосов
/ 10 ноября 2012

Вам нужно поменять местами биты, чтобы получить более плотный формат, такой как RGBA551 или RGB565, поскольку, как вы заметили, CGBitmapContext не поддерживает эти форматы для рисования (для простоты и эффективности).

memset не справится с задачей, но в Accelerate.framework.

см. vImageConvert_ARGB8888toRGB565(…) и vImageConvert_ARGB8888toARGB1555(…), доступные в iOS 5 и более поздних версиях, для «быстрого» преобразования.

1 голос
/ 06 января 2014

Для iOS 7.0, OS X.9 и более поздних версий:

vImage_CGImageFormat fmt = {
    .bitsPerComponent = 5,
    .bitsPerPixel = 16,
    .colorSpace = NULL, // faster with CGImageGetColorSpace(cgImage) if known to be RGB
    .bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder16Little // ARGB1555 little endian
};
vImage_Buffer buf;
vImageBuffer_InitWithCGImage( &buf, &fmt, NULL, cgImage, kvImageNoFlags );

...

free(buf.data);

Данные находятся в buf.data вместе с высотой изображения, шириной и rowBytes.Информация.Я не помню, каковы требования GL для того, разрешено ли заполнение строк.Вы можете контролировать это, предварительно выделив поля buf.data и buf.rowBytes и передав kvImageDoNotAllocate во флаги.

565_REV - это kCGImageAlphaNone |kCGBitmapByteOrder16Little.5551_REV - это kCGImageAlphaNoneSkipLast |kCGBitmapByteOrder16Little

...