3 #include <lib/gdi/epng.h>
7 gImage
*loadPNG(const char *filename
)
12 png_structp png_ptr
= 0;
13 png_infop info_ptr
= 0;
14 png_infop end_info
= 0;
16 if (!(fp
= fopen(filename
, "rb")))
18 // eDebug("[ePNG] %s not found\n", filename);
22 if (!fread(header
, 8, 1, fp
))
28 if (png_sig_cmp(header
, 0, 8))
31 if (!(png_ptr
=png_create_read_struct(PNG_LIBPNG_VER_STRING
, 0, 0, 0)))
34 if (!(info_ptr
=png_create_info_struct(png_ptr
)))
37 if (!(end_info
=png_create_info_struct(png_ptr
)))
40 if (setjmp(png_ptr
->jmpbuf
))
43 png_init_io(png_ptr
, fp
);
44 png_set_sig_bytes(png_ptr
, 8);
45 // png_set_invert_alpha(png_ptr); // has no effect on indexed images
46 png_read_info(png_ptr
, info_ptr
);
48 png_uint_32 width
, height
;
52 png_get_IHDR(png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
, 0, 0, 0);
54 // convert 1,2 and 4 bpp to 8bpp images that enigma can blit
56 png_set_packing(png_ptr
);
63 // eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type);
67 case PNG_COLOR_TYPE_GRAY
:
68 case PNG_COLOR_TYPE_PALETTE
:
69 // case PNG_COLOR_TYPE_RGB: // in theory, gImage can handle RGB pics - but enigma can't blit them, so
70 // until this is fixed, imho we should reject RGB pictures right here
71 // because later on we get an fatal blitting error followed by an enigma shutdown
73 res
=new gImage(eSize(width
, height
), bit_depth
);
75 png_bytep
*rowptr
=new png_bytep
[height
];
76 for (unsigned int i
=0; i
<height
; i
++)
77 rowptr
[i
]=((png_byte
*)(res
->data
))+i
*res
->stride
;
78 png_read_rows(png_ptr
, rowptr
, 0, height
);
82 if (color_type
== PNG_COLOR_TYPE_PALETTE
)
84 // indexed pictures without a palette make no sense
85 if (!png_get_valid(png_ptr
, info_ptr
, PNG_INFO_PLTE
))
90 png_get_PLTE(png_ptr
, info_ptr
, &palette
, &num_palette
);
93 res
->clut
.data
=new gRGB
[num_palette
];
94 res
->clut
.colors
=num_palette
;
97 for (int i
=0; i
<num_palette
; i
++)
99 res
->clut
.data
[i
].a
=0;
100 res
->clut
.data
[i
].r
=palette
[i
].red
;
101 res
->clut
.data
[i
].g
=palette
[i
].green
;
102 res
->clut
.data
[i
].b
=palette
[i
].blue
;
104 if (png_get_valid(png_ptr
, info_ptr
, PNG_INFO_tRNS
))
107 png_color_16
*transparent_color
;
109 png_get_tRNS(png_ptr
, info_ptr
, &trans
, &num_palette
, &transparent_color
);
110 if (transparent_color
)
111 res
->clut
.data
[transparent_color
->index
].a
=255;
113 for (int i
=0; i
<num_palette
; i
++)
114 res
->clut
.data
[i
].a
=255-trans
[i
];
120 eDebug("[ePNG] unsupported color_type in %s", filename
);
124 png_destroy_read_struct(&png_ptr
, &info_ptr
,&end_info
);
129 eDebug("[ePNG] png structure failure in %s\n", filename
);
134 png_destroy_read_struct(&png_ptr
, info_ptr
? &info_ptr
: (png_infopp
)NULL
, end_info
? &end_info
: (png_infopp
)NULL
);
140 int savePNG(const char *filename
, gPixmap
*pixmap
)
142 FILE *fp
=fopen(filename
, "wb");
145 png_structp png_ptr
=png_create_write_struct(PNG_LIBPNG_VER_STRING
, 0, 0, 0);
148 eDebug("write png, couldnt allocate write struct");
153 png_infop info_ptr
=png_create_info_struct(png_ptr
);
157 png_destroy_write_struct(&png_ptr
, 0);
162 if (setjmp(png_ptr
->jmpbuf
))
165 png_destroy_write_struct(&png_ptr
, &info_ptr
);
170 png_init_io(png_ptr
, fp
);
171 png_set_filter(png_ptr
, 0, PNG_FILTER_NONE
|PNG_FILTER_SUB
|PNG_FILTER_PAETH
);
172 png_set_compression_level(png_ptr
, Z_BEST_COMPRESSION
);
174 png_set_IHDR(png_ptr
, info_ptr
, pixmap
->x
, pixmap
->y
, pixmap
->bpp
,
175 pixmap
->clut
.data
? PNG_COLOR_TYPE_PALETTE
: PNG_COLOR_TYPE_GRAY
,
176 PNG_INTERLACE_NONE
, PNG_COMPRESSION_TYPE_DEFAULT
, PNG_FILTER_TYPE_DEFAULT
);
177 if (pixmap
->clut
.data
)
179 png_color palette
[pixmap
->clut
.colors
];
180 png_byte trans
[pixmap
->clut
.colors
];
181 for (int i
=0; i
<pixmap
->clut
.colors
; ++i
)
183 palette
[i
].red
=pixmap
->clut
.data
[i
].r
;
184 palette
[i
].green
=pixmap
->clut
.data
[i
].g
;
185 palette
[i
].blue
=pixmap
->clut
.data
[i
].b
;
186 trans
[i
]=255-pixmap
->clut
.data
[i
].a
;
188 png_set_PLTE(png_ptr
, info_ptr
, palette
, pixmap
->clut
.colors
);
189 png_set_tRNS(png_ptr
, info_ptr
, trans
, pixmap
->clut
.colors
, 0);
191 png_write_info(png_ptr
, info_ptr
);
192 png_set_packing(png_ptr
);
193 png_byte
*row_pointers
[pixmap
->y
];
194 for (int i
=0; i
<pixmap
->y
; ++i
)
195 row_pointers
[i
]=((png_byte
*)pixmap
->data
)+i
*pixmap
->stride
;
196 png_write_image(png_ptr
, row_pointers
);
197 png_write_end(png_ptr
, info_ptr
);
198 png_destroy_write_struct(&png_ptr
, &info_ptr
);
200 eDebug("wrote png ! fine !");