1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
43 // Loading and saving IPL images.
46 #include "precomp.hpp"
53 /****************************************************************************************\
55 \****************************************************************************************/
59 // TODO Add runtime configuration
60 #define CV_IO_MAX_IMAGE_PARAMS (50)
61 #define CV_IO_MAX_IMAGE_WIDTH (1<<20)
62 #define CV_IO_MAX_IMAGE_HEIGHT (1<<20)
63 #define CV_IO_MAX_IMAGE_PIXELS (1<<30) // 1 Gigapixel
65 static Size validateInputImageSize(const Size& size)
67 CV_Assert(size.width > 0);
68 CV_Assert(size.width <= CV_IO_MAX_IMAGE_WIDTH);
69 CV_Assert(size.height > 0);
70 CV_Assert(size.height <= CV_IO_MAX_IMAGE_HEIGHT);
71 uint64 pixels = (uint64)size.width * (uint64)size.height;
72 CV_Assert(pixels <= CV_IO_MAX_IMAGE_PIXELS);
77 struct ImageCodecInitializer
79 ImageCodecInitializer()
81 decoders.push_back( new BmpDecoder );
82 encoders.push_back( new BmpEncoder );
84 decoders.push_back( new JpegDecoder );
85 encoders.push_back( new JpegEncoder );
87 decoders.push_back( new SunRasterDecoder );
88 encoders.push_back( new SunRasterEncoder );
89 decoders.push_back( new PxMDecoder );
90 encoders.push_back( new PxMEncoder );
92 decoders.push_back( new TiffDecoder );
94 encoders.push_back( new TiffEncoder );
96 decoders.push_back( new PngDecoder );
97 encoders.push_back( new PngEncoder );
100 decoders.push_back( new Jpeg2KDecoder );
101 encoders.push_back( new Jpeg2KEncoder );
104 decoders.push_back( new ExrDecoder );
105 encoders.push_back( new ExrEncoder );
107 // because it is a generic image I/O API, supporting many formats,
108 // it should be last in the list.
110 decoders.push_back( new ImageIODecoder );
111 encoders.push_back( new ImageIOEncoder );
115 vector<ImageDecoder> decoders;
116 vector<ImageEncoder> encoders;
119 static ImageCodecInitializer codecs;
121 static ImageDecoder findDecoder( const string& filename )
123 size_t i, maxlen = 0;
124 for( i = 0; i < codecs.decoders.size(); i++ )
126 size_t len = codecs.decoders[i]->signatureLength();
127 maxlen = std::max(maxlen, len);
130 FILE* f= fopen( filename.c_str(), "rb" );
132 return ImageDecoder();
133 string signature(maxlen, ' ');
134 maxlen = fread( &signature[0], 1, maxlen, f );
136 signature = signature.substr(0, maxlen);
138 for( i = 0; i < codecs.decoders.size(); i++ )
140 if( codecs.decoders[i]->checkSignature(signature) )
141 return codecs.decoders[i]->newDecoder();
144 return ImageDecoder();
147 static ImageDecoder findDecoder( const Mat& buf )
149 size_t i, maxlen = 0;
151 if( buf.rows*buf.cols < 1 || !buf.isContinuous() )
152 return ImageDecoder();
154 for( i = 0; i < codecs.decoders.size(); i++ )
156 size_t len = codecs.decoders[i]->signatureLength();
157 maxlen = std::max(maxlen, len);
160 size_t bufSize = buf.rows*buf.cols*buf.elemSize();
161 maxlen = std::min(maxlen, bufSize);
162 string signature(maxlen, ' ');
163 memcpy( &signature[0], buf.data, maxlen );
165 for( i = 0; i < codecs.decoders.size(); i++ )
167 if( codecs.decoders[i]->checkSignature(signature) )
168 return codecs.decoders[i]->newDecoder();
171 return ImageDecoder();
174 static ImageEncoder findEncoder( const string& _ext )
176 if( _ext.size() <= 1 )
177 return ImageEncoder();
179 const char* ext = strrchr( _ext.c_str(), '.' );
181 return ImageEncoder();
183 for( ext++; isalnum(ext[len]) && len < 128; len++ )
186 for( size_t i = 0; i < codecs.encoders.size(); i++ )
188 string description = codecs.encoders[i]->getDescription();
189 const char* descr = strchr( description.c_str(), '(' );
193 descr = strchr( descr + 1, '.' );
197 for( descr++; isalnum(descr[j]) && j < len; j++ )
199 int c1 = tolower(ext[j]);
200 int c2 = tolower(descr[j]);
204 if( j == len && !isalnum(descr[j]))
205 return codecs.encoders[i]->newEncoder();
210 return ImageEncoder();
213 enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 };
216 imread_( const string& filename, int flags, int hdrtype, Mat* mat=0 )
220 Mat temp, *data = &temp;
222 ImageDecoder decoder = findDecoder(filename);
223 if( decoder.empty() )
225 decoder->setSource(filename);
229 // read the header to make sure it succeeds
230 if (!decoder->readHeader())
233 catch (const cv::Exception& e)
235 std::cerr << "imread_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
240 std::cerr << "imread_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
245 Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
247 int type = decoder->type();
250 if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
251 type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
253 if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
254 ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
255 type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
257 type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
260 if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )
262 if( hdrtype == LOAD_CVMAT )
264 matrix = cvCreateMat( size.height, size.width, type );
265 temp = cvarrToMat(matrix);
269 mat->create( size.height, size.width, type );
275 image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) );
276 temp = cvarrToMat(image);
279 bool success = false;
282 if (decoder->readData(*data))
285 catch (const cv::Exception& e)
287 std::cerr << "imread_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
291 std::cerr << "imread_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
295 cvReleaseImage( &image );
296 cvReleaseMat( &matrix );
302 return hdrtype == LOAD_CVMAT ? (void*)matrix :
303 hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
306 Mat imread( const string& filename, int flags )
309 imread_( filename, flags, LOAD_MAT, &img );
313 static bool imwrite_( const string& filename, const Mat& image,
314 const vector<int>& params, bool flipv )
317 const Mat* pimage = ℑ
319 CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 );
321 ImageEncoder encoder = findEncoder( filename );
322 if( encoder.empty() )
323 CV_Error( CV_StsError, "could not find a writer for the specified extension" );
325 if( !encoder->isFormatSupported(image.depth()) )
327 CV_Assert( encoder->isFormatSupported(CV_8U) );
328 image.convertTo( temp, CV_8U );
334 flip(*pimage, temp, 0);
338 encoder->setDestination( filename );
339 CV_Assert(params.size() <= CV_IO_MAX_IMAGE_PARAMS*2);
340 bool code = encoder->write( *pimage, params );
342 // CV_Assert( code );
346 bool imwrite( const string& filename, InputArray _img,
347 const vector<int>& params )
349 Mat img = _img.getMat();
350 return imwrite_(filename, img, params, false);
354 imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )
356 CV_Assert(buf.data && buf.isContinuous());
359 Mat temp, *data = &temp;
362 ImageDecoder decoder = findDecoder(buf);
363 if( decoder.empty() )
366 if( !decoder->setSource(buf) )
368 filename = tempfile();
369 FILE* f = fopen( filename.c_str(), "wb" );
372 size_t bufSize = buf.cols*buf.rows*buf.elemSize();
373 fwrite( &buf.data[0], 1, bufSize, f );
375 decoder->setSource(filename);
378 bool success = false;
381 if (decoder->readHeader())
384 catch (const cv::Exception& e)
386 std::cerr << "imdecode_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
390 std::cerr << "imdecode_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
394 if (!filename.empty())
396 if (0 != remove(filename.c_str()))
398 std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;
404 // established the required input image size
405 Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
407 int type = decoder->type();
410 if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
411 type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
413 if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
414 ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
415 type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
417 type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
420 if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )
422 if( hdrtype == LOAD_CVMAT )
424 matrix = cvCreateMat( size.height, size.width, type );
425 temp = cvarrToMat(matrix);
429 mat->create( size.height, size.width, type );
435 image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) );
436 temp = cvarrToMat(image);
442 if (decoder->readData(*data))
445 catch (const cv::Exception& e)
447 std::cerr << "imdecode_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
451 std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
454 if (!filename.empty())
456 if (0 != remove(filename.c_str()))
458 std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;
464 cvReleaseImage( &image );
465 cvReleaseMat( &matrix );
471 return hdrtype == LOAD_CVMAT ? (void*)matrix :
472 hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
476 Mat imdecode( InputArray _buf, int flags )
478 Mat buf = _buf.getMat(), img;
479 imdecode_( buf, flags, LOAD_MAT, &img );
483 Mat imdecode( InputArray _buf, int flags, Mat* dst )
485 Mat buf = _buf.getMat(), img;
486 dst = dst ? dst : &img;
487 imdecode_( buf, flags, LOAD_MAT, dst );
491 bool imencode( const string& ext, InputArray _image,
492 vector<uchar>& buf, const vector<int>& params )
494 Mat image = _image.getMat();
496 int channels = image.channels();
497 CV_Assert( channels == 1 || channels == 3 || channels == 4 );
499 ImageEncoder encoder = findEncoder( ext );
500 if( encoder.empty() )
501 CV_Error( CV_StsError, "could not find encoder for the specified extension" );
503 if( !encoder->isFormatSupported(image.depth()) )
505 CV_Assert( encoder->isFormatSupported(CV_8U) );
507 image.convertTo(temp, CV_8U);
512 if( encoder->setDestination(buf) )
514 code = encoder->write(image, params);
515 encoder->throwOnEror();
520 string filename = tempfile();
521 code = encoder->setDestination(filename);
524 code = encoder->write(image, params);
525 encoder->throwOnEror();
528 FILE* f = fopen( filename.c_str(), "rb" );
530 fseek( f, 0, SEEK_END );
532 buf.resize((size_t)pos);
533 fseek( f, 0, SEEK_SET );
534 buf.resize(fread( &buf[0], 1, buf.size(), f ));
536 remove(filename.c_str());
543 /****************************************************************************************\
544 * HighGUI loading & saving function implementation *
545 \****************************************************************************************/
548 cvHaveImageReader( const char* filename )
550 cv::ImageDecoder decoder = cv::findDecoder(filename);
551 return !decoder.empty();
554 CV_IMPL int cvHaveImageWriter( const char* filename )
556 cv::ImageEncoder encoder = cv::findEncoder(filename);
557 return !encoder.empty();
561 cvLoadImage( const char* filename, int iscolor )
563 return (IplImage*)cv::imread_(filename, iscolor, cv::LOAD_IMAGE );
567 cvLoadImageM( const char* filename, int iscolor )
569 return (CvMat*)cv::imread_( filename, iscolor, cv::LOAD_CVMAT );
573 cvSaveImage( const char* filename, const CvArr* arr, const int* _params )
578 for( ; _params[i] > 0; i += 2 )
579 CV_Assert(i < CV_IO_MAX_IMAGE_PARAMS*2); // Limit number of params for security reasons
581 return cv::imwrite_(filename, cv::cvarrToMat(arr),
582 i > 0 ? cv::vector<int>(_params, _params+i) : cv::vector<int>(),
583 CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL );
586 /* decode image stored in the buffer */
588 cvDecodeImage( const CvMat* _buf, int iscolor )
590 CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );
591 cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);
592 return (IplImage*)cv::imdecode_(buf, iscolor, cv::LOAD_IMAGE );
596 cvDecodeImageM( const CvMat* _buf, int iscolor )
598 CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );
599 cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);
600 return (CvMat*)cv::imdecode_(buf, iscolor, cv::LOAD_CVMAT );
604 cvEncodeImage( const char* ext, const CvArr* arr, const int* _params )
609 for( ; _params[i] > 0; i += 2 )
610 CV_Assert(i < CV_IO_MAX_IMAGE_PARAMS*2); // Limit number of params for security reasons
612 cv::Mat img = cv::cvarrToMat(arr);
613 if( CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL )
616 cv::flip(img, temp, 0);
619 cv::vector<uchar> buf;
621 bool code = cv::imencode(ext, img, buf,
622 i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>() );
625 CvMat* _buf = cvCreateMat(1, (int)buf.size(), CV_8U);
626 memcpy( _buf->data.ptr, &buf[0], buf.size() );