|
|
|
@ -50,10 +50,50 @@ |
|
|
|
|
#undef min |
|
|
|
|
#undef max |
|
|
|
|
#include <iostream> |
|
|
|
|
#include <fstream> |
|
|
|
|
|
|
|
|
|
/****************************************************************************************\
|
|
|
|
|
* Image Codecs * |
|
|
|
|
\****************************************************************************************/ |
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
class ByteStreamBuffer: public std::streambuf |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
ByteStreamBuffer(char* base, size_t length) |
|
|
|
|
{ |
|
|
|
|
setg(base, base, base + length); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
virtual pos_type seekoff( off_type offset, |
|
|
|
|
std::ios_base::seekdir dir, |
|
|
|
|
std::ios_base::openmode ) |
|
|
|
|
{ |
|
|
|
|
// get absolute offset
|
|
|
|
|
off_type off = offset; |
|
|
|
|
if (dir == std::ios_base::cur) |
|
|
|
|
{ |
|
|
|
|
off += gptr() - eback(); |
|
|
|
|
} |
|
|
|
|
else if (dir == std::ios_base::end) |
|
|
|
|
{ |
|
|
|
|
off += egptr() - eback(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// check limits
|
|
|
|
|
if (off >= (off_type)0 && off <= egptr() - eback()) |
|
|
|
|
{ |
|
|
|
|
setg(eback(), gptr() + off, egptr()); |
|
|
|
|
return gptr() - eback(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace cv |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
@ -232,23 +272,8 @@ static ImageEncoder findEncoder( const String& _ext ) |
|
|
|
|
|
|
|
|
|
enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 }; |
|
|
|
|
|
|
|
|
|
static void ApplyExifOrientation(const String& filename, Mat& img) |
|
|
|
|
static void ExifTransform(int orientation, Mat& img) |
|
|
|
|
{ |
|
|
|
|
int orientation = IMAGE_ORIENTATION_TL; |
|
|
|
|
|
|
|
|
|
if (filename.size() > 0) |
|
|
|
|
{ |
|
|
|
|
ExifReader reader( filename ); |
|
|
|
|
if( reader.parse() ) |
|
|
|
|
{ |
|
|
|
|
ExifEntry_t entry = reader.getTag( ORIENTATION ); |
|
|
|
|
if (entry.tag != INVALID_TAG) |
|
|
|
|
{ |
|
|
|
|
orientation = entry.field_u16; //orientation is unsigned short, so check field_u16
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch( orientation ) |
|
|
|
|
{ |
|
|
|
|
case IMAGE_ORIENTATION_TL: //0th row == visual top, 0th column == visual left-hand side
|
|
|
|
@ -284,6 +309,50 @@ static void ApplyExifOrientation(const String& filename, Mat& img) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ApplyExifOrientation(const String& filename, Mat& img) |
|
|
|
|
{ |
|
|
|
|
int orientation = IMAGE_ORIENTATION_TL; |
|
|
|
|
|
|
|
|
|
if (filename.size() > 0) |
|
|
|
|
{ |
|
|
|
|
std::ifstream stream( filename.c_str(), std::ios_base::in | std::ios_base::binary ); |
|
|
|
|
ExifReader reader( stream ); |
|
|
|
|
if( reader.parse() ) |
|
|
|
|
{ |
|
|
|
|
ExifEntry_t entry = reader.getTag( ORIENTATION ); |
|
|
|
|
if (entry.tag != INVALID_TAG) |
|
|
|
|
{ |
|
|
|
|
orientation = entry.field_u16; //orientation is unsigned short, so check field_u16
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
stream.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ExifTransform(orientation, img); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ApplyExifOrientation(const Mat& buf, Mat& img) |
|
|
|
|
{ |
|
|
|
|
int orientation = IMAGE_ORIENTATION_TL; |
|
|
|
|
|
|
|
|
|
if( buf.isContinuous() ) |
|
|
|
|
{ |
|
|
|
|
ByteStreamBuffer bsb( reinterpret_cast<char*>(buf.data), buf.total() * buf.elemSize() ); |
|
|
|
|
std::istream stream( &bsb ); |
|
|
|
|
ExifReader reader( stream ); |
|
|
|
|
if( reader.parse() ) |
|
|
|
|
{ |
|
|
|
|
ExifEntry_t entry = reader.getTag( ORIENTATION ); |
|
|
|
|
if (entry.tag != INVALID_TAG) |
|
|
|
|
{ |
|
|
|
|
orientation = entry.field_u16; //orientation is unsigned short, so check field_u16
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ExifTransform(orientation, img); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Read an image into memory and return the information |
|
|
|
|
* |
|
|
|
@ -494,7 +563,7 @@ Mat imread( const String& filename, int flags ) |
|
|
|
|
imread_( filename, flags, LOAD_MAT, &img ); |
|
|
|
|
|
|
|
|
|
/// optionally rotate the data if EXIF' orientation flag says so
|
|
|
|
|
if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED ) |
|
|
|
|
if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED ) |
|
|
|
|
{ |
|
|
|
|
ApplyExifOrientation(filename, img); |
|
|
|
|
} |
|
|
|
@ -658,6 +727,13 @@ Mat imdecode( InputArray _buf, int flags ) |
|
|
|
|
{ |
|
|
|
|
Mat buf = _buf.getMat(), img; |
|
|
|
|
imdecode_( buf, flags, LOAD_MAT, &img ); |
|
|
|
|
|
|
|
|
|
/// optionally rotate the data if EXIF' orientation flag says so
|
|
|
|
|
if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED ) |
|
|
|
|
{ |
|
|
|
|
ApplyExifOrientation(buf, img); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return img; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -666,6 +742,13 @@ Mat imdecode( InputArray _buf, int flags, Mat* dst ) |
|
|
|
|
Mat buf = _buf.getMat(), img; |
|
|
|
|
dst = dst ? dst : &img; |
|
|
|
|
imdecode_( buf, flags, LOAD_MAT, dst ); |
|
|
|
|
|
|
|
|
|
/// optionally rotate the data if EXIF' orientation flag says so
|
|
|
|
|
if( !dst->empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED ) |
|
|
|
|
{ |
|
|
|
|
ApplyExifOrientation(buf, *dst); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return *dst; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|