diff --git a/src/driver/pictureviewer/pictureviewer.cpp b/src/driver/pictureviewer/pictureviewer.cpp index 0e29a745d..db8fd143a 100644 --- a/src/driver/pictureviewer/pictureviewer.cpp +++ b/src/driver/pictureviewer/pictureviewer.cpp @@ -523,21 +523,26 @@ bool CPictureViewer::DisplayImage (const std::string & name, int posx, int posy, return false; } -fb_pixel_t * CPictureViewer::getImage(const std::string & name, int width, int height) +fb_pixel_t * CPictureViewer::int_getImage(const std::string & name, int *width, int *height, bool GetImage) { - int x, y, bpp = 0; + int x, y, load_ret, bpp = 0; CFormathandler *fh; unsigned char * buffer; fb_pixel_t * ret = NULL; - int load_ret; + std::string mode_str; + + if (GetImage) + mode_str = "getImage"; + else + mode_str = "getIcon"; fh = fh_getsize(name.c_str(), &x, &y, INT_MAX, INT_MAX); if (fh) { - buffer = (unsigned char *) malloc (x * y * 4); + buffer = (unsigned char *) malloc(x * y * 4); if (buffer == NULL) { - printf ("getImage: Error: malloc\n"); + printf("%s: Error: malloc\n", mode_str.c_str()); return false; } #ifdef FBV_SUPPORT_PNG @@ -548,70 +553,40 @@ fb_pixel_t * CPictureViewer::getImage(const std::string & name, int width, int h load_ret = fh->get_pic(name.c_str (), &buffer, &x, &y); if (load_ret == FH_ERROR_OK) { - printf("getImage: decoded %s, %d x %d \n", name.c_str(), x, y); - if(x != width || y != height) + printf("%s: decoded %s, %d x %d \n", mode_str.c_str(), name.c_str(), x, y); + // resize only getImage + if ((GetImage) && (x != *width || y != *height)) { - printf("getImage: resize %s to %d x %d \n", name.c_str(), width, height); + printf("%s: resize %s to %d x %d \n", mode_str.c_str(), name.c_str(), *width, *height); if (bpp == 4) - buffer = ResizeA(buffer, x, y, width, height); + buffer = ResizeA(buffer, x, y, *width, *height); else - buffer = Resize(buffer, x, y, width, height, COLOR); - x = width; - y = height; + buffer = Resize(buffer, x, y, *width, *height, COLOR); + x = *width; + y = *height; } if (bpp == 4) ret = (fb_pixel_t *) CFrameBuffer::getInstance()->convertRGBA2FB(buffer, x, y); else ret = (fb_pixel_t *) CFrameBuffer::getInstance()->convertRGB2FB(buffer, x, y, convertSetupAlpha2Alpha(g_settings.infobar_alpha)); + *width = x; + *height = y; }else - printf ("getImage: Error decoding file %s\n", name.c_str ()); + printf("%s: Error decoding file %s\n", mode_str.c_str(), name.c_str()); free(buffer); }else - printf("getImage: Error open file %s\n", name.c_str ()); - + printf("%s: Error open file %s\n", mode_str.c_str(), name.c_str()); return ret; } -fb_pixel_t * CPictureViewer::getIcon (const std::string & name, int *width, int *height) +fb_pixel_t * CPictureViewer::getImage(const std::string & name, int width, int height) { - int x, y; - CFormathandler *fh; - unsigned char * rgbbuff; - fb_pixel_t * fbbuff = NULL; + return int_getImage(name, &width, &height, true); +} - fh = fh_getsize (name.c_str (), &x, &y, INT_MAX, INT_MAX); - if (!fh) { - return NULL; - } - rgbbuff = (unsigned char *) malloc (x * y * 3); - if (rgbbuff == NULL) { - printf ("getIcon: Error: malloc\n"); - return NULL; - } - if (fh->get_pic (name.c_str (), &rgbbuff, &x, &y) == FH_ERROR_OK) { - int count = x*y; - - //fbbuff = (fb_pixel_t *) malloc(count * sizeof(fb_pixel_t)); - fbbuff = (fb_pixel_t *) cs_malloc_uncached(count * sizeof(fb_pixel_t)); - //printf("getIcon: decoded %s, %d x %d buf %x\n", name.c_str (), x, y, fbbuff); - - for(int i = 0; i < count ; i++) { - int transp = 0; - - if(rgbbuff[i*3] || rgbbuff[i*3+1] || rgbbuff[i*3+2]) - transp = 0xFF; - - fbbuff[i] = (transp << 24) | ((rgbbuff[i*3] << 16) & 0xFF0000) | ((rgbbuff[i*3+1] << 8) & 0xFF00) | (rgbbuff[i*3+2] & 0xFF); - } - - *width = x; - *height = y; - } else - printf ("Error decoding file %s\n", name.c_str ()); - - free (rgbbuff); - - return fbbuff; +fb_pixel_t * CPictureViewer::getIcon(const std::string & name, int *width, int *height) +{ + return int_getImage(name, width, height, false); } unsigned char * CPictureViewer::int_Resize(unsigned char *orgin, int ox, int oy, int dx, int dy, ScalingMode type, unsigned char * dst, bool alpha) diff --git a/src/driver/pictureviewer/pictureviewer.h b/src/driver/pictureviewer/pictureviewer.h index 89fc63a4e..b041baaf1 100644 --- a/src/driver/pictureviewer/pictureviewer.h +++ b/src/driver/pictureviewer/pictureviewer.h @@ -107,6 +107,7 @@ class CPictureViewer void init_handlers(void); void add_format(int (*picsize)(const char *,int *,int*,int,int),int (*picread)(const char *,unsigned char **,int*,int*), int (*id)(const char*)); unsigned char * int_Resize(unsigned char *orgin, int ox, int oy, int dx, int dy, ScalingMode type, unsigned char * dst, bool alpha); + fb_pixel_t * int_getImage(const std::string & name, int *width, int *height, bool GetImage); }; diff --git a/src/driver/pictureviewer/png.cpp b/src/driver/pictureviewer/png.cpp index 0a42de866..4bf6f375c 100644 --- a/src/driver/pictureviewer/png.cpp +++ b/src/driver/pictureviewer/png.cpp @@ -23,23 +23,22 @@ int fh_png_id(const char *name) return(0); } +int fh_png_load(const char *name, unsigned char **buffer, int* xp, int* yp); -int fh_png_load(const char *name,unsigned char **buffer,int* /*xp*/,int* /*yp*/) +int int_png_load(const char *name, unsigned char **buffer, int* xp, int* yp, int* bpp, bool alpha) { static const png_color_16 my_background = {0, 0, 0, 0, 0}; - png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; unsigned int i; - int bit_depth, color_type, interlace_type; - int number_passes,pass; + int bit_depth, color_type, interlace_type, number_passes, pass, int_bpp = 3; png_byte * fbptr; FILE * fh; - if(!(fh=fopen(name,"rb"))) return(FH_ERROR_FILE); - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); + if(!(fh=fopen(name,"rb"))) + return(FH_ERROR_FILE); + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(png_ptr == NULL) { fclose(fh); return(FH_ERROR_FORMAT); @@ -51,7 +50,6 @@ int fh_png_load(const char *name,unsigned char **buffer,int* /*xp*/,int* /*yp*/) fclose(fh); return(FH_ERROR_FORMAT); } - #if (PNG_LIBPNG_VER < 10500) if (setjmp(png_ptr->jmpbuf)) #else @@ -62,63 +60,66 @@ int fh_png_load(const char *name,unsigned char **buffer,int* /*xp*/,int* /*yp*/) fclose(fh); return(FH_ERROR_FORMAT); } - png_init_io(png_ptr,fh); - png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,&interlace_type, NULL, NULL); - - if (color_type == PNG_COLOR_TYPE_PALETTE) + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); + if (alpha) { - png_set_palette_to_rgb(png_ptr); - png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - /* other possibility for png_set_background: use png_get_bKGD */ - } - - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + *bpp = png_get_channels(png_ptr, info_ptr); + if ((*bpp != 4) || !(color_type & PNG_COLOR_MASK_ALPHA)) + { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + fclose(fh); + return fh_png_load(name, buffer, xp, yp); + } + // 24bit PNGs with alpha-channel + int_bpp = 4; + printf("##### [png.cpp]: Image: %s, bit_depth: %d, bpp: %d\n", name, bit_depth, *bpp); +// png_set_swap_alpha(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + }else // All other PNGs { - png_set_gray_to_rgb(png_ptr); - png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - } - - /* this test does not trigger for 8bit-paletted PNGs with newer libpng (1.2.36 at least), - but the data delivered is with alpha channel anyway, so always strip alpha for now - */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_set_palette_to_rgb(png_ptr); + png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + /* other possibility for png_set_background: use png_get_bKGD */ + } + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + png_set_gray_to_rgb(png_ptr); + png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + } + printf("##### [png.cpp]: Image: %s, bit_depth: %d\n", name, bit_depth); + /* this test does not trigger for 8bit-paletted PNGs with newer libpng (1.2.36 at least), + but the data delivered is with alpha channel anyway, so always strip alpha for now + */ #if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR <= 2 && PNG_LIBPNG_VER_RELEASE < 36 - if (color_type & PNG_COLOR_MASK_ALPHA) + if (color_type & PNG_COLOR_MASK_ALPHA) #endif - png_set_strip_alpha(png_ptr); - - if (bit_depth < 8) - png_set_packing(png_ptr); - + png_set_strip_alpha(png_ptr); + if (bit_depth < 8) + png_set_packing(png_ptr); + } if (bit_depth == 16) png_set_strip_16(png_ptr); - - /* on Intel PC ?: - if (bit_depth == 16) - png_set_swap(png_ptr); - */ - number_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr,info_ptr); - - if (width * 3 != png_get_rowbytes(png_ptr, info_ptr)) + unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr); + if (width * int_bpp != rowbytes) { printf("[png.cpp]: Error processing %s - please report (including image).\n", name); - printf(" width: %lu rowbytes: %lu\n", (unsigned long)width, (unsigned long)png_get_rowbytes(png_ptr, info_ptr)); + printf(" width: %lu rowbytes: %lu\n", (unsigned long)width, (unsigned long)rowbytes); fclose(fh); return(FH_ERROR_FORMAT); } - - for(pass = 0; pass < number_passes; pass++) + for (pass = 0; pass < number_passes; pass++) { fbptr = (png_byte *)(*buffer); - for (i = 0; i < height; i++, fbptr += width * 3) - { + for (i = 0; i < height; i++, fbptr += width * int_bpp) png_read_row(png_ptr, fbptr, NULL); - } } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); @@ -128,84 +129,12 @@ int fh_png_load(const char *name,unsigned char **buffer,int* /*xp*/,int* /*yp*/) int png_load_ext(const char *name, unsigned char **buffer, int* xp, int* yp, int* bpp) { - png_structp png_ptr; - png_infop info_ptr; - png_uint_32 width, height; - unsigned int i; - int bit_depth, color_type, interlace_type; - int number_passes,pass; - png_byte * fbptr; - FILE * fh; + return int_png_load(name, buffer, xp, yp, bpp, true); +} - if(!(fh=fopen(name,"rb"))) return(FH_ERROR_FILE); - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); - if(png_ptr == NULL) { - fclose(fh); - return(FH_ERROR_FORMAT); - } - info_ptr = png_create_info_struct(png_ptr); - if(info_ptr == NULL) - { - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - fclose(fh); - return(FH_ERROR_FORMAT); - } - -#if (PNG_LIBPNG_VER < 10500) - if (setjmp(png_ptr->jmpbuf)) -#else - if (setjmp(png_jmpbuf(png_ptr))) -#endif - { - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - fclose(fh); - return(FH_ERROR_FORMAT); - } - - png_init_io(png_ptr, fh); - - png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); - - *bpp = png_get_channels(png_ptr, info_ptr); - if ((*bpp != 4) || !(color_type & PNG_COLOR_MASK_ALPHA)) - { - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - fclose(fh); - return fh_png_load(name, buffer, xp, yp); - } - - printf("##### [png.cpp]: Image: %s, bit_depth: %d, bpp: %d\n", name, bit_depth, *bpp); -// png_set_swap_alpha(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png_ptr); - if (bit_depth == 16) - png_set_strip_16(png_ptr); - - number_passes = png_set_interlace_handling(png_ptr); - png_read_update_info(png_ptr,info_ptr); - unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr); - - if (width * 4 != rowbytes) - { - printf("[png.cpp]: Error processing %s - please report (including image).\n", name); - printf(" width: %lu rowbytes: %lu\n", (unsigned long)width, (unsigned long)rowbytes); - fclose(fh); - return(FH_ERROR_FORMAT); - } - - for(pass = 0; pass < number_passes; pass++) - { - fbptr = (png_byte *)(*buffer); - for (i = 0; i < height; i++, fbptr += width * 4) - png_read_row(png_ptr, fbptr, NULL); - } - png_read_end(png_ptr, info_ptr); - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - fclose(fh); - - return(FH_ERROR_OK); +int fh_png_load(const char *name, unsigned char **buffer, int* xp, int* yp) +{ + return int_png_load(name, buffer, xp, yp, NULL, false); } int fh_png_getsize(const char *name,int *x,int *y, int /*wanted_width*/, int /*wanted_height*/)