Skip to content

Commit 1f99dfa

Browse files
committed
Initial implementation draft
1 parent 4ce3f94 commit 1f99dfa

File tree

1 file changed

+135
-2
lines changed

1 file changed

+135
-2
lines changed

src/IMG_png.c

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ static struct {
115115
jmp_buf* (*png_set_longjmp_fn) (png_structrp, png_longjmp_ptr, size_t);
116116
#endif
117117
#endif
118+
int (*png_image_begin_read_from_memory) (png_imagep image, png_const_voidp memory, size_t size);
119+
int (*png_image_finish_read) (png_imagep image, png_const_colorp background, void *buffer, png_int_32 row_stride, void *colormap);
118120
#if SDL_IMAGE_SAVE_PNG
119121
png_structp (*png_create_write_struct) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn);
120122
void (*png_destroy_write_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr);
@@ -170,6 +172,8 @@ int IMG_InitPNG()
170172
FUNCTION_LOADER(png_set_longjmp_fn, jmp_buf* (*) (png_structrp, png_longjmp_ptr, size_t))
171173
#endif
172174
#endif
175+
FUNCTION_LOADER(png_image_begin_read_from_memory, int (*) (png_imagep image, png_const_voidp memory, size_t size))
176+
FUNCTION_LOADER(png_image_finish_read, int (*) (png_imagep image, png_const_colorp background, void *buffer, png_int_32 row_stride, void *colormap))
173177
#if SDL_IMAGE_SAVE_PNG
174178
FUNCTION_LOADER(png_create_write_struct, png_structp (*) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn))
175179
FUNCTION_LOADER(png_destroy_write_struct, void (*) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr))
@@ -224,6 +228,118 @@ int IMG_isPNG(SDL_RWops *src)
224228
return(is_PNG);
225229
}
226230

231+
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) {
232+
png_image image;
233+
Sint64 src_length;
234+
Uint8* raw_image_buffer;
235+
SDL_Surface *surface;
236+
SDL_Palette* palette = NULL;
237+
void* colormap = NULL;
238+
Uint32 pixelformat;
239+
240+
if ( (IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0 ) {
241+
return NULL;
242+
}
243+
244+
/* This function uses libpng's "Simplified API" to read a PNG.
245+
* See https://github.com/pnggroup/libpng/blob/libpng16/libpng-manual.txt
246+
* And https://github.com/pnggroup/libpng/blob/libpng16/contrib/examples/pngtopng.c
247+
* For information about this and example usage, respectively. */
248+
249+
/* Only the image structure version number needs to be set. */
250+
SDL_memset(&image, 0, sizeof(image));
251+
image.version = PNG_IMAGE_VERSION;
252+
253+
src_length = SDL_RWsize(src); //todo error check
254+
255+
printf("src_length=%i\n", src_length);
256+
257+
raw_image_buffer = SDL_malloc(src_length); // ec
258+
SDL_RWseek(src, RW_SEEK_SET, 0); // ec
259+
int objects_read = SDL_RWread(src, raw_image_buffer, 1, src_length); // ec
260+
261+
printf("objects_read=%i\n", objects_read);
262+
263+
if (lib.png_image_begin_read_from_memory(&image, raw_image_buffer, src_length)) {
264+
/* If the image is natively encoded with a colormap, set the format to
265+
/* PNG_FORMAT_RGBA_COLORMAP. This allows libpng to directly map into the
266+
/* colors of an allocated SDL_Palette. Libpng handles mapping the native
267+
/* colormap format into this consistent format. */
268+
269+
if (image.format & PNG_FORMAT_FLAG_COLORMAP) {
270+
image.format = PNG_FORMAT_RGBA_COLORMAP;
271+
pixelformat = SDL_PIXELFORMAT_INDEX8;
272+
273+
palette = SDL_AllocPalette(image.colormap_entries);
274+
colormap = palette->colors;
275+
SDL_assert(PNG_IMAGE_COLORMAP_SIZE(image) == palette->ncolors * 4);
276+
}
277+
278+
/* Otherwise, maps the existing PNG format to a SDL pixelformatenum.
279+
/* If no mapping is found it falls down to a default, libpng handles
280+
/* conversion. */
281+
else {
282+
switch (image.format) {
283+
case PNG_FORMAT_RGBA:
284+
pixelformat = SDL_PIXELFORMAT_RGBA32;
285+
break;
286+
case PNG_FORMAT_ARGB:
287+
pixelformat = SDL_PIXELFORMAT_ARGB32;
288+
break;
289+
290+
/* Lets have grey alpha -> BGRA */
291+
case PNG_FORMAT_GA:
292+
image.format = PNG_FORMAT_BGRA;
293+
case PNG_FORMAT_BGRA:
294+
pixelformat = SDL_PIXELFORMAT_BGRA32;
295+
break;
296+
297+
case PNG_FORMAT_ABGR:
298+
pixelformat = SDL_PIXELFORMAT_ABGR32;
299+
break;
300+
301+
/* Lets have gray (no alpha) -> RGB */
302+
case PNG_FORMAT_GRAY:
303+
image.format = PNG_FORMAT_RGB;
304+
case PNG_FORMAT_RGB:
305+
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
306+
pixelformat = SDL_PIXELFORMAT_BGR24;
307+
#else
308+
pixelformat = SDL_PIXELFORMAT_RGB24;
309+
#endif
310+
break;
311+
case PNG_FORMAT_BGR:
312+
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
313+
pixelformat = SDL_PIXELFORMAT_RGB24;
314+
#else
315+
pixelformat = SDL_PIXELFORMAT_BGR24;
316+
#endif
317+
break;
318+
319+
/* If it's another format, lets use BGRA by default */
320+
default:
321+
image.format = PNG_FORMAT_BGRA;
322+
pixelformat = SDL_PIXELFORMAT_BGRA32;
323+
}
324+
}
325+
326+
surface = SDL_CreateRGBSurfaceWithFormat(0, image.width, image.height, 0, pixelformat);
327+
328+
if (palette != NULL) {
329+
SDL_SetSurfacePalette(surface, palette);
330+
}
331+
332+
lib.png_image_finish_read(&image, NULL, surface->pixels, surface->pitch, colormap);
333+
334+
return surface;
335+
}
336+
337+
printf("image.message=%s\n", image.message);
338+
339+
SDL_SetError("FAILED");
340+
return NULL;
341+
}
342+
227343
/* Load a PNG type image from an SDL datasource */
228344
static void png_read_data(png_structp ctx, png_bytep area, png_size_t size)
229345
{
@@ -232,7 +348,7 @@ static void png_read_data(png_structp ctx, png_bytep area, png_size_t size)
232348
src = (SDL_RWops *)lib.png_get_io_ptr(ctx);
233349
SDL_RWread(src, area, size, 1);
234350
}
235-
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
351+
SDL_Surface *IMG_LoadPNG_RW2(SDL_RWops *src)
236352
{
237353
Sint64 start;
238354
const char *error;
@@ -315,9 +431,13 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
315431
*/
316432
lib.png_set_packing(png_ptr);
317433

434+
printf("COLOR TYPE = %i\n", color_type);
435+
318436
/* scale greyscale values to the range 0..255 */
319-
if (color_type == PNG_COLOR_TYPE_GRAY)
437+
if (color_type == PNG_COLOR_TYPE_GRAY) {
438+
printf("COLOR TYPE GRAY\n");
320439
lib.png_set_expand(png_ptr);
440+
}
321441

322442
/* For images with a single "transparent colour", set colour key;
323443
if more than one index has transparency, or if partially transparent
@@ -327,7 +447,9 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
327447
int num_trans;
328448
Uint8 *trans;
329449
lib.png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &transv);
450+
printf("here in the club\n");
330451
if (color_type == PNG_COLOR_TYPE_PALETTE) {
452+
printf("wowowowo\n");
331453
/* Check if all tRNS entries are opaque except one */
332454
int j, t = -1;
333455
for (j = 0; j < num_trans; j++) {
@@ -352,6 +474,8 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
352474
}
353475
}
354476

477+
printf("done with that stuff\n");
478+
355479
if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
356480
lib.png_set_gray_to_rgb(png_ptr);
357481

@@ -363,6 +487,8 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
363487
/* Allocate the SDL surface to hold the image */
364488
num_channels = lib.png_get_channels(png_ptr, info_ptr);
365489

490+
printf("bit_depth = %i, num_channels = %i\n", bit_depth, num_channels);
491+
366492
format = SDL_PIXELFORMAT_UNKNOWN;
367493
if (num_channels == 3) {
368494
format = SDL_PIXELFORMAT_RGB24;
@@ -402,6 +528,13 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
402528
}
403529

404530
if (ckey != -1) {
531+
if (color_type == PNG_COLOR_TYPE_GRAY) {
532+
/* FIXME: Should these be truncated or shifted down? */
533+
ckey = SDL_MapRGB(surface->format,
534+
(Uint8)transv->gray,
535+
(Uint8)transv->gray,
536+
(Uint8)transv->gray);
537+
}
405538
if (color_type != PNG_COLOR_TYPE_PALETTE) {
406539
/* FIXME: Should these be truncated or shifted down? */
407540
ckey = SDL_MapRGB(surface->format,

0 commit comments

Comments
 (0)