X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/d6f6602d7cea3a7899990fe79216af7d98d05917..06578d6778bff8aa2bd6a2387651dd0ba55aa27c:/lib/gdi/epng.cpp diff --git a/lib/gdi/epng.cpp b/lib/gdi/epng.cpp index 0d1072f8..6b08c2d8 100644 --- a/lib/gdi/epng.cpp +++ b/lib/gdi/epng.cpp @@ -3,6 +3,10 @@ #include #include +extern "C" { +#include +} + int loadPNG(ePtr &result, const char *filename) { __u8 header[8]; @@ -111,6 +115,7 @@ int loadPNG(ePtr &result, const char *filename) surface->clut.data=0; surface->clut.colors=0; } + surface->clut.start=0; png_read_end(png_ptr, end_info); } else result=0; @@ -120,6 +125,108 @@ int loadPNG(ePtr &result, const char *filename) return 0; } +struct my_error_mgr { + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +typedef struct my_error_mgr * my_error_ptr; + +static void +my_error_exit (j_common_ptr cinfo) +{ + my_error_ptr myerr = (my_error_ptr) cinfo->err; + (*cinfo->err->output_message) (cinfo); + longjmp(myerr->setjmp_buffer, 1); +} + +int loadJPG(ePtr &result, const char *filename, ePtr alpha) +{ + struct jpeg_decompress_struct cinfo; + struct my_error_mgr jerr; + FILE *infile; + JSAMPARRAY buffer; + int row_stride; + infile = fopen(filename, "rb"); + result = 0; + + if (alpha) + { + if (alpha->surface->bpp != 8) + { + eWarning("alpha channel for jpg must be 8bit"); + alpha = 0; + } + } + + if (!infile) + return -1; + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + if (setjmp(jerr.setjmp_buffer)) { + result = 0; + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return -1; + } + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, infile); + (void) jpeg_read_header(&cinfo, TRUE); + cinfo.out_color_space = JCS_RGB; + cinfo.scale_denom = 1; + + (void) jpeg_start_decompress(&cinfo); + + int grayscale = cinfo.output_components == 1; + + if (alpha) + { + if (((int)cinfo.output_width != alpha->surface->x) || ((int)cinfo.output_height != alpha->surface->y)) + { + eWarning("alpha channel size (%dx%d) must match jpeg size (%dx%d)", alpha->surface->x, alpha->surface->y, cinfo.output_width, cinfo.output_height); + alpha = 0; + } + if (grayscale) + { + eWarning("we don't support grayscale + alpha at the moment"); + alpha = 0; + } + } + + result = new gPixmap(eSize(cinfo.output_width, cinfo.output_height), grayscale ? 8 : 32); + + row_stride = cinfo.output_width * cinfo.output_components; + buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + while (cinfo.output_scanline < cinfo.output_height) { + int y = cinfo.output_scanline; + (void) jpeg_read_scanlines(&cinfo, buffer, 1); + unsigned char *dst = ((unsigned char*)result->surface->data) + result->surface->stride * y; + unsigned char *src = (unsigned char*)buffer[0]; + unsigned char *palpha = alpha ? ((unsigned char*)alpha->surface->data + alpha->surface->stride * y) : 0; + if (grayscale) + memcpy(dst, src, cinfo.output_width); + else + { + int x; + for (x = 0; x < (int)cinfo.output_width; ++x) + { + *dst++ = src[2]; + *dst++ = src[1]; + *dst++ = src[0]; + src += 3; + if (palpha) + *dst++ = *palpha++; + else + *dst++ = 0xFF; + } + } + } + (void) jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return 0; +} + int savePNG(const char *filename, gPixmap *pixmap) { FILE *fp=fopen(filename, "wb");