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 = ℑ 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