Ejemplo n.º 1
0
/* save_png:
 *  Writes a non-interlaced, no-frills PNG, taking the usual save_xyz
 *  parameters.  Returns non-zero on error.
 */
static int really_save_png(PACKFILE *fp, BITMAP *bmp, AL_CONST RGB *pal)
{
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    int depth;
    int colour_type;

    depth = bitmap_color_depth(bmp);
    if (depth == 8 && !pal)
	return -1;

    /* Create and initialize the png_struct with the
     * desired error handler functions.
     */
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
				      (void *)NULL, NULL, NULL);
    if (!png_ptr)
	goto Error;

    /* Allocate/initialize the image information data. */
    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
	goto Error;

    /* Set error handling. */
    if (setjmp(png_ptr->jmpbuf)) {
	/* If we get here, we had a problem reading the file. */
	goto Error;
    }

    /* Use packfile routines. */
    png_set_write_fn(png_ptr, fp, (png_rw_ptr)write_data, flush_data);

    /* Set the image information here.  Width and height are up to 2^31,
     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
     */
    if (depth == 8)
	colour_type = PNG_COLOR_TYPE_PALETTE;
    else if (depth == 32)
	colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
    else
	colour_type = PNG_COLOR_TYPE_RGB;

    /* Set compression level. */
    png_set_compression_level(png_ptr, _png_compression_level);

    png_set_IHDR(png_ptr, info_ptr, bmp->w, bmp->h, 8, colour_type,
		 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
		 PNG_FILTER_TYPE_BASE);

    /* Set the palette if there is one.  Required for indexed-color images. */
    if (colour_type == PNG_COLOR_TYPE_PALETTE) {
	png_color palette[256];
	int i;

	for (i = 0; i < 256; i++) {
	    palette[i].red   = _rgb_scale_6[pal[i].r];   /* 64 -> 256 */
	    palette[i].green = _rgb_scale_6[pal[i].g];
	    palette[i].blue  = _rgb_scale_6[pal[i].b];
	}

	/* Set palette colors. */
	png_set_PLTE(png_ptr, info_ptr, palette, 256);
    }

    /* Optionally write comments into the image ... Nah. */

    /* Write the file header information. */
    png_write_info(png_ptr, info_ptr);

    /* Once we write out the header, the compression type on the text
     * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
     * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
     * at the end.
     */

    /* Save the data. */
    switch (depth) {
	case 8:
	    if (!save_indexed(png_ptr, bmp))
		goto Error;
	    break;
	case 15:
	case 16:
	case 24:
	    if (!save_rgb(png_ptr, bmp))
		goto Error;
	    break;
	case 32:
	    if (!save_rgba(png_ptr, bmp))
		goto Error;
	    break;
	default:
	    ASSERT(FALSE);
	    goto Error;
    }

    png_write_end(png_ptr, info_ptr);

    png_destroy_write_struct(&png_ptr, &info_ptr);

    return 0;

  Error:

    if (png_ptr) {
	if (info_ptr)
	    png_destroy_write_struct(&png_ptr, &info_ptr);
	else
	    png_destroy_write_struct(&png_ptr, NULL);
    }

    return -1;
}
Ejemplo n.º 2
0
/* Writes a non-interlaced, no-frills PNG, taking the usual save_xyz
 *  parameters.  Returns non-zero on error.
 */
bool _al_save_png_f(ALLEGRO_FILE *fp, ALLEGRO_BITMAP *bmp)
{
   jmp_buf jmpbuf;
   png_structp png_ptr = NULL;
   png_infop info_ptr = NULL;
   int colour_type;

   /* Create and initialize the png_struct with the
    * desired error handler functions.
    */
   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                     (void *)NULL, NULL, NULL);
   if (!png_ptr)
      goto Error;

   /* Allocate/initialize the image information data. */
   info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr)
      goto Error;

   /* Set error handling. */
   if (setjmp(jmpbuf)) {
      goto Error;
   }
   png_set_error_fn(png_ptr, jmpbuf, user_error_fn, NULL);

   /* Use packfile routines. */
   png_set_write_fn(png_ptr, fp, (png_rw_ptr) write_data, flush_data);

   /* Set the image information here.  Width and height are up to 2^31,
    * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
    * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
    * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
    * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
    * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
    * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
    */
   colour_type = PNG_COLOR_TYPE_RGB_ALPHA;

   /* Set compression level. */
   png_set_compression_level(png_ptr, _al_png_compression_level);

   png_set_IHDR(png_ptr, info_ptr,
                al_get_bitmap_width(bmp), al_get_bitmap_height(bmp),
                8, colour_type,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_BASE);

   /* Optionally write comments into the image ... Nah. */

   /* Write the file header information. */
   png_write_info(png_ptr, info_ptr);

   /* Once we write out the header, the compression type on the text
    * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
    * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
    * at the end.
    */
   if (!save_rgba(png_ptr, bmp))
      goto Error;

   png_write_end(png_ptr, info_ptr);

   png_destroy_write_struct(&png_ptr, &info_ptr);

   return true;

 Error:

   if (png_ptr) {
      if (info_ptr)
         png_destroy_write_struct(&png_ptr, &info_ptr);
      else
         png_destroy_write_struct(&png_ptr, NULL);
   }

   return false;
}