/*
    Raydium - CQFD Corp.
    http://raydium.org/
    Released under both BSD license and Lesser GPL library license.
    See "license.txt" file.
*/

#ifndef DONT_INCLUDE_HEADERS
#include "index.h"
#else
#include "headers/capture.h"
#endif 

// Present capture code was inspired from various web files...
// Not a pure CQFD Corp. production :)

// proto
FILE *raydium_file_fopen(char *file, char *mode);

void raydium_capture_frame(char *filename)
{
raydium_capture_asked=RAYDIUM_CAPTURE_TGA;
strcpy(raydium_capture_filename,filename);
}

void raydium_capture_frame_now(char *filename)
{
unsigned char cGarbage = 0, type,mode,aux,bpp, *imageData;
short int iGarbage = 0;
GLuint i;
GLuint size;
FILE *file;

mode=3; // RGB (Bpp)
bpp=mode*8;
type=2; // Color


size=raydium_window_tx * raydium_window_ty * mode;
imageData=malloc(size+1);

glReadPixels(0, 0,raydium_window_tx,raydium_window_ty,GL_RGB,GL_UNSIGNED_BYTE,imageData);


// open file and check for errors
file = raydium_file_fopen(filename, "wb");
if (file == NULL) { raydium_log("Error: capture: cannot open %s for writing",filename); return; }

// write the header
fwrite(&cGarbage, sizeof(unsigned char), 1, file);
fwrite(&cGarbage, sizeof(unsigned char), 1, file);
fwrite(&type, sizeof(unsigned char), 1, file);
fwrite(&iGarbage, sizeof(short int), 1, file);
fwrite(&iGarbage, sizeof(short int), 1, file);
fwrite(&cGarbage, sizeof(unsigned char), 1, file);
fwrite(&iGarbage, sizeof(short int), 1, file);
fwrite(&iGarbage, sizeof(short int), 1, file);
fwrite(&raydium_window_tx, sizeof(short int), 1, file);
fwrite(&raydium_window_ty, sizeof(short int), 1, file);
fwrite(&bpp, sizeof(unsigned char), 1, file);
fwrite(&cGarbage, sizeof(unsigned char), 1, file);

// convert the image data from RGB(a) to BGR(A)
    for (i=0; i < size ; i+= mode) 
    {
    aux = imageData[i];
    imageData[i] = imageData[i+2];
    imageData[i+2] = aux;
    }

    // save the image data
    fwrite(imageData, sizeof(unsigned char), size, file);
    fclose(file);
    // release the memory
    free(imageData);
    raydium_log("screenshot saved as %s",filename);
}

void raydium_capture_frame_jpeg(char *filename)
{
raydium_capture_asked=RAYDIUM_CAPTURE_JPG;
strcpy(raydium_capture_filename,filename);
}

void raydium_capture_frame_jpeg_now(char *filename)
{
JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */
int image_height;       /* Number of rows in image */
int image_width;                /* Number of columns in image */
int quality;

struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * outfile;         /* target file */
JSAMPROW row_pointer[1];        /* pointer to JSAMPLE row[s] */
int row_stride;         /* physical row width in image buffer */
int size;

cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);

outfile = raydium_file_fopen(filename, "wb");
if (outfile == NULL) { raydium_log("Error: capture: cannot open %s for writing",filename); return; }

size=raydium_window_tx * raydium_window_ty * 3;
image_buffer=malloc(size+1);

glReadPixels(0, 0,raydium_window_tx,raydium_window_ty,GL_RGB,GL_UNSIGNED_BYTE,image_buffer);
image_width=raydium_window_tx;
image_height=raydium_window_ty;
quality=DEBUG_JPEG_QUALITY;

jpeg_stdio_dest(&cinfo, outfile);

cinfo.image_width = image_width;        /* image width and height, in pixels */
cinfo.image_height = image_height;
cinfo.input_components = 3;             /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB;         /* colorspace of input image */

jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

jpeg_start_compress(&cinfo, TRUE);

row_stride = image_width * 3;   /* JSAMPLEs per row in image_buffer */

while (cinfo.next_scanline < cinfo.image_height) 
    {
    row_pointer[0] = & image_buffer[(cinfo.image_height-cinfo.next_scanline-1) * row_stride];
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }


jpeg_finish_compress(&cinfo);
fclose(outfile);

jpeg_destroy_compress(&cinfo);
free(image_buffer);
}

void raydium_capture_filename_auto(char *dest,char *format)
{
static int cpt=0;
time_t rawtime;
struct tm *ptm;
    
time(&rawtime);
ptm=gmtime(&rawtime); // localtime() ?
sprintf(dest,"raycap%i-%02i-%02i-%02i%02i%02i-%02i.%s",
        ptm->tm_year+1900,
        ptm->tm_mon+1,
        ptm->tm_mday,
        ptm->tm_hour,
        ptm->tm_min,
        ptm->tm_sec,
        cpt,
        format);
cpt++;
}

void raydium_capture_frame_auto(void)
{

char f[RAYDIUM_MAX_NAME_LEN];
raydium_capture_filename_auto(f,"tga");
raydium_capture_frame(f);
}

void raydium_capture_frame_jpeg_auto(void)
{
char f[RAYDIUM_MAX_NAME_LEN];
raydium_capture_filename_auto(f,"jpg");
raydium_capture_frame_jpeg(f);
}