From 6846010416479143151cf28962587f5b123888be Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 25 Jul 2016 10:55:53 +0000 Subject: [PATCH] Fix a flip bug in ReadPngIntoPixmap. The only user of that was the background image, and it was flipped again when it was rendered, so the two bugs masked out each other. This adds a `bool flip` to ReadPng and FromPng, since that's cheap to do when writing the PNG file, expensive on the pixel arrays, and sometimes inconvenient in OpenGL due to offsets. --- src/resource.cpp | 14 ++++++++------ src/resource.h | 4 ++-- src/style.cpp | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/resource.cpp b/src/resource.cpp index 6dbcd393..4bd89038 100644 --- a/src/resource.cpp +++ b/src/resource.cpp @@ -87,7 +87,8 @@ RgbaColor Pixmap::GetPixel(size_t x, size_t y) const { ssassert(false, "Unexpected resource format"); } -static std::shared_ptr ReadPngIntoPixmap(png_struct *png_ptr, png_info *info_ptr) { +static std::shared_ptr ReadPngIntoPixmap(png_struct *png_ptr, png_info *info_ptr, + bool flip) { png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB, NULL); std::shared_ptr pixmap = std::make_shared(); @@ -106,7 +107,8 @@ static std::shared_ptr ReadPngIntoPixmap(png_struct *png_ptr, png_info * pixmap->data = std::vector(pixmap->stride * pixmap->height); uint8_t **rows = png_get_rows(png_ptr, info_ptr); for(size_t y = 0; y < pixmap->height; y++) { - memcpy(&pixmap->data[pixmap->stride * y], rows[y], + uint8_t *srcRow = flip ? rows[y] : rows[pixmap->height - y - 1]; + memcpy(&pixmap->data[pixmap->stride * y], srcRow, pixmap->width * pixmap->GetBytesPerPixel()); } @@ -114,7 +116,7 @@ static std::shared_ptr ReadPngIntoPixmap(png_struct *png_ptr, png_info * return pixmap; } -std::shared_ptr Pixmap::FromPng(const uint8_t *data, size_t size) { +std::shared_ptr Pixmap::FromPng(const uint8_t *data, size_t size, bool flip) { struct Slice { const uint8_t *data; size_t size; }; Slice dataSlice = { data, size }; png_struct *png_ptr = NULL; @@ -139,14 +141,14 @@ std::shared_ptr Pixmap::FromPng(const uint8_t *data, size_t size) { } }); - return ReadPngIntoPixmap(png_ptr, info_ptr); + return ReadPngIntoPixmap(png_ptr, info_ptr, flip); exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return nullptr; } -std::shared_ptr Pixmap::ReadPng(FILE *f) { +std::shared_ptr Pixmap::ReadPng(FILE *f, bool flip) { png_struct *png_ptr = NULL; png_info *info_ptr = NULL; @@ -164,7 +166,7 @@ std::shared_ptr Pixmap::ReadPng(FILE *f) { png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, sizeof(header)); - return ReadPngIntoPixmap(png_ptr, info_ptr); + return ReadPngIntoPixmap(png_ptr, info_ptr, flip); exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); diff --git a/src/resource.h b/src/resource.h index 3249f074..aab95069 100644 --- a/src/resource.h +++ b/src/resource.h @@ -33,9 +33,9 @@ public: std::vector data; static std::shared_ptr Create(Format format, size_t width, size_t height); - static std::shared_ptr FromPng(const uint8_t *data, size_t size); + static std::shared_ptr FromPng(const uint8_t *data, size_t size, bool flip = false); - static std::shared_ptr ReadPng(FILE *f); + static std::shared_ptr ReadPng(FILE *f, bool flip = false); bool WritePng(FILE *f, bool flip = false); size_t GetBytesPerPixel() const; diff --git a/src/style.cpp b/src/style.cpp index 9d8ffaed..8e0c9b9f 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -371,7 +371,7 @@ void TextWindow::ScreenBackgroundImage(int link, uint32_t v) { if(GetOpenFile(&bgImageFile, "", PngFileFilter)) { FILE *f = ssfopen(bgImageFile, "rb"); if(f) { - SS.bgImage.pixmap = Pixmap::ReadPng(f); + SS.bgImage.pixmap = Pixmap::ReadPng(f, /*flip=*/true); SS.bgImage.scale = SS.GW.scale; SS.bgImage.origin = SS.GW.offset.ScaledBy(-1); fclose(f);