Image::Image *
getDrawBufferImage(GLenum format) {
- GLint width, height;
-
- if (format != GL_RGBA) {
- // FIXME: this function can only handle 4-channel images
+ GLint channels = __gl_format_channels(format);
+ if (channels > 4) {
return NULL;
}
+ GLint width, height;
if (!getDrawableBounds(&width, &height)) {
return NULL;
}
- Image::Image *image = new Image::Image(width, height, true);
+ Image::Image *image = new Image::Image(width, height, channels, true);
if (!image) {
return NULL;
}
glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
+ glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, image->pixels);
glPopClientAttrib();
/**************************************************************************
*
+ * Copyright 2011 Jose Fonseca
* Copyright 2008-2010 VMware, Inc.
* All Rights Reserved.
*
#include <zlib.h>
#include <png.h>
+#include <assert.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
bool
Image::writeBMP(const char *filename) const {
+ assert(channels == 4);
+
struct FileHeader bmfh;
struct InfoHeader bmih;
unsigned x, y;
png_init_io(png_ptr, fp);
- png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
+ int color_type;
+ switch (channels) {
+ case 4:
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ break;
+ case 3:
+ color_type = PNG_COLOR_TYPE_RGB;
+ break;
+ case 2:
+ color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+ break;
+ case 1:
+ color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ default:
+ assert(0);
+ return false;
+ }
+
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8, color_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
if (!flipped) {
for (unsigned y = 0; y < height; ++y) {
- png_bytep row = (png_bytep)(pixels + y*width*4);
+ png_bytep row = (png_bytep)(pixels + y*width*channels);
png_write_rows(png_ptr, &row, 1);
}
} else {
unsigned y = height;
while (y--) {
- png_bytep row = (png_bytep)(pixels + y*width*4);
+ png_bytep row = (png_bytep)(pixels + y*width*channels);
png_write_rows(png_ptr, &row, 1);
}
}
double Image::compare(Image &ref)
{
if (width != ref.width ||
- height != ref.height) {
+ height != ref.height ||
+ channels != ref.channels) {
return 0.0;
}
const unsigned char *pSrc = start();
const unsigned char *pRef = ref.start();
+ assert(channels >= 3);
+
unsigned long long error = 0;
for (unsigned y = 0; y < height; ++y) {
for (unsigned x = 0; x < width; ++x) {
// FIXME: Ignore alpha channel until we are able to pick a visual
// that matches the traces
for (unsigned c = 0; c < 3; ++c) {
- int delta = pSrc[x*4 + c] - pRef[x*4 + c];
+ int delta = pSrc[x*channels + c] - pRef[x*channels + c];
error += delta*delta;
}
}
public:
unsigned width;
unsigned height;
+ unsigned channels;
// Flipped vertically or not
bool flipped;
// Pixels in RGBA format
unsigned char *pixels;
- inline Image(unsigned w, unsigned h, bool f = false) :
+ inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false) :
width(w),
height(h),
+ channels(c),
flipped(f),
- pixels(new unsigned char[h*w*4])
+ pixels(new unsigned char[h*w*c])
{}
inline ~Image() {
}
inline unsigned char *start(void) {
- return flipped ? pixels + (height - 1)*width*4 : pixels;
+ return flipped ? pixels + (height - 1)*width*channels : pixels;
}
inline unsigned char *end(void) {
- return flipped ? pixels - width*4 : pixels + height*width*4;
+ return flipped ? pixels - width*channels : pixels + height*width*channels;
}
inline signed stride(void) const {
- return flipped ? -width*4 : width*4;
+ return flipped ? -width*channels : width*channels;
}
bool writeBMP(const char *filename) const;