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:
committed by
Alexander Alekhin
parent
b37f0c5ac2
commit
9e054d3880
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user