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.pull/33/head
parent
0c90cd799d
commit
6846010416
|
@ -87,7 +87,8 @@ RgbaColor Pixmap::GetPixel(size_t x, size_t y) const {
|
||||||
ssassert(false, "Unexpected resource format");
|
ssassert(false, "Unexpected resource format");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<Pixmap> ReadPngIntoPixmap(png_struct *png_ptr, png_info *info_ptr) {
|
static std::shared_ptr<Pixmap> 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);
|
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB, NULL);
|
||||||
|
|
||||||
std::shared_ptr<Pixmap> pixmap = std::make_shared<Pixmap>();
|
std::shared_ptr<Pixmap> pixmap = std::make_shared<Pixmap>();
|
||||||
|
@ -106,7 +107,8 @@ static std::shared_ptr<Pixmap> ReadPngIntoPixmap(png_struct *png_ptr, png_info *
|
||||||
pixmap->data = std::vector<uint8_t>(pixmap->stride * pixmap->height);
|
pixmap->data = std::vector<uint8_t>(pixmap->stride * pixmap->height);
|
||||||
uint8_t **rows = png_get_rows(png_ptr, info_ptr);
|
uint8_t **rows = png_get_rows(png_ptr, info_ptr);
|
||||||
for(size_t y = 0; y < pixmap->height; y++) {
|
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());
|
pixmap->width * pixmap->GetBytesPerPixel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +116,7 @@ static std::shared_ptr<Pixmap> ReadPngIntoPixmap(png_struct *png_ptr, png_info *
|
||||||
return pixmap;
|
return pixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Pixmap> Pixmap::FromPng(const uint8_t *data, size_t size) {
|
std::shared_ptr<Pixmap> Pixmap::FromPng(const uint8_t *data, size_t size, bool flip) {
|
||||||
struct Slice { const uint8_t *data; size_t size; };
|
struct Slice { const uint8_t *data; size_t size; };
|
||||||
Slice dataSlice = { data, size };
|
Slice dataSlice = { data, size };
|
||||||
png_struct *png_ptr = NULL;
|
png_struct *png_ptr = NULL;
|
||||||
|
@ -139,14 +141,14 @@ std::shared_ptr<Pixmap> Pixmap::FromPng(const uint8_t *data, size_t size) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return ReadPngIntoPixmap(png_ptr, info_ptr);
|
return ReadPngIntoPixmap(png_ptr, info_ptr, flip);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Pixmap> Pixmap::ReadPng(FILE *f) {
|
std::shared_ptr<Pixmap> Pixmap::ReadPng(FILE *f, bool flip) {
|
||||||
png_struct *png_ptr = NULL;
|
png_struct *png_ptr = NULL;
|
||||||
png_info *info_ptr = NULL;
|
png_info *info_ptr = NULL;
|
||||||
|
|
||||||
|
@ -164,7 +166,7 @@ std::shared_ptr<Pixmap> Pixmap::ReadPng(FILE *f) {
|
||||||
png_init_io(png_ptr, f);
|
png_init_io(png_ptr, f);
|
||||||
png_set_sig_bytes(png_ptr, sizeof(header));
|
png_set_sig_bytes(png_ptr, sizeof(header));
|
||||||
|
|
||||||
return ReadPngIntoPixmap(png_ptr, info_ptr);
|
return ReadPngIntoPixmap(png_ptr, info_ptr, flip);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
|
|
@ -33,9 +33,9 @@ public:
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
static std::shared_ptr<Pixmap> Create(Format format, size_t width, size_t height);
|
static std::shared_ptr<Pixmap> Create(Format format, size_t width, size_t height);
|
||||||
static std::shared_ptr<Pixmap> FromPng(const uint8_t *data, size_t size);
|
static std::shared_ptr<Pixmap> FromPng(const uint8_t *data, size_t size, bool flip = false);
|
||||||
|
|
||||||
static std::shared_ptr<Pixmap> ReadPng(FILE *f);
|
static std::shared_ptr<Pixmap> ReadPng(FILE *f, bool flip = false);
|
||||||
bool WritePng(FILE *f, bool flip = false);
|
bool WritePng(FILE *f, bool flip = false);
|
||||||
|
|
||||||
size_t GetBytesPerPixel() const;
|
size_t GetBytesPerPixel() const;
|
||||||
|
|
|
@ -371,7 +371,7 @@ void TextWindow::ScreenBackgroundImage(int link, uint32_t v) {
|
||||||
if(GetOpenFile(&bgImageFile, "", PngFileFilter)) {
|
if(GetOpenFile(&bgImageFile, "", PngFileFilter)) {
|
||||||
FILE *f = ssfopen(bgImageFile, "rb");
|
FILE *f = ssfopen(bgImageFile, "rb");
|
||||||
if(f) {
|
if(f) {
|
||||||
SS.bgImage.pixmap = Pixmap::ReadPng(f);
|
SS.bgImage.pixmap = Pixmap::ReadPng(f, /*flip=*/true);
|
||||||
SS.bgImage.scale = SS.GW.scale;
|
SS.bgImage.scale = SS.GW.scale;
|
||||||
SS.bgImage.origin = SS.GW.offset.ScaledBy(-1);
|
SS.bgImage.origin = SS.GW.offset.ScaledBy(-1);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
Loading…
Reference in New Issue