2013-10-04 13 views
7

Così ho questo script che legge i dati di visualizzazione in un array di caratteri pixels:Come si scrivono i file PNG da una schermata openGL?

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

Normalmente, salvare questo in un file TGA, ma dato che questi ottengono mostruosamente grande speravo di usare PNG, invece, come ho rapidamente esaurito lo spazio su disco rigido in questo modo (le mie immagini sono altamente monotone e facilmente comprimibili, quindi il potenziale guadagno è enorme). Quindi guardo allo PNG writer ma sono aperto ad altri suggerimenti. L'esempio di utilizzo che danno a their website è questo:

#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; 
} 

Come io sono un po 'una novità per l'elaborazione delle immagini che sono un po' confuso circa la forma della mia pixels array e come avrei convertire questo ad una forma rappresentabili in il formato sopra. Come riferimento, ho usato il seguente script per convertire i file di TGA:

////////////////////////////////////////////////// 
    // 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; 
    } 

che normalmente non piace fare uscire solo e salvare su questi forum, ma in questo caso io sono semplicemente bloccato. Sono sicuro che la conversione è quasi banale, ma non capisco abbastanza l'elaborazione delle immagini per farlo. Se qualcuno potrebbe fornire un semplice esempio su come convertire l'array in image.plot() nella libreria di scrittori PNG o fornire un modo per ottenerlo utilizzando una libreria diversa che sarebbe eccezionale! Grazie.

risposta

5

La tua attuale implementazione fa quasi tutto il lavoro. Tutto quello che devi fare è scrivere nel file PNG i colori dei pixel restituiti da OpenGL. Poiché in PNG Writer non esiste alcun metodo per passare una matrice di colori, è necessario scrivere i pixel uno per uno.

La chiamata a glReadPixels() nasconde il formato colore richiesto. È necessario utilizzare una delle costanti predefinite (vedere format argument) anziché 0x80E0. In base al modo in cui costruisci l'array di pixel, suppongo tu stia richiedendo componenti rosso/verde/blu.

Così, il vostro codice di pixel-per-png può apparire come segue:

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

In alternativa al PNGwriter, si può avere uno sguardo a libclaw o utilizzare libpng così com'è.

+0

Non ho provato questo, ma anche se non funziona fuori dalla scatola è un ottimo punto di partenza - grazie Lo apprezzo! – arman

Problemi correlati