/*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" /****************************************************************************************\ * Splitting/extracting array channels * \****************************************************************************************/ #define ICV_DEF_PX2PL2PX_ENTRY_C2( arrtype_ptr, ptr ) \ arrtype_ptr plane0 = ptr[0]; \ arrtype_ptr plane1 = ptr[1]; #define ICV_DEF_PX2PL2PX_ENTRY_C3( arrtype_ptr, ptr ) \ arrtype_ptr plane0 = ptr[0]; \ arrtype_ptr plane1 = ptr[1]; \ arrtype_ptr plane2 = ptr[2]; #define ICV_DEF_PX2PL2PX_ENTRY_C4( arrtype_ptr, ptr ) \ arrtype_ptr plane0 = ptr[0]; \ arrtype_ptr plane1 = ptr[1]; \ arrtype_ptr plane2 = ptr[2]; \ arrtype_ptr plane3 = ptr[3]; #define ICV_DEF_PX2PL_C2( arrtype, len ) \ { \ int j; \ \ for( j = 0; j < (len); j++, (src) += 2 ) \ { \ arrtype t0 = (src)[0]; \ arrtype t1 = (src)[1]; \ \ plane0[j] = t0; \ plane1[j] = t1; \ } \ plane0 += dststep; \ plane1 += dststep; \ } #define ICV_DEF_PX2PL_C3( arrtype, len ) \ { \ int j; \ \ for( j = 0; j < (len); j++, (src) += 3 ) \ { \ arrtype t0 = (src)[0]; \ arrtype t1 = (src)[1]; \ arrtype t2 = (src)[2]; \ \ plane0[j] = t0; \ plane1[j] = t1; \ plane2[j] = t2; \ } \ plane0 += dststep; \ plane1 += dststep; \ plane2 += dststep; \ } #define ICV_DEF_PX2PL_C4( arrtype, len ) \ { \ int j; \ \ for( j = 0; j < (len); j++, (src) += 4 ) \ { \ arrtype t0 = (src)[0]; \ arrtype t1 = (src)[1]; \ \ plane0[j] = t0; \ plane1[j] = t1; \ \ t0 = (src)[2]; \ t1 = (src)[3]; \ \ plane2[j] = t0; \ plane3[j] = t1; \ } \ plane0 += dststep; \ plane1 += dststep; \ plane2 += dststep; \ plane3 += dststep; \ } #define ICV_DEF_PX2PL_COI( arrtype, len, cn ) \ { \ int j; \ \ for( j = 0; j <= (len) - 4; j += 4, (src) += 4*(cn))\ { \ arrtype t0 = (src)[0]; \ arrtype t1 = (src)[(cn)]; \ \ (dst)[j] = t0; \ (dst)[j+1] = t1; \ \ t0 = (src)[(cn)*2]; \ t1 = (src)[(cn)*3]; \ \ (dst)[j+2] = t0; \ (dst)[j+3] = t1; \ } \ \ for( ; j < (len); j++, (src) += (cn)) \ { \ (dst)[j] = (src)[0]; \ } \ } #define ICV_DEF_COPY_PX2PL_FUNC_2D( arrtype, flavor, \ cn, entry_macro ) \ IPCVAPI_IMPL( CvStatus, icvCopy_##flavor##_C##cn##P##cn##R,\ ( const arrtype* src, int srcstep, \ arrtype** dst, int dststep, CvSize size ), \ (src, srcstep, dst, dststep, size)) \ { \ entry_macro(arrtype*, dst); \ srcstep /= sizeof(src[0]); \ dststep /= sizeof(dst[0][0]); \ \ for( ; size.height--; src += srcstep ) \ { \ ICV_DEF_PX2PL_C##cn( arrtype, size.width ); \ src -= size.width*(cn); \ } \ \ return CV_OK; \ } #define ICV_DEF_COPY_PX2PL_FUNC_2D_COI( arrtype, flavor )\ IPCVAPI_IMPL( CvStatus, icvCopy_##flavor##_CnC1CR, \ ( const arrtype* src, int srcstep, arrtype* dst, int dststep,\ CvSize size, int cn, int coi ), \ (src, srcstep, dst, dststep, size, cn, coi)) \ { \ src += coi - 1; \ srcstep /= sizeof(src[0]); \ dststep /= sizeof(dst[0]); \ \ for( ; size.height--; src += srcstep, dst += dststep )\ { \ ICV_DEF_PX2PL_COI( arrtype, size.width, cn ); \ src -= size.width*(cn); \ } \ \ return CV_OK; \ } ICV_DEF_COPY_PX2PL_FUNC_2D( uchar, 8u, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 ) ICV_DEF_COPY_PX2PL_FUNC_2D( uchar, 8u, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 ) ICV_DEF_COPY_PX2PL_FUNC_2D( uchar, 8u, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 ) ICV_DEF_COPY_PX2PL_FUNC_2D( ushort, 16s, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 ) ICV_DEF_COPY_PX2PL_FUNC_2D( ushort, 16s, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 ) ICV_DEF_COPY_PX2PL_FUNC_2D( ushort, 16s, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 ) ICV_DEF_COPY_PX2PL_FUNC_2D( int, 32f, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 ) ICV_DEF_COPY_PX2PL_FUNC_2D( int, 32f, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 ) ICV_DEF_COPY_PX2PL_FUNC_2D( int, 32f, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 ) ICV_DEF_COPY_PX2PL_FUNC_2D( int64, 64f, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 ) ICV_DEF_COPY_PX2PL_FUNC_2D( int64, 64f, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 ) ICV_DEF_COPY_PX2PL_FUNC_2D( int64, 64f, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 ) ICV_DEF_COPY_PX2PL_FUNC_2D_COI( uchar, 8u ) ICV_DEF_COPY_PX2PL_FUNC_2D_COI( ushort, 16s ) ICV_DEF_COPY_PX2PL_FUNC_2D_COI( int, 32f ) ICV_DEF_COPY_PX2PL_FUNC_2D_COI( int64, 64f ) /****************************************************************************************\ * Merging/inserting array channels * \****************************************************************************************/ #define ICV_DEF_PL2PX_C2( arrtype, len ) \ { \ int j; \ \ for( j = 0; j < (len); j++, (dst) += 2 )\ { \ arrtype t0 = plane0[j]; \ arrtype t1 = plane1[j]; \ \ dst[0] = t0; \ dst[1] = t1; \ } \ plane0 += srcstep; \ plane1 += srcstep; \ } #define ICV_DEF_PL2PX_C3( arrtype, len ) \ { \ int j; \ \ for( j = 0; j < (len); j++, (dst) += 3 )\ { \ arrtype t0 = plane0[j]; \ arrtype t1 = plane1[j]; \ arrtype t2 = plane2[j]; \ \ dst[0] = t0; \ dst[1] = t1; \ dst[2] = t2; \ } \ plane0 += srcstep; \ plane1 += srcstep; \ plane2 += srcstep; \ } #define ICV_DEF_PL2PX_C4( arrtype, len ) \ { \ int j; \ \ for( j = 0; j < (len); j++, (dst) += 4 )\ { \ arrtype t0 = plane0[j]; \ arrtype t1 = plane1[j]; \ \ dst[0] = t0; \ dst[1] = t1; \ \ t0 = plane2[j]; \ t1 = plane3[j]; \ \ dst[2] = t0; \ dst[3] = t1; \ } \ plane0 += srcstep; \ plane1 += srcstep; \ plane2 += srcstep; \ plane3 += srcstep; \ } #define ICV_DEF_PL2PX_COI( arrtype, len, cn ) \ { \ int j; \ \ for( j = 0; j <= (len) - 4; j += 4, (dst) += 4*(cn))\ { \ arrtype t0 = (src)[j]; \ arrtype t1 = (src)[j+1]; \ \ (dst)[0] = t0; \ (dst)[(cn)] = t1; \ \ t0 = (src)[j+2]; \ t1 = (src)[j+3]; \ \ (dst)[(cn)*2] = t0; \ (dst)[(cn)*3] = t1; \ } \ \ for( ; j < (len); j++, (dst) += (cn)) \ { \ (dst)[0] = (src)[j]; \ } \ } #define ICV_DEF_COPY_PL2PX_FUNC_2D( arrtype, flavor, cn, entry_macro ) \ IPCVAPI_IMPL( CvStatus, icvCopy_##flavor##_P##cn##C##cn##R, \ ( const arrtype** src, int srcstep, \ arrtype* dst, int dststep, CvSize size ), \ (src, srcstep, dst, dststep, size)) \ { \ entry_macro(const arrtype*, src); \ srcstep /= sizeof(src[0][0]); \ dststep /= sizeof(dst[0]); \ \ for( ; size.height--; dst += dststep ) \ { \ ICV_DEF_PL2PX_C##cn( arrtype, size.width ); \ dst -= size.width*(cn); \ } \ \ return CV_OK; \ } #define ICV_DEF_COPY_PL2PX_FUNC_2D_COI( arrtype, flavor ) \ IPCVAPI_IMPL( CvStatus, icvCopy_##flavor##_C1CnCR, \ ( const arrtype* src, int srcstep, \ arrtype* dst, int dststep, \ CvSize size, int cn, int coi ), \ (src, srcstep, dst, dststep, size, cn, coi)) \ { \ dst += coi - 1; \ srcstep /= sizeof(src[0]); dststep /= sizeof(dst[0]); \ \ for( ; size.height--; src += srcstep, dst += dststep ) \ { \ ICV_DEF_PL2PX_COI( arrtype, size.width, cn ); \ dst -= size.width*(cn); \ } \ \ return CV_OK; \ } ICV_DEF_COPY_PL2PX_FUNC_2D( uchar, 8u, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 ) ICV_DEF_COPY_PL2PX_FUNC_2D( uchar, 8u, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 ) ICV_DEF_COPY_PL2PX_FUNC_2D( uchar, 8u, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 ) ICV_DEF_COPY_PL2PX_FUNC_2D( ushort, 16s, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 ) ICV_DEF_COPY_PL2PX_FUNC_2D( ushort, 16s, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 ) ICV_DEF_COPY_PL2PX_FUNC_2D( ushort, 16s, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 ) ICV_DEF_COPY_PL2PX_FUNC_2D( int, 32f, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 ) ICV_DEF_COPY_PL2PX_FUNC_2D( int, 32f, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 ) ICV_DEF_COPY_PL2PX_FUNC_2D( int, 32f, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 ) ICV_DEF_COPY_PL2PX_FUNC_2D( int64, 64f, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 ) ICV_DEF_COPY_PL2PX_FUNC_2D( int64, 64f, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 ) ICV_DEF_COPY_PL2PX_FUNC_2D( int64, 64f, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 ) ICV_DEF_COPY_PL2PX_FUNC_2D_COI( uchar, 8u ) ICV_DEF_COPY_PL2PX_FUNC_2D_COI( ushort, 16s ) ICV_DEF_COPY_PL2PX_FUNC_2D_COI( int, 32f ) ICV_DEF_COPY_PL2PX_FUNC_2D_COI( int64, 64f ) #define ICV_DEF_PXPLPX_TAB( name, FROM, TO ) \ static void \ name( CvBigFuncTable* tab ) \ { \ tab->fn_2d[CV_8UC2] = (void*)icvCopy##_8u_##FROM##2##TO##2R; \ tab->fn_2d[CV_8UC3] = (void*)icvCopy##_8u_##FROM##3##TO##3R; \ tab->fn_2d[CV_8UC4] = (void*)icvCopy##_8u_##FROM##4##TO##4R; \ \ tab->fn_2d[CV_8SC2] = (void*)icvCopy##_8u_##FROM##2##TO##2R; \ tab->fn_2d[CV_8SC3] = (void*)icvCopy##_8u_##FROM##3##TO##3R; \ tab->fn_2d[CV_8SC4] = (void*)icvCopy##_8u_##FROM##4##TO##4R; \ \ tab->fn_2d[CV_16UC2] = (void*)icvCopy##_16s_##FROM##2##TO##2R; \ tab->fn_2d[CV_16UC3] = (void*)icvCopy##_16s_##FROM##3##TO##3R; \ tab->fn_2d[CV_16UC4] = (void*)icvCopy##_16s_##FROM##4##TO##4R; \ \ tab->fn_2d[CV_16SC2] = (void*)icvCopy##_16s_##FROM##2##TO##2R; \ tab->fn_2d[CV_16SC3] = (void*)icvCopy##_16s_##FROM##3##TO##3R; \ tab->fn_2d[CV_16SC4] = (void*)icvCopy##_16s_##FROM##4##TO##4R; \ \ tab->fn_2d[CV_32SC2] = (void*)icvCopy##_32f_##FROM##2##TO##2R; \ tab->fn_2d[CV_32SC3] = (void*)icvCopy##_32f_##FROM##3##TO##3R; \ tab->fn_2d[CV_32SC4] = (void*)icvCopy##_32f_##FROM##4##TO##4R; \ \ tab->fn_2d[CV_32FC2] = (void*)icvCopy##_32f_##FROM##2##TO##2R; \ tab->fn_2d[CV_32FC3] = (void*)icvCopy##_32f_##FROM##3##TO##3R; \ tab->fn_2d[CV_32FC4] = (void*)icvCopy##_32f_##FROM##4##TO##4R; \ \ tab->fn_2d[CV_64FC2] = (void*)icvCopy##_64f_##FROM##2##TO##2R; \ tab->fn_2d[CV_64FC3] = (void*)icvCopy##_64f_##FROM##3##TO##3R; \ tab->fn_2d[CV_64FC4] = (void*)icvCopy##_64f_##FROM##4##TO##4R; \ } #define ICV_DEF_PXPLCOI_TAB( name, FROM, TO ) \ static void \ name( CvFuncTable* tab ) \ { \ tab->fn_2d[CV_8U] = (void*)icvCopy##_8u_##FROM##TO##CR; \ tab->fn_2d[CV_8S] = (void*)icvCopy##_8u_##FROM##TO##CR; \ tab->fn_2d[CV_16U] = (void*)icvCopy##_16s_##FROM##TO##CR; \ tab->fn_2d[CV_16S] = (void*)icvCopy##_16s_##FROM##TO##CR; \ tab->fn_2d[CV_32S] = (void*)icvCopy##_32f_##FROM##TO##CR; \ tab->fn_2d[CV_32F] = (void*)icvCopy##_32f_##FROM##TO##CR; \ tab->fn_2d[CV_64F] = (void*)icvCopy##_64f_##FROM##TO##CR; \ } ICV_DEF_PXPLPX_TAB( icvInitSplitRTable, C, P ) ICV_DEF_PXPLCOI_TAB( icvInitSplitRCoiTable, Cn, C1 ) ICV_DEF_PXPLPX_TAB( icvInitCvtPlaneToPixRTable, P, C ) ICV_DEF_PXPLCOI_TAB( icvInitCvtPlaneToPixRCoiTable, C1, Cn ) typedef CvStatus (CV_STDCALL *CvSplitFunc)( const void* src, int srcstep, void** dst, int dststep, CvSize size); typedef CvStatus (CV_STDCALL *CvExtractPlaneFunc)( const void* src, int srcstep, void* dst, int dststep, CvSize size, int cn, int coi ); typedef CvStatus (CV_STDCALL *CvMergeFunc)( const void** src, int srcstep, void* dst, int dststep, CvSize size); typedef CvStatus (CV_STDCALL *CvInsertPlaneFunc)( const void* src, int srcstep, void* dst, int dststep, CvSize size, int cn, int coi ); CV_IMPL void cvSplit( const void* srcarr, void* dstarr0, void* dstarr1, void* dstarr2, void* dstarr3 ) { static CvBigFuncTable pxpl_tab; static CvFuncTable pxplcoi_tab; static int inittab = 0; CV_FUNCNAME( "cvSplit" ); __BEGIN__; CvMat stub[5], *dst[4], *src = (CvMat*)srcarr; CvSize size; void* dstptr[4] = { 0, 0, 0, 0 }; int type, cn, coi = 0; int i, nzplanes = 0, nzidx = -1; int cont_flag; int src_step, dst_step = 0; if( !inittab ) { icvInitSplitRTable( &pxpl_tab ); icvInitSplitRCoiTable( &pxplcoi_tab ); inittab = 1; } dst[0] = (CvMat*)dstarr0; dst[1] = (CvMat*)dstarr1; dst[2] = (CvMat*)dstarr2; dst[3] = (CvMat*)dstarr3; CV_CALL( src = cvGetMat( src, stub + 4, &coi )); //if( coi != 0 ) // CV_ERROR( CV_BadCOI, "" ); type = CV_MAT_TYPE( src->type ); cn = CV_MAT_CN( type ); cont_flag = src->type; if( cn == 1 ) CV_ERROR( CV_BadNumChannels, "" ); for( i = 0; i < 4; i++ ) { if( dst[i] ) { nzplanes++; nzidx = i; CV_CALL( dst[i] = cvGetMat( dst[i], stub + i )); if( CV_MAT_CN( dst[i]->type ) != 1 ) CV_ERROR( CV_BadNumChannels, "" ); if( !CV_ARE_DEPTHS_EQ( dst[i], src )) CV_ERROR( CV_StsUnmatchedFormats, "" ); if( !CV_ARE_SIZES_EQ( dst[i], src )) CV_ERROR( CV_StsUnmatchedSizes, "" ); if( nzplanes > i && i > 0 && dst[i]->step != dst[i-1]->step ) CV_ERROR( CV_BadStep, "" ); dst_step = dst[i]->step; dstptr[nzplanes-1] = dst[i]->data.ptr; cont_flag &= dst[i]->type; } } src_step = src->step; size = cvGetMatSize( src ); if( CV_IS_MAT_CONT( cont_flag )) { size.width *= size.height; src_step = dst_step = CV_STUB_STEP; size.height = 1; } if( nzplanes == cn ) { CvSplitFunc func = (CvSplitFunc)pxpl_tab.fn_2d[type]; if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( src->data.ptr, src_step, dstptr, dst_step, size )); } else if( nzplanes == 1 ) { CvExtractPlaneFunc func = (CvExtractPlaneFunc)pxplcoi_tab.fn_2d[CV_MAT_DEPTH(type)]; if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( src->data.ptr, src_step, dst[nzidx]->data.ptr, dst_step, size, cn, nzidx + 1 )); } else { CV_ERROR( CV_StsBadArg, "Either all output planes or only one output plane should be non zero" ); } __END__; } CV_IMPL void cvMerge( const void* srcarr0, const void* srcarr1, const void* srcarr2, const void* srcarr3, void* dstarr ) { static CvBigFuncTable plpx_tab; static CvFuncTable plpxcoi_tab; static int inittab = 0; CV_FUNCNAME( "cvMerge" ); __BEGIN__; int src_step = 0, dst_step; CvMat stub[5], *src[4], *dst = (CvMat*)dstarr; CvSize size; const void* srcptr[4] = { 0, 0, 0, 0 }; int type, cn, coi = 0; int i, nzplanes = 0, nzidx = -1; int cont_flag; if( !inittab ) { icvInitCvtPlaneToPixRTable( &plpx_tab ); icvInitCvtPlaneToPixRCoiTable( &plpxcoi_tab ); inittab = 1; } src[0] = (CvMat*)srcarr0; src[1] = (CvMat*)srcarr1; src[2] = (CvMat*)srcarr2; src[3] = (CvMat*)srcarr3; CV_CALL( dst = cvGetMat( dst, stub + 4, &coi )); type = CV_MAT_TYPE( dst->type ); cn = CV_MAT_CN( type ); cont_flag = dst->type; if( cn == 1 ) CV_ERROR( CV_BadNumChannels, "" ); for( i = 0; i < 4; i++ ) { if( src[i] ) { nzplanes++; nzidx = i; CV_CALL( src[i] = cvGetMat( src[i], stub + i )); if( CV_MAT_CN( src[i]->type ) != 1 ) CV_ERROR( CV_BadNumChannels, "" ); if( !CV_ARE_DEPTHS_EQ( src[i], dst )) CV_ERROR( CV_StsUnmatchedFormats, "" ); if( !CV_ARE_SIZES_EQ( src[i], dst )) CV_ERROR( CV_StsUnmatchedSizes, "" ); if( nzplanes > i && i > 0 && src[i]->step != src[i-1]->step ) CV_ERROR( CV_BadStep, "" ); src_step = src[i]->step; srcptr[nzplanes-1] = (const void*)(src[i]->data.ptr); cont_flag &= src[i]->type; } } size = cvGetMatSize( dst ); dst_step = dst->step; if( CV_IS_MAT_CONT( cont_flag )) { size.width *= size.height; src_step = dst_step = CV_STUB_STEP; size.height = 1; } if( nzplanes == cn ) { CvMergeFunc func = (CvMergeFunc)plpx_tab.fn_2d[type]; if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( srcptr, src_step, dst->data.ptr, dst_step, size )); } else if( nzplanes == 1 ) { CvInsertPlaneFunc func = (CvInsertPlaneFunc)plpxcoi_tab.fn_2d[CV_MAT_DEPTH(type)]; if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( src[nzidx]->data.ptr, src_step, dst->data.ptr, dst_step, size, cn, nzidx + 1 )); } else { CV_ERROR( CV_StsBadArg, "Either all input planes or only one input plane should be non zero" ); } __END__; } /****************************************************************************************\ * Generalized split/merge: mixing channels * \****************************************************************************************/ #define ICV_DEF_MIX_CH_FUNC_2D( arrtype, flavor ) \ static CvStatus CV_STDCALL \ icvMixChannels_##flavor( const arrtype** src, int* sdelta0, \ int* sdelta1, arrtype** dst, \ int* ddelta0, int* ddelta1, \ int n, CvSize size ) \ { \ int i, k; \ int block_size0 = n == 1 ? size.width : 1024; \ \ for( ; size.height--; ) \ { \ int remaining = size.width; \ for( ; remaining > 0; ) \ { \ int block_size = MIN( remaining, block_size0 ); \ for( k = 0; k < n; k++ ) \ { \ const arrtype* s = src[k]; \ arrtype* d = dst[k]; \ int ds = sdelta1[k], dd = ddelta1[k]; \ if( s ) \ { \ for( i = 0; i <= block_size - 2; i += 2, \ s += ds*2, d += dd*2 ) \ { \ arrtype t0 = s[0], t1 = s[ds]; \ d[0] = t0; d[dd] = t1; \ } \ if( i < block_size ) \ d[0] = s[0], s += ds, d += dd; \ src[k] = s; \ } \ else \ { \ for( i=0; i <= block_size-2; i+=2, d+=dd*2 )\ d[0] = d[dd] = 0; \ if( i < block_size ) \ d[0] = 0, d += dd; \ } \ dst[k] = d; \ } \ remaining -= block_size; \ } \ for( k = 0; k < n; k++ ) \ src[k] += sdelta0[k], dst[k] += ddelta0[k]; \ } \ \ return CV_OK; \ } ICV_DEF_MIX_CH_FUNC_2D( uchar, 8u ) ICV_DEF_MIX_CH_FUNC_2D( ushort, 16u ) ICV_DEF_MIX_CH_FUNC_2D( int, 32s ) ICV_DEF_MIX_CH_FUNC_2D( int64, 64s ) static void icvInitMixChannelsTab( CvFuncTable* tab ) { tab->fn_2d[CV_8U] = (void*)icvMixChannels_8u; tab->fn_2d[CV_8S] = (void*)icvMixChannels_8u; tab->fn_2d[CV_16U] = (void*)icvMixChannels_16u; tab->fn_2d[CV_16S] = (void*)icvMixChannels_16u; tab->fn_2d[CV_32S] = (void*)icvMixChannels_32s; tab->fn_2d[CV_32F] = (void*)icvMixChannels_32s; tab->fn_2d[CV_64F] = (void*)icvMixChannels_64s; } typedef CvStatus (CV_STDCALL * CvMixChannelsFunc)( const void** src, int* sdelta0, int* sdelta1, void** dst, int* ddelta0, int* ddelta1, int n, CvSize size ); CV_IMPL void cvMixChannels( const CvArr** src, int src_count, CvArr** dst, int dst_count, const int* from_to, int pair_count ) { static CvFuncTable mixcn_tab; static int inittab = 0; uchar* buffer = 0; int heap_alloc = 0; CV_FUNCNAME( "cvMixChannels" ); __BEGIN__; CvSize size = {0,0}; int depth = -1, elem_size = 1; int *sdelta0 = 0, *sdelta1 = 0, *ddelta0 = 0, *ddelta1 = 0; uchar **sptr = 0, **dptr = 0; uchar **src0 = 0, **dst0 = 0; int* src_cn = 0, *dst_cn = 0; int* src_step = 0, *dst_step = 0; int buf_size, i, k; int cont_flag = CV_MAT_CONT_FLAG; CvMixChannelsFunc func; if( !inittab ) { icvInitMixChannelsTab( &mixcn_tab ); inittab = 1; } src_count = MAX( src_count, 0 ); if( !src && src_count > 0 ) CV_ERROR( CV_StsNullPtr, "The input array of arrays is NULL" ); if( !dst ) CV_ERROR( CV_StsNullPtr, "The output array of arrays is NULL" ); if( dst_count <= 0 || pair_count <= 0 ) CV_ERROR( CV_StsOutOfRange, "The number of output arrays and the number of copied channels must be positive" ); if( !from_to ) CV_ERROR( CV_StsNullPtr, "The array of copied channel indices is NULL" ); buf_size = (src_count + dst_count + 2)* (sizeof(src0[0]) + sizeof(src_cn[0]) + sizeof(src_step[0])) + pair_count*2*(sizeof(sptr[0]) + sizeof(sdelta0[0]) + sizeof(sdelta1[0])); if( buf_size > CV_MAX_LOCAL_SIZE ) { CV_CALL( buffer = (uchar*)cvAlloc( buf_size ) ); heap_alloc = 1; } else buffer = (uchar*)cvStackAlloc( buf_size ); src0 = (uchar**)buffer; dst0 = src0 + src_count; src_cn = (int*)(dst0 + dst_count); dst_cn = src_cn + src_count + 1; src_step = dst_cn + dst_count + 1; dst_step = src_step + src_count; sptr = (uchar**)cvAlignPtr( dst_step + dst_count, (int)sizeof(void*) ); dptr = sptr + pair_count; sdelta0 = (int*)(dptr + pair_count); sdelta1 = sdelta0 + pair_count; ddelta0 = sdelta1 + pair_count; ddelta1 = ddelta0 + pair_count; src_cn[0] = dst_cn[0] = 0; for( k = 0; k < 2; k++ ) { for( i = 0; i < (k == 0 ? src_count : dst_count); i++ ) { CvMat stub, *mat = (CvMat*)(k == 0 ? src[i] : dst[i]); int cn; if( !CV_IS_MAT(mat) ) CV_CALL( mat = cvGetMat( mat, &stub )); if( depth < 0 ) { depth = CV_MAT_DEPTH(mat->type); elem_size = CV_ELEM_SIZE1(depth); size = cvGetMatSize(mat); } if( CV_MAT_DEPTH(mat->type) != depth ) CV_ERROR( CV_StsUnmatchedFormats, "All the arrays must have the same bit depth" ); if( mat->cols != size.width || mat->rows != size.height ) CV_ERROR( CV_StsUnmatchedSizes, "All the arrays must have the same size" ); if( k == 0 ) { src0[i] = mat->data.ptr; cn = CV_MAT_CN(mat->type); src_cn[i+1] = src_cn[i] + cn; src_step[i] = mat->step / elem_size - size.width * cn; } else { dst0[i] = mat->data.ptr; cn = CV_MAT_CN(mat->type); dst_cn[i+1] = dst_cn[i] + cn; dst_step[i] = mat->step / elem_size - size.width * cn; } cont_flag &= mat->type; } } if( cont_flag ) { size.width *= size.height; size.height = 1; } for( i = 0; i < pair_count; i++ ) { for( k = 0; k < 2; k++ ) { int cn = from_to[i*2 + k]; const int* cn_arr = k == 0 ? src_cn : dst_cn; int a = 0, b = k == 0 ? src_count-1 : dst_count-1; if( cn < 0 || cn >= cn_arr[b+1] ) { if( k == 0 && cn < 0 ) { sptr[i] = 0; sdelta0[i] = sdelta1[i] = 0; continue; } else { char err_str[100]; sprintf( err_str, "channel index #%d in the array of pairs is negative " "or exceeds the total number of channels in all the %s arrays", i*2+k, k == 0 ? "input" : "output" ); CV_ERROR( CV_StsOutOfRange, err_str ); } } for( ; cn >= cn_arr[a+1]; a++ ) ; if( k == 0 ) { sptr[i] = src0[a] + (cn - cn_arr[a])*elem_size; sdelta1[i] = cn_arr[a+1] - cn_arr[a]; sdelta0[i] = src_step[a]; } else { dptr[i] = dst0[a] + (cn - cn_arr[a])*elem_size; ddelta1[i] = cn_arr[a+1] - cn_arr[a]; ddelta0[i] = dst_step[a]; } } } func = (CvMixChannelsFunc)mixcn_tab.fn_2d[depth]; if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "The data type is not supported by the function" ); IPPI_CALL( func( (const void**)sptr, sdelta0, sdelta1, (void**)dptr, ddelta0, ddelta1, pair_count, size )); __END__; if( buffer && heap_alloc ) cvFree( &buffer ); } /****************************************************************************************\ * cvConvertScaleAbs * \****************************************************************************************/ #define ICV_DEF_CVT_SCALE_ABS_CASE( srctype, worktype, \ scale_macro, abs_macro, cast_macro, a, b ) \ \ { \ const srctype* _src = (const srctype*)src; \ srcstep /= sizeof(_src[0]); /*dststep /= sizeof(_dst[0]);*/ \ \ for( ; size.height--; _src += srcstep, dst += dststep ) \ { \ int i; \ \ for( i = 0; i <= size.width - 4; i += 4 ) \ { \ worktype t0 = scale_macro((a)*_src[i] + (b)); \ worktype t1 = scale_macro((a)*_src[i+1] + (b)); \ \ t0 = (worktype)abs_macro(t0); \ t1 = (worktype)abs_macro(t1); \ \ dst[i] = cast_macro(t0); \ dst[i+1] = cast_macro(t1); \ \ t0 = scale_macro((a)*_src[i+2] + (b)); \ t1 = scale_macro((a)*_src[i+3] + (b)); \ \ t0 = (worktype)abs_macro(t0); \ t1 = (worktype)abs_macro(t1); \ \ dst[i+2] = cast_macro(t0); \ dst[i+3] = cast_macro(t1); \ } \ \ for( ; i < size.width; i++ ) \ { \ worktype t0 = scale_macro((a)*_src[i] + (b)); \ t0 = (worktype)abs_macro(t0); \ dst[i] = cast_macro(t0); \ } \ } \ } #define ICV_FIX_SHIFT 15 #define ICV_SCALE(x) (((x) + (1 << (ICV_FIX_SHIFT-1))) >> ICV_FIX_SHIFT) static CvStatus CV_STDCALL icvCvtScaleAbsTo_8u_C1R( const uchar* src, int srcstep, uchar* dst, int dststep, CvSize size, double scale, double shift, int param ) { int srctype = param; int srcdepth = CV_MAT_DEPTH(srctype); size.width *= CV_MAT_CN(srctype); switch( srcdepth ) { case CV_8S: case CV_8U: { uchar lut[256]; int i; double val = shift; for( i = 0; i < 128; i++, val += scale ) { int t = cvRound(fabs(val)); lut[i] = CV_CAST_8U(t); } if( srcdepth == CV_8S ) val = -val; for( ; i < 256; i++, val += scale ) { int t = cvRound(fabs(val)); lut[i] = CV_CAST_8U(t); } icvLUT_Transform8u_8u_C1R( src, srcstep, dst, dststep, size, lut ); } break; case CV_16U: if( fabs( scale ) <= 1. && fabs(shift) < DBL_EPSILON ) { int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT)); if( iscale == ICV_FIX_SHIFT ) { ICV_DEF_CVT_SCALE_ABS_CASE( ushort, int, CV_NOP, CV_IABS, CV_CAST_8U, 1, 0 ); } else { ICV_DEF_CVT_SCALE_ABS_CASE( ushort, int, ICV_SCALE, CV_IABS, CV_CAST_8U, iscale, 0 ); } } else { ICV_DEF_CVT_SCALE_ABS_CASE( ushort, int, cvRound, CV_IABS, CV_CAST_8U, scale, shift ); } break; case CV_16S: if( fabs( scale ) <= 1. && fabs( shift ) <= (INT_MAX*0.5)/(1 << ICV_FIX_SHIFT)) { int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT)); int ishift = cvRound(shift*(1 << ICV_FIX_SHIFT)); if( iscale == ICV_FIX_SHIFT && ishift == 0 ) { ICV_DEF_CVT_SCALE_ABS_CASE( short, int, CV_NOP, CV_IABS, CV_CAST_8U, 1, 0 ); } else { ICV_DEF_CVT_SCALE_ABS_CASE( short, int, ICV_SCALE, CV_IABS, CV_CAST_8U, iscale, ishift ); } } else { ICV_DEF_CVT_SCALE_ABS_CASE( short, int, cvRound, CV_IABS, CV_CAST_8U, scale, shift ); } break; case CV_32S: ICV_DEF_CVT_SCALE_ABS_CASE( int, int, cvRound, CV_IABS, CV_CAST_8U, scale, shift ); break; case CV_32F: ICV_DEF_CVT_SCALE_ABS_CASE( float, int, cvRound, CV_IABS, CV_CAST_8U, scale, shift ); break; case CV_64F: ICV_DEF_CVT_SCALE_ABS_CASE( double, int, cvRound, CV_IABS, CV_CAST_8U, scale, shift ); break; default: assert(0); return CV_BADFLAG_ERR; } return CV_OK; } CV_IMPL void cvConvertScaleAbs( const void* srcarr, void* dstarr, double scale, double shift ) { CV_FUNCNAME( "cvConvertScaleAbs" ); __BEGIN__; int coi1 = 0, coi2 = 0; CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; CvSize size; int src_step, dst_step; CV_CALL( src = cvGetMat( src, &srcstub, &coi1 )); CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 )); 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( dst->type ) != CV_8U ) CV_ERROR( CV_StsUnsupportedFormat, "" ); size = cvGetMatSize( src ); src_step = src->step; dst_step = dst->step; if( CV_IS_MAT_CONT( src->type & dst->type )) { size.width *= size.height; src_step = dst_step = CV_STUB_STEP; size.height = 1; } IPPI_CALL( icvCvtScaleAbsTo_8u_C1R( src->data.ptr, src_step, (uchar*)(dst->data.ptr), dst_step, size, scale, shift, CV_MAT_TYPE(src->type))); __END__; } /****************************************************************************************\ * cvConvertScale * \****************************************************************************************/ #define ICV_DEF_CVT_SCALE_CASE( srctype, worktype, \ scale_macro, cast_macro, a, b ) \ \ { \ const srctype* _src = (const srctype*)src; \ srcstep /= sizeof(_src[0]); \ \ for( ; size.height--; _src += srcstep, dst += dststep ) \ { \ for( i = 0; i <= size.width - 4; i += 4 ) \ { \ worktype t0 = scale_macro((a)*_src[i]+(b)); \ worktype t1 = scale_macro((a)*_src[i+1]+(b)); \ \ dst[i] = cast_macro(t0); \ dst[i+1] = cast_macro(t1); \ \ t0 = scale_macro((a)*_src[i+2] + (b)); \ t1 = scale_macro((a)*_src[i+3] + (b)); \ \ dst[i+2] = cast_macro(t0); \ dst[i+3] = cast_macro(t1); \ } \ \ for( ; i < size.width; i++ ) \ { \ worktype t0 = scale_macro((a)*_src[i] + (b)); \ dst[i] = cast_macro(t0); \ } \ } \ } #define ICV_DEF_CVT_SCALE_FUNC_INT( flavor, dsttype, cast_macro ) \ static CvStatus CV_STDCALL \ icvCvtScaleTo_##flavor##_C1R( const uchar* src, int srcstep, \ dsttype* dst, int dststep, CvSize size, \ double scale, double shift, int param ) \ { \ int i, srctype = param; \ dsttype lut[256]; \ dststep /= sizeof(dst[0]); \ \ switch( CV_MAT_DEPTH(srctype) ) \ { \ case CV_8U: \ if( size.width*size.height >= 256 ) \ { \ double val = shift; \ for( i = 0; i < 256; i++, val += scale ) \ { \ int t = cvRound(val); \ lut[i] = cast_macro(t); \ } \ \ icvLUT_Transform8u_##flavor##_C1R( src, srcstep, dst, \ dststep*sizeof(dst[0]), size, lut ); \ } \ else if( fabs( scale ) <= 128. && \ fabs( shift ) <= (INT_MAX*0.5)/(1 << ICV_FIX_SHIFT)) \ { \ int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT)); \ int ishift = cvRound(shift*(1 << ICV_FIX_SHIFT)); \ \ ICV_DEF_CVT_SCALE_CASE( uchar, int, ICV_SCALE, \ cast_macro, iscale, ishift ); \ } \ else \ { \ ICV_DEF_CVT_SCALE_CASE( uchar, int, cvRound, \ cast_macro, scale, shift ); \ } \ break; \ case CV_8S: \ if( size.width*size.height >= 256 ) \ { \ for( i = 0; i < 256; i++ ) \ { \ int t = cvRound( (schar)i*scale + shift ); \ lut[i] = cast_macro(t); \ } \ \ icvLUT_Transform8u_##flavor##_C1R( src, srcstep, dst, \ dststep*sizeof(dst[0]), size, lut ); \ } \ else if( fabs( scale ) <= 128. && \ fabs( shift ) <= (INT_MAX*0.5)/(1 << ICV_FIX_SHIFT)) \ { \ int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT)); \ int ishift = cvRound(shift*(1 << ICV_FIX_SHIFT)); \ \ ICV_DEF_CVT_SCALE_CASE( schar, int, ICV_SCALE, \ cast_macro, iscale, ishift ); \ } \ else \ { \ ICV_DEF_CVT_SCALE_CASE( schar, int, cvRound, \ cast_macro, scale, shift ); \ } \ break; \ case CV_16U: \ if( fabs( scale ) <= 1. && fabs(shift) < DBL_EPSILON ) \ { \ int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT)); \ \ ICV_DEF_CVT_SCALE_CASE( ushort, int, ICV_SCALE, \ cast_macro, iscale, 0 ); \ } \ else \ { \ ICV_DEF_CVT_SCALE_CASE( ushort, int, cvRound, \ cast_macro, scale, shift ); \ } \ break; \ case CV_16S: \ if( fabs( scale ) <= 1. && \ fabs( shift ) <= (INT_MAX*0.5)/(1 << ICV_FIX_SHIFT)) \ { \ int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT)); \ int ishift = cvRound(shift*(1 << ICV_FIX_SHIFT)); \ \ ICV_DEF_CVT_SCALE_CASE( short, int, ICV_SCALE, \ cast_macro, iscale, ishift ); \ } \ else \ { \ ICV_DEF_CVT_SCALE_CASE( short, int, cvRound, \ cast_macro, scale, shift ); \ } \ break; \ case CV_32S: \ ICV_DEF_CVT_SCALE_CASE( int, int, cvRound, \ cast_macro, scale, shift ); \ break; \ case CV_32F: \ ICV_DEF_CVT_SCALE_CASE( float, int, cvRound, \ cast_macro, scale, shift ); \ break; \ case CV_64F: \ ICV_DEF_CVT_SCALE_CASE( double, int, cvRound, \ cast_macro, scale, shift ); \ break; \ default: \ assert(0); \ return CV_BADFLAG_ERR; \ } \ \ return CV_OK; \ } #define ICV_DEF_CVT_SCALE_FUNC_FLT( flavor, dsttype, cast_macro ) \ static CvStatus CV_STDCALL \ icvCvtScaleTo_##flavor##_C1R( const uchar* src, int srcstep, \ dsttype* dst, int dststep, CvSize size, \ double scale, double shift, int param ) \ { \ int i, srctype = param; \ dsttype lut[256]; \ dststep /= sizeof(dst[0]); \ \ switch( CV_MAT_DEPTH(srctype) ) \ { \ case CV_8U: \ if( size.width*size.height >= 256 ) \ { \ double val = shift; \ for( i = 0; i < 256; i++, val += scale ) \ lut[i] = (dsttype)val; \ \ icvLUT_Transform8u_##flavor##_C1R( src, srcstep, dst, \ dststep*sizeof(dst[0]), size, lut ); \ } \ else \ { \ ICV_DEF_CVT_SCALE_CASE( uchar, double, CV_NOP, \ cast_macro, scale, shift ); \ } \ break; \ case CV_8S: \ if( size.width*size.height >= 256 ) \ { \ for( i = 0; i < 256; i++ ) \ lut[i] = (dsttype)((schar)i*scale + shift); \ \ icvLUT_Transform8u_##flavor##_C1R( src, srcstep, dst, \ dststep*sizeof(dst[0]), size, lut ); \ } \ else \ { \ ICV_DEF_CVT_SCALE_CASE( schar, double, CV_NOP, \ cast_macro, scale, shift ); \ } \ break; \ case CV_16U: \ ICV_DEF_CVT_SCALE_CASE( ushort, double, CV_NOP, \ cast_macro, scale, shift ); \ break; \ case CV_16S: \ ICV_DEF_CVT_SCALE_CASE( short, double, CV_NOP, \ cast_macro, scale, shift ); \ break; \ case CV_32S: \ ICV_DEF_CVT_SCALE_CASE( int, double, CV_NOP, \ cast_macro, scale, shift ); \ break; \ case CV_32F: \ ICV_DEF_CVT_SCALE_CASE( float, double, CV_NOP, \ cast_macro, scale, shift ); \ break; \ case CV_64F: \ ICV_DEF_CVT_SCALE_CASE( double, double, CV_NOP, \ cast_macro, scale, shift ); \ break; \ default: \ assert(0); \ return CV_BADFLAG_ERR; \ } \ \ return CV_OK; \ } ICV_DEF_CVT_SCALE_FUNC_INT( 8u, uchar, CV_CAST_8U ) ICV_DEF_CVT_SCALE_FUNC_INT( 8s, schar, CV_CAST_8S ) ICV_DEF_CVT_SCALE_FUNC_INT( 16s, short, CV_CAST_16S ) ICV_DEF_CVT_SCALE_FUNC_INT( 16u, ushort, CV_CAST_16U ) ICV_DEF_CVT_SCALE_FUNC_INT( 32s, int, CV_CAST_32S ) ICV_DEF_CVT_SCALE_FUNC_FLT( 32f, float, CV_CAST_32F ) ICV_DEF_CVT_SCALE_FUNC_FLT( 64f, double, CV_CAST_64F ) CV_DEF_INIT_FUNC_TAB_2D( CvtScaleTo, C1R ) /****************************************************************************************\ * Conversion w/o scaling macros * \****************************************************************************************/ #define ICV_DEF_CVT_CASE_2D( srctype, worktype, \ cast_macro1, cast_macro2 ) \ { \ const srctype* _src = (const srctype*)src; \ srcstep /= sizeof(_src[0]); \ \ for( ; size.height--; _src += srcstep, dst += dststep ) \ { \ int i; \ \ for( i = 0; i <= size.width - 4; i += 4 ) \ { \ worktype t0 = cast_macro1(_src[i]); \ worktype t1 = cast_macro1(_src[i+1]); \ \ dst[i] = cast_macro2(t0); \ dst[i+1] = cast_macro2(t1); \ \ t0 = cast_macro1(_src[i+2]); \ t1 = cast_macro1(_src[i+3]); \ \ dst[i+2] = cast_macro2(t0); \ dst[i+3] = cast_macro2(t1); \ } \ \ for( ; i < size.width; i++ ) \ { \ worktype t0 = cast_macro1(_src[i]); \ dst[i] = cast_macro2(t0); \ } \ } \ } #define ICV_DEF_CVT_FUNC_2D( flavor, dsttype, worktype, cast_macro2, \ srcdepth1, srctype1, cast_macro11, \ srcdepth2, srctype2, cast_macro12, \ srcdepth3, srctype3, cast_macro13, \ srcdepth4, srctype4, cast_macro14, \ srcdepth5, srctype5, cast_macro15, \ srcdepth6, srctype6, cast_macro16 ) \ static CvStatus CV_STDCALL \ icvCvtTo_##flavor##_C1R( const uchar* src, int srcstep, \ dsttype* dst, int dststep, \ CvSize size, int param ) \ { \ int srctype = param; \ dststep /= sizeof(dst[0]); \ \ switch( CV_MAT_DEPTH(srctype) ) \ { \ case srcdepth1: \ ICV_DEF_CVT_CASE_2D( srctype1, worktype, \ cast_macro11, cast_macro2 ); \ break; \ case srcdepth2: \ ICV_DEF_CVT_CASE_2D( srctype2, worktype, \ cast_macro12, cast_macro2 ); \ break; \ case srcdepth3: \ ICV_DEF_CVT_CASE_2D( srctype3, worktype, \ cast_macro13, cast_macro2 ); \ break; \ case srcdepth4: \ ICV_DEF_CVT_CASE_2D( srctype4, worktype, \ cast_macro14, cast_macro2 ); \ break; \ case srcdepth5: \ ICV_DEF_CVT_CASE_2D( srctype5, worktype, \ cast_macro15, cast_macro2 ); \ break; \ case srcdepth6: \ ICV_DEF_CVT_CASE_2D( srctype6, worktype, \ cast_macro16, cast_macro2 ); \ break; \ } \ \ return CV_OK; \ } ICV_DEF_CVT_FUNC_2D( 8u, uchar, int, CV_CAST_8U, CV_8S, schar, CV_NOP, CV_16U, ushort, CV_NOP, CV_16S, short, CV_NOP, CV_32S, int, CV_NOP, CV_32F, float, cvRound, CV_64F, double, cvRound ) ICV_DEF_CVT_FUNC_2D( 8s, schar, int, CV_CAST_8S, CV_8U, uchar, CV_NOP, CV_16U, ushort, CV_NOP, CV_16S, short, CV_NOP, CV_32S, int, CV_NOP, CV_32F, float, cvRound, CV_64F, double, cvRound ) ICV_DEF_CVT_FUNC_2D( 16u, ushort, int, CV_CAST_16U, CV_8U, uchar, CV_NOP, CV_8S, schar, CV_NOP, CV_16S, short, CV_NOP, CV_32S, int, CV_NOP, CV_32F, float, cvRound, CV_64F, double, cvRound ) ICV_DEF_CVT_FUNC_2D( 16s, short, int, CV_CAST_16S, CV_8U, uchar, CV_NOP, CV_8S, schar, CV_NOP, CV_16U, ushort, CV_NOP, CV_32S, int, CV_NOP, CV_32F, float, cvRound, CV_64F, double, cvRound ) ICV_DEF_CVT_FUNC_2D( 32s, int, int, CV_NOP, CV_8U, uchar, CV_NOP, CV_8S, schar, CV_NOP, CV_16U, ushort, CV_NOP, CV_16S, short, CV_NOP, CV_32F, float, cvRound, CV_64F, double, cvRound ) ICV_DEF_CVT_FUNC_2D( 32f, float, float, CV_NOP, CV_8U, uchar, CV_8TO32F, CV_8S, schar, CV_8TO32F, CV_16U, ushort, CV_NOP, CV_16S, short, CV_NOP, CV_32S, int, CV_CAST_32F, CV_64F, double, CV_CAST_32F ) ICV_DEF_CVT_FUNC_2D( 64f, double, double, CV_NOP, CV_8U, uchar, CV_8TO32F, CV_8S, schar, CV_8TO32F, CV_16U, ushort, CV_NOP, CV_16S, short, CV_NOP, CV_32S, int, CV_NOP, CV_32F, float, CV_NOP ) CV_DEF_INIT_FUNC_TAB_2D( CvtTo, C1R ) typedef CvStatus (CV_STDCALL *CvCvtFunc)( const void* src, int srcstep, void* dst, int dststep, CvSize size, int param ); typedef CvStatus (CV_STDCALL *CvCvtScaleFunc)( const void* src, int srcstep, void* dst, int dststep, CvSize size, double scale, double shift, int param ); CV_IMPL void cvConvertScale( const void* srcarr, void* dstarr, double scale, double shift ) { static CvFuncTable cvt_tab, cvtscale_tab; static int inittab = 0; CV_FUNCNAME( "cvConvertScale" ); __BEGIN__; int type; int is_nd = 0; CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; CvSize size; int src_step, dst_step; int no_scale = scale == 1 && shift == 0; if( !CV_IS_MAT(src) ) { if( CV_IS_MATND(src) ) is_nd = 1; else { int coi = 0; CV_CALL( src = cvGetMat( src, &srcstub, &coi )); if( coi != 0 ) CV_ERROR( CV_BadCOI, "" ); } } if( !CV_IS_MAT(dst) ) { if( CV_IS_MATND(dst) ) is_nd = 1; else { int coi = 0; CV_CALL( dst = cvGetMat( dst, &dststub, &coi )); if( coi != 0 ) CV_ERROR( CV_BadCOI, "" ); } } if( is_nd ) { CvArr* arrs[] = { src, dst }; CvMatND stubs[2]; CvNArrayIterator iterator; int dsttype; CV_CALL( cvInitNArrayIterator( 2, arrs, 0, stubs, &iterator, CV_NO_DEPTH_CHECK )); type = iterator.hdr[0]->type; dsttype = iterator.hdr[1]->type; iterator.size.width *= CV_MAT_CN(type); if( !inittab ) { icvInitCvtToC1RTable( &cvt_tab ); icvInitCvtScaleToC1RTable( &cvtscale_tab ); inittab = 1; } if( no_scale ) { CvCvtFunc func = (CvCvtFunc)(cvt_tab.fn_2d[CV_MAT_DEPTH(dsttype)]); if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); do { IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, iterator.ptr[1], CV_STUB_STEP, iterator.size, type )); } while( cvNextNArraySlice( &iterator )); } else { CvCvtScaleFunc func = (CvCvtScaleFunc)(cvtscale_tab.fn_2d[CV_MAT_DEPTH(dsttype)]); if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); do { IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, iterator.ptr[1], CV_STUB_STEP, iterator.size, scale, shift, type )); } while( cvNextNArraySlice( &iterator )); } EXIT; } if( no_scale && CV_ARE_TYPES_EQ( src, dst ) ) { if( src != dst ) cvCopy( src, dst ); EXIT; } if( !CV_ARE_SIZES_EQ( src, dst )) CV_ERROR( CV_StsUnmatchedSizes, "" ); size = cvGetMatSize( src ); type = CV_MAT_TYPE(src->type); src_step = src->step; dst_step = dst->step; if( CV_IS_MAT_CONT( src->type & dst->type )) { size.width *= size.height; src_step = dst_step = CV_STUB_STEP; size.height = 1; } size.width *= CV_MAT_CN( type ); if( CV_ARE_TYPES_EQ( src, dst ) && size.height == 1 && size.width <= CV_MAX_INLINE_MAT_OP_SIZE ) { if( CV_MAT_DEPTH(type) == CV_32F ) { const float* srcdata = (const float*)(src->data.ptr); float* dstdata = (float*)(dst->data.ptr); do { dstdata[size.width - 1] = (float)(srcdata[size.width-1]*scale + shift); } while( --size.width ); EXIT; } if( CV_MAT_DEPTH(type) == CV_64F ) { const double* srcdata = (const double*)(src->data.ptr); double* dstdata = (double*)(dst->data.ptr); do { dstdata[size.width - 1] = srcdata[size.width-1]*scale + shift; } while( --size.width ); EXIT; } } if( !inittab ) { icvInitCvtToC1RTable( &cvt_tab ); icvInitCvtScaleToC1RTable( &cvtscale_tab ); inittab = 1; } if( !CV_ARE_CNS_EQ( src, dst )) CV_ERROR( CV_StsUnmatchedFormats, "" ); if( no_scale ) { CvCvtFunc func = (CvCvtFunc)(cvt_tab.fn_2d[CV_MAT_DEPTH(dst->type)]); if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( src->data.ptr, src_step, dst->data.ptr, dst_step, size, type )); } else { CvCvtScaleFunc func = (CvCvtScaleFunc) (cvtscale_tab.fn_2d[CV_MAT_DEPTH(dst->type)]); if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( src->data.ptr, src_step, dst->data.ptr, dst_step, size, scale, shift, type )); } __END__; } /********************* helper functions for converting 32f<->64f ************************/ IPCVAPI_IMPL( CvStatus, icvCvt_32f64f, ( const float* src, double* dst, int len ), (src, dst, len) ) { int i; for( i = 0; i <= len - 4; i += 4 ) { double t0 = src[i]; double t1 = src[i+1]; dst[i] = t0; dst[i+1] = t1; t0 = src[i+2]; t1 = src[i+3]; dst[i+2] = t0; dst[i+3] = t1; } for( ; i < len; i++ ) dst[i] = src[i]; return CV_OK; } IPCVAPI_IMPL( CvStatus, icvCvt_64f32f, ( const double* src, float* dst, int len ), (src, dst, len) ) { int i = 0; for( ; i <= len - 4; i += 4 ) { double t0 = src[i]; double t1 = src[i+1]; dst[i] = (float)t0; dst[i+1] = (float)t1; t0 = src[i+2]; t1 = src[i+3]; dst[i+2] = (float)t0; dst[i+3] = (float)t1; } for( ; i < len; i++ ) dst[i] = (float)src[i]; return CV_OK; } CvStatus CV_STDCALL icvScale_32f( const float* src, float* dst, int len, float a, float b ) { int i; for( i = 0; i <= len - 4; i += 4 ) { double t0 = src[i]*a + b; double t1 = src[i+1]*a + b; dst[i] = (float)t0; dst[i+1] = (float)t1; t0 = src[i+2]*a + b; t1 = src[i+3]*a + b; dst[i+2] = (float)t0; dst[i+3] = (float)t1; } for( ; i < len; i++ ) dst[i] = (float)(src[i]*a + b); return CV_OK; } CvStatus CV_STDCALL icvScale_64f( const double* src, double* dst, int len, double a, double b ) { int i; for( i = 0; i <= len - 4; i += 4 ) { double t0 = src[i]*a + b; double t1 = src[i+1]*a + b; dst[i] = t0; dst[i+1] = t1; t0 = src[i+2]*a + b; t1 = src[i+3]*a + b; dst[i+2] = t0; dst[i+3] = t1; } for( ; i < len; i++ ) dst[i] = src[i]*a + b; return CV_OK; } /* End of file. */