/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // Intel License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * The name of Intel Corporation may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or implied warranties, including, but not limited to, the implied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ #include "_cxcore.h" /****************************************************************************************\ * LUT Transform * \****************************************************************************************/ #define ICV_LUT_CASE_C1( type ) \ for( i = 0; i <= size.width-4; i += 4 ) \ { \ type t0 = lut[src[i]]; \ type t1 = lut[src[i+1]]; \ dst[i] = t0; \ dst[i+1] = t1; \ \ t0 = lut[src[i+2]]; \ t1 = lut[src[i+3]]; \ dst[i+2] = t0; \ dst[i+3] = t1; \ } \ \ for( ; i < size.width; i++ ) \ { \ type t0 = lut[src[i]]; \ dst[i] = t0; \ } #define ICV_LUT_CASE_C2( type ) \ for( i = 0; i < size.width; i += 2 ) \ { \ type t0 = lut[src[i]*2]; \ type t1 = lut[src[i+1]*2 + 1]; \ dst[i] = t0; \ dst[i+1] = t1; \ } #define ICV_LUT_CASE_C3( type ) \ for( i = 0; i < size.width; i += 3 ) \ { \ type t0 = lut[src[i]*3]; \ type t1 = lut[src[i+1]*3 + 1]; \ type t2 = lut[src[i+2]*3 + 2]; \ dst[i] = t0; \ dst[i+1] = t1; \ dst[i+2] = t2; \ } #define ICV_LUT_CASE_C4( type ) \ for( i = 0; i < size.width; i += 4 ) \ { \ type t0 = lut[src[i]*4]; \ type t1 = lut[src[i+1]*4 + 1]; \ dst[i] = t0; \ dst[i+1] = t1; \ t0 = lut[src[i+2]*4 + 2]; \ t1 = lut[src[i+3]*4 + 3]; \ dst[i+2] = t0; \ dst[i+3] = t1; \ } #define ICV_DEF_LUT_FUNC_8U_CN( flavor, dsttype, cn ) \ CvStatus CV_STDCALL icvLUT_Transform8u_##flavor##_C##cn##R( \ const uchar* src, int srcstep, \ dsttype* dst, int dststep, CvSize size, \ const dsttype* lut ) \ { \ size.width *= cn; \ dststep /= sizeof(dst[0]); \ for( ; size.height--; src += srcstep, dst += dststep ) \ { \ int i; \ ICV_LUT_CASE_C##cn( dsttype ) \ } \ \ return CV_OK; \ } ICV_DEF_LUT_FUNC_8U_CN( 8u, uchar, 1 ) ICV_DEF_LUT_FUNC_8U_CN( 16u, ushort, 1 ) ICV_DEF_LUT_FUNC_8U_CN( 32s, int, 1 ) ICV_DEF_LUT_FUNC_8U_CN( 64f, double, 1 ) ICV_DEF_LUT_FUNC_8U_CN( 8u, uchar, 2 ) ICV_DEF_LUT_FUNC_8U_CN( 8u, uchar, 3 ) ICV_DEF_LUT_FUNC_8U_CN( 8u, uchar, 4 ) #define ICV_DEF_LUT_FUNC_8U( flavor, dsttype ) \ static CvStatus CV_STDCALL \ icvLUT_Transform8u_##flavor##_CnR( \ const uchar* src, int srcstep, \ dsttype* dst, int dststep, CvSize size, \ const dsttype* _lut, int cn ) \ { \ int max_block_size = (1 << 10)*cn; \ dsttype lutp[1024]; \ int i, k; \ \ size.width *= cn; \ dststep /= sizeof(dst[0]); \ \ if( size.width*size.height < 256 ) \ { \ for( ; size.height--; src+=srcstep, dst+=dststep ) \ for( k = 0; k < cn; k++ ) \ for( i = 0; i < size.width; i += cn ) \ dst[i+k] = _lut[src[i+k]*cn+k]; \ return CV_OK; \ } \ \ /* repack the lut to planar layout */ \ for( k = 0; k < cn; k++ ) \ for( i = 0; i < 256; i++ ) \ lutp[i+k*256] = _lut[i*cn+k]; \ \ for( ; size.height--; src += srcstep, dst += dststep ) \ { \ for( i = 0; i < size.width; ) \ { \ int j, limit = MIN(size.width,i+max_block_size);\ for( k=0; k<cn; k++, src++, dst++ ) \ { \ const dsttype* lut = lutp + k*256; \ for( j = i; j <= limit - cn*2; j += cn*2 ) \ { \ dsttype t0 = lut[src[j]]; \ dsttype t1 = lut[src[j+cn]]; \ dst[j] = t0; dst[j+cn] = t1; \ } \ \ for( ; j < limit; j += cn ) \ dst[j] = lut[src[j]]; \ } \ src -= cn; \ dst -= cn; \ i += limit; \ } \ } \ \ return CV_OK; \ } ICV_DEF_LUT_FUNC_8U( 8u, uchar ) ICV_DEF_LUT_FUNC_8U( 16u, ushort ) ICV_DEF_LUT_FUNC_8U( 32s, int ) ICV_DEF_LUT_FUNC_8U( 64f, double ) #undef icvLUT_Transform8u_8s_C1R #undef icvLUT_Transform8u_16s_C1R #undef icvLUT_Transform8u_32f_C1R #define icvLUT_Transform8u_8s_C1R icvLUT_Transform8u_8u_C1R #define icvLUT_Transform8u_16s_C1R icvLUT_Transform8u_16u_C1R #define icvLUT_Transform8u_32f_C1R icvLUT_Transform8u_32s_C1R #define icvLUT_Transform8u_8s_CnR icvLUT_Transform8u_8u_CnR #define icvLUT_Transform8u_16s_CnR icvLUT_Transform8u_16u_CnR #define icvLUT_Transform8u_32f_CnR icvLUT_Transform8u_32s_CnR CV_DEF_INIT_FUNC_TAB_2D( LUT_Transform8u, C1R ) CV_DEF_INIT_FUNC_TAB_2D( LUT_Transform8u, CnR ) typedef CvStatus (CV_STDCALL * CvLUT_TransformCnFunc)( const void* src, int srcstep, void* dst, int dststep, CvSize size, const void* lut, int cn ); CV_IMPL void cvLUT( const void* srcarr, void* dstarr, const void* lutarr ) { static CvFuncTable lut_c1_tab, lut_cn_tab; static CvLUT_TransformFunc lut_8u_tab[4]; static int inittab = 0; CV_FUNCNAME( "cvLUT" ); __BEGIN__; int coi1 = 0, coi2 = 0; int depth, cn, lut_cn; CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; CvMat lutstub, *lut = (CvMat*)lutarr; uchar* lut_data; uchar* shuffled_lut = 0; CvSize size; if( !inittab ) { icvInitLUT_Transform8uC1RTable( &lut_c1_tab ); icvInitLUT_Transform8uCnRTable( &lut_cn_tab ); lut_8u_tab[0] = (CvLUT_TransformFunc)icvLUT_Transform8u_8u_C1R; lut_8u_tab[1] = (CvLUT_TransformFunc)icvLUT_Transform8u_8u_C2R; lut_8u_tab[2] = (CvLUT_TransformFunc)icvLUT_Transform8u_8u_C3R; lut_8u_tab[3] = (CvLUT_TransformFunc)icvLUT_Transform8u_8u_C4R; inittab = 1; } if( !CV_IS_MAT(src) ) CV_CALL( src = cvGetMat( src, &srcstub, &coi1 )); if( !CV_IS_MAT(dst) ) CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 )); if( !CV_IS_MAT(lut) ) CV_CALL( lut = cvGetMat( lut, &lutstub )); if( coi1 != 0 || coi2 != 0 ) CV_ERROR( CV_BadCOI, "" ); if( !CV_ARE_SIZES_EQ( src, dst )) CV_ERROR( CV_StsUnmatchedSizes, "" ); if( !CV_ARE_CNS_EQ( src, dst )) CV_ERROR( CV_StsUnmatchedFormats, "" ); if( CV_MAT_DEPTH( src->type ) > CV_8S ) CV_ERROR( CV_StsUnsupportedFormat, "" ); depth = CV_MAT_DEPTH( dst->type ); cn = CV_MAT_CN( dst->type ); lut_cn = CV_MAT_CN( lut->type ); if( !CV_IS_MAT_CONT(lut->type) || (lut_cn != 1 && lut_cn != cn) || !CV_ARE_DEPTHS_EQ( dst, lut ) || lut->width*lut->height != 256 ) CV_ERROR( CV_StsBadArg, "The LUT must be continuous array \n" "with 256 elements of the same type as destination" ); size = cvGetMatSize( src ); if( lut_cn == 1 ) { size.width *= cn; cn = 1; } if( CV_IS_MAT_CONT( src->type & dst->type )) { size.width *= size.height; size.height = 1; } lut_data = lut->data.ptr; if( CV_MAT_DEPTH( src->type ) == CV_8S ) { int half_size = CV_ELEM_SIZE1(depth)*cn*128; shuffled_lut = (uchar*)cvStackAlloc(half_size*2); // shuffle lut memcpy( shuffled_lut, lut_data + half_size, half_size ); memcpy( shuffled_lut + half_size, lut_data, half_size ); lut_data = shuffled_lut; } if( lut_cn == 1 || (lut_cn <= 4 && depth == CV_8U) ) { CvLUT_TransformFunc func = depth == CV_8U ? lut_8u_tab[cn-1] : (CvLUT_TransformFunc)(lut_c1_tab.fn_2d[depth]); if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( src->data.ptr, src->step, dst->data.ptr, dst->step, size, lut_data )); } else { CvLUT_TransformCnFunc func = (CvLUT_TransformCnFunc)(lut_cn_tab.fn_2d[depth]); if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( src->data.ptr, src->step, dst->data.ptr, dst->step, size, lut_data, cn )); } __END__; } /* End of file. */