// Set array element to given value CV_IMPL void cvSetAt( CvArr* arr, CvScalar value, int y, int x ) { CV_FUNCNAME( "cvSetAt" ); __BEGIN__; uchar* ptr; int type; CV_CALL( ptr = cvGetPtrAt( arr, y, x )); if( CV_IS_ARR( arr )) { type = CV_ARR_TYPE( ((CvMat*)arr)->type ); } else { IplImage* img = (IplImage*)arr; type = icvIplToCvDepth( img->depth ); if( type < 0 || (unsigned)(img->nChannels - 1) > 3 ) CV_ERROR( CV_StsUnsupportedFormat, "" ); type = type*4 + img->nChannels - 1; } CV_CALL( cvScalarToRawData( &value, type, ptr )); __END__; }
CV_IMPL void cvCopyMakeBorder( const CvArr* srcarr, CvArr* dstarr, CvPoint offset, int bordertype, CvScalar value ) { CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; CvSize srcsize, dstsize; int srcstep, dststep; int pix_size, type; if( !CV_IS_MAT(src) ) src = cvGetMat( src, &srcstub ); if( !CV_IS_MAT(dst) ) dst = cvGetMat( dst, &dststub ); if( offset.x < 0 || offset.y < 0 ) CV_Error( CV_StsOutOfRange, "Offset (left/top border width) is negative" ); if( src->rows + offset.y > dst->rows || src->cols + offset.x > dst->cols ) CV_Error( CV_StsBadSize, "Source array is too big or destination array is too small" ); if( !CV_ARE_TYPES_EQ( src, dst )) CV_Error( CV_StsUnmatchedFormats, "" ); type = CV_MAT_TYPE(src->type); pix_size = CV_ELEM_SIZE(type); srcsize = cvGetMatSize(src); dstsize = cvGetMatSize(dst); srcstep = src->step; dststep = dst->step; if( srcstep == 0 ) srcstep = CV_STUB_STEP; if( dststep == 0 ) dststep = CV_STUB_STEP; bordertype &= 15; if( bordertype == IPL_BORDER_REPLICATE ) { icvCopyReplicateBorder_8u( src->data.ptr, srcstep, srcsize, dst->data.ptr, dststep, dstsize, offset.y, offset.x, pix_size ); } else if( bordertype == IPL_BORDER_REFLECT_101 ) { icvCopyReflect101Border_8u( src->data.ptr, srcstep, srcsize, dst->data.ptr, dststep, dstsize, offset.y, offset.x, pix_size ); } else if( bordertype == IPL_BORDER_CONSTANT ) { double buf[4]; cvScalarToRawData( &value, buf, src->type, 0 ); icvCopyConstBorder_8u( src->data.ptr, srcstep, srcsize, dst->data.ptr, dststep, dstsize, offset.y, offset.x, pix_size, (uchar*)buf ); } else CV_Error( CV_StsBadFlag, "Unknown/unsupported border type" ); }
CV_IMPL void cvAbsDiffS( const void* srcarr, void* dstarr, CvScalar scalar ) { static CvFuncTable adiffs_tab; static int inittab = 0; CV_FUNCNAME( "cvAbsDiffS" ); __BEGIN__; int coi1 = 0, coi2 = 0; int type, sctype; CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; int src_step = src->step; int dst_step = dst->step; double buf[12]; CvSize size; if( !inittab ) { icvInitAbsDiffCTable( &adiffs_tab ); inittab = 1; } 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_TYPES_EQ(src, dst) ) CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats ); if( !CV_ARE_SIZES_EQ(src, dst) ) CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes ); sctype = type = CV_MAT_TYPE( src->type ); if( CV_MAT_DEPTH(type) < CV_32S ) sctype = (type & CV_MAT_CN_MASK) | CV_32SC1; size = icvGetMatSize( src ); size.width *= CV_MAT_CN( type ); src_step = src->step; dst_step = dst->step; if( CV_IS_MAT_CONT( src->type & dst->type )) { size.width *= size.height; size.height = 1; src_step = dst_step = CV_STUB_STEP; } CV_CALL( cvScalarToRawData( &scalar, buf, sctype, 1 )); { CvFunc2D_2A1P func = (CvFunc2D_2A1P) (adiffs_tab.fn_2d[CV_MAT_DEPTH(type)]); if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( src->data.ptr, src_step, dst->data.ptr, dst_step, size, buf )); } __END__; }
CV_IMPL void cvFloodFill( CvArr* arr, CvPoint seed_point, CvScalar newVal, CvScalar lo_diff, CvScalar up_diff, CvConnectedComp* comp, int flags, CvArr* maskarr ) { cv::Ptr<CvMat> tempMask; std::vector<CvFFillSegment> buffer; if( comp ) memset( comp, 0, sizeof(*comp) ); int i, type, depth, cn, is_simple; int buffer_size, connectivity = flags & 255; union { uchar b[4]; int i[4]; float f[4]; double _[4]; } nv_buf; nv_buf._[0] = nv_buf._[1] = nv_buf._[2] = nv_buf._[3] = 0; struct { cv::Vec3b b; cv::Vec3i i; cv::Vec3f f; } ld_buf, ud_buf; CvMat stub, *img = cvGetMat(arr, &stub); CvMat maskstub, *mask = (CvMat*)maskarr; CvSize size; type = CV_MAT_TYPE( img->type ); depth = CV_MAT_DEPTH(type); cn = CV_MAT_CN(type); if( connectivity == 0 ) connectivity = 4; else if( connectivity != 4 && connectivity != 8 ) CV_Error( CV_StsBadFlag, "Connectivity must be 4, 0(=4) or 8" ); is_simple = mask == 0 && (flags & CV_FLOODFILL_MASK_ONLY) == 0; for( i = 0; i < cn; i++ ) { if( lo_diff.val[i] < 0 || up_diff.val[i] < 0 ) CV_Error( CV_StsBadArg, "lo_diff and up_diff must be non-negative" ); is_simple &= fabs(lo_diff.val[i]) < DBL_EPSILON && fabs(up_diff.val[i]) < DBL_EPSILON; } size = cvGetMatSize( img ); if( (unsigned)seed_point.x >= (unsigned)size.width || (unsigned)seed_point.y >= (unsigned)size.height ) CV_Error( CV_StsOutOfRange, "Seed point is outside of image" ); cvScalarToRawData( &newVal, &nv_buf, type, 0 ); buffer_size = MAX( size.width, size.height ) * 2; buffer.resize( buffer_size ); if( is_simple ) { int elem_size = CV_ELEM_SIZE(type); const uchar* seed_ptr = img->data.ptr + img->step*seed_point.y + elem_size*seed_point.x; for(i = 0; i < elem_size; i++) if (seed_ptr[i] != nv_buf.b[i]) break; if (i != elem_size) { if( type == CV_8UC1 ) icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.b[0], comp, flags, &buffer); else if( type == CV_8UC3 ) icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3b(nv_buf.b), comp, flags, &buffer); else if( type == CV_32SC1 ) icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.i[0], comp, flags, &buffer); else if( type == CV_32FC1 ) icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, nv_buf.f[0], comp, flags, &buffer); else if( type == CV_32SC3 ) icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3i(nv_buf.i), comp, flags, &buffer); else if( type == CV_32FC3 ) icvFloodFill_CnIR(img->data.ptr, img->step, size, seed_point, cv::Vec3f(nv_buf.f), comp, flags, &buffer); else CV_Error( CV_StsUnsupportedFormat, "" ); return; } } if( !mask ) { /* created mask will be 8-byte aligned */ tempMask = cvCreateMat( size.height + 2, (size.width + 9) & -8, CV_8UC1 ); mask = tempMask; } else { mask = cvGetMat( mask, &maskstub ); if( !CV_IS_MASK_ARR( mask )) CV_Error( CV_StsBadMask, "" ); if( mask->width != size.width + 2 || mask->height != size.height + 2 ) CV_Error( CV_StsUnmatchedSizes, "mask must be 2 pixel wider " "and 2 pixel taller than filled image" ); } int width = tempMask ? mask->step : size.width + 2; uchar* mask_row = mask->data.ptr + mask->step; memset( mask_row - mask->step, 1, width ); for( i = 1; i <= size.height; i++, mask_row += mask->step ) { if( tempMask ) memset( mask_row, 0, width ); mask_row[0] = mask_row[size.width+1] = (uchar)1; } memset( mask_row, 1, width ); if( depth == CV_8U ) for( i = 0; i < cn; i++ ) { int t = cvFloor(lo_diff.val[i]); ld_buf.b[i] = CV_CAST_8U(t); t = cvFloor(up_diff.val[i]); ud_buf.b[i] = CV_CAST_8U(t); } else if( depth == CV_32S ) for( i = 0; i < cn; i++ ) { int t = cvFloor(lo_diff.val[i]); ld_buf.i[i] = t; t = cvFloor(up_diff.val[i]); ud_buf.i[i] = t; } else if( depth == CV_32F ) for( i = 0; i < cn; i++ ) { ld_buf.f[i] = (float)lo_diff.val[i]; ud_buf.f[i] = (float)up_diff.val[i]; } else CV_Error( CV_StsUnsupportedFormat, "" ); if( type == CV_8UC1 ) icvFloodFillGrad_CnIR<uchar, int, Diff8uC1>( img->data.ptr, img->step, mask->data.ptr, mask->step, size, seed_point, nv_buf.b[0], Diff8uC1(ld_buf.b[0], ud_buf.b[0]), comp, flags, &buffer); else if( type == CV_8UC3 ) icvFloodFillGrad_CnIR<cv::Vec3b, cv::Vec3i, Diff8uC3>( img->data.ptr, img->step, mask->data.ptr, mask->step, size, seed_point, cv::Vec3b(nv_buf.b), Diff8uC3(ld_buf.b, ud_buf.b), comp, flags, &buffer); else if( type == CV_32SC1 ) icvFloodFillGrad_CnIR<int, int, Diff32sC1>( img->data.ptr, img->step, mask->data.ptr, mask->step, size, seed_point, nv_buf.i[0], Diff32sC1(ld_buf.i[0], ud_buf.i[0]), comp, flags, &buffer); else if( type == CV_32SC3 ) icvFloodFillGrad_CnIR<cv::Vec3i, cv::Vec3i, Diff32sC3>( img->data.ptr, img->step, mask->data.ptr, mask->step, size, seed_point, cv::Vec3i(nv_buf.i), Diff32sC3(ld_buf.i, ud_buf.i), comp, flags, &buffer); else if( type == CV_32FC1 ) icvFloodFillGrad_CnIR<float, float, Diff32fC1>( img->data.ptr, img->step, mask->data.ptr, mask->step, size, seed_point, nv_buf.f[0], Diff32fC1(ld_buf.f[0], ud_buf.f[0]), comp, flags, &buffer); else if( type == CV_32FC3 ) icvFloodFillGrad_CnIR<cv::Vec3f, cv::Vec3f, Diff32fC3>( img->data.ptr, img->step, mask->data.ptr, mask->step, size, seed_point, cv::Vec3f(nv_buf.f), Diff32fC3(ld_buf.f, ud_buf.f), comp, flags, &buffer); else CV_Error(CV_StsUnsupportedFormat, ""); }
CV_IMPL void cvFloodFill( CvArr* arr, CvPoint seed_point, CvScalar newVal, CvScalar lo_diff, CvScalar up_diff, CvConnectedComp* comp, int flags, CvArr* maskarr ) { static void* ffill_tab[4]; static void* ffillgrad_tab[4]; static int inittab = 0; CvMat* tempMask = 0; CvFFillSegment* buffer = 0; CV_FUNCNAME( "cvFloodFill" ); if( comp ) memset( comp, 0, sizeof(*comp) ); __BEGIN__; int i, type, depth, cn, is_simple, idx; int buffer_size, connectivity = flags & 255; double nv_buf[4] = {0,0,0,0}; union { uchar b[4]; float f[4]; } ld_buf, ud_buf; CvMat stub, *img = (CvMat*)arr; CvMat maskstub, *mask = (CvMat*)maskarr; CvSize size; if( !inittab ) { icvInitFloodFill( ffill_tab, ffillgrad_tab ); inittab = 1; } CV_CALL( img = cvGetMat( img, &stub )); type = CV_MAT_TYPE( img->type ); depth = CV_MAT_DEPTH(type); cn = CV_MAT_CN(type); idx = type == CV_8UC1 || type == CV_8UC3 ? 0 : type == CV_32FC1 || type == CV_32FC3 ? 1 : -1; if( idx < 0 ) CV_ERROR( CV_StsUnsupportedFormat, "" ); if( connectivity == 0 ) connectivity = 4; else if( connectivity != 4 && connectivity != 8 ) CV_ERROR( CV_StsBadFlag, "Connectivity must be 4, 0(=4) or 8" ); is_simple = mask == 0 && (flags & CV_FLOODFILL_MASK_ONLY) == 0; for( i = 0; i < cn; i++ ) { if( lo_diff.val[i] < 0 || up_diff.val[i] < 0 ) CV_ERROR( CV_StsBadArg, "lo_diff and up_diff must be non-negative" ); is_simple &= fabs(lo_diff.val[i]) < DBL_EPSILON && fabs(up_diff.val[i]) < DBL_EPSILON; } size = cvGetMatSize( img ); if( (unsigned)seed_point.x >= (unsigned)size.width || (unsigned)seed_point.y >= (unsigned)size.height ) CV_ERROR( CV_StsOutOfRange, "Seed point is outside of image" ); cvScalarToRawData( &newVal, &nv_buf, type, 0 ); buffer_size = MAX( size.width, size.height )*2; CV_CALL( buffer = (CvFFillSegment*)cvAlloc( buffer_size*sizeof(buffer[0]))); if( is_simple ) { CvFloodFillFunc func = (CvFloodFillFunc)ffill_tab[idx]; if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); IPPI_CALL( func( img->data.ptr, img->step, size, seed_point, &nv_buf, comp, flags, buffer, buffer_size, cn )); } else { CvFloodFillGradFunc func = (CvFloodFillGradFunc)ffillgrad_tab[idx]; if( !func ) CV_ERROR( CV_StsUnsupportedFormat, "" ); if( !mask ) { /* created mask will be 8-byte aligned */ tempMask = cvCreateMat( size.height + 2, (size.width + 9) & -8, CV_8UC1 ); mask = tempMask; } else { CV_CALL( mask = cvGetMat( mask, &maskstub )); if( !CV_IS_MASK_ARR( mask )) CV_ERROR( CV_StsBadMask, "" ); if( mask->width != size.width + 2 || mask->height != size.height + 2 ) CV_ERROR( CV_StsUnmatchedSizes, "mask must be 2 pixel wider " "and 2 pixel taller than filled image" ); } { int width = tempMask ? mask->step : size.width + 2; uchar* mask_row = mask->data.ptr + mask->step; memset( mask_row - mask->step, 1, width ); for( i = 1; i <= size.height; i++, mask_row += mask->step ) { if( tempMask ) memset( mask_row, 0, width ); mask_row[0] = mask_row[size.width+1] = (uchar)1; } memset( mask_row, 1, width ); } if( depth == CV_8U ) for( i = 0; i < cn; i++ ) { int t = cvFloor(lo_diff.val[i]); ld_buf.b[i] = CV_CAST_8U(t); t = cvFloor(up_diff.val[i]); ud_buf.b[i] = CV_CAST_8U(t); } else for( i = 0; i < cn; i++ ) { ld_buf.f[i] = (float)lo_diff.val[i]; ud_buf.f[i] = (float)up_diff.val[i]; } IPPI_CALL( func( img->data.ptr, img->step, mask->data.ptr, mask->step, size, seed_point, &nv_buf, ld_buf.f, ud_buf.f, comp, flags, buffer, buffer_size, cn )); } __END__; cvFree( &buffer ); cvReleaseMat( &tempMask ); }