2013-10-04 11 views
7

So habe ich dieses Skript, das die Anzeigedaten in ein Zeichenarray pixels lautet:Wie schreibe ich PNG-Dateien von einem OpenGL-Bildschirm?

 typedef unsigned char uchar; 
     // we will store the image data here 
     uchar *pixels; 
     // the thingy we use to write files 
     FILE * shot; 
     // we get the width/height of the screen into this array 
     int screenStats[4]; 

     // get the width/height of the window 
     glGetIntegerv(GL_VIEWPORT, screenStats); 

     // generate an array large enough to hold the pixel data 
     // (width*height*bytesPerPixel) 
     pixels = new unsigned char[screenStats[2]*screenStats[3]*3]; 
     // read in the pixel data, TGA's pixels are BGR aligned 
     glReadPixels(0, 0, screenStats[2], screenStats[3], 0x80E0, 
     GL_UNSIGNED_BYTE, pixels); 

Normalerweise speichere ich diese in eine TGA-Datei, aber da diese monströs groß bekommt ich hatte gehofft, PNG zu verwenden, anstatt, wie ich Auf diese Weise geht der Festplattenspeicher schnell aus (meine Bilder sind sehr monoton und leicht komprimierbar, so dass der potentielle Gewinn enorm ist). Ich sehe also PNG writer, aber ich bin offen für andere Vorschläge. Das Anwendungsbeispiel sie bei their website geben, ist dies:

#include <pngwriter.h> 


int main() 
{ 
pngwriter image(200, 300, 1.0, "out.png"); 
image.plot(30, 40, 1.0, 0.0, 0.0); // print a red dot 
image.close(); 
return 0; 
} 

Wie ich etwas bin neu zu Bildverarbeitung bin ich ein wenig verwirrt über die Form meiner pixels Array und wie ich würde das darstellbare in eine Form umwandeln in das obige Format. Als Referenz Ich habe das folgende Skript wurde mit meinen Dateien zu TGA konvertieren:

////////////////////////////////////////////////// 
    // Grab the OpenGL screen and save it as a .tga // 
    // Copyright (C) Marius Andra 2001    // 
    // http://cone3d.gz.ee EMAIL: [email protected] // 
    ////////////////////////////////////////////////// 
    // (modified by me a little) 
    int screenShot(int const num) 
    { 
     typedef unsigned char uchar; 
     // we will store the image data here 
     uchar *pixels; 
     // the thingy we use to write files 
     FILE * shot; 
     // we get the width/height of the screen into this array 
     int screenStats[4]; 

     // get the width/height of the window 
     glGetIntegerv(GL_VIEWPORT, screenStats); 

     // generate an array large enough to hold the pixel data 
     // (width*height*bytesPerPixel) 
     pixels = new unsigned char[screenStats[2]*screenStats[3]*3]; 
     // read in the pixel data, TGA's pixels are BGR aligned 
     glReadPixels(0, 0, screenStats[2], screenStats[3], 0x80E0, 
     GL_UNSIGNED_BYTE, pixels); 

     // open the file for writing. If unsucessful, return 1 
     std::string filename = kScreenShotFileNamePrefix + Function::Num2Str(num) + ".tga"; 

     shot=fopen(filename.c_str(), "wb"); 

     if (shot == NULL) 
      return 1; 

     // this is the tga header it must be in the beginning of 
     // every (uncompressed) .tga 
     uchar TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0}; 
     // the header that is used to get the dimensions of the .tga 
     // header[1]*256+header[0] - width 
     // header[3]*256+header[2] - height 
     // header[4] - bits per pixel 
     // header[5] - ? 
     uchar header[6]={((int)(screenStats[2]%256)), 
     ((int)(screenStats[2]/256)), 
     ((int)(screenStats[3]%256)), 
     ((int)(screenStats[3]/256)),24,0}; 

     // write out the TGA header 
     fwrite(TGAheader, sizeof(uchar), 12, shot); 
     // write out the header 
     fwrite(header, sizeof(uchar), 6, shot); 
     // write the pixels 
     fwrite(pixels, sizeof(uchar), 
     screenStats[2]*screenStats[3]*3, shot); 

     // close the file 
     fclose(shot); 
     // free the memory 
     delete [] pixels; 

     // return success 
     return 0; 
    } 

Ich mag normalerweise nicht gerade auf diesen Foren Dump und bürgen aber in diesem Fall bin ich einfach stecken. Ich bin mir sicher, dass die Konvertierung fast trivial ist. Ich verstehe einfach nicht genug über die Bildverarbeitung, um es zu erledigen. Wenn jemand ein einfaches Beispiel dafür geben könnte, wie man das pixels Array in image.plot() in der PNG Writer Bibliothek umwandelt oder eine Möglichkeit bietet, dies mit einer anderen Bibliothek zu erreichen, die großartig wäre! Vielen Dank.

Antwort

5

Ihre aktuelle Implementierung macht fast die ganze Arbeit. Alles, was Sie tun müssen, ist, in die PNG-Datei die von OpenGL zurückgegebenen Pixelfarben zu schreiben. Da es in PNG Writer keine Methode gibt, ein Array von Farben zu übergeben, müssen Sie die Pixel nacheinander schreiben.

Ihr Anruf an glReadPixels() verbirgt das gewünschte Farbformat. Sie sollten eine der vordefinierten Konstanten (siehe format argument) anstelle von 0x80E0 verwenden. Je nachdem, wie Sie das Pixel-Array erstellen, schätze ich, dass Sie rot/grün/blaue Komponenten anfordern.

So wird Ihr Pixel-zu-png Code wie folgt aussehen:

const std::size_t image_width(screenStats[2]); 
const std::size_t image_height(screenStats[3]); 

pngwriter image(image_width, image_height, /*…*/); 

for (std::size_t y(0); y != image_height; ++y) 
    for (std::size_t x(0); x != image_width; ++x) 
    { 
     unsigned char* rgb(pixels + 3 * (y * image_width + x)); 
     image.plot(x, y, rgb[0], rgb[1], rgb[2]); 
    } 

image.close() 

zu PNGwriter Als Alternative kann man einen Blick auf libclaw oder libpng verwenden, wie ist.

+0

Ich habe es noch nicht ausprobiert, aber auch wenn es nicht funktioniert, ist es ein großartiger Start. Danke, dass ich es schätze! – arman