2010-08-02 10 views
10

Ich erzeuge ein Bild mit Quarz 2d und ich möchte es als OpenGL-Textur verwenden. Der schwierige Teil ist, dass ich so wenig Bits pro Pixel wie möglich nutzen will, so dass ich die Schaffung CGcontext, wie folgend:Verwenden von mit CGBitmapContextCreate erstellten Bild als OpenGL-Textur

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. 

Wie here in der Dokumentation angegeben, ist dies das unterstützt wird, ist nur RGB-Pixelformat für CGBitmapContextCreate, das 16 Bits pro Pixel verwendet. Nun möchte ich dieses imageData, das aussieht wie "1 Bit übersprungen - 5 Bit rot - 5 Bit grün - 5 Bit blau" in eine OpenGL-Textur hochladen. Also sollte ich so etwas tun:

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); 

Das ist nicht, weil in diesem Aufruf funktioniert I-Pixel-Format wie "5 rot - 5 grün - 5 blau - 1 alpha" angegeben haben. Das ist falsch, aber es scheint, dass es kein Format gibt, das mit der Grafikausgabe übereinstimmt.
Es gibt einige andere Optionen wie GL_UNSIGNED_SHORT_1_5_5_5_REV, aber diese funktionieren nicht auf dem iPhone.

Ich brauche eine Möglichkeit, diese ImageData als Textur zu verwenden, aber ich möchte wirklich nicht Bytes um manuell mit Memset oder so umgehen, weil das schrecklich unwirksam scheint.

+0

Warum die Sorge über 5 Bits pro Pixel? Warum sollte nicht einfach der Kontext so sein, was für opengl am einfachsten funktioniert, und wenn die Quellbilder anders sind, erlaubt quartz die Konvertierung, wenn sie in den Kontext gezogen wird? Ich habe alle möglichen dynamischen Texturen in meinem Spiel und habe diese Probleme nie gehabt. – badweasel

+0

Ich habe diese Frage im Jahr 2010 erstellt, als wir noch 2g Deivces unterstützten. 2g und 3g hatten beide sehr wenig Speicher und die App war kein Spiel - es war ein E-Book-Reader. Wir mussten mindestens 10 MB Daten nur für unsere Textanalyse/Styling/Layout-Engine verwenden, und jedes winzige Byte war entscheidend. Ich bin mir nicht sicher, ob jemand das im Jahr 2012 verwenden müsste, aber vielleicht gibt es immer noch Apps, die mit der Memmory-Warnung getötet werden und den Speicherbedarf reduzieren wollen. – Alexey

+0

@Alexey: Können Sie uns bitte wissen, welche Auflösung von Bilddaten Sie für die Textur laden? – 8Ours

Antwort

2

Sie müssen Bits austauschen, um es in ein dichteres Format wie RGBA551 oder RGB565 zu bringen, da, wie Sie bemerken, CGBitmapContext diese Formate zum Zeichnen nicht unterstützt (der Einfachheit halber und der Effizienz halber).

memset wird nicht den Trick tun, aber es gibt "schnelle" Konvertierungsroutinen in Accelerate.framework.

Siehe vImageConvert_ARGB8888toRGB565(…) und vImageConvert_ARGB8888toARGB1555(…), verfügbar für iOS 5 und höher.

1

Für iOS 7.0, O X.9 und später:

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); 

Daten ist in buf.data, zusammen mit Bild Höhe, Breite und rowBytes info. Ich weiß nicht mehr, was die Anforderungen von GL sind, ob Zeilenauffüllung erlaubt ist. Sie können dies steuern, indem Sie die Felder buf.data und buf.rowBytes vorbelegen und kvImageDoNotAllocate in den Flags übergeben.

565_REV ist kCGImageAlphaNone | kCGBitmapByteOrder16Little. 5551_REV ist kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder16Little

Verwandte Themen