diff --git a/image/image.hpp b/image/image.hpp
index 7e13dd6..a5bff05 100644
--- a/image/image.hpp
+++ b/image/image.hpp
@@ -42,6 +42,7 @@ public:
     unsigned width;
     unsigned height;
     unsigned channels;
+    unsigned bpp;
 
     // Flipped vertically or not
     bool flipped;
@@ -49,12 +50,13 @@ public:
     // Pixels in RGBA format
     unsigned char *pixels;
 
-    inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false) : 
+    inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false, unsigned b = 8) :
         width(w),
         height(h),
         channels(c),
+        bpp(b),
         flipped(f),
-        pixels(new unsigned char[h*w*c])
+        pixels(new unsigned char[h*(w*c*b+7)/8])
     {}
 
     inline ~Image() {
@@ -62,23 +64,27 @@ public:
     }
 
     inline unsigned char *start(void) {
-        return flipped ? pixels + (height - 1)*width*channels : pixels;
+        return flipped ? pixels + (height - 1)*rowsize() : pixels;
     }
 
     inline const unsigned char *start(void) const {
-        return flipped ? pixels + (height - 1)*width*channels : pixels;
+        return flipped ? pixels + (height - 1)*rowsize() : pixels;
     }
 
     inline unsigned char *end(void) {
-        return flipped ? pixels - width*channels : pixels + height*width*channels;
+        return flipped ? pixels - rowsize() : pixels + height*rowsize();
     }
 
     inline const unsigned char *end(void) const {
-        return flipped ? pixels - width*channels : pixels + height*width*channels;
+        return flipped ? pixels - rowsize() : pixels + height*rowsize();
+    }
+
+    inline unsigned rowsize(void) const {
+        return (width*channels*bpp+7)/8;
     }
 
     inline signed stride(void) const {
-        return flipped ? -(signed)(width*channels) : width*channels;
+        return flipped ? -(signed)rowsize() : rowsize();
     }
 
     bool writeBMP(const char *filename) const;
diff --git a/image/image_bmp.cpp b/image/image_bmp.cpp
index e0c6428..8c25505 100644
--- a/image/image_bmp.cpp
+++ b/image/image_bmp.cpp
@@ -69,6 +69,7 @@ struct Pixel {
 bool
 Image::writeBMP(const char *filename) const {
     assert(channels == 4);
+    assert(bpp == 8);
 
     struct FileHeader bmfh;
     struct InfoHeader bmih;
diff --git a/image/image_png.cpp b/image/image_png.cpp
index dba07d4..4ad923e 100644
--- a/image/image_png.cpp
+++ b/image/image_png.cpp
@@ -53,6 +53,8 @@ pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length)
 bool
 Image::writePNG(std::ostream &os) const
 {
+    assert(bpp == 8);
+
     png_structp png_ptr;
     png_infop info_ptr;
     int color_type;
diff --git a/image/image_pnm.cpp b/image/image_pnm.cpp
index f9cd05d..f14c3f2 100644
--- a/image/image_pnm.cpp
+++ b/image/image_pnm.cpp
@@ -42,6 +42,7 @@ namespace image {
 void
 Image::writePNM(std::ostream &os, const char *comment) const {
     assert(channels == 1 || channels >= 3);
+    assert(bpp == 8);
 
     os << (channels == 1 ? "P5" : "P6") << "\n";
     if (comment) {
diff --git a/image/image_raw.cpp b/image/image_raw.cpp
index dd45d10..5e27999 100644
--- a/image/image_raw.cpp
+++ b/image/image_raw.cpp
@@ -40,7 +40,7 @@ Image::writeRAW(std::ostream &os) const {
     const unsigned char *row;
 
     for (row = start(); row != end(); row += stride()) {
-        os.write((const char *)row, width*channels);
+        os.write((const char *)row, rowsize());
     }
 }
 
diff --git a/retrace/d3dretrace.hpp b/retrace/d3dretrace.hpp
index 41cc1c5..2fa2985 100644
--- a/retrace/d3dretrace.hpp
+++ b/retrace/d3dretrace.hpp
@@ -51,7 +51,7 @@ public:
     {}
 
     image::Image *
-    getSnapshot(void) {
+    getSnapshot(bool raw) {
         if (!pLastDevice) {
             return NULL;
         }
diff --git a/retrace/glretrace_main.cpp b/retrace/glretrace_main.cpp
index d215133..f2d95a0 100755
--- a/retrace/glretrace_main.cpp
+++ b/retrace/glretrace_main.cpp
@@ -428,11 +428,11 @@ debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsi
 class GLDumper : public retrace::Dumper {
 public:
     image::Image *
-    getSnapshot(void) {
+    getSnapshot(bool raw) {
         if (!glretrace::getCurrentContext()) {
             return NULL;
         }
-        return glstate::getDrawBufferImage();
+        return glstate::getDrawBufferImage(raw);
     }
 
     bool
diff --git a/retrace/glstate.hpp b/retrace/glstate.hpp
index 6fb615f..ea8c7e2 100644
--- a/retrace/glstate.hpp
+++ b/retrace/glstate.hpp
@@ -45,7 +45,7 @@ const char *enumToString(GLenum pname);
 void dumpCurrentContext(std::ostream &os);
 
 image::Image *
-getDrawBufferImage(void);
+getDrawBufferImage(bool raw);
 
 
 } /* namespace glstate */
diff --git a/retrace/glstate_images.cpp b/retrace/glstate_images.cpp
index 6efc0a6..adb406b 100644
--- a/retrace/glstate_images.cpp
+++ b/retrace/glstate_images.cpp
@@ -74,6 +74,7 @@ struct ImageDesc
     GLint depth;
     GLint samples;
     GLint internalFormat;
+    GLint type;  // of the red or depth component
 
     inline
     ImageDesc() :
@@ -125,6 +126,176 @@ formatToString(GLenum internalFormat) {
 }
 
 
+struct InternalFormatDesc
+{
+    GLenum internalFormat;
+    GLenum format;
+    GLenum type;  // GL_NONE if no specific type is implied
+};
+
+
+static const InternalFormatDesc
+internalFormatDescs[] = {
+
+    {1,	GL_RED,	GL_NONE},
+    {2,	GL_RG,	GL_NONE},
+    {3,	GL_RGB,	GL_NONE},
+    {4,	GL_RGBA,	GL_NONE},
+
+    {GL_RED,	GL_RED,	GL_NONE},
+    {GL_GREEN,	GL_GREEN,	GL_NONE},
+    {GL_BLUE,	GL_BLUE,	GL_NONE},
+    {GL_ALPHA,	GL_ALPHA,	GL_NONE},
+    {GL_RG,	GL_RG,	GL_NONE},
+    {GL_RGB,	GL_RGB,	GL_NONE},
+    {GL_BGR,	GL_RGB,	GL_NONE},
+    {GL_RGBA,	GL_RGBA,	GL_NONE},
+    {GL_BGRA,	GL_RGBA,	GL_NONE},
+    {GL_LUMINANCE,	GL_LUMINANCE,	GL_NONE},
+    {GL_LUMINANCE_ALPHA,	GL_LUMINANCE_ALPHA,	GL_NONE},
+    {GL_INTENSITY,	GL_INTENSITY,	GL_NONE},
+ 
+    {GL_R8,	GL_RED,	GL_UNSIGNED_BYTE},
+    {GL_R16,	GL_RED,	GL_UNSIGNED_SHORT},
+    {GL_RG8,	GL_RG,	GL_UNSIGNED_BYTE},
+    {GL_RG16,	GL_RG,	GL_UNSIGNED_SHORT},
+    {GL_R3_G3_B2,	GL_RGB,	GL_UNSIGNED_BYTE_3_3_2},
+    {GL_RGB4,	GL_RGB,	GL_UNSIGNED_SHORT_4_4_4_4},
+    {GL_RGB5,	GL_RGB,	GL_UNSIGNED_SHORT_5_5_5_1},
+    {GL_RGB8,	GL_RGB,	GL_UNSIGNED_BYTE},
+    {GL_RGB10,	GL_RGBA,	GL_UNSIGNED_INT_10_10_10_2},
+    {GL_RGB16,	GL_RGB,	GL_UNSIGNED_SHORT},
+    {GL_RGBA4,	GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4},
+    {GL_RGBA8,	GL_RGBA,	GL_UNSIGNED_BYTE},
+    {GL_RGBA16,	GL_RGBA,	GL_UNSIGNED_SHORT},
+    {GL_RGB10_A2,	GL_RGBA,	GL_UNSIGNED_INT_10_10_10_2},
+    {GL_LUMINANCE8,	GL_LUMINANCE,	GL_UNSIGNED_BYTE},
+    {GL_LUMINANCE16,	GL_LUMINANCE,	GL_UNSIGNED_SHORT},
+    {GL_ALPHA8,	GL_ALPHA,	GL_UNSIGNED_BYTE},
+    {GL_ALPHA16,	GL_ALPHA,	GL_UNSIGNED_SHORT},
+    {GL_LUMINANCE8_ALPHA8,	GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE},
+    {GL_LUMINANCE16_ALPHA16,	GL_LUMINANCE_ALPHA,	GL_UNSIGNED_SHORT},
+    {GL_INTENSITY8,	GL_INTENSITY,	GL_UNSIGNED_BYTE},
+    {GL_INTENSITY16,	GL_INTENSITY,	GL_UNSIGNED_SHORT},
+    
+    {GL_RED_INTEGER,	GL_RED_INTEGER,	GL_NONE},
+    {GL_GREEN_INTEGER,	GL_GREEN_INTEGER,	GL_NONE},
+    {GL_BLUE_INTEGER,	GL_BLUE_INTEGER,	GL_NONE},
+    {GL_ALPHA_INTEGER,	GL_ALPHA_INTEGER,	GL_NONE},
+    {GL_RG_INTEGER,	GL_RG_INTEGER,	GL_NONE},
+    {GL_RGB_INTEGER,	GL_RGB_INTEGER,	GL_NONE},
+    {GL_BGR_INTEGER,	GL_RGB_INTEGER,	GL_NONE},
+    {GL_RGBA_INTEGER,	GL_RGBA_INTEGER,	GL_NONE},
+    {GL_BGRA_INTEGER,	GL_RGBA_INTEGER,	GL_NONE},
+    {GL_LUMINANCE_INTEGER_EXT,	GL_LUMINANCE_INTEGER_EXT,	GL_NONE},
+    {GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_NONE},
+ 
+    {GL_R8I,	GL_RED_INTEGER,	GL_BYTE},
+    {GL_R8UI,	GL_RED_INTEGER,	GL_UNSIGNED_BYTE},
+    {GL_R16I,	GL_RED_INTEGER,	GL_SHORT},
+    {GL_R16UI,	GL_RED_INTEGER,	GL_UNSIGNED_SHORT},
+    {GL_R32I,	GL_RED_INTEGER,	GL_INT},
+    {GL_R32UI,	GL_RED_INTEGER,	GL_UNSIGNED_INT},
+    {GL_RG8I,	GL_RG_INTEGER,	GL_BYTE},
+    {GL_RG8UI,	GL_RG_INTEGER,	GL_UNSIGNED_BYTE},
+    {GL_RG16I,	GL_RG_INTEGER,	GL_SHORT},
+    {GL_RG16UI,	GL_RG_INTEGER,	GL_UNSIGNED_SHORT},
+    {GL_RG32I,	GL_RG_INTEGER,	GL_INT},
+    {GL_RG32UI,	GL_RG_INTEGER,	GL_UNSIGNED_INT},
+    {GL_RGB8I,	GL_RGB_INTEGER,	GL_BYTE},
+    {GL_RGB8UI,	GL_RGB_INTEGER,	GL_UNSIGNED_BYTE},
+    {GL_RGB16I,	GL_RGB_INTEGER,	GL_SHORT},
+    {GL_RGB16UI,	GL_RGB_INTEGER,	GL_UNSIGNED_SHORT},
+    {GL_RGB32I,	GL_RGB_INTEGER,	GL_INT},
+    {GL_RGB32UI,	GL_RGB_INTEGER,	GL_UNSIGNED_INT},
+    {GL_RGBA8I,	GL_RGBA_INTEGER,	GL_BYTE},
+    {GL_RGBA8UI,	GL_RGBA_INTEGER,	GL_UNSIGNED_BYTE},
+    {GL_RGBA16I,	GL_RGBA_INTEGER,	GL_SHORT},
+    {GL_RGBA16UI,	GL_RGBA_INTEGER,	GL_UNSIGNED_SHORT},
+    {GL_RGBA32I,	GL_RGBA_INTEGER,	GL_INT},
+    {GL_RGBA32UI,	GL_RGBA_INTEGER,	GL_UNSIGNED_INT},
+    {GL_RGB10_A2UI,	GL_RGBA_INTEGER,	GL_UNSIGNED_INT_10_10_10_2},
+    {GL_LUMINANCE8I_EXT,	GL_LUMINANCE_INTEGER_EXT,	GL_BYTE},
+    {GL_LUMINANCE8UI_EXT,	GL_LUMINANCE_INTEGER_EXT,	GL_UNSIGNED_BYTE},
+    {GL_LUMINANCE16I_EXT,	GL_LUMINANCE_INTEGER_EXT,	GL_SHORT},
+    {GL_LUMINANCE16UI_EXT,	GL_LUMINANCE_INTEGER_EXT,	GL_UNSIGNED_SHORT},
+    {GL_LUMINANCE32I_EXT,	GL_LUMINANCE_INTEGER_EXT,	GL_INT},
+    {GL_LUMINANCE32UI_EXT,	GL_LUMINANCE_INTEGER_EXT,	GL_UNSIGNED_INT},
+    {GL_ALPHA8I_EXT,	GL_ALPHA_INTEGER_EXT,	GL_BYTE},
+    {GL_ALPHA8UI_EXT,	GL_ALPHA_INTEGER_EXT,	GL_UNSIGNED_BYTE},
+    {GL_ALPHA16I_EXT,	GL_ALPHA_INTEGER_EXT,	GL_SHORT},
+    {GL_ALPHA16UI_EXT,	GL_ALPHA_INTEGER_EXT,	GL_UNSIGNED_SHORT},
+    {GL_ALPHA32I_EXT,	GL_ALPHA_INTEGER_EXT,	GL_INT},
+    {GL_ALPHA32UI_EXT,	GL_ALPHA_INTEGER_EXT,	GL_UNSIGNED_INT},
+    {GL_LUMINANCE_ALPHA8I_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_BYTE},
+    {GL_LUMINANCE_ALPHA8UI_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_UNSIGNED_BYTE},
+    {GL_LUMINANCE_ALPHA16I_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_SHORT},
+    {GL_LUMINANCE_ALPHA16UI_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_UNSIGNED_SHORT},
+    {GL_LUMINANCE_ALPHA32I_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_INT},
+    {GL_LUMINANCE_ALPHA32UI_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_UNSIGNED_INT},
+    {GL_INTENSITY8I_EXT,	GL_RED_INTEGER,	GL_BYTE},
+    {GL_INTENSITY8UI_EXT,	GL_RED_INTEGER,	GL_UNSIGNED_BYTE},
+    {GL_INTENSITY16I_EXT,	GL_RED_INTEGER,	GL_SHORT},
+    {GL_INTENSITY16UI_EXT,	GL_RED_INTEGER,	GL_UNSIGNED_SHORT},
+    {GL_INTENSITY32I_EXT,	GL_RED_INTEGER,	GL_INT},
+    {GL_INTENSITY32UI_EXT,	GL_RED_INTEGER,	GL_UNSIGNED_INT},
+
+    {GL_R16F,	GL_RED,	GL_HALF_FLOAT},
+    {GL_R32F,	GL_RED,	GL_FLOAT},
+    {GL_RG16F,	GL_RG,	GL_HALF_FLOAT},
+    {GL_RG32F,	GL_RG,	GL_FLOAT},
+    {GL_RGB16F,	GL_RGB,	GL_HALF_FLOAT},
+    {GL_RGB32F,	GL_RGB,	GL_FLOAT},
+    {GL_RGBA16F,	GL_RGBA,	GL_HALF_FLOAT},
+    {GL_RGBA32F,	GL_RGBA,	GL_FLOAT},
+    {GL_R11F_G11F_B10F,	GL_RGB,	GL_UNSIGNED_INT_10F_11F_11F_REV},
+    {GL_RGB9_E5,	GL_RGB,	GL_UNSIGNED_INT_5_9_9_9_REV},
+    {GL_LUMINANCE16F_ARB,	GL_LUMINANCE,	GL_HALF_FLOAT},
+    {GL_LUMINANCE32F_ARB,	GL_LUMINANCE,	GL_FLOAT},
+    {GL_ALPHA16F_ARB,	GL_ALPHA,	GL_HALF_FLOAT},
+    {GL_ALPHA32F_ARB,	GL_ALPHA,	GL_FLOAT},
+    {GL_LUMINANCE_ALPHA16F_ARB,	GL_LUMINANCE_ALPHA,	GL_HALF_FLOAT},
+    {GL_LUMINANCE_ALPHA16F_ARB,	GL_LUMINANCE_ALPHA,	GL_FLOAT},
+    {GL_INTENSITY16F_ARB,	GL_INTENSITY,	GL_HALF_FLOAT},
+    {GL_INTENSITY32F_ARB,	GL_INTENSITY,	GL_FLOAT},
+    
+    {GL_DEPTH_COMPONENT,	GL_DEPTH_COMPONENT,	GL_NONE},
+    {GL_DEPTH_COMPONENT16,	GL_DEPTH_COMPONENT,	GL_UNSIGNED_SHORT},
+    {GL_DEPTH_COMPONENT24,	GL_DEPTH_COMPONENT,	GL_UNSIGNED_INT},
+    {GL_DEPTH_COMPONENT32,	GL_DEPTH_COMPONENT,	GL_UNSIGNED_INT},
+    {GL_DEPTH_COMPONENT32F,	GL_DEPTH_COMPONENT,	GL_FLOAT},
+    {GL_DEPTH_COMPONENT32F_NV,	GL_DEPTH_COMPONENT,	GL_FLOAT},
+    {GL_DEPTH_STENCIL,	        GL_DEPTH_COMPONENT,	GL_NONE},
+    {GL_DEPTH24_STENCIL8,	GL_DEPTH_COMPONENT,	GL_UNSIGNED_INT_24_8},
+    {GL_DEPTH32F_STENCIL8,	GL_DEPTH_COMPONENT,	GL_FLOAT_32_UNSIGNED_INT_24_8_REV},
+    {GL_DEPTH32F_STENCIL8_NV,	GL_DEPTH_COMPONENT,	GL_FLOAT_32_UNSIGNED_INT_24_8_REV},
+};
+
+
+static GLenum
+getFormat(GLenum internalFormat)
+{
+    for (unsigned i = 0; i < sizeof internalFormatDescs / sizeof internalFormatDescs[0]; ++i) {
+        if (internalFormatDescs[i].internalFormat == internalFormat) {
+            return internalFormatDescs[i].format;
+        }
+    }
+    return GL_RGBA;
+}
+
+
+static GLenum
+getType(GLenum internalFormat)
+{
+    for (unsigned i = 0; i < sizeof internalFormatDescs / sizeof internalFormatDescs[0]; ++i) {
+        if (internalFormatDescs[i].internalFormat == internalFormat) {
+            return internalFormatDescs[i].type;
+        }
+    }
+    return GL_NONE;
+}
+
+
 /**
  * OpenGL ES does not support glGetTexLevelParameteriv, but it is possible to
  * probe whether a texture has a given size by crafting a dummy glTexSubImage()
@@ -223,6 +394,7 @@ getActiveTextureLevelDescOES(Context &context, GLenum target, GLint level, Image
 
     // XXX: mere guess
     desc.internalFormat = GL_RGBA;
+    desc.type = GL_UNSIGNED_BYTE;
 
     GLint maxSize = 0;
     switch (target) {
@@ -277,6 +449,12 @@ getActiveTextureLevelDesc(Context &context, GLenum target, GLint level, ImageDes
 
     glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &desc.internalFormat);
 
+    if (getFormat(desc.internalFormat) == GL_DEPTH_COMPONENT) {
+        glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH_TYPE, &desc.type);
+    } else {
+        glGetTexLevelParameteriv(target, level, GL_TEXTURE_RED_TYPE, &desc.type);
+    }
+
     desc.width = 0;
     glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &desc.width);
 
@@ -392,137 +570,6 @@ getTexImageOES(GLenum target, GLint level, ImageDesc &desc, GLubyte *pixels)
 }
 
 
-struct InternalFormatDesc
-{
-    GLenum internalFormat;
-    GLenum format;
-};
-
-
-static const InternalFormatDesc
-internalFormatDescs[] = {
-
-    {1,	GL_RED},
-    {2,	GL_RG},
-    {3,	GL_RGB},
-    {4,	GL_RGBA},
-
-    {GL_RED,	GL_RED},
-    {GL_GREEN,	GL_GREEN},
-    {GL_BLUE,	GL_BLUE},
-    {GL_ALPHA,	GL_ALPHA},
-    {GL_RG,	GL_RG},
-    {GL_RGB,	GL_RGB},
-    {GL_BGR,	GL_RGB},
-    {GL_RGBA,	GL_RGBA},
-    {GL_BGRA,	GL_RGBA},
-    {GL_LUMINANCE,	GL_LUMINANCE},
-    {GL_LUMINANCE_ALPHA,	GL_LUMINANCE_ALPHA},
-    {GL_INTENSITY,	GL_INTENSITY},
- 
-    {GL_RG8,	GL_RG},
-    {GL_RG16,	GL_RG},
-    {GL_RGB8,	GL_RGB},
-    {GL_RGB16,	GL_RGB},
-    {GL_RGBA8,	GL_RGBA},
-    {GL_RGBA16,	GL_RGBA},
-    {GL_RGB10_A2,	GL_RGBA},
-    {GL_LUMINANCE8,	GL_LUMINANCE},
-    {GL_LUMINANCE16,	GL_LUMINANCE},
-    {GL_ALPHA8,	GL_ALPHA},
-    {GL_ALPHA16,	GL_ALPHA},
-    {GL_LUMINANCE8_ALPHA8,	GL_LUMINANCE_ALPHA},
-    {GL_LUMINANCE16_ALPHA16,	GL_LUMINANCE_ALPHA},
-    {GL_INTENSITY8,	GL_INTENSITY},
-    {GL_INTENSITY16,	GL_INTENSITY},
-    
-    {GL_RED_INTEGER,	GL_RED_INTEGER},
-    {GL_GREEN_INTEGER,	GL_GREEN_INTEGER},
-    {GL_BLUE_INTEGER,	GL_BLUE_INTEGER},
-    {GL_ALPHA_INTEGER,	GL_ALPHA_INTEGER},
-    {GL_RG_INTEGER,	GL_RG_INTEGER},
-    {GL_RGB_INTEGER,	GL_RGB_INTEGER},
-    {GL_BGR_INTEGER,	GL_RGB_INTEGER},
-    {GL_RGBA_INTEGER,	GL_RGBA_INTEGER},
-    {GL_BGRA_INTEGER,	GL_RGBA_INTEGER},
-    {GL_LUMINANCE_INTEGER_EXT,	GL_LUMINANCE_INTEGER_EXT},
-    {GL_LUMINANCE_ALPHA_INTEGER_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT},
- 
-    {GL_R8I,	GL_RED_INTEGER},
-    {GL_R8UI,	GL_RED_INTEGER},
-    {GL_R16I,	GL_RED_INTEGER},
-    {GL_R16UI,	GL_RED_INTEGER},
-    {GL_R32I,	GL_RED_INTEGER},
-    {GL_R32UI,	GL_RED_INTEGER},
-    {GL_RG8I,	GL_RG_INTEGER},
-    {GL_RG8UI,	GL_RG_INTEGER},
-    {GL_RG16I,	GL_RG_INTEGER},
-    {GL_RG16UI,	GL_RG_INTEGER},
-    {GL_RG32I,	GL_RG_INTEGER},
-    {GL_RG32UI,	GL_RG_INTEGER},
-    {GL_RGB8I,	GL_RGB_INTEGER},
-    {GL_RGB8UI,	GL_RGB_INTEGER},
-    {GL_RGB16I,	GL_RGB_INTEGER},
-    {GL_RGB16UI,	GL_RGB_INTEGER},
-    {GL_RGB32I,	GL_RGB_INTEGER},
-    {GL_RGB32UI,	GL_RGB_INTEGER},
-    {GL_RGBA8I,	GL_RGBA_INTEGER},
-    {GL_RGBA8UI,	GL_RGBA_INTEGER},
-    {GL_RGBA16I,	GL_RGBA_INTEGER},
-    {GL_RGBA16UI,	GL_RGBA_INTEGER},
-    {GL_RGBA32I,	GL_RGBA_INTEGER},
-    {GL_RGBA32UI,	GL_RGBA_INTEGER},
-    {GL_RGB10_A2UI,	GL_RGBA_INTEGER},
-    {GL_LUMINANCE8I_EXT,	GL_LUMINANCE_INTEGER_EXT},
-    {GL_LUMINANCE8UI_EXT,	GL_LUMINANCE_INTEGER_EXT},
-    {GL_LUMINANCE16I_EXT,	GL_LUMINANCE_INTEGER_EXT},
-    {GL_LUMINANCE16UI_EXT,	GL_LUMINANCE_INTEGER_EXT},
-    {GL_LUMINANCE32I_EXT,	GL_LUMINANCE_INTEGER_EXT},
-    {GL_LUMINANCE32UI_EXT,	GL_LUMINANCE_INTEGER_EXT},
-    {GL_ALPHA8I_EXT,	GL_ALPHA_INTEGER_EXT},
-    {GL_ALPHA8UI_EXT,	GL_ALPHA_INTEGER_EXT},
-    {GL_ALPHA16I_EXT,	GL_ALPHA_INTEGER_EXT},
-    {GL_ALPHA16UI_EXT,	GL_ALPHA_INTEGER_EXT},
-    {GL_ALPHA32I_EXT,	GL_ALPHA_INTEGER_EXT},
-    {GL_ALPHA32UI_EXT,	GL_ALPHA_INTEGER_EXT},
-    {GL_LUMINANCE_ALPHA8I_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT},
-    {GL_LUMINANCE_ALPHA8UI_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT},
-    {GL_LUMINANCE_ALPHA16I_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT},
-    {GL_LUMINANCE_ALPHA16UI_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT},
-    {GL_LUMINANCE_ALPHA32I_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT},
-    {GL_LUMINANCE_ALPHA32UI_EXT,	GL_LUMINANCE_ALPHA_INTEGER_EXT},
-    {GL_INTENSITY8I_EXT,	GL_RED_INTEGER},
-    {GL_INTENSITY8UI_EXT,	GL_RED_INTEGER},
-    {GL_INTENSITY16I_EXT,	GL_RED_INTEGER},
-    {GL_INTENSITY16UI_EXT,	GL_RED_INTEGER},
-    {GL_INTENSITY32I_EXT,	GL_RED_INTEGER},
-    {GL_INTENSITY32UI_EXT,	GL_RED_INTEGER},
-    
-    {GL_DEPTH_COMPONENT,	GL_DEPTH_COMPONENT},
-    {GL_DEPTH_COMPONENT16,	GL_DEPTH_COMPONENT},
-    {GL_DEPTH_COMPONENT24,	GL_DEPTH_COMPONENT},
-    {GL_DEPTH_COMPONENT32,	GL_DEPTH_COMPONENT},
-    {GL_DEPTH_COMPONENT32F,	GL_DEPTH_COMPONENT},
-    {GL_DEPTH_COMPONENT32F_NV,	GL_DEPTH_COMPONENT},
-    {GL_DEPTH_STENCIL,	        GL_DEPTH_COMPONENT},
-    {GL_DEPTH24_STENCIL8,	GL_DEPTH_COMPONENT},
-    {GL_DEPTH32F_STENCIL8,	GL_DEPTH_COMPONENT},
-    {GL_DEPTH32F_STENCIL8_NV,	GL_DEPTH_COMPONENT},
-};
-
-
-static GLenum
-getFormat(GLenum internalFormat)
-{
-    for (unsigned i = 0; i < sizeof internalFormatDescs / sizeof internalFormatDescs[0]; ++i) {
-        if (internalFormatDescs[i].internalFormat == internalFormat) {
-            return internalFormatDescs[i].format;
-        }
-    }
-    return GL_RGBA;
-}
-
-
 static inline void
 dumpActiveTextureLevel(JSONWriter &json, Context &context, GLenum target, GLint level)
 {
@@ -875,13 +922,7 @@ getFramebufferAttachmentDesc(Context &context, GLenum target, GLenum attachment,
 
 
 image::Image *
-getDrawBufferImage() {
-    GLenum format = GL_RGB;
-    GLint channels = _gl_format_channels(format);
-    if (channels > 4) {
-        return NULL;
-    }
-
+getDrawBufferImage(bool raw) {
     Context context;
 
     GLenum framebuffer_binding;
@@ -934,16 +975,82 @@ getDrawBufferImage() {
         desc.depth = 1;
     }
 
+    GLenum format = raw ? getFormat(desc.internalFormat) : GL_RGB;
+
+    GLint channels = _gl_format_channels(format);
+    if (channels > 4) {
+        return NULL;
+    }
+
     GLenum type = GL_UNSIGNED_BYTE;
+    unsigned bpp = 8;
+
+    if (raw) {
+        type = getType(desc.internalFormat);
+        if (type == GL_NONE) {
+            type = desc.type;
+        }
+        switch (type) {
+        case GL_UNSIGNED_BYTE:
+        case GL_BYTE:
+            bpp = 8;
+            break;
+        case GL_UNSIGNED_BYTE_3_3_2:
+        case GL_UNSIGNED_BYTE_2_3_3_REV:
+            bpp = 8;
+            channels = 1;
+            break;
+        case GL_UNSIGNED_SHORT:
+        case GL_SHORT:
+        case GL_HALF_FLOAT:
+            bpp = 16;
+            break;
+        case GL_UNSIGNED_SHORT_5_6_5:
+        case GL_UNSIGNED_SHORT_5_6_5_REV:
+        case GL_UNSIGNED_SHORT_4_4_4_4:
+        case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+        case GL_UNSIGNED_SHORT_5_5_5_1:
+        case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+            bpp = 16;
+            channels = 1;
+            break;
+        case GL_UNSIGNED_INT:
+        case GL_INT:
+        case GL_FLOAT:
+            bpp = 32;
+            break;
+        case GL_UNSIGNED_INT_8_8_8_8:
+        case GL_UNSIGNED_INT_8_8_8_8_REV:
+        case GL_UNSIGNED_INT_10_10_10_2:
+        case GL_UNSIGNED_INT_2_10_10_10_REV:
+        case GL_UNSIGNED_INT_24_8:
+        case GL_UNSIGNED_INT_10F_11F_11F_REV:
+        case GL_UNSIGNED_INT_5_9_9_9_REV:
+            bpp = 32;
+            channels = 1;
+            break;
+        case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+            bpp = 64;
+            channels = 1;
+            break;
+        default:
+            std::cerr << "warning: unknown type " << enumToString(type) << ", using UNSIGNED_BYTE\n";
+            type = GL_UNSIGNED_BYTE;
+            bpp = 8;
+            break;
+        }
+    }
+
 
 #if DEPTH_AS_RGBA
     if (format == GL_DEPTH_COMPONENT) {
         type = GL_UNSIGNED_INT;
         channels = 4;
+        bpp = 8;
     }
 #endif
 
-    image::Image *image = new image::Image(desc.width, desc.height, channels, true);
+    image::Image *image = new image::Image(desc.width, desc.height, channels, true, bpp);
     if (!image) {
         return NULL;
     }
diff --git a/retrace/retrace.hpp b/retrace/retrace.hpp
index 6e6bf13..4518d1c 100644
--- a/retrace/retrace.hpp
+++ b/retrace/retrace.hpp
@@ -173,7 +173,7 @@ class Dumper
 {
 public:
     virtual image::Image *
-    getSnapshot(void) {
+    getSnapshot(bool raw) {
         return NULL;
     }
 
diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp
index bff8983..70fb3a8 100644
--- a/retrace/retrace_main.cpp
+++ b/retrace/retrace_main.cpp
@@ -50,7 +50,8 @@ static bool loopOnFinish = false;
 static const char *snapshotPrefix = NULL;
 static enum {
     PNM_FMT,
-    RAW_RGB
+    RAW_RGB,
+    RAW_DATA
 } snapshotFormat = PNM_FMT;
 
 static trace::CallSet snapshotFrequency;
@@ -110,7 +111,7 @@ takeSnapshot(unsigned call_no) {
 
     assert(snapshotPrefix);
 
-    image::Image *src = dumper->getSnapshot();
+    image::Image *src = dumper->getSnapshot(snapshotFormat == RAW_DATA);
     if (!src) {
         std::cerr << call_no << ": warning: failed to get snapshot\n";
         return;
@@ -121,7 +122,7 @@ takeSnapshot(unsigned call_no) {
             char comment[21];
             snprintf(comment, sizeof comment, "%u",
                      useCallNos ? call_no : snapshot_no);
-            if (snapshotFormat == RAW_RGB)
+            if (snapshotFormat == RAW_RGB || snapshotFormat == RAW_DATA)
                 src->writeRAW(std::cout);
             else
                 src->writePNM(std::cout, comment);
@@ -701,6 +702,8 @@ int main(int argc, char **argv)
 	case SNAPSHOT_FORMAT_OPT:
             if (strcmp(optarg, "RGB") == 0)
                 snapshotFormat = RAW_RGB;
+            else if (strcmp(optarg, "RAW") == 0)
+                snapshotFormat = RAW_DATA;
             else
                 snapshotFormat = PNM_FMT;
             break;
