|
|
@ -55,6 +55,27 @@ |
|
|
|
/****************************************************************************************\
|
|
|
|
/****************************************************************************************\
|
|
|
|
* Image Codecs * |
|
|
|
* Image Codecs * |
|
|
|
\****************************************************************************************/ |
|
|
|
\****************************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace cv { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO Add runtime configuration
|
|
|
|
|
|
|
|
#define CV_IO_MAX_IMAGE_PARAMS (50) |
|
|
|
|
|
|
|
#define CV_IO_MAX_IMAGE_WIDTH (1<<20) |
|
|
|
|
|
|
|
#define CV_IO_MAX_IMAGE_HEIGHT (1<<20) |
|
|
|
|
|
|
|
#define CV_IO_MAX_IMAGE_PIXELS (1<<30) // 1 Gigapixel
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static Size validateInputImageSize(const Size& size) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_Assert(size.width > 0); |
|
|
|
|
|
|
|
CV_Assert(size.width <= CV_IO_MAX_IMAGE_WIDTH); |
|
|
|
|
|
|
|
CV_Assert(size.height > 0); |
|
|
|
|
|
|
|
CV_Assert(size.height <= CV_IO_MAX_IMAGE_HEIGHT); |
|
|
|
|
|
|
|
uint64 pixels = (uint64)size.width * (uint64)size.height; |
|
|
|
|
|
|
|
CV_Assert(pixels <= CV_IO_MAX_IMAGE_PIXELS); |
|
|
|
|
|
|
|
return size; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
|
|
class ByteStreamBuffer: public std::streambuf |
|
|
|
class ByteStreamBuffer: public std::streambuf |
|
|
@ -94,9 +115,6 @@ protected: |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
namespace cv |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @struct ImageCodecInitializer |
|
|
|
* @struct ImageCodecInitializer |
|
|
|
* |
|
|
|
* |
|
|
@ -408,14 +426,26 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 ) |
|
|
|
/// set the filename in the driver
|
|
|
|
/// set the filename in the driver
|
|
|
|
decoder->setSource( filename ); |
|
|
|
decoder->setSource( filename ); |
|
|
|
|
|
|
|
|
|
|
|
// read the header to make sure it succeeds
|
|
|
|
try |
|
|
|
if( !decoder->readHeader() ) |
|
|
|
{ |
|
|
|
|
|
|
|
// read the header to make sure it succeeds
|
|
|
|
|
|
|
|
if( !decoder->readHeader() ) |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (const cv::Exception& e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imread_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush; |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (...) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imread_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush; |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// established the required input image size
|
|
|
|
// established the required input image size
|
|
|
|
CvSize size; |
|
|
|
Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); |
|
|
|
size.width = decoder->width(); |
|
|
|
|
|
|
|
size.height = decoder->height(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// grab the decoded type
|
|
|
|
// grab the decoded type
|
|
|
|
int type = decoder->type(); |
|
|
|
int type = decoder->type(); |
|
|
@ -451,7 +481,21 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 ) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// read the image data
|
|
|
|
// read the image data
|
|
|
|
if( !decoder->readData( *data )) |
|
|
|
bool success = false; |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (decoder->readData(*data)) |
|
|
|
|
|
|
|
success = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (const cv::Exception& e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imread_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (...) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imread_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!success) |
|
|
|
{ |
|
|
|
{ |
|
|
|
cvReleaseImage( &image ); |
|
|
|
cvReleaseImage( &image ); |
|
|
|
cvReleaseMat( &matrix ); |
|
|
|
cvReleaseMat( &matrix ); |
|
|
@ -504,8 +548,22 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats) |
|
|
|
decoder->setSource(filename); |
|
|
|
decoder->setSource(filename); |
|
|
|
|
|
|
|
|
|
|
|
// read the header to make sure it succeeds
|
|
|
|
// read the header to make sure it succeeds
|
|
|
|
if (!decoder->readHeader()) |
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// read the header to make sure it succeeds
|
|
|
|
|
|
|
|
if( !decoder->readHeader() ) |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (const cv::Exception& e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imreadmulti_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush; |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (...) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imreadmulti_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush; |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (;;) |
|
|
|
for (;;) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -523,17 +581,32 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats) |
|
|
|
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); |
|
|
|
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// established the required input image size
|
|
|
|
|
|
|
|
Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); |
|
|
|
|
|
|
|
|
|
|
|
// read the image data
|
|
|
|
// read the image data
|
|
|
|
Mat mat(decoder->height(), decoder->width(), type); |
|
|
|
Mat mat(size.height, size.width, type); |
|
|
|
if (!decoder->readData(mat)) |
|
|
|
bool success = false; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
{ |
|
|
|
// optionally rotate the data if EXIF' orientation flag says so
|
|
|
|
if (decoder->readData(mat)) |
|
|
|
if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED ) |
|
|
|
success = true; |
|
|
|
{ |
|
|
|
} |
|
|
|
ApplyExifOrientation(filename, mat); |
|
|
|
catch (const cv::Exception& e) |
|
|
|
} |
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imreadmulti_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (...) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imreadmulti_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!success) |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// optionally rotate the data if EXIF' orientation flag says so
|
|
|
|
|
|
|
|
if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ApplyExifOrientation(filename, mat); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
mats.push_back(mat); |
|
|
|
mats.push_back(mat); |
|
|
@ -616,6 +689,7 @@ static bool imwrite_( const String& filename, const Mat& image, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
encoder->setDestination( filename ); |
|
|
|
encoder->setDestination( filename ); |
|
|
|
|
|
|
|
CV_Assert(params.size() <= CV_IO_MAX_IMAGE_PARAMS*2); |
|
|
|
bool code = encoder->write( *pimage, params ); |
|
|
|
bool code = encoder->write( *pimage, params ); |
|
|
|
|
|
|
|
|
|
|
|
// CV_Assert( code );
|
|
|
|
// CV_Assert( code );
|
|
|
@ -663,22 +737,35 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 ) |
|
|
|
decoder->setSource(filename); |
|
|
|
decoder->setSource(filename); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( !decoder->readHeader() ) |
|
|
|
bool success = false; |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (decoder->readHeader()) |
|
|
|
|
|
|
|
success = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (const cv::Exception& e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imdecode_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (...) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imdecode_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!success) |
|
|
|
{ |
|
|
|
{ |
|
|
|
decoder.release(); |
|
|
|
decoder.release(); |
|
|
|
if ( !filename.empty() ) |
|
|
|
if (!filename.empty()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( remove(filename.c_str()) != 0 ) |
|
|
|
if (0 != remove(filename.c_str())) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_Error( CV_StsError, "unable to remove temporary file" ); |
|
|
|
std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CvSize size; |
|
|
|
// established the required input image size
|
|
|
|
size.width = decoder->width(); |
|
|
|
Size size = validateInputImageSize(Size(decoder->width(), decoder->height())); |
|
|
|
size.height = decoder->height(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int type = decoder->type(); |
|
|
|
int type = decoder->type(); |
|
|
|
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ) |
|
|
|
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ) |
|
|
@ -712,17 +799,30 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 ) |
|
|
|
temp = cvarrToMat(image); |
|
|
|
temp = cvarrToMat(image); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool code = decoder->readData( *data ); |
|
|
|
success = false; |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (decoder->readData(*data)) |
|
|
|
|
|
|
|
success = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (const cv::Exception& e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imdecode_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (...) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush; |
|
|
|
|
|
|
|
} |
|
|
|
decoder.release(); |
|
|
|
decoder.release(); |
|
|
|
if ( !filename.empty() ) |
|
|
|
if (!filename.empty()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( remove(filename.c_str()) != 0 ) |
|
|
|
if (0 != remove(filename.c_str())) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_Error( CV_StsError, "unable to remove temporary file" ); |
|
|
|
std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( !code ) |
|
|
|
if (!success) |
|
|
|
{ |
|
|
|
{ |
|
|
|
cvReleaseImage( &image ); |
|
|
|
cvReleaseImage( &image ); |
|
|
|
cvReleaseMat( &matrix ); |
|
|
|
cvReleaseMat( &matrix ); |
|
|
@ -859,7 +959,7 @@ cvSaveImage( const char* filename, const CvArr* arr, const int* _params ) |
|
|
|
if( _params ) |
|
|
|
if( _params ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for( ; _params[i] > 0; i += 2 ) |
|
|
|
for( ; _params[i] > 0; i += 2 ) |
|
|
|
; |
|
|
|
CV_Assert(i < CV_IO_MAX_IMAGE_PARAMS*2); // Limit number of params for security reasons
|
|
|
|
} |
|
|
|
} |
|
|
|
return cv::imwrite_(filename, cv::cvarrToMat(arr), |
|
|
|
return cv::imwrite_(filename, cv::cvarrToMat(arr), |
|
|
|
i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>(), |
|
|
|
i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>(), |
|
|
@ -890,7 +990,7 @@ cvEncodeImage( const char* ext, const CvArr* arr, const int* _params ) |
|
|
|
if( _params ) |
|
|
|
if( _params ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for( ; _params[i] > 0; i += 2 ) |
|
|
|
for( ; _params[i] > 0; i += 2 ) |
|
|
|
; |
|
|
|
CV_Assert(i < CV_IO_MAX_IMAGE_PARAMS*2); // Limit number of params for security reasons
|
|
|
|
} |
|
|
|
} |
|
|
|
cv::Mat img = cv::cvarrToMat(arr); |
|
|
|
cv::Mat img = cv::cvarrToMat(arr); |
|
|
|
if( CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL ) |
|
|
|
if( CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL ) |
|
|
|