| /*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. */ |