16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cv.h"
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* initializes 8-element array for fast access to 3x3 neighborhood of a pixel */
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define  CV_INIT_3X3_DELTAS( deltas, step, nch )            \
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ((deltas)[0] =  (nch),  (deltas)[1] = -(step) + (nch),  \
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     (deltas)[2] = -(step), (deltas)[3] = -(step) - (nch),  \
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     (deltas)[4] = -(nch),  (deltas)[5] =  (step) - (nch),  \
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     (deltas)[6] =  (step), (deltas)[7] =  (step) + (nch))
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const CvPoint icvCodeDeltas[8] =
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    { {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvStartReadChainPoints( CvChain * chain, CvChainPtReader * reader )
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvStartReadChainPoints" );
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !chain || !reader )
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( chain->elem_size != 1 || chain->header_size < (int)sizeof(CvChain))
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR );
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( (CvSeq *) chain, (CvSeqReader *) reader, 0 );
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK();
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    reader->pt = chain->origin;
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < 8; i++ )
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->deltas[i][0] = (schar) icvCodeDeltas[i].x;
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->deltas[i][1] = (schar) icvCodeDeltas[i].y;
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* retrieves next point of the chain curve and updates reader */
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvPoint
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvReadChainPoint( CvChainPtReader * reader )
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *ptr;
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int code;
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint pt = { 0, 0 };
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvReadChainPoint" );
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !reader )
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pt = reader->pt;
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = reader->ptr;
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( ptr )
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        code = *ptr++;
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ptr >= reader->block_max )
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvChangeSeqBlock( (CvSeqReader *) reader, 1 );
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = reader->ptr;
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr = ptr;
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->code = (schar)code;
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( (code & ~7) == 0 );
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->pt.x = pt.x + icvCodeDeltas[code].x;
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->pt.y = pt.y + icvCodeDeltas[code].y;
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return pt;
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                         Raster->Chain Tree (Suzuki algorithms)                         *
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct _CvContourInfo
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int flags;
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct _CvContourInfo *next;        /* next contour with the same mark value */
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct _CvContourInfo *parent;      /* information about parent contour */
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *contour;             /* corresponding contour (may be 0, if rejected) */
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvRect rect;                /* bounding rectangle */
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint origin;             /* origin point (where the contour was traced from) */
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_hole;                /* hole flag */
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn_CvContourInfo;
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  Structure that is used for sequental retrieving contours from the image.
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  It supports both hierarchical and plane variants of Suzuki algorithm.
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*/
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct _CvContourScanner
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage *storage1;     /* contains fetched contours */
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage *storage2;     /* contains approximated contours
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   (!=storage1 if approx_method2 != approx_method1) */
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage *cinfo_storage;        /* contains _CvContourInfo nodes */
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSet *cinfo_set;           /* set of _CvContourInfo nodes */
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStoragePos initial_pos;        /* starting storage pos */
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStoragePos backup_pos; /* beginning of the latest approx. contour */
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStoragePos backup_pos2;        /* ending of the latest approx. contour */
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *img0;                /* image origin */
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *img;                 /* current image row */
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int img_step;               /* image step */
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize img_size;            /* ROI size */
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint offset;             /* ROI offset: coordinates, added to each contour point */
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint pt;                 /* current scanner position */
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint lnbd;               /* position of the last met contour */
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int nbd;                    /* current mark val */
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _CvContourInfo *l_cinfo;    /* information about latest approx. contour */
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _CvContourInfo cinfo_temp;  /* temporary var which is used in simple modes */
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _CvContourInfo frame_info;  /* information about frame */
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq frame;                /* frame itself */
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int approx_method1;         /* approx method when tracing */
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int approx_method2;         /* final approx method */
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int mode;                   /* contour scanning mode:
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   0 - external only
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   1 - all the contours w/o any hierarchy
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   2 - connected components (i.e. two-level structure -
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   external contours and holes) */
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int subst_flag;
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int seq_type1;              /* type of fetched contours */
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int header_size1;           /* hdr size of fetched contours */
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size1;             /* elem size of fetched contours */
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int seq_type2;              /*                                       */
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int header_size2;           /*        the same for approx. contours  */
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size2;             /*                                       */
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _CvContourInfo *cinfo_table[126];
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn_CvContourScanner;
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define _CV_FIND_CONTOURS_FLAGS_EXTERNAL_ONLY    1
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define _CV_FIND_CONTOURS_FLAGS_HIERARCHIC       2
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   Initializes scanner structure.
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   Prepare image for scanning ( clear borders and convert all pixels to 0-1.
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*/
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvContourScanner
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvStartFindContours( void* _img, CvMemStorage* storage,
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     int  header_size, int mode,
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     int  method, CvPoint offset )
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int y;
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int step;
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size;
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar *img = 0;
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvContourScanner scanner = 0;
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat stub, *mat = (CvMat*)_img;
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvStartFindContours" );
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mat = cvGetMat( mat, &stub ));
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MASK_ARR( mat ))
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat, "[Start]FindContours support only 8uC1 images" );
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size = cvSize( mat->width, mat->height );
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    step = mat->step;
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    img = (uchar*)(mat->data.ptr);
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( method < 0 || method > CV_CHAIN_APPROX_TC89_KCOS )
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR_FROM_STATUS( CV_BADRANGE_ERR );
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_size < (int) (method == CV_CHAIN_CODE ? sizeof( CvChain ) : sizeof( CvContour )))
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR );
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner = (CvContourScanner)cvAlloc( sizeof( *scanner ));
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !scanner )
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR );
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( scanner, 0, sizeof( *scanner ));
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->storage1 = scanner->storage2 = storage;
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->img0 = (schar *) img;
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->img = (schar *) (img + step);
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->img_step = step;
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->img_size.width = size.width - 1;   /* exclude rightest column */
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->img_size.height = size.height - 1; /* exclude bottomost row */
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->mode = mode;
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->offset = offset;
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->pt.x = scanner->pt.y = 1;
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->lnbd.x = 0;
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->lnbd.y = 1;
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->nbd = 2;
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->mode = (int) mode;
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->frame_info.contour = &(scanner->frame);
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->frame_info.is_hole = 1;
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->frame_info.next = 0;
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->frame_info.parent = 0;
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->frame_info.rect = cvRect( 0, 0, size.width, size.height );
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->l_cinfo = 0;
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->subst_flag = 0;
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->frame.flags = CV_SEQ_FLAG_HOLE;
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->approx_method2 = scanner->approx_method1 = method;
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( method == CV_CHAIN_APPROX_TC89_L1 || method == CV_CHAIN_APPROX_TC89_KCOS )
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->approx_method1 = CV_CHAIN_CODE;
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( scanner->approx_method1 == CV_CHAIN_CODE )
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->seq_type1 = CV_SEQ_CHAIN_CONTOUR;
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->header_size1 = scanner->approx_method1 == scanner->approx_method2 ?
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            header_size : sizeof( CvChain );
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->elem_size1 = sizeof( char );
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->seq_type1 = CV_SEQ_POLYGON;
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->header_size1 = scanner->approx_method1 == scanner->approx_method2 ?
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            header_size : sizeof( CvContour );
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->elem_size1 = sizeof( CvPoint );
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->header_size2 = header_size;
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( scanner->approx_method2 == CV_CHAIN_CODE )
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->seq_type2 = scanner->seq_type1;
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->elem_size2 = scanner->elem_size1;
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->seq_type2 = CV_SEQ_POLYGON;
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->elem_size2 = sizeof( CvPoint );
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->seq_type1 = scanner->approx_method1 == CV_CHAIN_CODE ?
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SEQ_CHAIN_CONTOUR : CV_SEQ_POLYGON;
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->seq_type2 = scanner->approx_method2 == CV_CHAIN_CODE ?
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SEQ_CHAIN_CONTOUR : CV_SEQ_POLYGON;
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSaveMemStoragePos( storage, &(scanner->initial_pos) );
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( method > CV_CHAIN_APPROX_SIMPLE )
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->storage1 = cvCreateChildMemStorage( scanner->storage2 );
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( mode > CV_RETR_LIST )
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->cinfo_storage = cvCreateChildMemStorage( scanner->storage2 );
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->cinfo_set = cvCreateSet( 0, sizeof( CvSet ), sizeof( _CvContourInfo ),
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                          scanner->cinfo_storage );
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( scanner->cinfo_storage == 0 || scanner->cinfo_set == 0 )
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR );
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* make zero borders */
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( img, 0, size.width );
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( img + step * (size.height - 1), 0, size.width );
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 1, img += step; y < size.height - 1; y++, img += step )
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        img[0] = img[size.width - 1] = 0;
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* converts all pixels to 0 or 1 */
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvThreshold( mat, mat, 0, 1, CV_THRESH_BINARY );
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK();
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &scanner );
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return scanner;
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   Final stage of contour processing.
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   Three variants possible:
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      1. Contour, which was retrieved using border following, is added to
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         the contour tree. It is the case when the icvSubstituteContour function
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         was not called after retrieving the contour.
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      2. New contour, assigned by icvSubstituteContour function, is added to the
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         tree. The retrieved contour itself is removed from the storage.
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         Here two cases are possible:
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            2a. If one deals with plane variant of algorithm
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (hierarchical strucutre is not reconstructed),
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                the contour is removed completely.
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            2b. In hierarchical case, the header of the contour is not removed.
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                It's marked as "link to contour" and h_next pointer of it is set to
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                new, substituting contour.
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      3. The similar to 2, but when NULL pointer was assigned by
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         icvSubstituteContour function. In this case, the function removes
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         retrieved contour completely if plane case and
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         leaves header if hierarchical (but doesn't mark header as "link").
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      ------------------------------------------------------------------------
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      The 1st variant can be used to retrieve and store all the contours from the image
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      (with optional convertion from chains to contours using some approximation from
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      restriced set of methods). Some characteristics of contour can be computed in the
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      same pass.
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      The usage scheme can look like:
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      icvContourScanner scanner;
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CvMemStorage*  contour_storage;
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CvSeq*  first_contour;
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CvStatus  result;
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      ...
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      icvCreateMemStorage( &contour_storage, block_size/0 );
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      ...
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      cvStartFindContours
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              ( img, contour_storage,
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                header_size, approx_method,
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                [external_only,]
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                &scanner );
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for(;;)
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      {
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          [CvSeq* contour;]
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          result = icvFindNextContour( &scanner, &contour/0 );
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          if( result != CV_OK ) break;
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          // calculate some characteristics
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          ...
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      if( result < 0 ) goto error_processing;
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      cvEndFindContours( &scanner, &first_contour );
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      ...
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      -----------------------------------------------------------------
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      Second variant is more complex and can be used when someone wants store not
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      the retrieved contours but transformed ones. (e.g. approximated with some
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      non-default algorithm ).
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      The scheme can be the as following:
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      icvContourScanner scanner;
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CvMemStorage*  contour_storage;
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CvMemStorage*  temp_storage;
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CvSeq*  first_contour;
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CvStatus  result;
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      ...
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      icvCreateMemStorage( &contour_storage, block_size/0 );
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      icvCreateMemStorage( &temp_storage, block_size/0 );
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      ...
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      icvStartFindContours8uC1R
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              ( <img_params>, temp_storage,
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                header_size, approx_method,
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                [retrival_mode],
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                &scanner );
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for(;;)
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      {
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          CvSeq* temp_contour;
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          CvSeq* new_contour;
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          result = icvFindNextContour( scanner, &temp_contour );
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          if( result != CV_OK ) break;
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          <approximation_function>( temp_contour, contour_storage,
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    &new_contour, <parameters...> );
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          icvSubstituteContour( scanner, new_contour );
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          ...
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      if( result < 0 ) goto error_processing;
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      cvEndFindContours( &scanner, &first_contour );
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      ...
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      ----------------------------------------------------------------------------
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      Third method to retrieve contours may be applied if contours are irrelevant
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      themselves but some characteristics of them are used only.
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      The usage is similar to second except slightly different internal loop
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for(;;)
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      {
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          CvSeq* temp_contour;
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          result = icvFindNextContour( &scanner, &temp_contour );
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          if( result != CV_OK ) break;
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          // calculate some characteristics of temp_contour
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          icvSubstituteContour( scanner, 0 );
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          ...
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      new_storage variable is not needed here.
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      Two notes.
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      1. Second and third method can interleave. I.e. it is possible to
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         remain contours that satisfy with some criteria and reject others.
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         In hierarchic case the resulting tree is the part of original tree with
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         some nodes absent. But in the resulting tree the contour1 is a child
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         (may be indirect) of contour2 iff in the original tree the contour1
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         is a child (may be indirect) of contour2.
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*/
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvEndProcessContour( CvContourScanner scanner )
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _CvContourInfo *l_cinfo = scanner->l_cinfo;
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( l_cinfo )
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( scanner->subst_flag )
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvMemStoragePos temp;
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSaveMemStoragePos( scanner->storage2, &temp );
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( temp.top == scanner->backup_pos2.top &&
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                temp.free_space == scanner->backup_pos2.free_space )
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvRestoreMemStoragePos( scanner->storage2, &scanner->backup_pos );
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            scanner->subst_flag = 0;
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( l_cinfo->contour )
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvInsertNodeIntoTree( l_cinfo->contour, l_cinfo->parent->contour,
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  &(scanner->frame) );
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->l_cinfo = 0;
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* replaces one contour with another */
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSubstituteContour( CvContourScanner scanner, CvSeq * new_contour )
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _CvContourInfo *l_cinfo;
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSubstituteContour" );
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !scanner )
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    l_cinfo = scanner->l_cinfo;
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( l_cinfo && l_cinfo->contour && l_cinfo->contour != new_contour )
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        l_cinfo->contour = new_contour;
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        scanner->subst_flag = 1;
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    marks domain border with +/-<constant> and stores the contour into CvSeq.
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        method:
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            <0  - chain
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ==0 - direct
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            >0  - simple approximation
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*/
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvStatus
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFetchContour( schar                  *ptr,
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 int                    step,
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 CvPoint                pt,
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 CvSeq*                 contour,
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 int    _method )
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const schar     nbd = 2;
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int             deltas[16];
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqWriter     writer;
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar           *i0 = ptr, *i1, *i3, *i4 = 0;
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int             prev_s = -1, s, s_end;
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int             method = _method - 1;
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( (unsigned) _method <= CV_CHAIN_APPROX_SIMPLE );
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* initialize local state */
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_INIT_3X3_DELTAS( deltas, step, 1 );
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memcpy( deltas + 8, deltas, 8 * sizeof( deltas[0] ));
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* initialize writer */
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartAppendToSeq( contour, &writer );
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( method < 0 )
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ((CvChain *) contour)->origin = pt;
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    s_end = s = CV_IS_SEQ_HOLE( contour ) ? 0 : 4;
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        s = (s - 1) & 7;
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i1 = i0 + deltas[s];
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( *i1 != 0 )
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( s != s_end );
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( s == s_end )            /* single pixel domain */
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *i0 = (schar) (nbd | -128);
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( method >= 0 )
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_WRITE_SEQ_ELEM( pt, writer );
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i3 = i0;
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_s = s ^ 4;
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* follow border */
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ;; )
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s_end = s;
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ;; )
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                i4 = i3 + deltas[++s];
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *i4 != 0 )
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s &= 7;
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            /* check "right" bound */
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (unsigned) (s - 1) < (unsigned) s_end )
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *i3 = (schar) (nbd | -128);
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( *i3 == 1 )
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *i3 = nbd;
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( method < 0 )
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                schar _s = (schar) s;
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_WRITE_SEQ_ELEM( _s, writer );
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( s != prev_s || method == 0 )
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_WRITE_SEQ_ELEM( pt, writer );
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    prev_s = s;
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                pt.x += icvCodeDeltas[s].x;
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                pt.y += icvCodeDeltas[s].y;
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( i4 == i0 && i3 == i1 )
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i3 = i4;
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s = (s + 4) & 7;
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                       /* end of border following loop */
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteSeq( &writer );
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _method != CV_CHAIN_CODE )
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvBoundingRect( contour, 1 );
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( writer.seq->total == 0 && writer.seq->first == 0 ||
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            writer.seq->total > writer.seq->first->count ||
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (writer.seq->first->prev == writer.seq->first &&
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             writer.seq->first->next == writer.seq->first) );
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_OK;
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   trace contour until certain point is met.
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   returns 1 if met, 0 else.
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*/
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvTraceContour( schar *ptr, int step, schar *stop_ptr, int is_hole )
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int deltas[16];
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *i0 = ptr, *i1, *i3, *i4;
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int s, s_end;
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* initialize local state */
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_INIT_3X3_DELTAS( deltas, step, 1 );
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memcpy( deltas + 8, deltas, 8 * sizeof( deltas[0] ));
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( (*i0 & -2) != 0 );
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    s_end = s = is_hole ? 0 : 4;
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        s = (s - 1) & 7;
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i1 = i0 + deltas[s];
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( *i1 != 0 )
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( s != s_end );
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    i3 = i0;
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* check single pixel domain */
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( s != s_end )
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* follow border */
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ;; )
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s_end = s;
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ;; )
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                i4 = i3 + deltas[++s];
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *i4 != 0 )
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( i3 == stop_ptr || (i4 == i0 && i3 == i1) )
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i3 = i4;
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s = (s + 4) & 7;
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                       /* end of border following loop */
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return i3 == stop_ptr;
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvStatus
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFetchContourEx( schar*               ptr,
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   int                  step,
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   CvPoint              pt,
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   CvSeq*               contour,
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   int  _method,
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   int                  nbd,
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   CvRect*              _rect )
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int         deltas[16];
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqWriter writer;
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar        *i0 = ptr, *i1, *i3, *i4;
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvRect      rect;
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int         prev_s = -1, s, s_end;
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int         method = _method - 1;
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( (unsigned) _method <= CV_CHAIN_APPROX_SIMPLE );
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( 1 < nbd && nbd < 128 );
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* initialize local state */
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_INIT_3X3_DELTAS( deltas, step, 1 );
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memcpy( deltas + 8, deltas, 8 * sizeof( deltas[0] ));
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* initialize writer */
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartAppendToSeq( contour, &writer );
7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( method < 0 )
7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ((CvChain *)contour)->origin = pt;
7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rect.x = rect.width = pt.x;
7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rect.y = rect.height = pt.y;
7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    s_end = s = CV_IS_SEQ_HOLE( contour ) ? 0 : 4;
7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do
7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        s = (s - 1) & 7;
7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i1 = i0 + deltas[s];
7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( *i1 != 0 )
7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( s != s_end );
7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( s == s_end )            /* single pixel domain */
7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *i0 = (schar) (nbd | 0x80);
7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( method >= 0 )
7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_WRITE_SEQ_ELEM( pt, writer );
7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i3 = i0;
7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_s = s ^ 4;
7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* follow border */
7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ;; )
7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s_end = s;
7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ;; )
7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                i4 = i3 + deltas[++s];
7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *i4 != 0 )
7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s &= 7;
7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            /* check "right" bound */
7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (unsigned) (s - 1) < (unsigned) s_end )
7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *i3 = (schar) (nbd | 0x80);
7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( *i3 == 1 )
7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *i3 = (schar) nbd;
7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( method < 0 )
7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                schar _s = (schar) s;
7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_WRITE_SEQ_ELEM( _s, writer );
7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( s != prev_s || method == 0 )
7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_WRITE_SEQ_ELEM( pt, writer );
7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( s != prev_s )
7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* update bounds */
7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( pt.x < rect.x )
7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    rect.x = pt.x;
7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( pt.x > rect.width )
7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    rect.width = pt.x;
7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( pt.y < rect.y )
7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    rect.y = pt.y;
8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( pt.y > rect.height )
8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    rect.height = pt.y;
8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            prev_s = s;
8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pt.x += icvCodeDeltas[s].x;
8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pt.y += icvCodeDeltas[s].y;
8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( i4 == i0 && i3 == i1 )  break;
8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i3 = i4;
8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s = (s + 4) & 7;
8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                       /* end of border following loop */
8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rect.width -= rect.x - 1;
8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rect.height -= rect.y - 1;
8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteSeq( &writer );
8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _method != CV_CHAIN_CODE )
8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ((CvContour*)contour)->rect = rect;
8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( writer.seq->total == 0 && writer.seq->first == 0 ||
8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            writer.seq->total > writer.seq->first->count ||
8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (writer.seq->first->prev == writer.seq->first &&
8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             writer.seq->first->next == writer.seq->first) );
8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _rect )  *_rect = rect;
8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_OK;
8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSeq *
8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFindNextContour( CvContourScanner scanner )
8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *img0;
8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *img;
8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int step;
8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int width, height;
8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int x, y;
8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int prev;
8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint lnbd;
8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *contour = 0;
8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int nbd;
8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int mode;
8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStatus result = (CvStatus) 1;
8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvFindNextContour" );
8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !scanner )
8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    icvEndProcessContour( scanner );
8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* initialize local state */
8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    img0 = scanner->img0;
8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    img = scanner->img;
8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    step = scanner->img_step;
8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    x = scanner->pt.x;
8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y = scanner->pt.y;
8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width = scanner->img_size.width;
8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    height = scanner->img_size.height;
8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    mode = scanner->mode;
8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lnbd = scanner->lnbd;
8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    nbd = scanner->nbd;
8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    prev = img[x - 1];
8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; y < height; y++, img += step )
8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; x < width; x++ )
8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int p = img[x];
8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( p != prev )
8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                _CvContourInfo *par_info = 0;
8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                _CvContourInfo *l_cinfo = 0;
8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvSeq *seq = 0;
8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int is_hole = 0;
8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvPoint origin;
8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !(prev == 0 && p == 1) )    /* if not external contour */
8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    /* check hole */
8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( p != 0 || prev < 1 )
8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        goto resume_scan;
8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( prev & -2 )
8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        lnbd.x = x - 1;
8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    is_hole = 1;
8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( mode == 0 && (is_hole || img0[lnbd.y * step + lnbd.x] > 0) )
8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    goto resume_scan;
9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                origin.y = y;
9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                origin.x = x - is_hole;
9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* find contour parent */
9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( mode <= 1 || (!is_hole && mode == 2) || lnbd.x <= 0 )
9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    par_info = &(scanner->frame_info);
9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int lval = img0[lnbd.y * step + lnbd.x] & 0x7f;
9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    _CvContourInfo *cur = scanner->cinfo_table[lval - 2];
9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    assert( lval >= 2 );
9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    /* find the first bounding contour */
9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    while( cur )
9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( (unsigned) (lnbd.x - cur->rect.x) < (unsigned) cur->rect.width &&
9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            (unsigned) (lnbd.y - cur->rect.y) < (unsigned) cur->rect.height )
9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( par_info )
9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            {
9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                if( icvTraceContour( scanner->img0 +
9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                     par_info->origin.y * step +
9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                     par_info->origin.x, step, img + lnbd.x,
9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                     par_info->is_hole ) > 0 )
9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    break;
9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            }
9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            par_info = cur;
9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cur = cur->next;
9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    assert( par_info != 0 );
9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    /* if current contour is a hole and previous contour is a hole or
9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       current contour is external and previous contour is external then
9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       the parent of the contour is the parent of the previous contour else
9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       the parent is the previous contour itself. */
9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( par_info->is_hole == is_hole )
9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        par_info = par_info->parent;
9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        /* every contour must have a parent
9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           (at least, the frame of the image) */
9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( !par_info )
9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            par_info = &(scanner->frame_info);
9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    /* hole flag of the parent must differ from the flag of the contour */
9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    assert( par_info->is_hole != is_hole );
9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( par_info->contour == 0 )        /* removed contour */
9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        goto resume_scan;
9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                lnbd.x = x - is_hole;
9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvSaveMemStoragePos( scanner->storage2, &(scanner->backup_pos) );
9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                seq = cvCreateSeq( scanner->seq_type1, scanner->header_size1,
9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   scanner->elem_size1, scanner->storage1 );
9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !seq )
9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    result = CV_OUTOFMEM_ERR;
9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    goto exit_func;
9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                seq->flags |= is_hole ? CV_SEQ_FLAG_HOLE : 0;
9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* initialize header */
9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( mode <= 1 )
9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    l_cinfo = &(scanner->cinfo_temp);
9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    result = icvFetchContour( img + x - is_hole, step,
9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                              cvPoint( origin.x + scanner->offset.x,
9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                       origin.y + scanner->offset.y),
9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                              seq, scanner->approx_method1 );
9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( result < 0 )
9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        goto exit_func;
9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    union { _CvContourInfo* ci; CvSetElem* se; } v;
9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    v.ci = l_cinfo;
9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetAdd( scanner->cinfo_set, 0, &v.se );
9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    l_cinfo = v.ci;
9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    result = icvFetchContourEx( img + x - is_hole, step,
9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                cvPoint( origin.x + scanner->offset.x,
9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                         origin.y + scanner->offset.y),
9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                seq, scanner->approx_method1,
9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                nbd, &(l_cinfo->rect) );
9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( result < 0 )
9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        goto exit_func;
9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    l_cinfo->rect.x -= scanner->offset.x;
9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    l_cinfo->rect.y -= scanner->offset.y;
9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    l_cinfo->next = scanner->cinfo_table[nbd - 2];
9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    scanner->cinfo_table[nbd - 2] = l_cinfo;
9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    /* change nbd */
10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    nbd = (nbd + 1) & 127;
10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    nbd += nbd == 0 ? 3 : 0;
10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                l_cinfo->is_hole = is_hole;
10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                l_cinfo->contour = seq;
10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                l_cinfo->origin = origin;
10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                l_cinfo->parent = par_info;
10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( scanner->approx_method1 != scanner->approx_method2 )
10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    result = icvApproximateChainTC89( (CvChain *) seq,
10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                      scanner->header_size2,
10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                      scanner->storage2,
10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                      &(l_cinfo->contour),
10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                      scanner->approx_method2 );
10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( result < 0 )
10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        goto exit_func;
10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvClearMemStorage( scanner->storage1 );
10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                l_cinfo->contour->v_prev = l_cinfo->parent->contour;
10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( par_info->contour == 0 )
10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    l_cinfo->contour = 0;
10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( scanner->storage1 == scanner->storage2 )
10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cvRestoreMemStoragePos( scanner->storage1, &(scanner->backup_pos) );
10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cvClearMemStorage( scanner->storage1 );
10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p = img[x];
10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    goto resume_scan;
10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvSaveMemStoragePos( scanner->storage2, &(scanner->backup_pos2) );
10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                scanner->l_cinfo = l_cinfo;
10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                scanner->pt.x = x + 1;
10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                scanner->pt.y = y;
10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                scanner->lnbd = lnbd;
10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                scanner->img = (schar *) img;
10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                scanner->nbd = nbd;
10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                contour = l_cinfo->contour;
10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                result = CV_OK;
10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                goto exit_func;
10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              resume_scan:
10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                prev = p;
10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* update lnbd */
10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( prev & -2 )
10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    lnbd.x = x;
10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                   /* end of prev != p */
10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                       /* end of loop on x */
10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lnbd.x = 0;
10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lnbd.y = y + 1;
10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x = 1;
10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev = 0;
10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                           /* end of loop on y */
10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  exit_func:
10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( result != 0 )
10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        contour = 0;
10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( result < 0 )
10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR_FROM_STATUS( result );
10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return contour;
10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   The function add to tree the last retrieved/substituted contour,
10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   releases temp_storage, restores state of dst_storage (if needed), and
10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   returns pointer to root of the contour tree */
10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq *
10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvEndFindContours( CvContourScanner * _scanner )
10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvContourScanner scanner;
10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *first = 0;
10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvFindNextContour" );
10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !_scanner )
10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner = *_scanner;
10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( scanner )
10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvEndProcessContour( scanner );
11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( scanner->storage1 != scanner->storage2 )
11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMemStorage( &(scanner->storage1) );
11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( scanner->cinfo_storage )
11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMemStorage( &(scanner->cinfo_storage) );
11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        first = scanner->frame.v_next;
11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( _scanner );
11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return first;
11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_SINGLE                  0
11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_CONNECTING_ABOVE        1
11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_CONNECTING_BELOW        -1
11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_IS_COMPONENT_POINT(val) ((val) != 0)
11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_GET_WRITTEN_ELEM( writer ) ((writer).ptr - (writer).seq->elem_size)
11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef  struct CvLinkedRunPoint
11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct CvLinkedRunPoint* link;
11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct CvLinkedRunPoint* next;
11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint pt;
11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLinkedRunPoint;
11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFindContoursInInterval( const CvArr* src,
11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           /*int minValue, int maxValue,*/
11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           CvMemStorage* storage,
11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           CvSeq** result,
11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           int contourHeaderSize )
11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count = 0;
11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* storage00 = 0;
11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* storage01 = 0;
11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* first = 0;
11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvFindContoursInInterval" );
11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k, n;
11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar*  src_data = 0;
11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  img_step = 0;
11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize  img_size;
11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  connect_flag;
11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  lower_total;
11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  upper_total;
11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  all_total;
11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq*  runs;
11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinkedRunPoint  tmp;
11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinkedRunPoint*  tmp_prev;
11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinkedRunPoint*  upper_line = 0;
11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinkedRunPoint*  lower_line = 0;
11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinkedRunPoint*  last_elem;
11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinkedRunPoint*  upper_run = 0;
11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinkedRunPoint*  lower_run = 0;
11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinkedRunPoint*  prev_point = 0;
11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqWriter  writer_ext;
11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqWriter  writer_int;
11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqWriter  writer;
11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader  reader;
11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* external_contours;
11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* internal_contours;
11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* prev = 0;
11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !result )
11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL double CvSeq pointer" );
11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( contourHeaderSize < (int)sizeof(CvContour))
11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "Contour header size must be >= sizeof(CvContour)" );
11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( storage00 = cvCreateChildMemStorage(storage));
11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( storage01 = cvCreateChildMemStorage(storage));
11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMat stub, *mat;
11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( mat = cvGetMat( src, &stub ));
11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_IS_MASK_ARR(mat))
11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Input array must be 8uC1 or 8sC1" );
11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_data = mat->data.ptr;
12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        img_step = mat->step;
12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        img_size = cvGetMatSize( mat );
12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Create temporary sequences
12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    runs = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvLinkedRunPoint), storage00 );
12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartAppendToSeq( runs, &writer );
12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteSeq( 0, sizeof(CvSeq), sizeof(CvLinkedRunPoint*), storage01, &writer_ext );
12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteSeq( 0, sizeof(CvSeq), sizeof(CvLinkedRunPoint*), storage01, &writer_int );
12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tmp_prev = &(tmp);
12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tmp_prev->next = 0;
12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tmp_prev->link = 0;
12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // First line. None of runs is binded
12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tmp.pt.y = 0;
12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    i = 0;
12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_WRITE_SEQ_ELEM( tmp, writer );
12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    upper_line = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer );
12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tmp_prev = upper_line;
12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( j = 0; j < img_size.width; )
12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; j < img_size.width && !ICV_IS_COMPONENT_POINT(src_data[j]); j++ )
12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ;
12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( j == img_size.width )
12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp.pt.x = j;
12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM( tmp, writer );
12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp_prev->next = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer );
12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp_prev = tmp_prev->next;
12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; j < img_size.width && ICV_IS_COMPONENT_POINT(src_data[j]); j++ )
12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ;
12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp.pt.x = j-1;
12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM( tmp, writer );
12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp_prev->next = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer );
12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp_prev->link = tmp_prev->next;
12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // First point of contour
12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM( tmp_prev, writer_ext );
12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp_prev = tmp_prev->next;
12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFlushSeqWriter( &writer );
12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    upper_line = upper_line->next;
12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    upper_total = runs->total - 1;
12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    last_elem = tmp_prev;
12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tmp_prev->next = 0;
12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 1; i < img_size.height; i++ )
12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------// Find runs in next line
12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_data += img_step;
12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp.pt.y = i;
12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        all_total = runs->total;
12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = 0; j < img_size.width; )
12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; j < img_size.width && !ICV_IS_COMPONENT_POINT(src_data[j]); j++ )
12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ;
12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( j == img_size.width ) break;
12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            tmp.pt.x = j;
12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_WRITE_SEQ_ELEM( tmp, writer );
12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            tmp_prev->next = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer );
12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            tmp_prev = tmp_prev->next;
12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; j < img_size.width && ICV_IS_COMPONENT_POINT(src_data[j]); j++ )
12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ;
12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            tmp.pt.x = j-1;
12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_WRITE_SEQ_ELEM( tmp, writer );
12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            tmp_prev = tmp_prev->next = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer );
12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }//j
12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFlushSeqWriter( &writer );
12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lower_line = last_elem->next;
12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lower_total = runs->total - all_total;
12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        last_elem = tmp_prev;
12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp_prev->next = 0;
12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------//
12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------// Find links between runs of lower_line and upper_line
12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        upper_run = upper_line;
12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lower_run = lower_line;
12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        connect_flag = ICV_SINGLE;
12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 0, n = 0; k < upper_total/2 && n < lower_total/2; )
12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            switch( connect_flag )
12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            case ICV_SINGLE:
12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( upper_run->next->pt.x < lower_run->next->pt.x )
12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( upper_run->next->pt.x >= lower_run->pt.x  -1 )
12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        lower_run->link = upper_run;
12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        connect_flag = ICV_CONNECTING_ABOVE;
12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        prev_point = upper_run->next;
12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        upper_run->next->link = upper_run;
13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    k++;
13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    upper_run = upper_run->next->next;
13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( upper_run->pt.x <= lower_run->next->pt.x  +1 )
13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        lower_run->link = upper_run;
13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        connect_flag = ICV_CONNECTING_BELOW;
13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        prev_point = lower_run->next;
13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        lower_run->link = lower_run->next;
13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        // First point of contour
13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_WRITE_SEQ_ELEM( lower_run, writer_ext );
13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    n++;
13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    lower_run = lower_run->next->next;
13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            case ICV_CONNECTING_ABOVE:
13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( upper_run->pt.x > lower_run->next->pt.x +1 )
13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    prev_point->link = lower_run->next;
13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    connect_flag = ICV_SINGLE;
13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    n++;
13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    lower_run = lower_run->next->next;
13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    prev_point->link = upper_run;
13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( upper_run->next->pt.x < lower_run->next->pt.x )
13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        k++;
13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        prev_point = upper_run->next;
13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        upper_run = upper_run->next->next;
13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        connect_flag = ICV_CONNECTING_BELOW;
13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        prev_point = lower_run->next;
13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        n++;
13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        lower_run = lower_run->next->next;
13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            case ICV_CONNECTING_BELOW:
13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( lower_run->pt.x > upper_run->next->pt.x +1 )
13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    upper_run->next->link = prev_point;
13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    connect_flag = ICV_SINGLE;
13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    k++;
13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    upper_run = upper_run->next->next;
13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // First point of contour
13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_WRITE_SEQ_ELEM( lower_run, writer_int );
13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    lower_run->link = prev_point;
13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( lower_run->next->pt.x < upper_run->next->pt.x )
13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        n++;
13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        prev_point = lower_run->next;
13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        lower_run = lower_run->next->next;
13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        connect_flag = ICV_CONNECTING_ABOVE;
13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        k++;
13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        prev_point = upper_run->next;
13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        upper_run = upper_run->next->next;
13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }// k, n
13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; n < lower_total/2; n++ )
13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( connect_flag != ICV_SINGLE )
13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                prev_point->link = lower_run->next;
13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                connect_flag = ICV_SINGLE;
13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                lower_run = lower_run->next->next;
13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                continue;
13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lower_run->link = lower_run->next;
13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            //First point of contour
13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_WRITE_SEQ_ELEM( lower_run, writer_ext );
13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lower_run = lower_run->next->next;
13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; k < upper_total/2; k++ )
13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( connect_flag != ICV_SINGLE )
14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                upper_run->next->link = prev_point;
14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                connect_flag = ICV_SINGLE;
14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                upper_run = upper_run->next->next;
14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                continue;
14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            upper_run->next->link = upper_run;
14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            upper_run = upper_run->next->next;
14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        upper_line = lower_line;
14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        upper_total = lower_total;
14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }//i
14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    upper_run = upper_line;
14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //the last line of image
14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < upper_total/2; k++ )
14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        upper_run->next->link = upper_run;
14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        upper_run = upper_run->next->next;
14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------//
14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------//Find end read contours
14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    external_contours = cvEndWriteSeq( &writer_ext );
14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    internal_contours = cvEndWriteSeq( &writer_int );
14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < 2; k++ )
14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeq* contours = k == 0 ? external_contours : internal_contours;
14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( contours, &reader );
14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = 0; j < contours->total; j++, count++ )
14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvLinkedRunPoint* p_temp;
14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvLinkedRunPoint* p00;
14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvLinkedRunPoint* p01;
14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSeq* contour;
14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_READ_SEQ_ELEM( p00, reader );
14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            p01 = p00;
14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !p00->link )
14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                continue;
14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvStartWriteSeq( CV_SEQ_ELTYPE_POINT | CV_SEQ_POLYLINE | CV_SEQ_FLAG_CLOSED,
14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             contourHeaderSize, sizeof(CvPoint), storage, &writer );
14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            do
14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_WRITE_SEQ_ELEM( p00->pt, writer );
14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                p_temp = p00;
14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                p00 = p00->link;
14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                p_temp->link = 0;
14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( p00 != p01 );
14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            contour = cvEndWriteSeq( &writer );
14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvBoundingRect( contour, 1 );
14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( k != 0 )
14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                contour->flags |= CV_SEQ_FLAG_HOLE;
14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !first )
14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                prev = first = contour;
14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                contour->h_prev = prev;
14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                prev = prev->h_next = contour;
14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !first )
14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        count = -1;
14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( result )
14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *result = first;
14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMemStorage(&storage00);
14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMemStorage(&storage01);
14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return count;
14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name: cvFindContours
14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose:
14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      Finds all the contours on the bi-level image.
14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      img  - source image.
14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//             Non-zero pixels are considered as 1-pixels
14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//             and zero pixels as 0-pixels.
14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      step - full width of source image in bytes.
14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      size - width and height of the image in pixels
15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      storage - pointer to storage where will the output contours be placed.
15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      header_size - header size of resulting contours
15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      mode - mode of contour retrieval.
15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      method - method of approximation that is applied to contours
15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      first_contour - pointer to first contour pointer
15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns:
15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      CV_OK or error code
15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Notes:
15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFindContours( void*  img,  CvMemStorage*  storage,
15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvSeq**  firstContour, int  cntHeaderSize,
15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int  mode,
15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int  method, CvPoint offset )
15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvContourScanner scanner = 0;
15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *contour = 0;
15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count = -1;
15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvFindContours" );
15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !firstContour )
15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL double CvSeq pointer" );
15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( method == CV_LINK_RUNS )
15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( offset.x != 0 || offset.y != 0 )
15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsOutOfRange,
15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Nonzero offset is not supported in CV_LINK_RUNS yet" );
15316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( count = icvFindContoursInInterval( img, storage,
15336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    firstContour, cntHeaderSize ));
15346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
15366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
15376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( scanner = cvStartFindContours( img, storage,
15386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cntHeaderSize, mode, method, offset ));
15396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( scanner );
15406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        do
15426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
15436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count++;
15446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            contour = cvFindNextContour( scanner );
15456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
15466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( contour != 0 );
15476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *firstContour = cvEndFindContours( &scanner );
15496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return count;
15546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
1558