IMAGE: Move bitmap writing code out of OpenGLGraphicsManager

This commit is contained in:
Cameron Cawley 2019-03-01 00:15:43 +00:00 committed by Bastien Bouclet
parent fd1162cb71
commit 8ae17b481a
3 changed files with 68 additions and 30 deletions

View file

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

View file

@ -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

View file

@ -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