%% options copyright owner = Dirk Krause copyright year = 2011-2014 license = bsd %% header #ifdef __cplusplus extern "C" { #endif /** Set up resampling structure. This function must be called before you start any conversion using dk3pixre_convert(). @param pp Resampling structure. @param inw Input number of bits per component. @param outw Output number of bits per component. @return 1 on success, 0 on error. */ int dk3pixre_set(dk3_pixel_resample_t *pp, size_t inw, size_t outw); /** Check whether a pixel value can be converted without quality loss. @param pp Pixel resampling structure. @param inval Value to convert. @return 1 on success, 0 on error. */ int dk3pixre_can_convert(dk3_pixel_resample_t const *pp, dk3_bif_pixel_t inval); /** Resample pixel. The dk3_pixel_resample_t structure must already be set up using dk3pixre_set(). @param pp Resampling structure. @param inval Value to resample. @return Pixel component resampled. */ dk3_bif_pixel_t dk3pixre_convert(dk3_pixel_resample_t const *pp, dk3_bif_pixel_t inval); /** Get mask for maximum output value. @param pp Resampling structure. @return Maximum value for given number of output bits. */ dk3_bif_pixel_t dk3pixre_get_max_value(dk3_pixel_resample_t const *pp); /** Get one pixel component value from packed bytes. @param row Pixel data. @param vi Value index. @param bpc Number of bits per component. @return Pixel component value. */ dk3_bif_pixel_t dk3pixre_get_value_from_packed_bytes( unsigned char const *row, dk3_bif_coord_t vi, size_t bpc ); /** Get maximum pixel value for a given bit width. @param w Bit width. @return Maximum value on success, 0 on error. */ dk3_bif_pixel_t dk3pixre_maximum_for_width(size_t w); #ifdef __cplusplus } #endif %% module #include "dk3all.h" #include "dk3pixre.h" $!trace-include dk3_bif_pixel_t dk3pixre_maximum_for_width(size_t w) { dk3_bif_pixel_t back = 0; unsigned val = 1; size_t i; for(i = 0; i < w; i++) { val = val * 2; } if(val) { val--; back = (dk3_bif_pixel_t)val; #if VERSION_BEFORE_20140809 if (((unsigned)back) != val) { back = 0; } #else if (val > (unsigned)(DK3_US_MAX)) { back = 0; } #endif } return back; } int dk3pixre_set(dk3_pixel_resample_t *pp, size_t inw, size_t outw) { int back = 0; dk3_bif_pixel_t im; dk3_bif_pixel_t om; if (pp) { im = dk3pixre_maximum_for_width(inw); om = dk3pixre_maximum_for_width(outw); if ((im) && (om)) { pp->iw = inw; pp->ow = outw; pp->im = im; pp->om = om; pp->im2 = im / 2; back = 1; } } return back; } #if DK3_SIZEOF_INT >= (2 * DK3_SIZEOF_BIF_PIXEL_T) /* BEGIN unsigned */ dk3_bif_pixel_t dk3pixre_convert(dk3_pixel_resample_t const *pp, dk3_bif_pixel_t inval) { unsigned counter; unsigned res; unsigned rem; int ec = 0; dk3_bif_pixel_t back; back = inval; if (pp) { if (pp->iw != pp->ow) { if (1 < pp->ow) { counter = dk3ma_ui_mul_ok( (unsigned)inval, (unsigned)(pp->om), &ec ); if (0 == ec) { if (pp->im) { res = counter / (unsigned)(pp->im); rem = counter % (unsigned)(pp->im); if (rem > ((unsigned)(pp->im2))) { res++; } back = (dk3_bif_pixel_t)res; #if VERSION_BEFORE_20140809 if (((unsigned)back) != res) { back = 0; } #else if (res > (unsigned)(DK3_US_MAX)) { back = 0; } #endif } } } else { back = ((inval > pp->im2) ? 1 : 0); } } } return back; } int dk3pixre_can_convert(dk3_pixel_resample_t const *pp, dk3_bif_pixel_t inval) { unsigned counter; unsigned rem; unsigned res; int ec = 0; int back = 0; #if VERSION_BEFORE_20140809 dk3_bif_pixel_t tv; #endif if (pp) { if (pp->iw != pp->ow) { if (1 < pp->ow) { counter = dk3ma_ui_mul_ok( (unsigned)inval, (unsigned)(pp->om), &ec ); if (0 == ec) { if (pp->im) { res = counter / (unsigned)(pp->im); rem = counter % (unsigned)(pp->im); if (0 == rem) { #if VERSION_BEFORE_20140809 tv = (dk3_bif_pixel_t)res; if (((unsigned)tv) == res) { back = 1; } #else if (res <= (unsigned)(DK3_US_MAX)) { back = 1; } #endif } } } } else { if ((0 == inval) || (pp->im == inval)) { back = 1; } } } else { back = 1; } } return back; } /* END unsigned */ #else #if DK3_SIZEOF_LONG >= (2 * DK3_SIZEOF_BIF_PIXEL_T) /* BEGIN unsigned long */ dk3_bif_pixel_t dk3pixre_convert(dk3_pixel_resample_t const *pp, dk3_bif_pixel_t inval) { unsigned long counter; unsigned long res; unsigned long rem; int ec = 0; dk3_bif_pixel_t back; back = inval; if (pp) { if (pp->iw != pp->ow) { counter = dk3ma_ul_mul_ok( (unsigned long)inval, (unsigned long)(pp->om), &ec ); if (0 == ec) { if (pp->im) { res = counter / (unsigned long)(pp->im); rem = counter % (unsigned long)(pp->im); if (rem > (((unsigned long)(pp->im)) / 2UL)) { res++; } back = (dk3_bif_pixel_t)res; #if VERSION_BEFORE_20140809 if (((unsigned long)back) != res) { back = 0; } #else if (res > (unsigned long)(DK3_US_MAX)) { back = 0; } #endif } } } } return back; } int dk3pixre_can_convert(dk3_pixel_resample_t const *pp, dk3_bif_pixel_t inval) { unsigned long counter; unsigned long rem; unsigned long res; int ec = 0; int back = 0; #if VERSION_BEFORE_20140809 dk3_bif_pixel_t tv; #endif if (pp) { if (pp->iw != pp->ow) { counter = dk3ma_ul_mul_ok( (unsigned long)inval, (unsigned long)(pp->om), &ec ); if (0 == ec) { if (pp->im) { res = counter / (unsigned long)(pp->im); rem = counter % (unsigned long)(pp->im); if (0 == rem) { #if VERSION_BEFORE_20140809 tv = (dk3_bif_pixel_t)res; if (((unsigned long)tv) == res) { back = 1; } #else if (res <= (unsigned long)(DK3_US_MAX)) { back = 1; } #endif } } } } else { back = 1; } } return back; } /* END unsigned long */ #else /* BEGIN dk3_um_t */ dk3_bif_pixel_t dk3pixre_convert(dk3_pixel_resample_t const *pp, dk3_bif_pixel_t inval) { dk3_um_t counter; dk3_um_t res; dk3_um_t rem; int ec = 0; dk3_bif_pixel_t back; back = inval; if (pp) { if (pp->iw != pp->ow) { counter = dk3ma_um_mul_ok( (dk3_um_t)inval, (dk3_um_t)(pp->om), &ec ); if (0 == ec) { if (pp->im) { res = counter / (dk3_um_t)(pp->im); rem = counter % (dk3_um_t)(pp->im); if (rem > (((dk3_um_t)(pp->im)) / DK3_UM_2)) { res++; } back = (dk3_bif_pixel_t)res; if (((dk3_um_t)back) != res) { back = 0; } } } } } return back; } int dk3pixre_can_convert(dk3_pixel_resample_t const *pp, dk3_bif_pixel_t inval) { dk3_um_t counter; dk3_um_t rem; dk3_um_t res; int ec = 0; int back = 0; dk3_bif_pixel_t tv; if (pp) { if (pp->iw != pp->ow) { counter = dk3ma_um_mul_ok( (dk3_um_t)inval, (dk3_um_t)(pp->om), &ec ); if (0 == ec) { if (pp->im) { res = counter / (dk3_um_t)(pp->im); rem = counter % (dk3_um_t)(pp->im); if (0 == rem) { tv = (dk3_bif_pixel_t)res; if (((dk3_um_t)tv) == res) { back = 1; } } } } } else { back = 1; } } return back; } /* END dk3_um_t */ #endif #endif dk3_bif_pixel_t dk3pixre_get_value_from_packed_bytes( unsigned char const *row, dk3_bif_coord_t vi, size_t bpc ) { unsigned short const *us; unsigned char uc; dk3_bif_coord_t byteindex; dk3_bif_coord_t inbyte; dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; switch(bpc) { case 16: { us = (unsigned short const *)row; back = us[vi]; } break; case 8: { back = (dk3_bif_pixel_t)(row[vi]); back &= 0x00FFU; } break; case 4: { byteindex = vi / 2L; inbyte = vi % 2L; uc = row[byteindex]; switch((int)inbyte) { case 0: { uc = uc >> 4; } break; } back = (dk3_bif_pixel_t)uc; back &= 0x000FU; } break; case 2: { byteindex = vi / 4L; inbyte = vi % 4L; uc = row[byteindex]; switch((int)inbyte) { case 0: { uc = uc >> 6; } break; case 1: { uc = uc >> 4; } break; case 2: { uc = uc >> 2; } break; } back = (dk3_bif_pixel_t)uc; back &= 0x0003U; } break; case 1: { byteindex = vi / 8L; inbyte = vi % 8L; uc = row[byteindex]; switch((int)inbyte) { case 0: { uc = uc >> 7; } break; case 1: { uc = uc >> 6; } break; case 2: { uc = uc >> 5; } break; case 3: { uc = uc >> 4; } break; case 4: { uc = uc >> 3; } break; case 5: { uc = uc >> 2; } break; case 6: { uc = uc >> 1; } break; } back = (dk3_bif_pixel_t)uc; back &= 0x0001U; } break; } return back; } dk3_bif_pixel_t dk3pixre_get_max_value(dk3_pixel_resample_t const *pp) { dk3_bif_pixel_t back = (dk3_bif_pixel_t)0U; if(pp) { back = pp->om; } return back; }