Cloud save: working implementation, no dialog to select your games yet
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
APP_MODULES := application sdl-1.2 sdl_main sdl_native_helpers jpeg png ogg flac vorbis freetype tremor ogg
|
||||
|
||||
# To filter out static libs from all libs in makefile
|
||||
APP_AVAILABLE_STATIC_LIBS := jpeg png tremor freetype xerces ogg tremor vorbis flac boost_date_time boost_filesystem boost_iostreams boost_program_options boost_regex boost_signals boost_system boost_thread boost_locale glu icudata icutest icui18n icuio icule iculx icutu icuuc
|
||||
APP_AVAILABLE_STATIC_LIBS := jpeg png tremor freetype xerces ogg tremor vorbis flac boost_date_time boost_filesystem boost_iostreams boost_program_options boost_regex boost_signals boost_system boost_thread boost_locale glu icudata icutest icui18n icuio icule iculx icutu icuuc sdl_savepng
|
||||
|
||||
APP_ABI := armeabi
|
||||
|
||||
|
||||
@@ -1251,7 +1251,8 @@ BNX_BOOL saveGame( BNX_GAME *game )
|
||||
sysFPut16( game->level_count, file );
|
||||
|
||||
fclose( file );
|
||||
SDL_ANDROID_CloudSave( sysGetFullFileName( csSaveGameName ) );
|
||||
SDL_SaveBMP(SDL_GetVideoSurface(), "screenshot.bmp");
|
||||
SDL_ANDROID_CloudSave( sysGetFullFileName( csSaveGameName ), "save", "Biniax2", "savegame", "screenshot.bmp", game->moves );
|
||||
|
||||
return BNX_TRUE;
|
||||
}
|
||||
@@ -1262,7 +1263,7 @@ BNX_BOOL loadGame( BNX_GAME *game )
|
||||
BNX_INT32 i;
|
||||
BNX_INT32 j;
|
||||
|
||||
SDL_ANDROID_CloudLoad( sysGetFullFileName( csSaveGameName ) );
|
||||
SDL_ANDROID_CloudLoad( sysGetFullFileName( csSaveGameName ), "save", "Biniax2" );
|
||||
|
||||
if ( sysGetFileLen( sysGetFullFileName( csSaveGameName ) ) != cSaveFileSize )
|
||||
return BNX_FALSE;
|
||||
|
||||
@@ -96,26 +96,27 @@ extern DECLSPEC void SDLCALL SDL_ANDROID_CloseAudioRecording(void);
|
||||
/*
|
||||
Save the file to the cloud, filename must be already present on disk.
|
||||
This function will block, until user signs in to the cloud account, and presses Save button.
|
||||
Description and imageFile may be NULL.
|
||||
If saveId is NULL or empty, user will select the savegame from the dialog, if it's not empty -
|
||||
do not show any dialog to the user, except foir sign-in, and write the savegame with specified ID.
|
||||
dialogTitle may be NULL.
|
||||
description and screenshotFile may be NULL. playedTimeMs is used for conflict resolution -
|
||||
savegame with longer play time will get priority.
|
||||
Use SDL_SaveBMP(SDL_GetVideoSurface(), "screenshot.bmp") to create the screenshot.
|
||||
Returns 1 if save succeeded, 0 if user aborted sign-in, or there was no network available.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_ANDROID_CloudSave(const char * filename, const char * description, const char * imageFile);
|
||||
extern DECLSPEC int SDLCALL SDL_ANDROID_CloudSave(const char *filename, const char *saveId, const char *dialogTitle,
|
||||
const char *description, const char *screenshotFile, long long playedTimeMs);
|
||||
|
||||
/*
|
||||
Load the specified file from the cloud.
|
||||
This function will block, until user signs in to the cloud account.
|
||||
Returns 1 if load succeeded, 0 if user aborted sign-in, or there was no network available.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_ANDROID_CloudLoad(const char *filename);
|
||||
|
||||
/*
|
||||
Show the file loading dialog, to allow user to pick up a file from the cloud.
|
||||
This function will block, until user signs in to the cloud account, and selects a file.
|
||||
The resulting filename is written to the filename buffer, which must be 512 bytes or more.
|
||||
This function will block, until user signs in to the cloud account, and selects a savegame.
|
||||
The resulting savegame is written to the passed filename.
|
||||
If saveId is NULL or empty, user will select the savegame from the dialog, if it's not empty -
|
||||
do not show any dialog to the user, except foir sign-in, and read the savegame with specified ID.
|
||||
dialogTitle may be NULL.
|
||||
Returns 1 if load succeeded, 0 if user aborted sign-in, or there was no network available.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_ANDROID_CloudLoadDialog(char *filename, int len, const char *dialogTitle);
|
||||
extern DECLSPEC int SDLCALL SDL_ANDROID_CloudLoad(const char *filename, const char *saveId, const char *dialogTitle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -80,6 +80,8 @@ static jmethodID JavaGetAdvertisementParams = NULL;
|
||||
static jmethodID JavaSetAdvertisementVisible = NULL;
|
||||
static jmethodID JavaSetAdvertisementPosition = NULL;
|
||||
static jmethodID JavaRequestNewAdvertisement = NULL;
|
||||
static jmethodID JavaRequestCloudSave = NULL;
|
||||
static jmethodID JavaRequestCloudLoad = NULL;
|
||||
static int glContextLost = 0;
|
||||
static int showScreenKeyboardDeferred = 0;
|
||||
static const char * showScreenKeyboardOldText = "";
|
||||
@@ -347,6 +349,11 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeInitJavaCallbacks) ( JNIEnv* env, jobject t
|
||||
JavaSetAdvertisementVisible = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "setAdvertisementVisible", "(I)V");
|
||||
JavaSetAdvertisementPosition = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "setAdvertisementPosition", "(II)V");
|
||||
JavaRequestNewAdvertisement = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "requestNewAdvertisement", "()V");
|
||||
|
||||
JavaRequestCloudSave = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "cloudSave",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)Z");
|
||||
JavaRequestCloudLoad = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "cloudLoad",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z");
|
||||
|
||||
ANDROID_InitOSKeymap();
|
||||
}
|
||||
@@ -467,20 +474,55 @@ int SDLCALL SDL_ANDROID_RequestNewAdvertisement(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SDLCALL SDL_ANDROID_CloudSave(const char * filename, const char * description, const char * imageFile)
|
||||
int SDLCALL SDL_ANDROID_CloudSave(const char *filename, const char *saveId, const char *dialogTitle,
|
||||
const char *description, const char *screenshotFile, long long playedTimeMs)
|
||||
{
|
||||
return 0;
|
||||
if( !filename )
|
||||
return 0;
|
||||
if( !saveId )
|
||||
saveId = "";
|
||||
if( !dialogTitle )
|
||||
dialogTitle = "";
|
||||
if( !description )
|
||||
description = "";
|
||||
if( !screenshotFile )
|
||||
screenshotFile = "";
|
||||
(*JavaEnv)->PushLocalFrame(JavaEnv, 5);
|
||||
jstring s1 = (*JavaEnv)->NewStringUTF(JavaEnv, filename);
|
||||
jstring s2 = (*JavaEnv)->NewStringUTF(JavaEnv, saveId);
|
||||
jstring s3 = (*JavaEnv)->NewStringUTF(JavaEnv, dialogTitle);
|
||||
jstring s4 = (*JavaEnv)->NewStringUTF(JavaEnv, description);
|
||||
jstring s5 = (*JavaEnv)->NewStringUTF(JavaEnv, screenshotFile);
|
||||
int result = (*JavaEnv)->CallBooleanMethod( JavaEnv, JavaRenderer, JavaRequestCloudSave, s1, s2, s3, s4, s5, playedTimeMs );
|
||||
(*JavaEnv)->DeleteLocalRef(JavaEnv, s5);
|
||||
(*JavaEnv)->DeleteLocalRef(JavaEnv, s4);
|
||||
(*JavaEnv)->DeleteLocalRef(JavaEnv, s3);
|
||||
(*JavaEnv)->DeleteLocalRef(JavaEnv, s2);
|
||||
(*JavaEnv)->DeleteLocalRef(JavaEnv, s1);
|
||||
(*JavaEnv)->PopLocalFrame(JavaEnv, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
int SDLCALL SDL_ANDROID_CloudLoad(const char *filename)
|
||||
int SDLCALL SDL_ANDROID_CloudLoad(const char *filename, const char *saveId, const char *dialogTitle)
|
||||
{
|
||||
return 0;
|
||||
if( !filename )
|
||||
return 0;
|
||||
if( !saveId )
|
||||
saveId = "";
|
||||
if( !dialogTitle )
|
||||
dialogTitle = "";
|
||||
(*JavaEnv)->PushLocalFrame(JavaEnv, 3);
|
||||
jstring s1 = (*JavaEnv)->NewStringUTF(JavaEnv, filename);
|
||||
jstring s2 = (*JavaEnv)->NewStringUTF(JavaEnv, saveId);
|
||||
jstring s3 = (*JavaEnv)->NewStringUTF(JavaEnv, dialogTitle);
|
||||
int result = (*JavaEnv)->CallBooleanMethod( JavaEnv, JavaRenderer, JavaRequestCloudLoad, s1, s2, s3 );
|
||||
(*JavaEnv)->DeleteLocalRef(JavaEnv, s3);
|
||||
(*JavaEnv)->DeleteLocalRef(JavaEnv, s2);
|
||||
(*JavaEnv)->DeleteLocalRef(JavaEnv, s1);
|
||||
(*JavaEnv)->PopLocalFrame(JavaEnv, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
int SDLCALL SDL_ANDROID_CloudLoadDialog(char *filename, int len, const char *dialogTitle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Dummy callback for SDL2 to satisfy linker
|
||||
extern void SDL_Android_Init(JNIEnv* env, jclass cls);
|
||||
|
||||
19
project/jni/sdl_savepng/Android.mk
Normal file
19
project/jni/sdl_savepng/Android.mk
Normal file
@@ -0,0 +1,19 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := sdl_savepng
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/../png/include $(LOCAL_PATH)/../sdl-$(SDL_VERSION)/include $(LOCAL_PATH)/include
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cpp
|
||||
|
||||
LOCAL_SRC_FILES := $(notdir $(wildcard $(LOCAL_PATH)/*.c))
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := png
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := sdl-$(SDL_VERSION)
|
||||
|
||||
LOCAL_LDLIBS := -lz
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
101
project/jni/sdl_savepng/README.md
Normal file
101
project/jni/sdl_savepng/README.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# SDL_SavePNG
|
||||
|
||||
Minimal libpng interface to save SDL_Surfaces as PNG files.
|
||||
|
||||
You might want to take a look in "savepng.h" - it is much shorter and simpler
|
||||
than this README.
|
||||
|
||||
## Install
|
||||
|
||||
Add "savepng.c" and "savepng.h" to your project.
|
||||
|
||||
Link the libpng library, i.e. add the `-lpng` LDFLAG (even if you already have
|
||||
`-lSDL_image`).
|
||||
|
||||
## Use
|
||||
|
||||
```
|
||||
#include "savepng.h"
|
||||
|
||||
SDL_Surface *bmp = ... //your surface
|
||||
if (SDL_SavePNG(bmp, "image.png")) { //boring way with error checking
|
||||
printf("Unable to save png -- %s\n", SDL_GetError());
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, `SDL_SavePNG` accepts an SDL_Surface and a filename for it's
|
||||
input. Similar to SDL_SaveBMP, it is a wrapper around the actual RWops-based
|
||||
`SDL_SavePNG_RW` function, so you could use that, if needed.
|
||||
|
||||
Lastly, there is `SDL_PNGFormatAlpha`, modeled after SDL_DisplayFormatAlpha,
|
||||
that would convert *any SDL_Surface* to an *SDL_Surface suitable for PNG
|
||||
output*. Each call to `SDL_PNGFormatAlpha` produces a **new** SDL_Surface that
|
||||
**must** be freed using `SDL_FreeSurface`.
|
||||
|
||||
```
|
||||
//safest way, usefull for 'screen' surface
|
||||
SDL_Surface *tmp = SDL_PNGFormatAlpha(screen);
|
||||
SDL_SavePNG(tmp, "screenshot.png");
|
||||
SDL_FreeSurface(tmp)
|
||||
```
|
||||
|
||||
Such conversion is actually only required for *one* surface format (see below),
|
||||
and would do **nothing** for all other formats, making it **very fast**. The
|
||||
format in question is:
|
||||
|
||||
### 32-bpp surfaces without alpha
|
||||
|
||||
There is a interesting caveat of combining naive libpng and cunning SDL in a
|
||||
32-bpp video mode.
|
||||
|
||||
The *screen* surface (obtained by `SDL_SetVideoMode` or similarly) might (and
|
||||
will!) ignore it's alpha-component even in the 32bpp mode. Meaning that an
|
||||
0xAARRGGBB color would be blitted as 0xFFrrggbb irregardless, as if it was a
|
||||
24bpp color.
|
||||
|
||||
Since screen itself is never blitted onto anything else, ignoring the alpha
|
||||
makes perfect sense. However, unlike 24bpp images, the alpha component *does*
|
||||
exist. Thus, when such surface is saved, it appears to be completely
|
||||
transparent, as the alpha values for each pixel are set to 0.
|
||||
|
||||
Depending on your video mode, you might or might not need to first convert your
|
||||
surface using `SDL_PNGFormatAlpha`. If you have absolute control over the video
|
||||
surface, you can force it to 24bpp (or less) mode, which would avoid the
|
||||
problem.
|
||||
|
||||
If the surface passed to `SDL_PNGFormatAlpha` is already suitable, a no-op is
|
||||
performed. It is very fast, so you should probably always convert your surfaces
|
||||
before saving.
|
||||
|
||||
### No text chunks
|
||||
|
||||
Unfortunately, a simplistic interface such as SDL_SavePNG provides no means to
|
||||
write PNG meta-data. If you need to add iTXT chunks to your PNGs, you would
|
||||
have to modify this code or write your own version.
|
||||
|
||||
If you have some kind of simple API, that would be thematically consistent with
|
||||
SDL, in mind -- please share.
|
||||
|
||||
## Demo
|
||||
|
||||
See `main.c` and `Makefile` for an example program. It too is shorter than this
|
||||
README.
|
||||
|
||||
# About
|
||||
|
||||
The problem in question is very simple, and this little piece of functionality
|
||||
was implemented and re-implemented multiple times by multiple authors (notably,
|
||||
Angelo "Encelo" Theodorou and Darren Grant, among others). I decided to write
|
||||
my own version to ensure it's correctness, learn more about libpng, and to
|
||||
provide a copy-pastable, maintained, libpng15-aware, palette-supporting
|
||||
variation that I could link to. You can view it as a continuation of their
|
||||
efforts.
|
||||
|
||||
SDL_Image would've been perfect place for this, but that library has different
|
||||
purposes.
|
||||
|
||||
*Next up: code to load SDL_Surfaces as OpenGL 1.1 textures. J/K ;)*
|
||||
|
||||
# Copying
|
||||
|
||||
SDL_SavePNG is available under the zlib/libpng license.
|
||||
36
project/jni/sdl_savepng/include/savepng.h
Normal file
36
project/jni/sdl_savepng/include/savepng.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#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>
|
||||
/*
|
||||
* 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);
|
||||
|
||||
#endif
|
||||
155
project/jni/sdl_savepng/savepng.c
Normal file
155
project/jni/sdl_savepng/savepng.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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");
|
||||
if (freedst) SDL_RWclose(dst);
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user