| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- #ifndef _CRT_SECURE_NO_WARNINGS
- #define _CRT_SECURE_NO_WARNINGS
- #endif
- #include "save-png.h"
- #include <cstdio>
- #include <cstring>
- #include <vector>
- #include "../core/pixel-conversion.hpp"
- #ifdef MSDFGEN_USE_LIBPNG
- #include <png.h>
- namespace msdfgen {
- class PngGuard {
- png_structp png;
- png_infop info;
- FILE *file;
- public:
- inline PngGuard(png_structp png, png_infop info) : png(png), info(info), file(NULL) { }
- inline ~PngGuard() {
- png_destroy_write_struct(&png, &info);
- if (file)
- fclose(file);
- }
- inline void setFile(FILE *file) {
- this->file = file;
- }
- };
- static void pngIgnoreError(png_structp, png_const_charp) { }
- static void pngWrite(png_structp png, png_bytep data, png_size_t length) {
- if (fwrite(data, 1, length, reinterpret_cast<FILE *>(png_get_io_ptr(png))) != length)
- png_error(png, "File write error");
- }
- static void pngFlush(png_structp png) {
- fflush(reinterpret_cast<FILE *>(png_get_io_ptr(png)));
- }
- static bool pngSave(const byte *pixels, int width, int height, int rowStride, int colorType, const char *filename) {
- if (!(pixels && width && height))
- return false;
- png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &pngIgnoreError, &pngIgnoreError);
- if (!png)
- return false;
- png_infop info = png_create_info_struct(png);
- PngGuard guard(png, info);
- if (!info)
- return false;
- FILE *file = fopen(filename, "wb");
- if (!file)
- return false;
- guard.setFile(file);
- std::vector<const byte *> rows(height);
- for (int y = 0; y < height; ++y)
- rows[y] = pixels+rowStride*y;
- if (setjmp(png_jmpbuf(png)))
- return false;
- png_set_write_fn(png, file, &pngWrite, &pngFlush);
- png_set_IHDR(png, info, width, height, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
- png_set_compression_level(png, 9);
- png_set_rows(png, info, const_cast<png_bytepp>(&rows[0]));
- png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
- return true;
- }
- static bool pngSave(const float *pixels, int width, int height, int rowStride, int channels, int colorType, const char *filename) {
- if (!(pixels && width && height))
- return false;
- std::vector<byte> bytePixels(channels*width*height);
- byte *dst = &bytePixels[0];
- const float *rowStart = pixels;
- for (int y = 0; y < height; ++y) {
- for (const float *src = rowStart, *end = rowStart+channels*width; src < end; ++src)
- *dst++ = pixelFloatToByte(*src);
- rowStart += rowStride;
- }
- return pngSave(&bytePixels[0], width, height, channels*width, colorType, filename);
- }
- bool savePng(BitmapConstSection<byte, 1> bitmap, const char *filename) {
- bitmap.reorient(Y_DOWNWARD);
- return pngSave(bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, PNG_COLOR_TYPE_GRAY, filename);
- }
- bool savePng(BitmapConstSection<byte, 3> bitmap, const char *filename) {
- bitmap.reorient(Y_DOWNWARD);
- return pngSave(bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, PNG_COLOR_TYPE_RGB, filename);
- }
- bool savePng(BitmapConstSection<byte, 4> bitmap, const char *filename) {
- bitmap.reorient(Y_DOWNWARD);
- return pngSave(bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, PNG_COLOR_TYPE_RGB_ALPHA, filename);
- }
- bool savePng(BitmapConstSection<float, 1> bitmap, const char *filename) {
- bitmap.reorient(Y_DOWNWARD);
- return pngSave(bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, 1, PNG_COLOR_TYPE_GRAY, filename);
- }
- bool savePng(BitmapConstSection<float, 3> bitmap, const char *filename) {
- bitmap.reorient(Y_DOWNWARD);
- return pngSave(bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, 3, PNG_COLOR_TYPE_RGB, filename);
- }
- bool savePng(BitmapConstSection<float, 4> bitmap, const char *filename) {
- bitmap.reorient(Y_DOWNWARD);
- return pngSave(bitmap.pixels, bitmap.width, bitmap.height, bitmap.rowStride, 4, PNG_COLOR_TYPE_RGB_ALPHA, filename);
- }
- }
- #endif
- #ifdef MSDFGEN_USE_LODEPNG
- #include <lodepng.h>
- namespace msdfgen {
- bool savePng(BitmapConstSection<byte, 1> bitmap, const char *filename) {
- std::vector<byte> pixels(bitmap.width*bitmap.height);
- bitmap.reorient(Y_DOWNWARD);
- for (int y = 0; y < bitmap.height; ++y)
- memcpy(&pixels[bitmap.width*y], bitmap(0, y), 1*bitmap.width);
- return !lodepng::encode(filename, pixels, bitmap.width, bitmap.height, LCT_GREY);
- }
- bool savePng(BitmapConstSection<byte, 3> bitmap, const char *filename) {
- std::vector<byte> pixels(3*bitmap.width*bitmap.height);
- bitmap.reorient(Y_DOWNWARD);
- for (int y = 0; y < bitmap.height; ++y)
- memcpy(&pixels[3*bitmap.width*y], bitmap(0, y), 3*bitmap.width);
- return !lodepng::encode(filename, pixels, bitmap.width, bitmap.height, LCT_RGB);
- }
- bool savePng(BitmapConstSection<byte, 4> bitmap, const char *filename) {
- std::vector<byte> pixels(4*bitmap.width*bitmap.height);
- bitmap.reorient(Y_DOWNWARD);
- for (int y = 0; y < bitmap.height; ++y)
- memcpy(&pixels[4*bitmap.width*y], bitmap(0, y), 4*bitmap.width);
- return !lodepng::encode(filename, pixels, bitmap.width, bitmap.height, LCT_RGBA);
- }
- bool savePng(BitmapConstSection<float, 1> bitmap, const char *filename) {
- std::vector<byte> pixels(bitmap.width*bitmap.height);
- std::vector<byte>::iterator it = pixels.begin();
- bitmap.reorient(Y_DOWNWARD);
- for (int y = 0; y < bitmap.height; ++y) {
- for (int x = 0; x < bitmap.width; ++x)
- *it++ = pixelFloatToByte(*bitmap(x, y));
- }
- return !lodepng::encode(filename, pixels, bitmap.width, bitmap.height, LCT_GREY);
- }
- bool savePng(BitmapConstSection<float, 3> bitmap, const char *filename) {
- std::vector<byte> pixels(3*bitmap.width*bitmap.height);
- std::vector<byte>::iterator it = pixels.begin();
- bitmap.reorient(Y_DOWNWARD);
- for (int y = 0; y < bitmap.height; ++y) {
- for (int x = 0; x < bitmap.width; ++x) {
- *it++ = pixelFloatToByte(bitmap(x, y)[0]);
- *it++ = pixelFloatToByte(bitmap(x, y)[1]);
- *it++ = pixelFloatToByte(bitmap(x, y)[2]);
- }
- }
- return !lodepng::encode(filename, pixels, bitmap.width, bitmap.height, LCT_RGB);
- }
- bool savePng(BitmapConstSection<float, 4> bitmap, const char *filename) {
- std::vector<byte> pixels(4*bitmap.width*bitmap.height);
- std::vector<byte>::iterator it = pixels.begin();
- bitmap.reorient(Y_DOWNWARD);
- for (int y = 0; y < bitmap.height; ++y) {
- for (int x = 0; x < bitmap.width; ++x) {
- *it++ = pixelFloatToByte(bitmap(x, y)[0]);
- *it++ = pixelFloatToByte(bitmap(x, y)[1]);
- *it++ = pixelFloatToByte(bitmap(x, y)[2]);
- *it++ = pixelFloatToByte(bitmap(x, y)[3]);
- }
- }
- return !lodepng::encode(filename, pixels, bitmap.width, bitmap.height, LCT_RGBA);
- }
- }
- #endif
|