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