1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 07:13:02 +04:00

Merge pull request #8492 from brian-armstrong-discord:exif_inmemory

autorotate in-memory jpegs (#8492)

* autorotate in-memory jpegs

* correct indentation (4 spaces)

* imgcodecs: don't apply EXIF rotation for unloaded images

* videoio: don't try to rotate MJPEG stream

* imgcodecs: ByteStreamBuffer::seekoff support all seek "dir"

* imgcodecs: fix condition: "off == egptr() - eback()" is valid offset
This commit is contained in:
brian-armstrong-discord
2017-04-14 13:12:07 -07:00
committed by Alexander Alekhin
parent b37f0c5ac2
commit 9e054d3880
4 changed files with 128 additions and 52 deletions
+100 -17
View File
@@ -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;
}