Exemplo n.º 1
0
void SavePNG( Img const& img, RGBx const* palette, const char* filename )
{
    assert(img.Format()==Img::INDEXED8BIT);
    // TODO: set error handler to capture error msg?

    FILE *fp = fopen(filename, "wb");
    if (!fp)
    {
        throw Wobbly( "open failed: %s", strerror(errno) );
    }

    png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)0,0,0 );
    if (!png_ptr)
    {
        fclose(fp);
        throw Wobbly( "failed writing PNG (png_create_write() failed)" );
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        fclose(fp);
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        throw Wobbly( "failed writing PNG (png_create_info_struct() failed)" );
    }

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        throw Wobbly( "failed writing PNG" );
    }

    png_init_io(png_ptr, fp);

    png_set_IHDR( png_ptr,
        info_ptr,
        img.W(), img.H(),
        8,
        PNG_COLOR_TYPE_PALETTE,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT,
        PNG_FILTER_TYPE_DEFAULT );

    {
        png_color tmp_palette[256];
        int i;
        for(i=0;i<256;++i)
        {
            tmp_palette[i].red = palette[i].r;
            tmp_palette[i].green = palette[i].g;
            tmp_palette[i].blue = palette[i].b;
        }
        png_set_PLTE( png_ptr, info_ptr, tmp_palette, 256 );
    }

    //png_set_bKGD( png_ptr, info_ptr, 0 );

    {
        png_bytep row_pointers[ img.H() ];
        int y;
        for( y=0;y<img.H();++y)
            row_pointers[y] = (png_bytep)img.PtrConst(0,y);

        png_set_rows( png_ptr, info_ptr, row_pointers );

        png_write_png(png_ptr, info_ptr, 0, NULL);
    }

    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
}