www.pudn.com > 3DEDITOR.rar > IMAGECAPTURE.CPP


// ImageCapture.cpp: implementation of the CImageCapture class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "3DEditor.h" 
#include "ImageCapture.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
extern "C" { 
#ifdef _WIN32 
#include "jpeglib.h" 
#else 
#include  
#endif 
} 
 
#include "png.h" 
 
// Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng 
#ifndef png_jmpbuf 
#define png_jmpbuf(png_ptr) png_ptr->jmpbuf 
#endif 
 
// Define various expansion transformations for old versions of libpng 
#if PNG_LIBPNG_VER < 10004 
#define png_set_palette_to_rgb(p)  png_set_expand(p) 
#define png_set_gray_1_2_4_to_8(p) png_set_expand(p) 
#define png_set_tRNS_to_alpha(p)   png_set_expand(p) 
#endif 
 
//using namespace std; 
 
CImageCapture::CImageCapture() 
{ 
 
} 
 
CImageCapture::~CImageCapture() 
{ 
 
} 
 
bool CImageCapture::CaptureGLBufferToJPEG(CString filename, 
                           int x, int y, 
                           int width, int height) 
{ 
    int rowStride = (width * 3 + 3) & ~0x3; 
    int imageSize = height * rowStride; 
    unsigned char* pixels = new unsigned char[imageSize]; 
 
    glReadPixels(x, y, width, height, 
                 GL_RGB, GL_UNSIGNED_BYTE, 
                 pixels); 
 
    // TODO: Check for GL errors 
 
    FILE* out; 
    out = fopen(filename, "wb"); 
    if (out == NULL) 
    { 
        MessageBox(NULL,"Can't open screen capture file.","ERROR", MB_OK); 
        delete[] pixels; 
        return false; 
    } 
 
    struct jpeg_compress_struct cinfo; 
 
    struct jpeg_error_mgr jerr; 
    JSAMPROW row[1]; 
 
    cinfo.err = jpeg_std_error(&jerr); 
    jpeg_create_compress(&cinfo); 
 
    jpeg_stdio_dest(&cinfo, out); 
 
    cinfo.image_width = width; 
    cinfo.image_height = height; 
    cinfo.input_components = 3; 
    cinfo.in_color_space = JCS_RGB; 
 
    jpeg_set_defaults(&cinfo); 
 
    // jpeg_set_quality(&cinfo, quality, TRUE); 
 
    jpeg_start_compress(&cinfo, TRUE); 
 
    while (cinfo.next_scanline < cinfo.image_height) 
    { 
        row[0] = &pixels[rowStride * (cinfo.image_height - cinfo.next_scanline - 1)]; 
        (void) jpeg_write_scanlines(&cinfo, row, 1); 
    } 
 
    jpeg_finish_compress(&cinfo); 
    fclose(out); 
    jpeg_destroy_compress(&cinfo); 
 
    delete[] pixels; 
 
    return true; 
} 
 
 
void PNGWriteData(png_structp png_ptr, png_bytep data, png_size_t length) 
{ 
    FILE* fp = (FILE*) png_get_io_ptr(png_ptr); 
    fwrite((void*) data, 1, length, fp); 
} 
 
                            
bool CImageCapture::CaptureGLBufferToPNG(CString filename, 
                           int x, int y, 
                           int width, int height) 
{ 
    int rowStride = (width * 3 + 3) & ~0x3; 
    int imageSize = height * rowStride; 
    unsigned char* pixels = new unsigned char[imageSize]; 
 
    glReadPixels(x, y, width, height, 
                 GL_RGB, GL_UNSIGNED_BYTE, 
                 pixels); 
 
    // TODO: Check for GL errors 
 
    FILE* out; 
    out = fopen(filename, "wb"); 
    if (out == NULL) 
    { 
        MessageBox(NULL,"Can't open screen capture file.","ERROR",MB_OK); 
        delete[] pixels; 
        return false; 
    } 
 
    png_bytep* row_pointers = new png_bytep[height]; 
    for (int i = 0; i < height; i++) 
        row_pointers[i] = (png_bytep) &pixels[rowStride * (height - i - 1)]; 
 
    png_structp png_ptr; 
    png_infop info_ptr; 
 
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 
                                      NULL, NULL, NULL); 
 
    if (png_ptr == NULL) 
    { 
        MessageBox(NULL,"Screen capture: error allocating png_ptr","ERROR",MB_OK); 
        fclose(out); 
        delete[] pixels; 
        delete[] row_pointers; 
        return false; 
    } 
 
    info_ptr = png_create_info_struct(png_ptr); 
    if (info_ptr == NULL) 
    { 
        MessageBox(NULL,"Screen capture: error allocating info_ptr","ERROR",MB_OK); 
        fclose(out); 
        delete[] pixels; 
        delete[] row_pointers; 
        png_destroy_write_struct(&png_ptr, (png_infopp) NULL); 
        return false; 
    } 
 
    if (setjmp(png_jmpbuf(png_ptr))) 
    { 
        MessageBox(NULL,"Error writing PNG file.","ERROR",MB_OK); 
        fclose(out); 
        delete[] pixels; 
        delete[] row_pointers; 
        png_destroy_write_struct(&png_ptr, &info_ptr); 
        return false; 
    } 
 
    // png_init_io(png_ptr, out); 
    png_set_write_fn(png_ptr, (void*) out, PNGWriteData, NULL); 
 
    png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); 
    png_set_IHDR(png_ptr, info_ptr, 
                 width, height, 
                 8, 
                 PNG_COLOR_TYPE_RGB, 
                 PNG_INTERLACE_NONE, 
                 PNG_COMPRESSION_TYPE_DEFAULT, 
                 PNG_FILTER_TYPE_DEFAULT); 
 
    png_write_info(png_ptr, info_ptr); 
    png_write_image(png_ptr, row_pointers); 
    png_write_end(png_ptr, info_ptr); 
 
    // Clean up everything . . . 
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 
    delete[] row_pointers; 
    delete[] pixels; 
    fclose(out); 
 
    return true; 
} 
 
bool CImageCapture::CaptureGLBufferToBMP(CString filename, 
                           int x, int y, 
                           int width, int height) 
{ 
		void* imageData = malloc(width*height*3);		// allocate memory for the imageData 
		memset(imageData, 0, width*height*3);	// clear imageData memory contents 
 
		// read the image data from the window 
		glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char*)imageData); 
 
	 
		// write the image data to a file 
		WriteBitmapFile(filename, width, height, (unsigned char*)imageData); 
 
		// free the image data memory 
		free(imageData); 
		return true; 
} 
 
// WriteBitmapFile() 
// desc: takes image data and saves it into a 24-bit RGB .BMP file 
//       with width X height dimensions 
int CImageCapture::WriteBitmapFile(CString filename, int width, int height, unsigned char *imageData) 
{ 
	FILE			 *filePtr;			// file pointer 
	BITMAPFILEHEADER bitmapFileHeader;	// bitmap file header 
	BITMAPINFOHEADER bitmapInfoHeader;	// bitmap info header 
	int				 imageIdx;			// used for swapping RGB->BGR 
	unsigned char	 tempRGB;			// used for swapping 
 
	// open file for writing binary mode 
	filePtr = fopen(filename, "wb"); 
	if (!filePtr) 
		return 0; 
 
	// define the bitmap file header 
	bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER); 
	bitmapFileHeader.bfType = 0x4D42; 
	bitmapFileHeader.bfReserved1 = 0; 
	bitmapFileHeader.bfReserved2 = 0; 
	bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 
	 
	// define the bitmap information header 
	bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER); 
	bitmapInfoHeader.biPlanes = 1; 
	bitmapInfoHeader.biBitCount = 24;						// 24-bit 
	bitmapInfoHeader.biCompression = BI_RGB;				// no compression 
	bitmapInfoHeader.biSizeImage = width * abs(height) * 3;	// width * height * (RGB bytes) 
	bitmapInfoHeader.biXPelsPerMeter = 0; 
	bitmapInfoHeader.biYPelsPerMeter = 0; 
	bitmapInfoHeader.biClrUsed = 0; 
	bitmapInfoHeader.biClrImportant = 0; 
	bitmapInfoHeader.biWidth = width;						// bitmap width 
	bitmapInfoHeader.biHeight = height;						// bitmap height 
 
	// switch the image data from RGB to BGR 
	for (imageIdx = 0; imageIdx < bitmapInfoHeader.biSizeImage; imageIdx+=3) 
	{ 
		tempRGB = imageData[imageIdx]; 
		imageData[imageIdx] = imageData[imageIdx + 2]; 
		imageData[imageIdx + 2] = tempRGB; 
	} 
 
	// write the bitmap file header 
	fwrite(&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), filePtr); 
 
	// write the bitmap info header 
	fwrite(&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), filePtr); 
 
	// write the image data 
	fwrite(imageData, 1, bitmapInfoHeader.biSizeImage, filePtr); 
 
	// close our file 
	fclose(filePtr); 
 
	return 1; 
}