Save images as PNG (can be a bit slow).
This commit is contained in:
parent
b4d681a4eb
commit
cdb0230bc7
|
@ -30,7 +30,7 @@ vpath %.h $(SEARCHPATH)
|
||||||
|
|
||||||
DEPS += defs.h structs.h
|
DEPS += defs.h structs.h
|
||||||
|
|
||||||
_OBJS += atlas.o atlasTest.o aquaBlob.o
|
_OBJS += atlas.o aquaBlob.o
|
||||||
_OBJS += battery.o blaze.o bob.o boss.o blobBoss.o bullet.o
|
_OBJS += battery.o blaze.o bob.o boss.o blobBoss.o bullet.o
|
||||||
_OBJS += camera.o cannon.o cardReader.o cell.o cherry.o combat.o controls.o consumable.o
|
_OBJS += camera.o cannon.o cardReader.o cell.o cherry.o combat.o controls.o consumable.o
|
||||||
_OBJS += debris.o destructable.o door.o draw.o
|
_OBJS += debris.o destructable.o door.o draw.o
|
||||||
|
@ -47,10 +47,10 @@ _OBJS += objectives.o options.o
|
||||||
_OBJS += particles.o player.o plasmaBlob.o plasmaDroid.o pistolBlob.o pistolDroid.o postMission.o powerPoint.o powerPool.o pressurePlate.o pushBlock.o
|
_OBJS += particles.o player.o plasmaBlob.o plasmaDroid.o pistolBlob.o pistolDroid.o postMission.o powerPoint.o powerPool.o pressurePlate.o pushBlock.o
|
||||||
_OBJS += quadtree.o
|
_OBJS += quadtree.o
|
||||||
_OBJS += radar.o
|
_OBJS += radar.o
|
||||||
_OBJS += shotgunBlob.o shotgunDroid.o sound.o spreadGunBlob.o spreadGunDroid.o sprites.o stats.o structures.o
|
_OBJS += savepng.o shotgunBlob.o shotgunDroid.o sound.o spreadGunBlob.o spreadGunDroid.o sprites.o stats.o structures.o
|
||||||
_OBJS += tankCommander.o tankTrack.o teeka.o teleporter.o text.o textures.o title.o transition.o triggers.o trophies.o
|
_OBJS += tankCommander.o tankTrack.o teeka.o teleporter.o text.o textures.o title.o transition.o triggers.o trophies.o
|
||||||
_OBJS += unit.o util.o
|
_OBJS += unit.o util.o
|
||||||
_OBJS += weapons.o weaponPickup.o widgets.o world.o worldLoader.o worldSaver.o
|
_OBJS += weapons.o weaponPickup.o widgets.o world.o worldLoader.o worldSaver.o worldTest.o
|
||||||
|
|
||||||
OBJS = $(patsubst %,$(OUT)/%,$(_OBJS))
|
OBJS = $(patsubst %,$(OUT)/%,$(_OBJS))
|
||||||
|
|
||||||
|
|
2
makefile
2
makefile
|
@ -25,7 +25,7 @@ CXXFLAGS += -Wall -Wempty-body -ansi -pedantic -Werror -Wstrict-prototypes -Werr
|
||||||
CXXFLAGS += -g -lefence
|
CXXFLAGS += -g -lefence
|
||||||
CXXFLAGS += -fms-extensions -std=gnu11
|
CXXFLAGS += -fms-extensions -std=gnu11
|
||||||
|
|
||||||
LDFLAGS += `sdl2-config --libs` -lSDL2_mixer -lSDL2_image -lSDL2_ttf -lm -lz
|
LDFLAGS += `sdl2-config --libs` -lSDL2_mixer -lSDL2_image -lSDL2_ttf -lm -lz -lpng
|
||||||
|
|
||||||
SHARED_FILES = CHANGELOG LICENSE README.md data gfx manual music sound icons
|
SHARED_FILES = CHANGELOG LICENSE README.md data gfx manual music sound icons
|
||||||
DIST_FILES = $(SHARED_FILES) locale $(PROG)
|
DIST_FILES = $(SHARED_FILES) locale $(PROG)
|
||||||
|
|
|
@ -266,15 +266,15 @@ void saveScreenshot(char *name)
|
||||||
|
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
{
|
{
|
||||||
sprintf(filename, "%s/%s.bmp", app.saveDir, name);
|
sprintf(filename, "%s/%s.png", app.saveDir, name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(filename, "%s/%d.bmp", dev.screenshotFolder, SDL_GetTicks());
|
sprintf(filename, "%s/%d.png", dev.screenshotFolder, SDL_GetTicks());
|
||||||
}
|
}
|
||||||
|
|
||||||
screenshot = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
|
screenshot = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
|
||||||
SDL_RenderReadPixels(app.renderer, NULL, SDL_PIXELFORMAT_ARGB8888, screenshot->pixels, screenshot->pitch);
|
SDL_RenderReadPixels(app.renderer, NULL, SDL_PIXELFORMAT_ARGB8888, screenshot->pixels, screenshot->pitch);
|
||||||
SDL_SaveBMP(screenshot, filename);
|
SDL_SavePNG(screenshot, filename);
|
||||||
SDL_FreeSurface(screenshot);
|
SDL_FreeSurface(screenshot);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
#include "savepng.h"
|
||||||
|
|
||||||
extern void drawText(int x, int y, int size, int align, SDL_Color c, const char *format, ...);
|
extern void drawText(int x, int y, int size, int align, SDL_Color c, const char *format, ...);
|
||||||
|
|
||||||
|
|
|
@ -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.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);
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef _SDL_SAVEPNG
|
||||||
|
#define _SDL_SAVEPNG
|
||||||
|
/*
|
||||||
|
* 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_video.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { /* This helps CPP projects that include this header */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save an SDL_Surface as a PNG file.
|
||||||
|
*
|
||||||
|
* Returns 0 success or -1 on failure, the error message is then retrievable
|
||||||
|
* via SDL_GetError().
|
||||||
|
*/
|
||||||
|
#define SDL_SavePNG(surface, file) \
|
||||||
|
SDL_SavePNG_RW(surface, SDL_RWFromFile(file, "wb"), 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save an SDL_Surface as a PNG file, using writable RWops.
|
||||||
|
*
|
||||||
|
* surface - the SDL_Surface structure containing the image to be saved
|
||||||
|
* dst - a data stream to save to
|
||||||
|
* freedst - non-zero to close the stream after being written
|
||||||
|
*
|
||||||
|
* Returns 0 success or -1 on failure, the error message is then retrievable
|
||||||
|
* via SDL_GetError().
|
||||||
|
*/
|
||||||
|
extern int SDL_SavePNG_RW(SDL_Surface *surface, SDL_RWops *rw, int freedst);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return new SDL_Surface with a format suitable for PNG output.
|
||||||
|
*/
|
||||||
|
extern SDL_Surface *SDL_PNGFormatAlpha(SDL_Surface *src);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue