3 #include <lib/gdi/epng.h>
10 int loadPNG(ePtr<gPixmap> &result, const char *filename)
13 FILE *fp=fopen(filename, "rb");
17 // eDebug("couldn't open %s", filename );
20 if (!fread(header, 8, 1, fp))
22 eDebug("couldn't read");
26 if (png_sig_cmp(header, 0, 8))
31 png_structp png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
38 png_infop info_ptr=png_create_info_struct(png_ptr);
41 eDebug("no info ptr");
42 png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0);
46 png_infop end_info = png_create_info_struct(png_ptr);
50 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
54 if (setjmp(png_ptr->jmpbuf))
56 eDebug("das war wohl nix");
57 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
62 png_init_io(png_ptr, fp);
63 png_set_sig_bytes(png_ptr, 8);
64 png_set_invert_alpha(png_ptr);
65 png_read_info(png_ptr, info_ptr);
67 png_uint_32 width, height;
71 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
73 // eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type);
77 result=new gPixmap(eSize(width, height), bit_depth);
78 gSurface *surface = result->surface;
80 png_bytep *rowptr=new png_bytep[height];
82 for (unsigned int i=0; i<height; i++)
83 rowptr[i]=((png_byte*)(surface->data))+i*surface->stride;
84 png_read_rows(png_ptr, rowptr, 0, height);
88 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))
92 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
94 surface->clut.data=new gRGB[num_palette];
97 surface->clut.colors=num_palette;
99 for (int i=0; i<num_palette; i++)
101 surface->clut.data[i].a=0;
102 surface->clut.data[i].r=palette[i].red;
103 surface->clut.data[i].g=palette[i].green;
104 surface->clut.data[i].b=palette[i].blue;
106 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
109 png_get_tRNS(png_ptr, info_ptr, &trans, &num_palette, 0);
110 for (int i=0; i<num_palette; i++)
111 surface->clut.data[i].a=255-trans[i];
115 surface->clut.data=0;
116 surface->clut.colors=0;
118 surface->clut.start=0;
119 png_read_end(png_ptr, end_info);
123 png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
128 struct my_error_mgr {
129 struct jpeg_error_mgr pub;
130 jmp_buf setjmp_buffer;
133 typedef struct my_error_mgr * my_error_ptr;
136 my_error_exit (j_common_ptr cinfo)
138 my_error_ptr myerr = (my_error_ptr) cinfo->err;
139 (*cinfo->err->output_message) (cinfo);
140 longjmp(myerr->setjmp_buffer, 1);
143 int loadJPG(ePtr<gPixmap> &result, const char *filename, ePtr<gPixmap> alpha)
145 struct jpeg_decompress_struct cinfo;
146 struct my_error_mgr jerr;
150 infile = fopen(filename, "rb");
155 if (alpha->surface->bpp != 8)
157 eWarning("alpha channel for jpg must be 8bit");
164 cinfo.err = jpeg_std_error(&jerr.pub);
165 jerr.pub.error_exit = my_error_exit;
166 if (setjmp(jerr.setjmp_buffer)) {
168 jpeg_destroy_decompress(&cinfo);
172 jpeg_create_decompress(&cinfo);
173 jpeg_stdio_src(&cinfo, infile);
174 (void) jpeg_read_header(&cinfo, TRUE);
175 cinfo.out_color_space = JCS_RGB;
176 cinfo.scale_denom = 1;
178 (void) jpeg_start_decompress(&cinfo);
180 int grayscale = cinfo.output_components == 1;
184 if (((int)cinfo.output_width != alpha->surface->x) || ((int)cinfo.output_height != alpha->surface->y))
186 eWarning("alpha channel size (%dx%d) must match jpeg size (%dx%d)", alpha->surface->x, alpha->surface->y, cinfo.output_width, cinfo.output_height);
191 eWarning("we don't support grayscale + alpha at the moment");
196 result = new gPixmap(eSize(cinfo.output_width, cinfo.output_height), grayscale ? 8 : 32);
198 row_stride = cinfo.output_width * cinfo.output_components;
199 buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
200 while (cinfo.output_scanline < cinfo.output_height) {
201 int y = cinfo.output_scanline;
202 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
203 unsigned char *dst = ((unsigned char*)result->surface->data) + result->surface->stride * y;
204 unsigned char *src = (unsigned char*)buffer[0];
205 unsigned char *palpha = alpha ? ((unsigned char*)alpha->surface->data + alpha->surface->stride * y) : 0;
207 memcpy(dst, src, cinfo.output_width);
211 for (x = 0; x < (int)cinfo.output_width; ++x)
224 (void) jpeg_finish_decompress(&cinfo);
225 jpeg_destroy_decompress(&cinfo);
230 int savePNG(const char *filename, gPixmap *pixmap)
232 FILE *fp=fopen(filename, "wb");
236 gSurface *surface = pixmap->surface;
240 png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
243 eDebug("write png, couldnt allocate write struct");
248 png_infop info_ptr=png_create_info_struct(png_ptr);
252 png_destroy_write_struct(&png_ptr, 0);
257 if (setjmp(png_ptr->jmpbuf))
260 png_destroy_write_struct(&png_ptr, &info_ptr);
265 png_init_io(png_ptr, fp);
266 png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH);
267 png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
269 png_set_IHDR(png_ptr, info_ptr, surface->x, surface->y, surface->bpp,
270 surface->clut.data ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY,
271 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
272 if (surface->clut.data)
274 png_color palette[surface->clut.colors];
275 png_byte trans[surface->clut.colors];
276 for (int i=0; i<surface->clut.colors; ++i)
278 palette[i].red=surface->clut.data[i].r;
279 palette[i].green=surface->clut.data[i].g;
280 palette[i].blue=surface->clut.data[i].b;
281 trans[i]=255-surface->clut.data[i].a;
283 png_set_PLTE(png_ptr, info_ptr, palette, surface->clut.colors);
284 png_set_tRNS(png_ptr, info_ptr, trans, surface->clut.colors, 0);
286 png_write_info(png_ptr, info_ptr);
287 png_set_packing(png_ptr);
288 png_byte *row_pointers[surface->y];
289 for (int i=0; i<surface->y; ++i)
290 row_pointers[i]=((png_byte*)surface->data)+i*surface->stride;
291 png_write_image(png_ptr, row_pointers);
292 png_write_end(png_ptr, info_ptr);
293 png_destroy_write_struct(&png_ptr, &info_ptr);
295 eDebug("wrote png ! fine !");