Path: blob/master/modules/imgcodecs/src/loadsave.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000, Intel Corporation, all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041//42// Loading and saving IPL images.43//4445#include "precomp.hpp"46#include "grfmts.hpp"47#include "utils.hpp"48#include "exif.hpp"49#undef min50#undef max51#include <iostream>52#include <fstream>5354/****************************************************************************************\55* Image Codecs *56\****************************************************************************************/5758namespace cv {5960// TODO Add runtime configuration61#define CV_IO_MAX_IMAGE_PARAMS (50)62#define CV_IO_MAX_IMAGE_WIDTH (1<<20)63#define CV_IO_MAX_IMAGE_HEIGHT (1<<20)64#define CV_IO_MAX_IMAGE_PIXELS (1<<30) // 1 Gigapixel6566static Size validateInputImageSize(const Size& size)67{68CV_Assert(size.width > 0);69CV_Assert(size.width <= CV_IO_MAX_IMAGE_WIDTH);70CV_Assert(size.height > 0);71CV_Assert(size.height <= CV_IO_MAX_IMAGE_HEIGHT);72uint64 pixels = (uint64)size.width * (uint64)size.height;73CV_Assert(pixels <= CV_IO_MAX_IMAGE_PIXELS);74return size;75}767778namespace {7980class ByteStreamBuffer: public std::streambuf81{82public:83ByteStreamBuffer(char* base, size_t length)84{85setg(base, base, base + length);86}8788protected:89virtual pos_type seekoff( off_type offset,90std::ios_base::seekdir dir,91std::ios_base::openmode ) CV_OVERRIDE92{93char* whence = eback();94if (dir == std::ios_base::cur)95{96whence = gptr();97}98else if (dir == std::ios_base::end)99{100whence = egptr();101}102char* to = whence + offset;103104// check limits105if (to >= eback() && to <= egptr())106{107setg(eback(), to, egptr());108return gptr() - eback();109}110111return -1;112}113};114115}116117/**118* @struct ImageCodecInitializer119*120* Container which stores the registered codecs to be used by OpenCV121*/122struct ImageCodecInitializer123{124/**125* Default Constructor for the ImageCodeInitializer126*/127ImageCodecInitializer()128{129/// BMP Support130decoders.push_back( makePtr<BmpDecoder>() );131encoders.push_back( makePtr<BmpEncoder>() );132133#ifdef HAVE_IMGCODEC_HDR134decoders.push_back( makePtr<HdrDecoder>() );135encoders.push_back( makePtr<HdrEncoder>() );136#endif137#ifdef HAVE_JPEG138decoders.push_back( makePtr<JpegDecoder>() );139encoders.push_back( makePtr<JpegEncoder>() );140#endif141#ifdef HAVE_WEBP142decoders.push_back( makePtr<WebPDecoder>() );143encoders.push_back( makePtr<WebPEncoder>() );144#endif145#ifdef HAVE_IMGCODEC_SUNRASTER146decoders.push_back( makePtr<SunRasterDecoder>() );147encoders.push_back( makePtr<SunRasterEncoder>() );148#endif149#ifdef HAVE_IMGCODEC_PXM150decoders.push_back( makePtr<PxMDecoder>() );151encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_AUTO) );152encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PBM) );153encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PGM) );154encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PPM) );155decoders.push_back( makePtr<PAMDecoder>() );156encoders.push_back( makePtr<PAMEncoder>() );157#endif158#ifdef HAVE_IMGCODEC_PFM159decoders.push_back( makePtr<PFMDecoder>() );160encoders.push_back( makePtr<PFMEncoder>() );161#endif162#ifdef HAVE_TIFF163decoders.push_back( makePtr<TiffDecoder>() );164encoders.push_back( makePtr<TiffEncoder>() );165#endif166#ifdef HAVE_PNG167decoders.push_back( makePtr<PngDecoder>() );168encoders.push_back( makePtr<PngEncoder>() );169#endif170#ifdef HAVE_GDCM171decoders.push_back( makePtr<DICOMDecoder>() );172#endif173#ifdef HAVE_JASPER174decoders.push_back( makePtr<Jpeg2KDecoder>() );175encoders.push_back( makePtr<Jpeg2KEncoder>() );176#endif177#ifdef HAVE_OPENEXR178decoders.push_back( makePtr<ExrDecoder>() );179encoders.push_back( makePtr<ExrEncoder>() );180#endif181182#ifdef HAVE_GDAL183/// Attach the GDAL Decoder184decoders.push_back( makePtr<GdalDecoder>() );185#endif/*HAVE_GDAL*/186}187188std::vector<ImageDecoder> decoders;189std::vector<ImageEncoder> encoders;190};191192static ImageCodecInitializer codecs;193194/**195* Find the decoders196*197* @param[in] filename File to search198*199* @return Image decoder to parse image file.200*/201static ImageDecoder findDecoder( const String& filename ) {202203size_t i, maxlen = 0;204205/// iterate through list of registered codecs206for( i = 0; i < codecs.decoders.size(); i++ )207{208size_t len = codecs.decoders[i]->signatureLength();209maxlen = std::max(maxlen, len);210}211212/// Open the file213FILE* f= fopen( filename.c_str(), "rb" );214215/// in the event of a failure, return an empty image decoder216if( !f )217return ImageDecoder();218219// read the file signature220String signature(maxlen, ' ');221maxlen = fread( (void*)signature.c_str(), 1, maxlen, f );222fclose(f);223signature = signature.substr(0, maxlen);224225/// compare signature against all decoders226for( i = 0; i < codecs.decoders.size(); i++ )227{228if( codecs.decoders[i]->checkSignature(signature) )229return codecs.decoders[i]->newDecoder();230}231232/// If no decoder was found, return base type233return ImageDecoder();234}235236static ImageDecoder findDecoder( const Mat& buf )237{238size_t i, maxlen = 0;239240if( buf.rows*buf.cols < 1 || !buf.isContinuous() )241return ImageDecoder();242243for( i = 0; i < codecs.decoders.size(); i++ )244{245size_t len = codecs.decoders[i]->signatureLength();246maxlen = std::max(maxlen, len);247}248249String signature(maxlen, ' ');250size_t bufSize = buf.rows*buf.cols*buf.elemSize();251maxlen = std::min(maxlen, bufSize);252memcpy( (void*)signature.c_str(), buf.data, maxlen );253254for( i = 0; i < codecs.decoders.size(); i++ )255{256if( codecs.decoders[i]->checkSignature(signature) )257return codecs.decoders[i]->newDecoder();258}259260return ImageDecoder();261}262263static ImageEncoder findEncoder( const String& _ext )264{265if( _ext.size() <= 1 )266return ImageEncoder();267268const char* ext = strrchr( _ext.c_str(), '.' );269if( !ext )270return ImageEncoder();271int len = 0;272for( ext++; len < 128 && isalnum(ext[len]); len++ )273;274275for( size_t i = 0; i < codecs.encoders.size(); i++ )276{277String description = codecs.encoders[i]->getDescription();278const char* descr = strchr( description.c_str(), '(' );279280while( descr )281{282descr = strchr( descr + 1, '.' );283if( !descr )284break;285int j = 0;286for( descr++; j < len && isalnum(descr[j]) ; j++ )287{288int c1 = tolower(ext[j]);289int c2 = tolower(descr[j]);290if( c1 != c2 )291break;292}293if( j == len && !isalnum(descr[j]))294return codecs.encoders[i]->newEncoder();295descr += j;296}297}298299return ImageEncoder();300}301302303enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 };304305static void ExifTransform(int orientation, Mat& img)306{307switch( orientation )308{309case IMAGE_ORIENTATION_TL: //0th row == visual top, 0th column == visual left-hand side310//do nothing, the image already has proper orientation311break;312case IMAGE_ORIENTATION_TR: //0th row == visual top, 0th column == visual right-hand side313flip(img, img, 1); //flip horizontally314break;315case IMAGE_ORIENTATION_BR: //0th row == visual bottom, 0th column == visual right-hand side316flip(img, img, -1);//flip both horizontally and vertically317break;318case IMAGE_ORIENTATION_BL: //0th row == visual bottom, 0th column == visual left-hand side319flip(img, img, 0); //flip vertically320break;321case IMAGE_ORIENTATION_LT: //0th row == visual left-hand side, 0th column == visual top322transpose(img, img);323break;324case IMAGE_ORIENTATION_RT: //0th row == visual right-hand side, 0th column == visual top325transpose(img, img);326flip(img, img, 1); //flip horizontally327break;328case IMAGE_ORIENTATION_RB: //0th row == visual right-hand side, 0th column == visual bottom329transpose(img, img);330flip(img, img, -1); //flip both horizontally and vertically331break;332case IMAGE_ORIENTATION_LB: //0th row == visual left-hand side, 0th column == visual bottom333transpose(img, img);334flip(img, img, 0); //flip vertically335break;336default:337//by default the image read has normal (JPEG_ORIENTATION_TL) orientation338break;339}340}341342static void ApplyExifOrientation(const String& filename, Mat& img)343{344int orientation = IMAGE_ORIENTATION_TL;345346if (filename.size() > 0)347{348std::ifstream stream( filename.c_str(), std::ios_base::in | std::ios_base::binary );349ExifReader reader( stream );350if( reader.parse() )351{352ExifEntry_t entry = reader.getTag( ORIENTATION );353if (entry.tag != INVALID_TAG)354{355orientation = entry.field_u16; //orientation is unsigned short, so check field_u16356}357}358stream.close();359}360361ExifTransform(orientation, img);362}363364static void ApplyExifOrientation(const Mat& buf, Mat& img)365{366int orientation = IMAGE_ORIENTATION_TL;367368if( buf.isContinuous() )369{370ByteStreamBuffer bsb( reinterpret_cast<char*>(buf.data), buf.total() * buf.elemSize() );371std::istream stream( &bsb );372ExifReader reader( stream );373if( reader.parse() )374{375ExifEntry_t entry = reader.getTag( ORIENTATION );376if (entry.tag != INVALID_TAG)377{378orientation = entry.field_u16; //orientation is unsigned short, so check field_u16379}380}381}382383ExifTransform(orientation, img);384}385386/**387* Read an image into memory and return the information388*389* @param[in] filename File to load390* @param[in] flags Flags391* @param[in] hdrtype { LOAD_CVMAT=0,392* LOAD_IMAGE=1,393* LOAD_MAT=2394* }395* @param[in] mat Reference to C++ Mat object (If LOAD_MAT)396* @param[in] scale_denom Scale value397*398*/399static void*400imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 )401{402CV_Assert(mat || hdrtype != LOAD_MAT); // mat is required in LOAD_MAT case403404IplImage* image = 0;405CvMat *matrix = 0;406Mat temp, *data = &temp;407408/// Search for the relevant decoder to handle the imagery409ImageDecoder decoder;410411#ifdef HAVE_GDAL412if(flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL ){413decoder = GdalDecoder().newDecoder();414}else{415#endif416decoder = findDecoder( filename );417#ifdef HAVE_GDAL418}419#endif420421/// if no decoder was found, return nothing.422if( !decoder ){423return 0;424}425426int scale_denom = 1;427if( flags > IMREAD_LOAD_GDAL )428{429if( flags & IMREAD_REDUCED_GRAYSCALE_2 )430scale_denom = 2;431else if( flags & IMREAD_REDUCED_GRAYSCALE_4 )432scale_denom = 4;433else if( flags & IMREAD_REDUCED_GRAYSCALE_8 )434scale_denom = 8;435}436437/// set the scale_denom in the driver438decoder->setScale( scale_denom );439440/// set the filename in the driver441decoder->setSource( filename );442443CV_TRY444{445// read the header to make sure it succeeds446if( !decoder->readHeader() )447return 0;448}449CV_CATCH (cv::Exception, e)450{451std::cerr << "imread_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;452return 0;453}454CV_CATCH_ALL455{456std::cerr << "imread_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;457return 0;458}459460461// established the required input image size462Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));463464// grab the decoded type465int type = decoder->type();466if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )467{468if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )469type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));470471if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||472((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )473type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);474else475type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);476}477478if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )479{480if( hdrtype == LOAD_CVMAT )481{482matrix = cvCreateMat( size.height, size.width, type );483temp = cvarrToMat( matrix );484}485else486{487mat->create( size.height, size.width, type );488data = mat;489}490}491else492{493image = cvCreateImage(cvSize(size), cvIplDepth(type), CV_MAT_CN(type));494temp = cvarrToMat( image );495}496497// read the image data498bool success = false;499CV_TRY500{501if (decoder->readData(*data))502success = true;503}504CV_CATCH (cv::Exception, e)505{506std::cerr << "imread_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;507}508CV_CATCH_ALL509{510std::cerr << "imread_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;511}512if (!success)513{514cvReleaseImage( &image );515cvReleaseMat( &matrix );516if( mat )517mat->release();518return 0;519}520521if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1522{523resize( *mat, *mat, Size( size.width / scale_denom, size.height / scale_denom ), 0, 0, INTER_LINEAR_EXACT);524}525526return hdrtype == LOAD_CVMAT ? (void*)matrix :527hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;528}529530531/**532* Read an image into memory and return the information533*534* @param[in] filename File to load535* @param[in] flags Flags536* @param[in] mats Reference to C++ vector<Mat> object to hold the images537*538*/539static bool540imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)541{542/// Search for the relevant decoder to handle the imagery543ImageDecoder decoder;544545#ifdef HAVE_GDAL546if (flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL){547decoder = GdalDecoder().newDecoder();548}549else{550#endif551decoder = findDecoder(filename);552#ifdef HAVE_GDAL553}554#endif555556/// if no decoder was found, return nothing.557if (!decoder){558return 0;559}560561/// set the filename in the driver562decoder->setSource(filename);563564// read the header to make sure it succeeds565CV_TRY566{567// read the header to make sure it succeeds568if( !decoder->readHeader() )569return 0;570}571CV_CATCH (cv::Exception, e)572{573std::cerr << "imreadmulti_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;574return 0;575}576CV_CATCH_ALL577{578std::cerr << "imreadmulti_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;579return 0;580}581582for (;;)583{584// grab the decoded type585int type = decoder->type();586if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )587{588if ((flags & CV_LOAD_IMAGE_ANYDEPTH) == 0)589type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));590591if ((flags & CV_LOAD_IMAGE_COLOR) != 0 ||592((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))593type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);594else595type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);596}597598// established the required input image size599Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));600601// read the image data602Mat mat(size.height, size.width, type);603bool success = false;604CV_TRY605{606if (decoder->readData(mat))607success = true;608}609CV_CATCH (cv::Exception, e)610{611std::cerr << "imreadmulti_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;612}613CV_CATCH_ALL614{615std::cerr << "imreadmulti_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;616}617if (!success)618break;619620// optionally rotate the data if EXIF' orientation flag says so621if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )622{623ApplyExifOrientation(filename, mat);624}625626mats.push_back(mat);627if (!decoder->nextPage())628{629break;630}631}632633return !mats.empty();634}635636/**637* Read an image638*639* This function merely calls the actual implementation above and returns itself.640*641* @param[in] filename File to load642* @param[in] flags Flags you wish to set.643*/644Mat imread( const String& filename, int flags )645{646CV_TRACE_FUNCTION();647648/// create the basic container649Mat img;650651/// load the data652imread_( filename, flags, LOAD_MAT, &img );653654/// optionally rotate the data if EXIF' orientation flag says so655if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )656{657ApplyExifOrientation(filename, img);658}659660/// return a reference to the data661return img;662}663664/**665* Read a multi-page image666*667* This function merely calls the actual implementation above and returns itself.668*669* @param[in] filename File to load670* @param[in] mats Reference to C++ vector<Mat> object to hold the images671* @param[in] flags Flags you wish to set.672*673*/674bool imreadmulti(const String& filename, std::vector<Mat>& mats, int flags)675{676CV_TRACE_FUNCTION();677678return imreadmulti_(filename, flags, mats);679}680681static bool imwrite_( const String& filename, const std::vector<Mat>& img_vec,682const std::vector<int>& params, bool flipv )683{684bool isMultiImg = img_vec.size() > 1;685std::vector<Mat> write_vec;686687ImageEncoder encoder = findEncoder( filename );688if( !encoder )689CV_Error( CV_StsError, "could not find a writer for the specified extension" );690691for (size_t page = 0; page < img_vec.size(); page++)692{693Mat image = img_vec[page];694CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 );695696Mat temp;697if( !encoder->isFormatSupported(image.depth()) )698{699CV_Assert( encoder->isFormatSupported(CV_8U) );700image.convertTo( temp, CV_8U );701image = temp;702}703704if( flipv )705{706flip(image, temp, 0);707image = temp;708}709710write_vec.push_back(image);711}712713encoder->setDestination( filename );714CV_Assert(params.size() <= CV_IO_MAX_IMAGE_PARAMS*2);715bool code = false;716try717{718if (!isMultiImg)719code = encoder->write( write_vec[0], params );720else721code = encoder->writemulti( write_vec, params ); //to be implemented722}723catch (const cv::Exception& e)724{725std::cerr << "imwrite_('" << filename << "'): can't write data: " << e.what() << std::endl << std::flush;726}727catch (...)728{729std::cerr << "imwrite_('" << filename << "'): can't write data: unknown exception" << std::endl << std::flush;730}731732// CV_Assert( code );733return code;734}735736bool imwrite( const String& filename, InputArray _img,737const std::vector<int>& params )738{739CV_TRACE_FUNCTION();740std::vector<Mat> img_vec;741if (_img.isMatVector() || _img.isUMatVector())742_img.getMatVector(img_vec);743else744img_vec.push_back(_img.getMat());745746CV_Assert(!img_vec.empty());747return imwrite_(filename, img_vec, params, false);748}749750static void*751imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )752{753CV_Assert(!buf.empty() && buf.isContinuous());754IplImage* image = 0;755CvMat *matrix = 0;756Mat temp, *data = &temp;757String filename;758759ImageDecoder decoder = findDecoder(buf);760if( !decoder )761return 0;762763if( !decoder->setSource(buf) )764{765filename = tempfile();766FILE* f = fopen( filename.c_str(), "wb" );767if( !f )768return 0;769size_t bufSize = buf.cols*buf.rows*buf.elemSize();770if( fwrite( buf.ptr(), 1, bufSize, f ) != bufSize )771{772fclose( f );773CV_Error( CV_StsError, "failed to write image data to temporary file" );774}775if( fclose(f) != 0 )776{777CV_Error( CV_StsError, "failed to write image data to temporary file" );778}779decoder->setSource(filename);780}781782bool success = false;783CV_TRY784{785if (decoder->readHeader())786success = true;787}788CV_CATCH (cv::Exception, e)789{790std::cerr << "imdecode_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;791}792CV_CATCH_ALL793{794std::cerr << "imdecode_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;795}796if (!success)797{798decoder.release();799if (!filename.empty())800{801if (0 != remove(filename.c_str()))802{803std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;804}805}806return 0;807}808809// established the required input image size810Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));811812int type = decoder->type();813if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )814{815if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )816type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));817818if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||819((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )820type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);821else822type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);823}824825if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )826{827if( hdrtype == LOAD_CVMAT )828{829matrix = cvCreateMat( size.height, size.width, type );830temp = cvarrToMat(matrix);831}832else833{834mat->create( size.height, size.width, type );835data = mat;836}837}838else839{840image = cvCreateImage(cvSize(size), cvIplDepth(type), CV_MAT_CN(type));841temp = cvarrToMat(image);842}843844success = false;845CV_TRY846{847if (decoder->readData(*data))848success = true;849}850CV_CATCH (cv::Exception, e)851{852std::cerr << "imdecode_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;853}854CV_CATCH_ALL855{856std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;857}858decoder.release();859if (!filename.empty())860{861if (0 != remove(filename.c_str()))862{863std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;864}865}866867if (!success)868{869cvReleaseImage( &image );870cvReleaseMat( &matrix );871if( mat )872mat->release();873return 0;874}875876return hdrtype == LOAD_CVMAT ? (void*)matrix :877hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;878}879880881Mat imdecode( InputArray _buf, int flags )882{883CV_TRACE_FUNCTION();884885Mat buf = _buf.getMat(), img;886imdecode_( buf, flags, LOAD_MAT, &img );887888/// optionally rotate the data if EXIF' orientation flag says so889if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )890{891ApplyExifOrientation(buf, img);892}893894return img;895}896897Mat imdecode( InputArray _buf, int flags, Mat* dst )898{899CV_TRACE_FUNCTION();900901Mat buf = _buf.getMat(), img;902dst = dst ? dst : &img;903imdecode_( buf, flags, LOAD_MAT, dst );904905/// optionally rotate the data if EXIF' orientation flag says so906if( !dst->empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )907{908ApplyExifOrientation(buf, *dst);909}910911return *dst;912}913914bool imencode( const String& ext, InputArray _image,915std::vector<uchar>& buf, const std::vector<int>& params )916{917CV_TRACE_FUNCTION();918919Mat image = _image.getMat();920921int channels = image.channels();922CV_Assert( channels == 1 || channels == 3 || channels == 4 );923924ImageEncoder encoder = findEncoder( ext );925if( !encoder )926CV_Error( CV_StsError, "could not find encoder for the specified extension" );927928if( !encoder->isFormatSupported(image.depth()) )929{930CV_Assert( encoder->isFormatSupported(CV_8U) );931Mat temp;932image.convertTo(temp, CV_8U);933image = temp;934}935936bool code;937if( encoder->setDestination(buf) )938{939code = encoder->write(image, params);940encoder->throwOnEror();941CV_Assert( code );942}943else944{945String filename = tempfile();946code = encoder->setDestination(filename);947CV_Assert( code );948949code = encoder->write(image, params);950encoder->throwOnEror();951CV_Assert( code );952953FILE* f = fopen( filename.c_str(), "rb" );954CV_Assert(f != 0);955fseek( f, 0, SEEK_END );956long pos = ftell(f);957buf.resize((size_t)pos);958fseek( f, 0, SEEK_SET );959buf.resize(fread( &buf[0], 1, buf.size(), f ));960fclose(f);961remove(filename.c_str());962}963return code;964}965966}967968/****************************************************************************************\969* Imgcodecs loading & saving function implementation *970\****************************************************************************************/971972CV_IMPL int973cvHaveImageReader( const char* filename )974{975cv::ImageDecoder decoder = cv::findDecoder(filename);976return !decoder.empty();977}978979CV_IMPL int cvHaveImageWriter( const char* filename )980{981cv::ImageEncoder encoder = cv::findEncoder(filename);982return !encoder.empty();983}984985CV_IMPL IplImage*986cvLoadImage( const char* filename, int iscolor )987{988return (IplImage*)cv::imread_(filename, iscolor, cv::LOAD_IMAGE );989}990991CV_IMPL CvMat*992cvLoadImageM( const char* filename, int iscolor )993{994return (CvMat*)cv::imread_( filename, iscolor, cv::LOAD_CVMAT );995}996997CV_IMPL int998cvSaveImage( const char* filename, const CvArr* arr, const int* _params )999{1000int i = 0;1001if( _params )1002{1003for( ; _params[i] > 0; i += 2 )1004CV_Assert(i < CV_IO_MAX_IMAGE_PARAMS*2); // Limit number of params for security reasons1005}1006return cv::imwrite_(filename, cv::cvarrToMat(arr),1007i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>(),1008CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL );1009}10101011/* decode image stored in the buffer */1012CV_IMPL IplImage*1013cvDecodeImage( const CvMat* _buf, int iscolor )1014{1015CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );1016cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);1017return (IplImage*)cv::imdecode_(buf, iscolor, cv::LOAD_IMAGE );1018}10191020CV_IMPL CvMat*1021cvDecodeImageM( const CvMat* _buf, int iscolor )1022{1023CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );1024cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);1025return (CvMat*)cv::imdecode_(buf, iscolor, cv::LOAD_CVMAT );1026}10271028CV_IMPL CvMat*1029cvEncodeImage( const char* ext, const CvArr* arr, const int* _params )1030{1031int i = 0;1032if( _params )1033{1034for( ; _params[i] > 0; i += 2 )1035CV_Assert(i < CV_IO_MAX_IMAGE_PARAMS*2); // Limit number of params for security reasons1036}1037cv::Mat img = cv::cvarrToMat(arr);1038if( CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL )1039{1040cv::Mat temp;1041cv::flip(img, temp, 0);1042img = temp;1043}1044std::vector<uchar> buf;10451046bool code = cv::imencode(ext, img, buf,1047i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>() );1048if( !code )1049return 0;1050CvMat* _buf = cvCreateMat(1, (int)buf.size(), CV_8U);1051memcpy( _buf->data.ptr, &buf[0], buf.size() );10521053return _buf;1054}10551056/* End of file. */105710581059