%% options copyright owner = Dirk Krause copyright year = 2011-2014 license = bsd %% header #ifdef __cplusplus extern "C" { #endif /** Check bits per component really used and alpha and color usage. As a result of this function (bp->cf)->realbits, (bp->cf)->realcolor, and (bp->cf)->realalpha is set. @param bp Bitmap image file to check. @param at Analysis type, DK3_BIF_ANALYSIS_xxx, @param pcomm Communicator object. @param minpb Minimum progress bar value (0-1000). @param maxpb Maximum progress bar value (0-1000). see @ref bifanalysis. */ void dk3bif_analyze_progress( dk3_bif_t *bp, int at, void *pcomm, int minpb, int maxpb ); /** Check bits per component really used and alpha and color usage. As a result of this function (bp->cf)->realbits, (bp->cf)->realcolor, and (bp->cf)->realalpha is set. @param bp Bitmap image file to check. @param at Analysis type, DK3_BIF_ANALYSIS_xxx, see @ref bifanalysis. */ void dk3bif_analyze(dk3_bif_t *bp, int at); #ifdef __cplusplus } #endif %% module #include "dk3const.h" #include "dk3mem.h" #include "dk3str.h" #include "dk3sf.h" #include "dk3sto.h" #include "dk3bif.h" #include "dk3bifa.h" #include "dk3pixre.h" #include "dk3ma.h" #include "dk3bits.h" #include "dk3app.h" #include #if DK3_USE_WX #include #include #include "DkWxCommunicator.h" #endif $!trace-include /** Default texts for debug messages in bit depth analysis. */ static dkChar const * const dk3bif_analysis_msg[] = { $!string-table macro=dkT,file=dk3bifa.str # # 0 # Image analysis: Original image is color image. # # 1 # Image analysis: Original image is greyscaled image. # # 2 # Image analysis: Can reduce image to greyscaled image. # # 3 # Image analysis: Really a color image. # # 4 # Image analysis: Original image contains alpha channel. # # 5 # Image analysis: No alpha channel in original image. # # 6 # Image analysis: Alpha channel is used. # # 7 # Image analysis: Alpha channel is not used. # # 8 9 # Image analysis: Original image contains bits per component. # # 10 11 # Image analysis: Output image contains bits per component. $!end }; #if 0 /** Find number of significant bits in pixel value. @param v Pixel value to inspect. @param nbits Bits per component information from image. @return Number of significant bits in @a v. */ static size_t dk3bif_real_bits(dk3_bif_pixel_t v, size_t nbits) { size_t back = 1; int st = 0; size_t i; size_t j; $? "+ dk3bif_real_bits %u %u", (unsigned)v, (unsigned)nbits for(i = 0; i < nbits; i++) { j = nbits - i - 1; if(i == 0) { if(v & dk3bits_get(j)) { st = 1; } else { st = 0; } back = 1; } else { if(v & dk3bits_get(j)) { if(st == 0) { back = i + 1; } st = 1; } else { if(st == 1) { back = i + 1; } st = 0; } } } $? "- dk3bif_real_bits %u", (unsigned)back return back; } #endif #if DK3_USE_WX /** Show progress during image analysis. Progress is only shown when the module is compiled with DK3_USE_WX defined unequal zero. @param pc Communicator object. @param minpb Minimum progress bar value (0-1000). @param maxpb Maximum progress bar value (0-1000). @param h Image height (number of lines). @param y Current line completed. */ static void dk3bif_show_lines_progress( void *pc, int minpb, int maxpb, dk3_bif_coord_t h, dk3_bif_coord_t y ) { DkWxCommunicator *pComm; unsigned long umax; unsigned long umin; unsigned long uh; unsigned long uy; int ec = 0; if((pc) && (maxpb > minpb) && (h)) { pComm = (DkWxCommunicator *)pc; umax = (unsigned long)maxpb; umin = (unsigned long)minpb; uh = (unsigned long)h; uy = (unsigned long)y; /* umax = umin + (uy + 1UL) * (umax - umin) / (uh); */ umax = dk3ma_ul_add_ok( umin, dk3ma_ul_div_ok( dk3ma_ul_mul_ok( dk3ma_ul_add_ok(uy, 1UL, &ec), dk3ma_ul_sub_ok(umax, umin, &ec), &ec ), uh, &ec ), &ec ); if(ec == 0) { ec = (int)umax; if((minpb <= ec) && (ec <= maxpb)) { pComm->updateGauge(ec); } } } } #endif /** Structure to analyze bit depth of an image frame. */ typedef struct { dk3_pixel_resample_t r01; /**< Pixel resampling to 1 bit. */ dk3_pixel_resample_t r02; /**< Pixel resampling to 2 bit. */ dk3_pixel_resample_t r04; /**< Pixel resampling to 4 bit. */ dk3_pixel_resample_t r08; /**< Pixel resampling to 8 bit. */ dk3_pixel_resample_t r12; /**< Pixel resampling to 12 bit. */ int finished; /**< Flag: Analysis finished. */ int f01; /**< Flag: Can resample to 1 bit. */ int f02; /**< Flag: Can resample to 2 bit. */ int f04; /**< Flag: Can resample to 4 bit. */ int f08; /**< Flag: Can resample to 8 bit. */ int f12; /**< Flag: Can resample to 12 bit. */ } dk3_bif_analyze_bitdepth_t; /** Set up analysis structure. @param p Bitdepth analysis structure. @param at Analysis type. @param srcw Source bit width. */ static void dk3bif_analyze_setup_structure( dk3_bif_analyze_bitdepth_t *p, int at, size_t srcw ) { p->f01 = 0; p->f02 = 0; p->f04 = 0; p->f08 = 0; p->f12 = 0; dk3pixre_set(&(p->r01), srcw, 1); dk3pixre_set(&(p->r02), srcw, 2); dk3pixre_set(&(p->r04), srcw, 4); dk3pixre_set(&(p->r08), srcw, 8); dk3pixre_set(&(p->r12), srcw, 12); p->finished = 1; if ( 1 < srcw) { p->f01 = 1; p->finished = 0; } if ( 2 < srcw) { p->f02 = 1; } if ( 4 < srcw) { p->f04 = 1; } if ( 8 < srcw) { p->f08 = 1; } if (12 < srcw) { p->f12 = 1; } } /** Analyse one pixel value. @param p Bit depth analysis structure. @param v Value to analyze. */ static void dk3bif_analyze_check_bitvalue( dk3_bif_analyze_bitdepth_t *p, dk3_bif_pixel_t v ) { int changed = 0; if (p->f01) { if (!(dk3pixre_can_convert(&(p->r01), v))) { p->f01 = 0; changed = 1; } } if (p->f02) { if (!(dk3pixre_can_convert(&(p->r02), v))) { p->f02 = 0; changed = 1; } } if (p->f04) { if (!(dk3pixre_can_convert(&(p->r04), v))) { p->f04 = 0; changed = 1; } } if (p->f08) { if (!(dk3pixre_can_convert(&(p->r08), v))) { p->f08 = 0; changed = 1; } } if (p->f12) { if (!(dk3pixre_can_convert(&(p->r12), v))) { p->f12 = 0; changed = 1; } } if (changed) { if (!((p->f01) || (p->f02) || (p->f04) || (p->f08) || (p->f12))) { p->finished = 1; } } } void dk3bif_analyze_progress( dk3_bif_t *bp, int at, void *pcomm, int minpb, int maxpb ) { dk3_bif_analyze_bitdepth_t ana; dk3_bif_coord_t x; dk3_bif_coord_t y; int cc; int found_color; int found_alpha; int search_color; int search_alpha; dk3_bif_pixel_t maxval; dk3_bif_pixel_t r; dk3_bif_pixel_t g; dk3_bif_pixel_t b; dk3_bif_pixel_t a; if (bp) { if (bp->cf) { /* Default values for all color space types. */ (bp->cf)->realbits = (bp->cf)->bits; (bp->cf)->realcolor = 0; (bp->cf)->realalpha = 0; switch ((bp->cf)->cs) { /* For some color space we can not do the analysis. */ case DK3_COLOR_SPACE_HSB: case DK3_COLOR_SPACE_YCCK: case DK3_COLOR_SPACE_YCbCr: case DK3_COLOR_SPACE_CMYK: { (bp->cf)->realcolor = 1; (bp->cf)->realalpha = 1; } break; /* Do analysis. */ default: { /* Default values. */ (bp->cf)->realcolor = 0; (bp->cf)->realalpha = 0; search_alpha = 0; search_color = 0; switch ((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { if (DK3_BIF_ANALYSIS_ALPHA & at) { search_alpha = 1; } else { (bp->cf)->realalpha = 1; } } break; } switch ((bp->cf)->cs) { case DK3_COLOR_SPACE_RGB: case DK3_COLOR_SPACE_RGBA: { if (DK3_BIF_ANALYSIS_COLOR & at) { search_color = 1; } else { (bp->cf)->realcolor = 1; } } break; } /* Do analysis */ dk3bif_analyze_setup_structure(&ana, at, (bp->cf)->bits); maxval = dk3pixre_maximum_for_width((bp->cf)->bits); found_color = 0; found_alpha = 0; switch ((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { if((bp->cf)->bgr != (bp->cf)->bgg) { found_color = 1; } if((bp->cf)->bgr != (bp->cf)->bgb) { found_color = 1; } if (DK3_BIF_ANALYSIS_BITS & at) { dk3bif_analyze_check_bitvalue(&ana, (bp->cf)->bgr); dk3bif_analyze_check_bitvalue(&ana, (bp->cf)->bgg); dk3bif_analyze_check_bitvalue(&ana, (bp->cf)->bgb); } } break; } cc = 1; for (y = 0; ((y < (bp->cf)->h) && (cc)); y++) { for (x = 0; ((x < (bp->cf)->w) && (cc)); x++) { switch ((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY: { r = dk3bif_get_pixel_component_not_resampled(bp, x, y, 0); if (DK3_BIF_ANALYSIS_BITS & at) { dk3bif_analyze_check_bitvalue(&ana, r); } } break; case DK3_COLOR_SPACE_GRAY_ALPHA: { r = dk3bif_get_pixel_component_not_resampled(bp, x, y, 0); a = dk3bif_get_pixel_component_not_resampled(bp, x, y, 3); if (DK3_BIF_ANALYSIS_BITS & at) { dk3bif_analyze_check_bitvalue(&ana, r); dk3bif_analyze_check_bitvalue(&ana, a); } if (search_alpha) { if (maxval != a) { found_alpha = 1; } } } break; case DK3_COLOR_SPACE_RGB: { r = dk3bif_get_pixel_component_not_resampled(bp, x, y, 0); g = dk3bif_get_pixel_component_not_resampled(bp, x, y, 1); b = dk3bif_get_pixel_component_not_resampled(bp, x, y, 2); if (DK3_BIF_ANALYSIS_BITS & at) { dk3bif_analyze_check_bitvalue(&ana, r); dk3bif_analyze_check_bitvalue(&ana, g); dk3bif_analyze_check_bitvalue(&ana, b); } if (search_color) { if((r != g) || (r != b)) { found_color = 1; } } } break; case DK3_COLOR_SPACE_RGBA: { r = dk3bif_get_pixel_component_not_resampled(bp, x, y, 0); g = dk3bif_get_pixel_component_not_resampled(bp, x, y, 1); b = dk3bif_get_pixel_component_not_resampled(bp, x, y, 2); a = dk3bif_get_pixel_component_not_resampled(bp, x, y, 3); if (DK3_BIF_ANALYSIS_BITS & at) { dk3bif_analyze_check_bitvalue(&ana, r); dk3bif_analyze_check_bitvalue(&ana, g); dk3bif_analyze_check_bitvalue(&ana, b); dk3bif_analyze_check_bitvalue(&ana, a); } if (search_color) { if((r != g) || (r != b)) { found_color = 1; } } if (search_alpha) { if (maxval != a) { found_alpha = 1; } } } break; } cc = 0; if (DK3_BIF_ANALYSIS_BITS & at) { if(!(ana.finished)) { cc = 1; } } if (search_color) { if(!(found_color)) { cc = 1; } } if (search_alpha) { if(!(found_alpha)) { cc = 1; } } } #if DK3_USE_WX dk3bif_show_lines_progress(pcomm, minpb, maxpb, (bp->cf)->h, y); #endif } /* After analysis apply results. */ if (DK3_BIF_ANALYSIS_BITS & at) { if (ana.f01) { (bp->cf)->realbits = 1; } else { if (ana.f02) { (bp->cf)->realbits = 2; } else { if (ana.f04) { (bp->cf)->realbits = 4; } else { if (ana.f08) { (bp->cf)->realbits = 8; } else { if (ana.f12) { (bp->cf)->realbits = 12; } } } } } } if (search_color) { (bp->cf)->realcolor = found_color; } if (search_alpha) { (bp->cf)->realalpha = found_alpha; } if (bp->app) { if (DK3_LL_DEBUG <= dk3app_max_log_level(bp->app)) { dkChar buffer[128]; dkChar const * const *msg; msg = dk3app_messages( bp->app, dkT("dk3bifa.str"), dk3bif_analysis_msg ); if (DK3_BIF_ANALYSIS_COLOR & at) { switch ((bp->cf)->cs) { case DK3_COLOR_SPACE_RGB: case DK3_COLOR_SPACE_RGBA: { /* Original image: color */ dk3app_log_1(bp->app, DK3_LL_DEBUG, msg, 0); if (found_color) { dk3app_log_1(bp->app, DK3_LL_DEBUG, msg, 3); } else { /* Grayscale image */ dk3app_log_1(bp->app, DK3_LL_DEBUG, msg, 2); } } break; default: { /* Gray image */ dk3app_log_1(bp->app, DK3_LL_DEBUG, msg, 1); } break; } } if (DK3_BIF_ANALYSIS_ALPHA & at) { switch ((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { dk3app_log_1(bp->app, DK3_LL_DEBUG, msg, 4); if (found_alpha) { /* Alpha data found */ dk3app_log_1(bp->app, DK3_LL_DEBUG, msg, 6); } else { /* No real alpha data */ dk3app_log_1(bp->app, DK3_LL_DEBUG, msg, 7); } } break; default: { /* No alpha channel in image */ dk3app_log_1(bp->app, DK3_LL_DEBUG, msg, 5); } break; } } if (DK3_BIF_ANALYSIS_BITS & at) { #if VERSION_BEFORE_20140716 /* Original bits per component */ dk3sf_sprintf3(buffer, dkT("%u"), (unsigned)((bp->cf)->bits)); dk3app_log_3(bp->app, DK3_LL_DEBUG, msg, 8, 9, buffer); /* Output bits per component */ dk3sf_sprintf3(buffer,dkT("%u"),(unsigned)((bp->cf)->realbits)); dk3app_log_3(bp->app, DK3_LL_DEBUG, msg, 10, 11, buffer); #else int res; res = dk3ma_um_to_string( buffer, DK3_SIZEOF(buffer,dkChar), (dk3_um_t)((bp->cf)->bits) ); if (0 != res) { dk3app_log_3(bp->app, DK3_LL_DEBUG, msg, 8, 9, buffer); } res = dk3ma_um_to_string( buffer, DK3_SIZEOF(buffer,dkChar), (dk3_um_t)((bp->cf)->realbits) ); if (0 != res) { dk3app_log_3(bp->app, DK3_LL_DEBUG, msg, 10, 11, buffer); } #endif } } } } break; } } } #if DK3_USE_WX dk3bif_show_lines_progress(pcomm, minpb, maxpb, 1UL, 0UL); #endif } void dk3bif_analyze(dk3_bif_t *bp, int at) { dk3bif_analyze_progress(bp, at, NULL, 0, 1000); }