Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 //
     43 //  Loading and saving IPL images.
     44 //
     45 
     46 #include "precomp.hpp"
     47 #include "grfmts.hpp"
     48 #undef min
     49 #undef max
     50 #include <iostream>
     51 
     52 /****************************************************************************************\
     53 *                                      Image Codecs                                      *
     54 \****************************************************************************************/
     55 namespace cv
     56 {
     57 
     58 /**
     59  * @struct ImageCodecInitializer
     60  *
     61  * Container which stores the registered codecs to be used by OpenCV
     62 */
     63 struct ImageCodecInitializer
     64 {
     65     /**
     66      * Default Constructor for the ImageCodeInitializer
     67     */
     68     ImageCodecInitializer()
     69     {
     70         /// BMP Support
     71         decoders.push_back( makePtr<BmpDecoder>() );
     72         encoders.push_back( makePtr<BmpEncoder>() );
     73 
     74         decoders.push_back( makePtr<HdrDecoder>() );
     75         encoders.push_back( makePtr<HdrEncoder>() );
     76     #ifdef HAVE_JPEG
     77         decoders.push_back( makePtr<JpegDecoder>() );
     78         encoders.push_back( makePtr<JpegEncoder>() );
     79     #endif
     80     #ifdef HAVE_WEBP
     81         decoders.push_back( makePtr<WebPDecoder>() );
     82         encoders.push_back( makePtr<WebPEncoder>() );
     83     #endif
     84         decoders.push_back( makePtr<SunRasterDecoder>() );
     85         encoders.push_back( makePtr<SunRasterEncoder>() );
     86         decoders.push_back( makePtr<PxMDecoder>() );
     87         encoders.push_back( makePtr<PxMEncoder>() );
     88     #ifdef HAVE_TIFF
     89         decoders.push_back( makePtr<TiffDecoder>() );
     90     #endif
     91         encoders.push_back( makePtr<TiffEncoder>() );
     92     #ifdef HAVE_PNG
     93         decoders.push_back( makePtr<PngDecoder>() );
     94         encoders.push_back( makePtr<PngEncoder>() );
     95     #endif
     96     #ifdef HAVE_JASPER
     97         decoders.push_back( makePtr<Jpeg2KDecoder>() );
     98         encoders.push_back( makePtr<Jpeg2KEncoder>() );
     99     #endif
    100     #ifdef HAVE_OPENEXR
    101         decoders.push_back( makePtr<ExrDecoder>() );
    102         encoders.push_back( makePtr<ExrEncoder>() );
    103     #endif
    104 
    105     #ifdef HAVE_GDAL
    106         /// Attach the GDAL Decoder
    107         decoders.push_back( makePtr<GdalDecoder>() );
    108     #endif/*HAVE_GDAL*/
    109     }
    110 
    111     std::vector<ImageDecoder> decoders;
    112     std::vector<ImageEncoder> encoders;
    113 };
    114 
    115 static ImageCodecInitializer codecs;
    116 
    117 /**
    118  * Find the decoders
    119  *
    120  * @param[in] filename File to search
    121  *
    122  * @return Image decoder to parse image file.
    123 */
    124 static ImageDecoder findDecoder( const String& filename ) {
    125 
    126     size_t i, maxlen = 0;
    127 
    128     /// iterate through list of registered codecs
    129     for( i = 0; i < codecs.decoders.size(); i++ )
    130     {
    131         size_t len = codecs.decoders[i]->signatureLength();
    132         maxlen = std::max(maxlen, len);
    133     }
    134 
    135     /// Open the file
    136     FILE* f= fopen( filename.c_str(), "rb" );
    137 
    138     /// in the event of a failure, return an empty image decoder
    139     if( !f )
    140         return ImageDecoder();
    141 
    142     // read the file signature
    143     String signature(maxlen, ' ');
    144     maxlen = fread( (void*)signature.c_str(), 1, maxlen, f );
    145     fclose(f);
    146     signature = signature.substr(0, maxlen);
    147 
    148     /// compare signature against all decoders
    149     for( i = 0; i < codecs.decoders.size(); i++ )
    150     {
    151         if( codecs.decoders[i]->checkSignature(signature) )
    152             return codecs.decoders[i]->newDecoder();
    153     }
    154 
    155     /// If no decoder was found, return base type
    156     return ImageDecoder();
    157 }
    158 
    159 static ImageDecoder findDecoder( const Mat& buf )
    160 {
    161     size_t i, maxlen = 0;
    162 
    163     if( buf.rows*buf.cols < 1 || !buf.isContinuous() )
    164         return ImageDecoder();
    165 
    166     for( i = 0; i < codecs.decoders.size(); i++ )
    167     {
    168         size_t len = codecs.decoders[i]->signatureLength();
    169         maxlen = std::max(maxlen, len);
    170     }
    171 
    172     String signature(maxlen, ' ');
    173     size_t bufSize = buf.rows*buf.cols*buf.elemSize();
    174     maxlen = std::min(maxlen, bufSize);
    175     memcpy( (void*)signature.c_str(), buf.data, maxlen );
    176 
    177     for( i = 0; i < codecs.decoders.size(); i++ )
    178     {
    179         if( codecs.decoders[i]->checkSignature(signature) )
    180             return codecs.decoders[i]->newDecoder();
    181     }
    182 
    183     return ImageDecoder();
    184 }
    185 
    186 static ImageEncoder findEncoder( const String& _ext )
    187 {
    188     if( _ext.size() <= 1 )
    189         return ImageEncoder();
    190 
    191     const char* ext = strrchr( _ext.c_str(), '.' );
    192     if( !ext )
    193         return ImageEncoder();
    194     int len = 0;
    195     for( ext++; len < 128 && isalnum(ext[len]); len++ )
    196         ;
    197 
    198     for( size_t i = 0; i < codecs.encoders.size(); i++ )
    199     {
    200         String description = codecs.encoders[i]->getDescription();
    201         const char* descr = strchr( description.c_str(), '(' );
    202 
    203         while( descr )
    204         {
    205             descr = strchr( descr + 1, '.' );
    206             if( !descr )
    207                 break;
    208             int j = 0;
    209             for( descr++; j < len && isalnum(descr[j]) ; j++ )
    210             {
    211                 int c1 = tolower(ext[j]);
    212                 int c2 = tolower(descr[j]);
    213                 if( c1 != c2 )
    214                     break;
    215             }
    216             if( j == len && !isalnum(descr[j]))
    217                 return codecs.encoders[i]->newEncoder();
    218             descr += j;
    219         }
    220     }
    221 
    222     return ImageEncoder();
    223 }
    224 
    225 enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 };
    226 
    227 /**
    228  * Read an image into memory and return the information
    229  *
    230  * @param[in] filename File to load
    231  * @param[in] flags Flags
    232  * @param[in] hdrtype { LOAD_CVMAT=0,
    233  *                      LOAD_IMAGE=1,
    234  *                      LOAD_MAT=2
    235  *                    }
    236  * @param[in] mat Reference to C++ Mat object (If LOAD_MAT)
    237  *
    238 */
    239 static void*
    240 imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 )
    241 {
    242     IplImage* image = 0;
    243     CvMat *matrix = 0;
    244     Mat temp, *data = &temp;
    245 
    246     /// Search for the relevant decoder to handle the imagery
    247     ImageDecoder decoder;
    248 
    249 #ifdef HAVE_GDAL
    250     if(flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL ){
    251         decoder = GdalDecoder().newDecoder();
    252     }else{
    253 #endif
    254         decoder = findDecoder(filename);
    255 #ifdef HAVE_GDAL
    256     }
    257 #endif
    258 
    259     /// if no decoder was found, return nothing.
    260     if( !decoder ){
    261         return 0;
    262     }
    263 
    264     /// set the filename in the driver
    265     decoder->setSource(filename);
    266 
    267    // read the header to make sure it succeeds
    268    if( !decoder->readHeader() )
    269         return 0;
    270 
    271     // established the required input image size
    272     CvSize size;
    273     size.width = decoder->width();
    274     size.height = decoder->height();
    275 
    276     // grab the decoded type
    277     int type = decoder->type();
    278     if( flags != IMREAD_UNCHANGED )
    279     {
    280         if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
    281             type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
    282 
    283         if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
    284            ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
    285             type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
    286         else
    287             type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
    288     }
    289 
    290     if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )
    291     {
    292         if( hdrtype == LOAD_CVMAT )
    293         {
    294             matrix = cvCreateMat( size.height, size.width, type );
    295             temp = cvarrToMat(matrix);
    296         }
    297         else
    298         {
    299             mat->create( size.height, size.width, type );
    300             data = mat;
    301         }
    302     }
    303     else
    304     {
    305         image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) );
    306         temp = cvarrToMat(image);
    307     }
    308 
    309     // read the image data
    310     if( !decoder->readData( *data ))
    311     {
    312         cvReleaseImage( &image );
    313         cvReleaseMat( &matrix );
    314         if( mat )
    315             mat->release();
    316         return 0;
    317     }
    318 
    319     return hdrtype == LOAD_CVMAT ? (void*)matrix :
    320         hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
    321 }
    322 
    323 
    324 /**
    325 * Read an image into memory and return the information
    326 *
    327 * @param[in] filename File to load
    328 * @param[in] flags Flags
    329 * @param[in] mats Reference to C++ vector<Mat> object to hold the images
    330 *
    331 */
    332 static bool
    333 imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
    334 {
    335     /// Search for the relevant decoder to handle the imagery
    336     ImageDecoder decoder;
    337 
    338 #ifdef HAVE_GDAL
    339     if (flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL){
    340         decoder = GdalDecoder().newDecoder();
    341     }
    342     else{
    343 #endif
    344         decoder = findDecoder(filename);
    345 #ifdef HAVE_GDAL
    346     }
    347 #endif
    348 
    349     /// if no decoder was found, return nothing.
    350     if (!decoder){
    351         return 0;
    352     }
    353 
    354     /// set the filename in the driver
    355     decoder->setSource(filename);
    356 
    357     // read the header to make sure it succeeds
    358     if (!decoder->readHeader())
    359         return 0;
    360 
    361     for (;;)
    362     {
    363         // grab the decoded type
    364         int type = decoder->type();
    365         if (flags != IMREAD_UNCHANGED)
    366         {
    367             if ((flags & CV_LOAD_IMAGE_ANYDEPTH) == 0)
    368                 type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
    369 
    370             if ((flags & CV_LOAD_IMAGE_COLOR) != 0 ||
    371                 ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
    372                 type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
    373             else
    374                 type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
    375         }
    376 
    377         // read the image data
    378         Mat mat(decoder->height(), decoder->width(), type);
    379         if (!decoder->readData(mat))
    380         {
    381             break;
    382         }
    383 
    384         mats.push_back(mat);
    385         if (!decoder->nextPage())
    386         {
    387             break;
    388         }
    389     }
    390 
    391     return !mats.empty();
    392 }
    393 
    394 /**
    395  * Read an image
    396  *
    397  *  This function merely calls the actual implementation above and returns itself.
    398  *
    399  * @param[in] filename File to load
    400  * @param[in] flags Flags you wish to set.
    401 */
    402 Mat imread( const String& filename, int flags )
    403 {
    404     /// create the basic container
    405     Mat img;
    406 
    407     /// load the data
    408     imread_( filename, flags, LOAD_MAT, &img );
    409 
    410     /// return a reference to the data
    411     return img;
    412 }
    413 
    414 /**
    415 * Read a multi-page image
    416 *
    417 *  This function merely calls the actual implementation above and returns itself.
    418 *
    419 * @param[in] filename File to load
    420 * @param[in] mats Reference to C++ vector<Mat> object to hold the images
    421 * @param[in] flags Flags you wish to set.
    422 *
    423 */
    424 bool imreadmulti(const String& filename, std::vector<Mat>& mats, int flags)
    425 {
    426     return imreadmulti_(filename, flags, mats);
    427 }
    428 
    429 static bool imwrite_( const String& filename, const Mat& image,
    430                       const std::vector<int>& params, bool flipv )
    431 {
    432     Mat temp;
    433     const Mat* pimage = &image;
    434 
    435     CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 );
    436 
    437     ImageEncoder encoder = findEncoder( filename );
    438     if( !encoder )
    439         CV_Error( CV_StsError, "could not find a writer for the specified extension" );
    440     if( !encoder->isFormatSupported(image.depth()) )
    441     {
    442         CV_Assert( encoder->isFormatSupported(CV_8U) );
    443         image.convertTo( temp, CV_8U );
    444         pimage = &temp;
    445     }
    446 
    447     if( flipv )
    448     {
    449         flip(*pimage, temp, 0);
    450         pimage = &temp;
    451     }
    452 
    453     encoder->setDestination( filename );
    454     bool code = encoder->write( *pimage, params );
    455 
    456     //    CV_Assert( code );
    457     return code;
    458 }
    459 
    460 bool imwrite( const String& filename, InputArray _img,
    461               const std::vector<int>& params )
    462 {
    463     Mat img = _img.getMat();
    464     return imwrite_(filename, img, params, false);
    465 }
    466 
    467 static void*
    468 imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )
    469 {
    470     CV_Assert(!buf.empty() && buf.isContinuous());
    471     IplImage* image = 0;
    472     CvMat *matrix = 0;
    473     Mat temp, *data = &temp;
    474     String filename;
    475 
    476     ImageDecoder decoder = findDecoder(buf);
    477     if( !decoder )
    478         return 0;
    479 
    480     if( !decoder->setSource(buf) )
    481     {
    482         filename = tempfile();
    483         FILE* f = fopen( filename.c_str(), "wb" );
    484         if( !f )
    485             return 0;
    486         size_t bufSize = buf.cols*buf.rows*buf.elemSize();
    487         fwrite( buf.ptr(), 1, bufSize, f );
    488         fclose(f);
    489         decoder->setSource(filename);
    490     }
    491 
    492     if( !decoder->readHeader() )
    493     {
    494         if( !filename.empty() )
    495             remove(filename.c_str());
    496         return 0;
    497     }
    498 
    499     CvSize size;
    500     size.width = decoder->width();
    501     size.height = decoder->height();
    502 
    503     int type = decoder->type();
    504     if( flags != IMREAD_UNCHANGED )
    505     {
    506         if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
    507             type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
    508 
    509         if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
    510            ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
    511             type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
    512         else
    513             type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
    514     }
    515 
    516     if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )
    517     {
    518         if( hdrtype == LOAD_CVMAT )
    519         {
    520             matrix = cvCreateMat( size.height, size.width, type );
    521             temp = cvarrToMat(matrix);
    522         }
    523         else
    524         {
    525             mat->create( size.height, size.width, type );
    526             data = mat;
    527         }
    528     }
    529     else
    530     {
    531         image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) );
    532         temp = cvarrToMat(image);
    533     }
    534 
    535     bool code = decoder->readData( *data );
    536     if( !filename.empty() )
    537         remove(filename.c_str());
    538 
    539     if( !code )
    540     {
    541         cvReleaseImage( &image );
    542         cvReleaseMat( &matrix );
    543         if( mat )
    544             mat->release();
    545         return 0;
    546     }
    547 
    548     return hdrtype == LOAD_CVMAT ? (void*)matrix :
    549         hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
    550 }
    551 
    552 
    553 Mat imdecode( InputArray _buf, int flags )
    554 {
    555     Mat buf = _buf.getMat(), img;
    556     imdecode_( buf, flags, LOAD_MAT, &img );
    557     return img;
    558 }
    559 
    560 Mat imdecode( InputArray _buf, int flags, Mat* dst )
    561 {
    562     Mat buf = _buf.getMat(), img;
    563     dst = dst ? dst : &img;
    564     imdecode_( buf, flags, LOAD_MAT, dst );
    565     return *dst;
    566 }
    567 
    568 bool imencode( const String& ext, InputArray _image,
    569                std::vector<uchar>& buf, const std::vector<int>& params )
    570 {
    571     Mat image = _image.getMat();
    572 
    573     int channels = image.channels();
    574     CV_Assert( channels == 1 || channels == 3 || channels == 4 );
    575 
    576     ImageEncoder encoder = findEncoder( ext );
    577     if( !encoder )
    578         CV_Error( CV_StsError, "could not find encoder for the specified extension" );
    579 
    580     if( !encoder->isFormatSupported(image.depth()) )
    581     {
    582         CV_Assert( encoder->isFormatSupported(CV_8U) );
    583         Mat temp;
    584         image.convertTo(temp, CV_8U);
    585         image = temp;
    586     }
    587 
    588     bool code;
    589     if( encoder->setDestination(buf) )
    590     {
    591         code = encoder->write(image, params);
    592         encoder->throwOnEror();
    593         CV_Assert( code );
    594     }
    595     else
    596     {
    597         String filename = tempfile();
    598         code = encoder->setDestination(filename);
    599         CV_Assert( code );
    600 
    601         code = encoder->write(image, params);
    602         encoder->throwOnEror();
    603         CV_Assert( code );
    604 
    605         FILE* f = fopen( filename.c_str(), "rb" );
    606         CV_Assert(f != 0);
    607         fseek( f, 0, SEEK_END );
    608         long pos = ftell(f);
    609         buf.resize((size_t)pos);
    610         fseek( f, 0, SEEK_SET );
    611         buf.resize(fread( &buf[0], 1, buf.size(), f ));
    612         fclose(f);
    613         remove(filename.c_str());
    614     }
    615     return code;
    616 }
    617 
    618 }
    619 
    620 /****************************************************************************************\
    621 *                         Imgcodecs loading & saving function implementation            *
    622 \****************************************************************************************/
    623 
    624 CV_IMPL int
    625 cvHaveImageReader( const char* filename )
    626 {
    627     cv::ImageDecoder decoder = cv::findDecoder(filename);
    628     return !decoder.empty();
    629 }
    630 
    631 CV_IMPL int cvHaveImageWriter( const char* filename )
    632 {
    633     cv::ImageEncoder encoder = cv::findEncoder(filename);
    634     return !encoder.empty();
    635 }
    636 
    637 CV_IMPL IplImage*
    638 cvLoadImage( const char* filename, int iscolor )
    639 {
    640     return (IplImage*)cv::imread_(filename, iscolor, cv::LOAD_IMAGE );
    641 }
    642 
    643 CV_IMPL CvMat*
    644 cvLoadImageM( const char* filename, int iscolor )
    645 {
    646     return (CvMat*)cv::imread_( filename, iscolor, cv::LOAD_CVMAT );
    647 }
    648 
    649 CV_IMPL int
    650 cvSaveImage( const char* filename, const CvArr* arr, const int* _params )
    651 {
    652     int i = 0;
    653     if( _params )
    654     {
    655         for( ; _params[i] > 0; i += 2 )
    656             ;
    657     }
    658     return cv::imwrite_(filename, cv::cvarrToMat(arr),
    659         i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>(),
    660         CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL );
    661 }
    662 
    663 /* decode image stored in the buffer */
    664 CV_IMPL IplImage*
    665 cvDecodeImage( const CvMat* _buf, int iscolor )
    666 {
    667     CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );
    668     cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);
    669     return (IplImage*)cv::imdecode_(buf, iscolor, cv::LOAD_IMAGE );
    670 }
    671 
    672 CV_IMPL CvMat*
    673 cvDecodeImageM( const CvMat* _buf, int iscolor )
    674 {
    675     CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );
    676     cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);
    677     return (CvMat*)cv::imdecode_(buf, iscolor, cv::LOAD_CVMAT );
    678 }
    679 
    680 CV_IMPL CvMat*
    681 cvEncodeImage( const char* ext, const CvArr* arr, const int* _params )
    682 {
    683     int i = 0;
    684     if( _params )
    685     {
    686         for( ; _params[i] > 0; i += 2 )
    687             ;
    688     }
    689     cv::Mat img = cv::cvarrToMat(arr);
    690     if( CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL )
    691     {
    692         cv::Mat temp;
    693         cv::flip(img, temp, 0);
    694         img = temp;
    695     }
    696     std::vector<uchar> buf;
    697 
    698     bool code = cv::imencode(ext, img, buf,
    699         i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>() );
    700     if( !code )
    701         return 0;
    702     CvMat* _buf = cvCreateMat(1, (int)buf.size(), CV_8U);
    703     memcpy( _buf->data.ptr, &buf[0], buf.size() );
    704 
    705     return _buf;
    706 }
    707 
    708 /* End of file. */
    709