Использование образа, созданного с помощью CGBitmapContextCreate, в качестве текстуры opengl
Я генерирую изображение с использованием 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 или что-то подобное, потому что это кажется ужасно неэффективным.
Ответы
Ответ 1
Вам нужно поменять местами, чтобы получить его в более плотном формате, таком как RGBA551 или RGB565, поскольку, как вы помните, CGBitmapContext не поддерживает эти форматы для рисования (для простоты и эффективности).
memset
не собирается делать трюк, но в Accelerate.framework
есть "быстрые" процедуры преобразования.
См. vImageConvert_ARGB8888toRGB565(…)
и vImageConvert_ARGB8888toARGB1555(…)
, доступные на iOS 5 и более поздних версиях.
Ответ 2
Для 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