diff options
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 34 | ||||
-rw-r--r-- | image/bmp.cpp | 55 | ||||
-rw-r--r-- | image/bmp.h | 9 |
3 files changed, 68 insertions, 30 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index cfddc93e2f..ad6094b9a1 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -46,6 +46,8 @@ #ifdef USE_PNG #include "image/png.h" +#else +#include "image/bmp.h" #endif namespace OpenGL { @@ -1212,41 +1214,13 @@ bool OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const pixels.resize(lineSize * height); GL_CALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, &pixels.front())); -#ifdef USE_PNG const Graphics::PixelFormat format(3, 8, 8, 8, 0, 16, 8, 0, 0); Graphics::Surface data; data.init(width, height, lineSize, &pixels.front(), format); +#ifdef USE_PNG return Image::writePNG(out, data, true); #else - // BMP stores as BGR. Since we can't assume that GL_BGR is supported we - // will swap the components from the RGB we read to BGR on our own. - for (uint y = height; y-- > 0;) { - uint8 *line = &pixels.front() + y * lineSize; - - for (uint x = width; x > 0; --x, line += 3) { - SWAP(line[0], line[2]); - } - } - - out.writeByte('B'); - out.writeByte('M'); - out.writeUint32LE(height * lineSize + 54); - out.writeUint32LE(0); - out.writeUint32LE(54); - out.writeUint32LE(40); - out.writeUint32LE(width); - out.writeUint32LE(height); - out.writeUint16LE(1); - out.writeUint16LE(24); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.write(&pixels.front(), pixels.size()); - - return true; + return Image::writeBMP(out, data, true); #endif } diff --git a/image/bmp.cpp b/image/bmp.cpp index 28eb049035..ce2b099797 100644 --- a/image/bmp.cpp +++ b/image/bmp.cpp @@ -132,4 +132,59 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) { return true; } +bool writeBMP(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp) { + const Graphics::PixelFormat requiredFormat_3byte(3, 8, 8, 8, 0, 0, 8, 16, 0); + + Graphics::Surface *tmp = NULL; + const Graphics::Surface *surface; + + if (input.format == requiredFormat_3byte) { + surface = &input; + } else { + surface = tmp = input.convertTo(requiredFormat_3byte); + } + + int dstPitch = surface->w * 3; + int extraDataLength = (dstPitch % 4) ? 4 - (dstPitch % 4) : 0; + int padding = 0; + + out.writeByte('B'); + out.writeByte('M'); + out.writeUint32LE(surface->h * dstPitch + 54); + out.writeUint32LE(0); + out.writeUint32LE(54); + out.writeUint32LE(40); + out.writeUint32LE(surface->w); + out.writeUint32LE(surface->h); + out.writeUint16LE(1); + out.writeUint16LE(24); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + + + if (bottomUp) { + for (uint y = 0; y < surface->h; ++y) { + out.write((const void *)surface->getBasePtr(0, y), dstPitch); + out.write(&padding, extraDataLength); + } + } else { + for (uint y = surface->h; y-- > 0;) { + out.write((const void *)surface->getBasePtr(0, y), dstPitch); + out.write(&padding, extraDataLength); + } + } + + // free tmp surface + if (tmp) { + tmp->free(); + delete tmp; + } + + return true; +} + } // End of namespace Image diff --git a/image/bmp.h b/image/bmp.h index b482cc674b..a23f1e0978 100644 --- a/image/bmp.h +++ b/image/bmp.h @@ -37,6 +37,7 @@ namespace Common { class SeekableReadStream; +class WriteStream; } namespace Graphics { @@ -66,6 +67,14 @@ private: uint16 _paletteColorCount; }; +/** + * Outputs an uncompressed BMP stream of the given input surface. + * + * @param bottomUp Flip the vertical axis so pixel data is drawn from the + * bottom up, instead of from the top down. + */ +bool writeBMP(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp = false); + } // End of namespace Image #endif |