From b7996917b34edd9c47ca5ffd53f0bd681bd9c79a Mon Sep 17 00:00:00 2001 From: Jiyong Min Date: Thu, 1 Sep 2016 17:02:56 +0900 Subject: [PATCH] Add color pick enabled feature for product TV Change-Id: I339ca379d7b7cea44dc7dbccfa08c6254e519152 Signed-off-by: Jiyong Min --- packaging/libpng.spec | 7 +++ png.h | 33 ++++++++++ pngread.c | 124 ++++++++++++++++++++++++++++++++++++++ pngrutil.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++ scripts/symbols.def | 1 + 5 files changed, 329 insertions(+) diff --git a/packaging/libpng.spec b/packaging/libpng.spec index f8f35c3..624570d 100644 --- a/packaging/libpng.spec +++ b/packaging/libpng.spec @@ -34,6 +34,13 @@ for developing programs using the PNG (Portable Network Graphics) library. cp %{SOURCE1001} . %build +%ifarch %{arm} +CFLAGS+=" -D_ARCH_ARM_ -mfpu=neon" +%endif + +%if 0%{?TIZEN_PRODUCT_TV} +CFLAGS+=" -D_PNG_COLOR_PICK_ENABLED_ -D_PNG_SEQUENTIAL_READ_SUPPORTED_" +%endif %configure \ --disable-static \ diff --git a/png.h b/png.h index 123201d..f297f47 100644 --- a/png.h +++ b/png.h @@ -581,6 +581,32 @@ typedef struct png_text_struct png_charp lang_key; /* keyword translated UTF-8 string, 0 or more chars or a NULL pointer */ } png_text; + +/* VD_TIZEN_ONLY */ +/* Adding PNG Color pick feature.*/ +typedef enum _Png_Color_Pick_Region_ +{ + PNG_COLORPICK_TOP = 0, + PNG_COLORPICK_MIDDLE, + PNG_COLORPICK_BOTTOM, +}PngColorPickRegion; + +struct _Png_Color_Pick_Struct_ +{ + unsigned int sumR; + unsigned int sumG; + unsigned int sumB; + int enable; + int perc; + int x1; + int y1; + int x2; + int y2; + PngColorPickRegion region; +}; +typedef struct _Png_Color_Pick_Struct_ PngPickColor; /* TODO : PngPickColor will be changed to PngColorPick in future*/ +/* VD_TIZEN_ONLY_END */ + typedef png_text * png_textp; typedef const png_text * png_const_textp; typedef png_text * * png_textpp; @@ -3106,6 +3132,13 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, int onoff)); #endif /* SET_OPTION */ +/* VD_TIZEN_ONLY */ +/* Read the whole image into memory at once. */ +PNG_EXPORT(245, void, png_read_image_with_pick_color, (png_structp png_ptr, + png_bytepp image, + PngPickColor *pickcolor)); +/* VD_TIZEN_ONLY_END */ + /******************************************************************************* * END OF HARDWARE AND SOFTWARE OPTIONS ******************************************************************************/ diff --git a/pngread.c b/pngread.c index dca3d7d..dfe6015 100644 --- a/pngread.c +++ b/pngread.c @@ -746,6 +746,130 @@ png_read_image(png_structrp png_ptr, png_bytepp image) } } } + +#ifdef _PNG_COLOR_PICK_ENABLED_ +void PNGAPI +png_read_image_with_pick_color(png_structp png_ptr, png_bytepp image, PngPickColor *pickcolor) +{ + png_uint_32 i, image_height; + int pass, j; + png_uint_32 /*k = 0,*/ image_bpp = 0, image_width; + png_bytepp rp; + //png_bytep rc; + unsigned int npixels; + int perc_enable_y1, perc_enable_y2; + png_debug(1, "in png_read_image"); + + if (png_ptr == NULL || pickcolor == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + pass = png_set_interlace_handling(png_ptr); + /* And make sure transforms are initialized. */ + png_start_read_image(png_ptr); + } + else + { + if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) + { + /* Caller called png_start_read_image or png_read_update_info without + * first turning on the PNG_INTERLACE transform. We can fix this here, + * but the caller should do it! + */ + png_warning(png_ptr, "Interlace handling should be turned on when " + "using png_read_image"); + /* Make sure this is set correctly */ + png_ptr->num_rows = png_ptr->height; + } + + /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in + * the above error case. + */ + pass = png_set_interlace_handling(png_ptr); + } +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled"); + + pass = 1; +#endif + + image_height=png_ptr->height; + image_bpp=png_ptr->rowbytes; + image_width=png_ptr->width; + png_ptr->user_chunk_ptr = pickcolor; + + if(pickcolor->perc < 0) + { + png_error(png_ptr, "ColorPick percentage is negative"); + return; + } + if( (pickcolor->region < PNG_COLORPICK_TOP) || (pickcolor->region > PNG_COLORPICK_BOTTOM)) + { + png_error(png_ptr, "ColorPick Region is out of bound"); + return; + } + if(pickcolor->region == PNG_COLORPICK_TOP) + { + perc_enable_y1 = 0; + perc_enable_y2 = (pickcolor->perc*image_height/100) - 1; + } + else if(pickcolor->region == PNG_COLORPICK_MIDDLE) + { + perc_enable_y1 = (image_height/2) - (((pickcolor->perc/2)*image_height)/100); + perc_enable_y2 = perc_enable_y1 + ((pickcolor->perc*image_height)/100) - 1; + } + else + { + perc_enable_y1 = (image_height) - ( pickcolor->perc * image_height / 100 ); + perc_enable_y2 = image_height - 1; + } + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + pickcolor->enable = 0; + if( pickcolor->perc > 0 ) + { + if( (int)i >= perc_enable_y1 && (int)i <= perc_enable_y2) + { + pickcolor->enable = 1; + } + } + else + { + if( ((int)i >= pickcolor->y1) && ((int)i <= pickcolor->y2) ) + { + pickcolor->enable = 1; + } + } + png_read_row(png_ptr, *rp, NULL); + rp++; + } + } + + + if(pickcolor->perc > 0) + { + npixels = (pickcolor->perc*image_height*image_width)/100; + } + else + { + npixels = (pickcolor->x2-pickcolor->x1+1)*(pickcolor->y2-pickcolor->y1+1); + } + if(npixels > 0) + { + pickcolor->sumR = pickcolor->sumR/npixels; + pickcolor->sumG = pickcolor->sumG/npixels; + pickcolor->sumB = pickcolor->sumB/npixels; + } +} +#endif /* _PNG_COLOR_PICK_ENABLED_ */ #endif /* SEQUENTIAL_READ */ #ifdef PNG_SEQUENTIAL_READ_SUPPORTED diff --git a/pngrutil.c b/pngrutil.c index c9747fc..f3eb84f 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -14,6 +14,9 @@ * libpng itself during the course of reading an image. */ +#ifdef _ARCH_ARM_ +#include "arm_neon.h" +#endif #include "pngpriv.h" #ifdef PNG_READ_SUPPORTED @@ -3046,6 +3049,167 @@ png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) } } +#ifdef _PNG_COLOR_PICK_ENABLED_ +#ifdef _ARCH_ARM_ +void +copy_src_to_dst(png_bytep dp, png_bytep sp, int width, + int row_stride, int nplanes, PngPickColor *png_pickcolor) +{ + int j; + unsigned char *src = (unsigned char *)sp; + unsigned char *dst = (unsigned char *)dp; + + unsigned long long sumRGBA[4] = {0, 0, 0, 0}; + const int const0 = 0; + + + uint32x4_t sumR_32x4 = vmovq_n_u32 ( 0 ); + uint32x4_t sumG_32x4 = vmovq_n_u32 ( 0 ); + uint32x4_t sumB_32x4 = vmovq_n_u32 ( 0 ); + + uint8x16_t R_8x16; + uint8x16_t G_8x16; + uint8x16_t B_8x16; + + uint64x1x3_t sumRGB_64x1; + + for(j = 0; j < width-(width&0xf); j += 16) + { + if(nplanes == 3) + { + uint8x16x3_t rgb = vld3q_u8 ( src ); + vst3q_u8(dst, rgb); + R_8x16 = rgb.val[0]; + G_8x16 = rgb.val[1]; + B_8x16 = rgb.val[2]; + } + else + { + uint8x16x4_t rgb = vld4q_u8 ( src ); + vst4q_u8(dst, rgb); + R_8x16 = rgb.val[0]; + G_8x16 = rgb.val[1]; + B_8x16 = rgb.val[2]; + } + + if(png_pickcolor && png_pickcolor->enable) + { + if(png_pickcolor->perc > 0) + { + uint16x8_t sumR_16x8 = vpaddlq_u8 ( R_8x16 ); + uint16x8_t sumG_16x8 = vpaddlq_u8 ( G_8x16 ); + uint16x8_t sumB_16x8 = vpaddlq_u8 ( B_8x16 ); + + sumR_32x4 = vpadalq_u16 ( sumR_32x4, sumR_16x8 ); + sumG_32x4 = vpadalq_u16 ( sumG_32x4, sumG_16x8 ); + sumB_32x4 = vpadalq_u16 ( sumB_32x4, sumB_16x8 ); + } + else if( (png_pickcolor->x1 > j) && (png_pickcolor->x1 < j + 16) ) + { + int x = png_pickcolor->x1; + unsigned char *from = sp + (png_pickcolor->x1 * nplanes); + while( x < j + 16 ) + { + png_pickcolor->sumR += from[0]; + png_pickcolor->sumG += from[1]; + png_pickcolor->sumB += from[2]; + from += nplanes; + x ++; + } + } + else if( (png_pickcolor->x2 >= j) && (png_pickcolor->x2 < j + 16) ) + { + int x = j; + unsigned char *from = sp + (j * nplanes); + while(x <= png_pickcolor->x2) + { + png_pickcolor->sumR += from[0]; + png_pickcolor->sumG += from[1]; + png_pickcolor->sumB += from[2]; + from += nplanes; + x ++; + } + } + else if ( (j >= png_pickcolor->x1) && (j+15 <= png_pickcolor->x2) ) + { + uint16x8_t sumR_16x8 = vpaddlq_u8 ( R_8x16 ); + uint16x8_t sumG_16x8 = vpaddlq_u8 ( G_8x16 ); + uint16x8_t sumB_16x8 = vpaddlq_u8 ( B_8x16 ); + + sumR_32x4 = vpadalq_u16 ( sumR_32x4, sumR_16x8 ); + sumG_32x4 = vpadalq_u16 ( sumG_32x4, sumG_16x8 ); + sumB_32x4 = vpadalq_u16 ( sumB_32x4, sumB_16x8 ); + } + } + dst += (nplanes*16); + src += (nplanes*16); + } + + if(png_pickcolor && png_pickcolor->enable) + { + + uint64x2_t sumR_64x2 = vpaddlq_u32 ( sumR_32x4 ); + uint64x2_t sumG_64x2 = vpaddlq_u32 ( sumG_32x4 ); + uint64x2_t sumB_64x2 = vpaddlq_u32 ( sumB_32x4 ); + + uint64x1_t sumR_Lo_64x1 = vget_low_u64 ( sumR_64x2 ); + uint64x1_t sumR_Hi_64x1 = vget_high_u64 ( sumR_64x2 ); + + uint64x1_t sumG_Lo_64x1 = vget_low_u64 ( sumG_64x2 ); + uint64x1_t sumG_Hi_64x1 = vget_high_u64 ( sumG_64x2 ); + + uint64x1_t sumB_Lo_64x1 = vget_low_u64 ( sumB_64x2 ); + uint64x1_t sumB_Hi_64x1 = vget_high_u64 ( sumB_64x2 ); + + sumRGB_64x1.val[0] = vadd_u64 ( sumR_Lo_64x1, sumR_Hi_64x1 ); + sumRGB_64x1.val[1] = vadd_u64 ( sumG_Lo_64x1, sumG_Hi_64x1 ); + sumRGB_64x1.val[2] = vadd_u64 ( sumB_Lo_64x1, sumB_Hi_64x1 ); + + vst3_u64( sumRGBA, sumRGB_64x1); + + png_pickcolor->sumR += sumRGBA[0]; + png_pickcolor->sumG += sumRGBA[1]; + png_pickcolor->sumB += sumRGBA[2]; + } + + memcpy(dst, src, (width-j)*nplanes); + if(png_pickcolor && png_pickcolor->enable) + { + if(png_pickcolor->perc <= 0) + { + if(j < png_pickcolor->x1) + { + j = png_pickcolor->x1; + dst = dp + (j*nplanes); + } + width = png_pickcolor->x2; + } + for(; j < width ; j ++) + { + png_pickcolor->sumR += dst[0]; + png_pickcolor->sumG += dst[1]; + png_pickcolor->sumB += dst[2]; + dst += nplanes; + } + } +} + +void copy_row(png_bytep dp, png_bytep sp, int width, int pixel_bits, PngPickColor *png_pickcolor) +{ + int row_stride = PNG_ROWBYTES(pixel_bits, width); + if(pixel_bits == 24 || pixel_bits == 32) + { + copy_src_to_dst(dp, sp, width, row_stride, pixel_bits >> 3, png_pickcolor); + } + else + { + memcpy(dp, sp, row_stride); + } + +} +#endif +#endif + /* Combines the row recently read in with the existing pixels in the row. This * routine takes care of alpha and transparency if requested. This routine also * handles the two methods of progressive display of interlaced images, diff --git a/scripts/symbols.def b/scripts/symbols.def index 4c35fd7..4df4a4f 100644 --- a/scripts/symbols.def +++ b/scripts/symbols.def @@ -249,3 +249,4 @@ EXPORTS png_set_check_for_invalid_index @242 png_get_palette_max @243 png_set_option @244 + png_read_image_with_pick_color @245 -- 2.7.4