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