From cab59587e8af62b04c0a6c0f84251546f7fef32e Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sat, 16 May 2015 12:32:05 +0200 Subject: [PATCH] gsdx: add a PNG wrapper Normally it supports all formats but I didn't have luck with 16 bits depth gray --- plugins/GSdx/GSPng.cpp | 158 +++++++++++++++++++++++++++++++++++++++++ plugins/GSdx/GSPng.h | 38 ++++++++++ 2 files changed, 196 insertions(+) create mode 100644 plugins/GSdx/GSPng.cpp create mode 100644 plugins/GSdx/GSPng.h diff --git a/plugins/GSdx/GSPng.cpp b/plugins/GSdx/GSPng.cpp new file mode 100644 index 0000000000..a29ce0f1fa --- /dev/null +++ b/plugins/GSdx/GSPng.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2011-2015 Gregory hainaut + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GSPng.h" + +namespace GSPng { + + void Save(GSPng::Format fmt, const string& file, char* image, int w, int h, int pitch) + { +#ifdef ENABLE_OGL_PNG + std::string root = file; + root.replace(file.length()-4, 4, ""); + + uint8* data = (uint8*)image; + + switch (fmt) { + case R8I_PNG: + { + png::image img(w, h); + for(int y = 0; y < h; y++, data += pitch) { + for (int x = 0; x < w; x++) { + png::gray_pixel p(data[x]); + img.set_pixel(x, y, p); + } + } + img.write(root + "_R8.png"); + } + + case R16I_PNG: + { + png::image img(w, h); + for(int y = 0; y < h; y++, data += pitch) { + for (int x = 0; x < w; x++) { + png::gray_pixel_16 p(data[2*x]); + img.set_pixel(x, y, p); + } + } + img.write(root + "_R16.png"); + } + + case R32I_PNG: + { + png::image img_msb(w, h); + png::image img_lsb(w, h); + for(int y = 0; y < h; y++, data += pitch) { + for (int x = 0; x < w; x++) { + png::gray_pixel_16 msb(data[2*x]); + png::gray_pixel_16 lsb(data[2*x+2]); + + img_msb.set_pixel(x, y, msb); + img_lsb.set_pixel(x, y, lsb); + } + } + img_msb.write(root + "_R32I_msb.png"); + img_lsb.write(root + "_R32I_lsb.png"); + } + + case DEPTH_PNG: + { + png::image img_msb(w, h); + png::image img_lsb(w, h); + for(int y = 0; y < h; y++, data += pitch) { + for (int x = 0; x < w; x++) { + // TODO packed or not + uint32 depth = data[4*x]; //floorf((float)data[2*x] * exp2f(32)); + + png::gray_pixel_16 msb(depth >> 16); + png::gray_pixel_16 lsb((depth >> 16) ? 0xFFFF : depth & 0xFFFF); + + img_msb.set_pixel(x, y, msb); + img_lsb.set_pixel(x, y, lsb); + } + } + img_msb.write(root + "_msb.png"); + img_lsb.write(root + "_lsb.png"); + } + break; + + case ALPHA_PNG: + { + png::image img_alpha(w, h); + for(int y = 0; y < h; y++, data += pitch) { + for (int x = 0; x < w; x++) { + png::gray_pixel pa(data[4*x+3]); + img_alpha.set_pixel(x, y, pa); + } + } + img_alpha.write(root + "_alpha.png"); + } + break; + + case RGB_PNG: + { + png::image img_opaque(w, h); + for(int y = 0; y < h; y++, data += pitch) { + for (int x = 0; x < w; x++) { + png::rgb_pixel po(data[4*x+0], data[4*x+1], data[4*x+2]); + img_opaque.set_pixel(x, y, po); + } + } + img_opaque.write(root + ".png"); + } + break; + + case RGBA_PNG: + { + png::image img(w, h); + for(int y = 0; y < h; y++, data += pitch) { + for (int x = 0; x < w; x++) { + png::rgba_pixel p(data[4*x+0], data[4*x+1], data[4*x+2], data[4*x+3]); + img.set_pixel(x, y, p); + } + } + img.write(root + "_full.png"); + } + break; + + case RGB_A_PNG: + { + png::image img_opaque(w, h); + png::image img_alpha(w, h); + for(int y = 0; y < h; y++, data += pitch) { + for (int x = 0; x < w; x++) { + png::rgb_pixel po(data[4*x+0], data[4*x+1], data[4*x+2]); + img_opaque.set_pixel(x, y, po); + + png::gray_pixel pa(data[4*x+3]); + img_alpha.set_pixel(x, y, pa); + } + } + img_opaque.write(root + ".png"); + img_alpha.write(root + "_alpha.png"); + } + + default: + ASSERT(0); + } +#endif + } +} diff --git a/plugins/GSdx/GSPng.h b/plugins/GSdx/GSPng.h new file mode 100644 index 0000000000..a449f52d4c --- /dev/null +++ b/plugins/GSdx/GSPng.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011-2015 Gregory hainaut + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#ifdef ENABLE_OGL_PNG +#include "png++/png.hpp" +#endif + +namespace GSPng { + enum Format { + RGBA_PNG, + RGB_PNG, + RGB_A_PNG, + ALPHA_PNG, + DEPTH_PNG, + R8I_PNG, + R16I_PNG, + R32I_PNG, + }; + + void Save(GSPng::Format fmt, const string& file, char* image, int w, int h, int pitch); +}