aboutsummaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
authorColin Snover2017-05-12 12:44:44 -0500
committerColin Snover2017-05-21 15:55:39 -0500
commitfa0bb7dd5a60c8f323ecbd5e190ad705bec3e934 (patch)
tree3d7006e16ca0aeeca20b85c7258e979ed07756cb /image
parent71989715d02075ebedfd72e4ec5704b3beb91cca (diff)
downloadscummvm-rg350-fa0bb7dd5a60c8f323ecbd5e190ad705bec3e934.tar.gz
scummvm-rg350-fa0bb7dd5a60c8f323ecbd5e190ad705bec3e934.tar.bz2
scummvm-rg350-fa0bb7dd5a60c8f323ecbd5e190ad705bec3e934.zip
BACKENDS: Compress screenshots using PNG if available
Closes gh-948.
Diffstat (limited to 'image')
-rw-r--r--image/png.cpp67
-rw-r--r--image/png.h9
2 files changed, 75 insertions, 1 deletions
diff --git a/image/png.cpp b/image/png.cpp
index dffd512b88..37617a1690 100644
--- a/image/png.cpp
+++ b/image/png.cpp
@@ -34,6 +34,7 @@
#include "graphics/pixelformat.h"
#include "graphics/surface.h"
+#include "common/array.h"
#include "common/stream.h"
namespace Image {
@@ -65,12 +66,24 @@ void pngWarning(png_structp pngptr, png_const_charp warningMsg) {
warning("%s", warningMsg);
}
-// libpng-I/O-helper:
+// libpng-I/O-helpers:
void pngReadFromStream(png_structp pngPtr, png_bytep data, png_size_t length) {
void *readIOptr = png_get_io_ptr(pngPtr);
Common::SeekableReadStream *stream = (Common::SeekableReadStream *)readIOptr;
stream->read(data, length);
}
+
+void pngWriteToStream(png_structp pngPtr, png_bytep data, png_size_t length) {
+ void *writeIOptr = png_get_io_ptr(pngPtr);
+ Common::WriteStream *stream = (Common::WriteStream *)writeIOptr;
+ stream->write(data, length);
+}
+
+void pngFlushStream(png_structp pngPtr) {
+ void *writeIOptr = png_get_io_ptr(pngPtr);
+ Common::WriteStream *stream = (Common::WriteStream *)writeIOptr;
+ stream->flush();
+}
#endif
/*
@@ -232,4 +245,56 @@ bool PNGDecoder::loadStream(Common::SeekableReadStream &stream) {
#endif
}
+bool writePNG(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp) {
+#ifdef USE_PNG
+ const Graphics::PixelFormat requiredFormat(3, 8, 8, 8, 0, 16, 8, 0, 0);
+
+ if (input.format != requiredFormat) {
+ warning("Cannot currently write PNG with pixel format other than %s", requiredFormat.toString().c_str());
+ return false;
+ }
+
+ png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!pngPtr) {
+ return false;
+ }
+ png_infop infoPtr = png_create_info_struct(pngPtr);
+ if (!infoPtr) {
+ png_destroy_write_struct(&pngPtr, NULL);
+ return false;
+ }
+ png_infop endInfo = png_create_info_struct(pngPtr);
+ if (!endInfo) {
+ png_destroy_write_struct(&pngPtr, &infoPtr);
+ return false;
+ }
+
+ png_set_error_fn(pngPtr, NULL, pngError, pngWarning);
+ // TODO: The manual says errors should be handled via setjmp
+
+ png_set_write_fn(pngPtr, &out, pngWriteToStream, pngFlushStream);
+
+ png_set_IHDR(pngPtr, infoPtr, input.w, input.h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+ Common::Array<const uint8 *> rows;
+ rows.reserve(input.h);
+ if (bottomUp) {
+ for (uint y = input.h; y-- > 0;) {
+ rows.push_back((const uint8 *)input.getBasePtr(0, y));
+ }
+ } else {
+ for (uint y = 0; y < input.h; ++y) {
+ rows.push_back((const uint8 *)input.getBasePtr(0, y));
+ }
+ }
+
+ png_set_rows(pngPtr, infoPtr, const_cast<uint8 **>(&rows.front()));
+ png_write_png(pngPtr, infoPtr, 0, NULL);
+ png_destroy_write_struct(&pngPtr, &infoPtr);
+ return true;
+#else
+ return false;
+#endif
+}
+
} // End of namespace Image
diff --git a/image/png.h b/image/png.h
index b7ac91a3d2..7ecf68e76d 100644
--- a/image/png.h
+++ b/image/png.h
@@ -37,6 +37,7 @@
namespace Common {
class SeekableReadStream;
+class WriteStream;
}
namespace Graphics {
@@ -62,6 +63,14 @@ private:
Graphics::Surface *_outputSurface;
};
+/**
+ * Outputs a compressed PNG 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 writePNG(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp = false);
+
} // End of namespace Image
#endif