mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-01-23 15:36:59 +00:00
Add support for savepng.c
This commit is contained in:
parent
18bee70dc8
commit
27a0e0e0a1
@ -3,7 +3,7 @@ bin_PROGRAMS = hyperrogue
|
||||
hyperroguedir = $(datadir)/hyperrogue
|
||||
dist_hyperrogue_DATA = music/hyperrogue-music.txt DejaVuSans-Bold.ttf
|
||||
dist_doc_DATA = README.md
|
||||
hyperrogue_SOURCES = hyper.cpp
|
||||
hyperrogue_SOURCES = hyper.cpp savepng.c
|
||||
|
||||
# Some definitions used in graph.cpp
|
||||
hyperrogue_CPPFLAGS = -DFONTDESTDIR=\"$(pkgdatadir)/DejaVuSans-Bold.ttf\" -DMUSICDESTDIR=\"$(pkgdatadir)/hyperrogue-music.txt\" -O2
|
||||
@ -26,6 +26,10 @@ langen_CXXFLAGS = -O0
|
||||
language-data.cpp: langen
|
||||
./langen > language-data.cpp
|
||||
|
||||
# Generation of savepng
|
||||
#noinst_PROGRAMS += savepng
|
||||
#savepng_SOURCES = savepng.c
|
||||
|
||||
# Local clean rules
|
||||
clean-local:
|
||||
rm -rf language-data.cpp
|
||||
|
@ -34,6 +34,8 @@ AC_CHECK_LIB([SDL_mixer], [main], [], AC_MSG_ERROR([SDL_mixer library was not fo
|
||||
AC_CHECK_LIB([SDL_gfx], [main], [], [AS_IF( test ["${host_os#*mingw}" != "$host_os"], [export wincppflags=$wincppflags" dll/SDL_gfx.dll" && AC_MSG_RESULT([Building for windows, ignoring])] ,AC_MSG_ERROR([SDL_gfx library was not found]))])
|
||||
# FIXME: Replace `main' with a function in `-lSDL_ttf':
|
||||
AC_CHECK_LIB([SDL_ttf], [main], [], [AS_IF( test ["${host_os#*mingw}" != "$host_os"], [export wincppflags=$wincppflags" dll/SDL_ttf.dll" && AC_MSG_RESULT([Building for windows, ignoring])] ,AC_MSG_ERROR([SDL_ttf library was not found]))])
|
||||
# Test for libpng
|
||||
AC_CHECK_LIB([png], [main], [], AC_MSG_ERROR([png library was not found]))
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([stdlib.h unistd.h])
|
||||
|
154
savepng.c
Normal file
154
savepng.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* SDL_SavePNG -- libpng-based SDL_Surface writer.
|
||||
*
|
||||
* This code is free software, available under zlib/libpng license.
|
||||
* http://www.libpng.org/pub/png/src/libpng-LICENSE.txt
|
||||
*/
|
||||
#include <SDL/SDL.h>
|
||||
#include <png.h>
|
||||
|
||||
#define SUCCESS 0
|
||||
#define ERROR -1
|
||||
|
||||
#define USE_ROW_POINTERS
|
||||
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
#define rmask 0xFF000000
|
||||
#define gmask 0x00FF0000
|
||||
#define bmask 0x0000FF00
|
||||
#define amask 0x000000FF
|
||||
#else
|
||||
#define rmask 0x000000FF
|
||||
#define gmask 0x0000FF00
|
||||
#define bmask 0x00FF0000
|
||||
#define amask 0xFF000000
|
||||
#endif
|
||||
|
||||
/* libpng callbacks */
|
||||
static void png_error_SDL(png_structp ctx, png_const_charp str)
|
||||
{
|
||||
SDL_SetError("libpng: %s\n", str);
|
||||
}
|
||||
static void png_write_SDL(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
SDL_RWops *rw = (SDL_RWops*)png_get_io_ptr(png_ptr);
|
||||
SDL_RWwrite(rw, data, sizeof(png_byte), length);
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_PNGFormatAlpha(SDL_Surface *src)
|
||||
{
|
||||
SDL_Surface *surf;
|
||||
SDL_Rect rect = { 0 };
|
||||
|
||||
/* NO-OP for images < 32bpp and 32bpp images that already have Alpha channel */
|
||||
if (src->format->BitsPerPixel <= 24 || src->format->Amask) {
|
||||
src->refcount++;
|
||||
return src;
|
||||
}
|
||||
|
||||
/* Convert 32bpp alpha-less image to 24bpp alpha-less image */
|
||||
rect.w = src->w;
|
||||
rect.h = src->h;
|
||||
surf = SDL_CreateRGBSurface(src->flags, src->w, src->h, 24,
|
||||
src->format->Rmask, src->format->Gmask, src->format->Bmask, 0);
|
||||
SDL_LowerBlit(src, &rect, surf, &rect);
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
int SDL_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_colorp pal_ptr;
|
||||
SDL_Palette *pal;
|
||||
int i, colortype;
|
||||
#ifdef USE_ROW_POINTERS
|
||||
png_bytep *row_pointers;
|
||||
#endif
|
||||
/* Initialize and do basic error checking */
|
||||
if (!dst)
|
||||
{
|
||||
SDL_SetError("Argument 2 to SDL_SavePNG_RW can't be NULL, expecting SDL_RWops*\n");
|
||||
return (ERROR);
|
||||
}
|
||||
if (!surface)
|
||||
{
|
||||
SDL_SetError("Argument 1 to SDL_SavePNG_RW can't be NULL, expecting SDL_Surface*\n");
|
||||
if (freedst) SDL_RWclose(dst);
|
||||
return (ERROR);
|
||||
}
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_SDL, NULL); /* err_ptr, err_fn, warn_fn */
|
||||
if (!png_ptr)
|
||||
{
|
||||
SDL_SetError("Unable to png_create_write_struct on %s\n", PNG_LIBPNG_VER_STRING);
|
||||
if (freedst) SDL_RWclose(dst);
|
||||
return (ERROR);
|
||||
}
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr)
|
||||
{
|
||||
SDL_SetError("Unable to png_create_info_struct\n");
|
||||
png_destroy_write_struct(&png_ptr, NULL);
|
||||
if (freedst) SDL_RWclose(dst);
|
||||
return (ERROR);
|
||||
}
|
||||
if (setjmp(png_jmpbuf(png_ptr))) /* All other errors, see also "png_error_SDL" */
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
if (freedst) SDL_RWclose(dst);
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
/* Setup our RWops writer */
|
||||
png_set_write_fn(png_ptr, dst, png_write_SDL, NULL); /* w_ptr, write_fn, flush_fn */
|
||||
|
||||
/* Prepare chunks */
|
||||
colortype = PNG_COLOR_MASK_COLOR;
|
||||
if (surface->format->BytesPerPixel > 0
|
||||
&& surface->format->BytesPerPixel <= 8
|
||||
&& (pal = surface->format->palette))
|
||||
{
|
||||
colortype |= PNG_COLOR_MASK_PALETTE;
|
||||
pal_ptr = (png_colorp)malloc(pal->ncolors * sizeof(png_color));
|
||||
for (i = 0; i < pal->ncolors; i++) {
|
||||
pal_ptr[i].red = pal->colors[i].r;
|
||||
pal_ptr[i].green = pal->colors[i].g;
|
||||
pal_ptr[i].blue = pal->colors[i].b;
|
||||
}
|
||||
png_set_PLTE(png_ptr, info_ptr, pal_ptr, pal->ncolors);
|
||||
free(pal_ptr);
|
||||
}
|
||||
else if (surface->format->BytesPerPixel > 3 || surface->format->Amask)
|
||||
colortype |= PNG_COLOR_MASK_ALPHA;
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, 8, colortype,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
// png_set_packing(png_ptr);
|
||||
|
||||
/* Allow BGR surfaces */
|
||||
if (surface->format->Rmask == bmask
|
||||
&& surface->format->Gmask == gmask
|
||||
&& surface->format->Bmask == rmask)
|
||||
png_set_bgr(png_ptr);
|
||||
|
||||
/* Write everything */
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
#ifdef USE_ROW_POINTERS
|
||||
row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*surface->h);
|
||||
for (i = 0; i < surface->h; i++)
|
||||
row_pointers[i] = (png_bytep)(Uint8*)surface->pixels + i * surface->pitch;
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
free(row_pointers);
|
||||
#else
|
||||
for (i = 0; i < surface->h; i++)
|
||||
png_write_row(png_ptr, (png_bytep)(Uint8*)surface->pixels + i * surface->pitch);
|
||||
#endif
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
/* Done */
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
if (freedst) SDL_RWclose(dst);
|
||||
return (SUCCESS);
|
||||
}
|
Loading…
Reference in New Issue
Block a user