@@ -292,6 +292,131 @@ static int really_save_png(PACKFILE *fp, BITMAP *bmp, AL_CONST RGB *pal)
292292 return -1 ;
293293}
294294
295+ /* save_memory_png:
296+ * Writes a non-interlaced, no-frills PNG, taking the usual save_xyz
297+ * parameters. Returns non-zero on error.
298+ */
299+ static int save_memory_png (void * buffer , BITMAP * bmp , AL_CONST RGB * pal )
300+ {
301+ jmp_buf jmpbuf ;
302+ png_structp png_ptr = NULL ;
303+ png_infop info_ptr = NULL ;
304+ int depth ;
305+ int colour_type ;
306+
307+ depth = bitmap_color_depth (bmp );
308+ if (depth == 8 && !pal )
309+ return -1 ;
310+
311+ /* Create and initialize the png_struct with the
312+ * desired error handler functions.
313+ */
314+ png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING ,
315+ (void * )NULL , NULL , NULL );
316+ if (!png_ptr )
317+ goto Error ;
318+
319+ /* Allocate/initialize the image information data. */
320+ info_ptr = png_create_info_struct (png_ptr );
321+ if (!info_ptr )
322+ goto Error ;
323+
324+ /* Set error handling. */
325+ if (setjmp (jmpbuf )) {
326+ /* If we get here, we had a problem reading the file. */
327+ goto Error ;
328+ }
329+ png_set_error_fn (png_ptr , jmpbuf , user_error_fn , NULL );
330+
331+ /* Use memory routines. */
332+ png_set_write_fn (png_ptr , buffer , NULL , NULL );
333+
334+ /* Set the image information here. Width and height are up to 2^31,
335+ * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
336+ * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
337+ * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
338+ * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
339+ * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
340+ * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
341+ */
342+ if (depth == 8 )
343+ colour_type = PNG_COLOR_TYPE_PALETTE ;
344+ else if (depth == 32 )
345+ colour_type = PNG_COLOR_TYPE_RGB_ALPHA ;
346+ else
347+ colour_type = PNG_COLOR_TYPE_RGB ;
348+
349+ /* Set compression level. */
350+ png_set_compression_level (png_ptr , _png_compression_level );
351+
352+ png_set_IHDR (png_ptr , info_ptr , bmp -> w , bmp -> h , 8 , colour_type ,
353+ PNG_INTERLACE_NONE , PNG_COMPRESSION_TYPE_BASE ,
354+ PNG_FILTER_TYPE_BASE );
355+
356+ /* Set the palette if there is one. Required for indexed-color images. */
357+ if (colour_type == PNG_COLOR_TYPE_PALETTE ) {
358+ png_color palette [256 ];
359+ int i ;
360+
361+ for (i = 0 ; i < 256 ; i ++ ) {
362+ palette [i ].red = pal [i ].r ; /* 64 -> 256 */
363+ palette [i ].green = pal [i ].g ;
364+ palette [i ].blue = pal [i ].b ;
365+ }
366+
367+ /* Set palette colors. */
368+ png_set_PLTE (png_ptr , info_ptr , palette , 256 );
369+ }
370+
371+ /* Optionally write comments into the image ... Nah. */
372+
373+ /* Write the file header information. */
374+ png_write_info (png_ptr , info_ptr );
375+
376+ /* Once we write out the header, the compression type on the text
377+ * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
378+ * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
379+ * at the end.
380+ */
381+
382+ /* Save the data. */
383+ switch (depth ) {
384+ case 8 :
385+ if (!save_indexed (png_ptr , bmp ))
386+ goto Error ;
387+ break ;
388+ case 15 :
389+ case 16 :
390+ case 24 :
391+ if (!save_rgb (png_ptr , bmp ))
392+ goto Error ;
393+ break ;
394+ case 32 :
395+ if (!save_rgba (png_ptr , bmp ))
396+ goto Error ;
397+ break ;
398+ default :
399+ ASSERT (FALSE);
400+ goto Error ;
401+ }
402+
403+ png_write_end (png_ptr , info_ptr );
404+
405+ png_destroy_write_struct (& png_ptr , & info_ptr );
406+
407+ return 0 ;
408+
409+ Error :
410+
411+ if (png_ptr ) {
412+ if (info_ptr )
413+ png_destroy_write_struct (& png_ptr , & info_ptr );
414+ else
415+ png_destroy_write_struct (& png_ptr , NULL );
416+ }
417+
418+ return -1 ;
419+ }
295420
296421int save_png (AL_CONST char * filename , BITMAP * bmp , AL_CONST RGB * pal )
297422{
0 commit comments