diff --git a/src/driver/framebuffer.cpp b/src/driver/framebuffer.cpp index ec387d513..19a1fe0cb 100644 --- a/src/driver/framebuffer.cpp +++ b/src/driver/framebuffer.cpp @@ -1618,32 +1618,49 @@ void CFrameBuffer::Unlock() locked = false; } -void * CFrameBuffer::convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp) +void * CFrameBuffer::int_convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp, bool alpha) { unsigned long i; unsigned int *fbbuff; - unsigned long count = x*y; + unsigned long count = x * y; - //fbbuff = (unsigned int *) malloc(count * sizeof(unsigned int)); fbbuff = (unsigned int *) cs_malloc_uncached(count * sizeof(unsigned int)); if(fbbuff == NULL) { - printf("convertRGB2FB: Error: malloc\n"); + printf("convertRGB2FB%s: Error: cs_malloc_uncached\n", ((alpha) ? " (Alpha)" : "")); return NULL; } - for(i = 0; i < count ; i++) { - 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); + if (alpha) + { + for(i = 0; i < count ; i++) + fbbuff[i] = ((rgbbuff[i*4+3] << 24) & 0xFF000000) | + ((rgbbuff[i*4] << 16) & 0x00FF0000) | + ((rgbbuff[i*4+1] << 8) & 0x0000FF00) | + ((rgbbuff[i*4+2]) & 0x000000FF); + }else + { + for(i = 0; i < count ; i++) + { + 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); + } } - return (void *) fbbuff; } +void * CFrameBuffer::convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp) +{ + return int_convertRGB2FB(rgbbuff, x, y, transp, false); +} + +void * CFrameBuffer::convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y) +{ + return int_convertRGB2FB(rgbbuff, x, y, 0, true); +} + void CFrameBuffer::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp) { int xc, yc; diff --git a/src/driver/framebuffer.h b/src/driver/framebuffer.h index c91b5c5a2..f9e813385 100644 --- a/src/driver/framebuffer.h +++ b/src/driver/framebuffer.h @@ -114,6 +114,8 @@ class CFrameBuffer bool locked; std::map icon_cache; int cache_size; + void * int_convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp, bool alpha); + public: fb_pixel_t realcolor[256]; @@ -213,6 +215,7 @@ class CFrameBuffer inline void waitForIdle(void) {}; #endif void* convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp = 0xFF); + void* convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y); void displayRGB(unsigned char *rgbbuff, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, bool clearfb = true, int transp = 0xFF); void blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp = 0, uint32_t yp = 0, bool transp = false); bool blitToPrimary(unsigned int * data, int dx, int dy, int sw, int sh); diff --git a/src/driver/pictureviewer/pictureviewer.cpp b/src/driver/pictureviewer/pictureviewer.cpp index 29750c6eb..3996d3e83 100644 --- a/src/driver/pictureviewer/pictureviewer.cpp +++ b/src/driver/pictureviewer/pictureviewer.cpp @@ -25,6 +25,7 @@ extern int fh_jpeg_id (const char *); #ifdef FBV_SUPPORT_PNG extern int fh_png_getsize (const char *, int *, int *, int, int); extern int fh_png_load (const char *, unsigned char **, int *, int *); +extern int png_load_ext (const char * name, unsigned char ** buffer, int * xp, int * yp, int * bpp); extern int fh_png_id (const char *); #endif #ifdef FBV_SUPPORT_BMP @@ -450,8 +451,8 @@ bool CPictureViewer::GetLogoName(uint64_t channel_id, std::string ChannelName, s sprintf(strChanId, "%llx", channel_id & 0xFFFFFFFFFFFFULL); /* first the channel-id, then the channelname */ std::string strLogoName[2] = { (std::string)strChanId, ChannelName }; - /* first jpg, then gif */ - std::string strLogoExt[3] = { ".jpg", ".gif" , ".png" }; + /* first png, then jpg, then gif */ + std::string strLogoExt[3] = { ".png", ".jpg" , ".gif" }; for (i = 0; i < 2; i++) { @@ -522,37 +523,51 @@ 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::getImage(const std::string & name, int width, int height) { - int x, y; + int x, y, bpp = 0; CFormathandler *fh; unsigned char * buffer; fb_pixel_t * ret = NULL; + int load_ret; - fh = fh_getsize (name.c_str (), &x, &y, INT_MAX, INT_MAX); - if (fh) { - - buffer = (unsigned char *) malloc (x * y * 3); - if (buffer == NULL) { + fh = fh_getsize(name.c_str(), &x, &y, INT_MAX, INT_MAX); + if (fh) + { + buffer = (unsigned char *) malloc (x * y * 4); + if (buffer == NULL) + { printf ("getImage: Error: malloc\n"); return false; } - if (fh->get_pic (name.c_str (), &buffer, &x, &y) == FH_ERROR_OK) { -printf("getImage: decoded %s, %d x %d \n", name.c_str (), x, y); +#ifdef FBV_SUPPORT_PNG + if (name.find(".png")) // FIXME + load_ret = png_load_ext(name.c_str(), &buffer, &x, &y, &bpp); + else +#endif + 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("getImage: resize %s to %d x %d \n", name.c_str (), width, height); - buffer = Resize(buffer, x, y, width, height, COLOR); + printf("getImage: resize %s to %d x %d \n", name.c_str(), width, height); + if (bpp == 4) + buffer = ResizeA(buffer, x, y, width, height); + else + buffer = Resize(buffer, x, y, width, height, COLOR); x = width; y = height; - } - ret = (fb_pixel_t *) CFrameBuffer::getInstance()->convertRGB2FB(buffer, x, y, convertSetupAlpha2Alpha(g_settings.infobar_alpha)); - } else { - printf ("Error decoding file %s\n", name.c_str ()); - } + } + 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)); + }else + printf ("getImage: Error decoding file %s\n", name.c_str ()); free(buffer); - } else - printf("Error open file %s\n", name.c_str ()); + }else + printf("getImage: Error open file %s\n", name.c_str ()); return ret; } @@ -599,21 +614,23 @@ fb_pixel_t * CPictureViewer::getIcon (const std::string & name, int *width, int return fbbuff; } -unsigned char * CPictureViewer::Resize(unsigned char *orgin, int ox, int oy, int dx, int dy, ScalingMode type, unsigned char * dst) +unsigned char * CPictureViewer::int_Resize(unsigned char *orgin, int ox, int oy, int dx, int dy, ScalingMode type, unsigned char * dst, bool alpha) { unsigned char * cr; - if(dst == NULL) { - cr = (unsigned char*) malloc(dx*dy*3); + if(dst == NULL) + { + cr = (unsigned char*) malloc(dx * dy * ((alpha) ? 4 : 3)); - if(cr==NULL) + if(cr == NULL) { - printf("Error: malloc\n"); + printf("Resize Error: malloc\n"); return(orgin); } - } else + }else cr = dst; - if(type == SIMPLE) { + if(type == SIMPLE) + { unsigned char *p,*l; int i,j,k,ip; l=cr; @@ -627,10 +644,11 @@ unsigned char * CPictureViewer::Resize(unsigned char *orgin, int ox, int oy, int memmove(l+k, p+ip, 3); } } - } else { + }else + { unsigned char *p,*q; int i,j,k,l,ya,yb; - int sq,r,g,b; + int sq,r,g,b,a; p=cr; @@ -644,24 +662,57 @@ unsigned char * CPictureViewer::Resize(unsigned char *orgin, int ox, int oy, int if(xb_v[i]>=ox) xb_v[i]=ox-1; } - for(j=0;j=oy) yb=oy-1; - for(i=0;i=oy) yb=oy-1; + for(i=0;i=oy) yb=oy-1; + for(i=0;ijmpbuf)) +#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_getsize(const char *name,int *x,int *y, int /*wanted_width*/, int /*wanted_height*/) { png_structp png_ptr;