Commit f893ee5c authored by Arkadiusz Raj's avatar Arkadiusz Raj

Added IMREAD_IGNORE_ORIENTATION flag

parent 17ffb288
...@@ -67,8 +67,8 @@ list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.hpp) ...@@ -67,8 +67,8 @@ list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.hpp)
list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.cpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.cpp)
list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp) list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp)
list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.cpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.cpp)
list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/jpeg_exif.hpp) list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/exif.hpp)
list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/jpeg_exif.cpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/exif.cpp)
source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs}) source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs})
......
...@@ -73,7 +73,8 @@ enum ImreadModes { ...@@ -73,7 +73,8 @@ enum ImreadModes {
IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4. IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4. IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8. IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
IMREAD_REDUCED_COLOR_8 = 65 //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8. IMREAD_REDUCED_COLOR_8 = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
IMREAD_IGNORE_ORIENTATION = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
}; };
//! Imwrite flags //! Imwrite flags
......
...@@ -63,7 +63,9 @@ enum ...@@ -63,7 +63,9 @@ enum
/* any depth, ? */ /* any depth, ? */
CV_LOAD_IMAGE_ANYDEPTH =2, CV_LOAD_IMAGE_ANYDEPTH =2,
/* ?, any color */ /* ?, any color */
CV_LOAD_IMAGE_ANYCOLOR =4 CV_LOAD_IMAGE_ANYCOLOR =4,
/* ?, no rotate */
CV_LOAD_IMAGE_IGNORE_ORIENTATION =128
}; };
/* load image from file /* load image from file
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
// //
//M*/ //M*/
#include "jpeg_exif.hpp" #include "exif.hpp"
namespace { namespace {
...@@ -73,7 +73,7 @@ ExifReader::~ExifReader() ...@@ -73,7 +73,7 @@ ExifReader::~ExifReader()
} }
/** /**
* @brief Parsing the jpeg file and prepare (internally) exif directory structure * @brief Parsing the file and prepare (internally) exif directory structure
* @return true if parsing was successful and exif information exists in JpegReader object * @return true if parsing was successful and exif information exists in JpegReader object
* false in case of unsuccessful parsing * false in case of unsuccessful parsing
*/ */
...@@ -114,7 +114,7 @@ ExifEntry_t ExifReader::getTag(const ExifTagName tag) ...@@ -114,7 +114,7 @@ ExifEntry_t ExifReader::getTag(const ExifTagName tag)
/** /**
* @brief Get exif directory structure contained in jpeg file (if any) * @brief Get exif directory structure contained in file (if any)
* This is internal function and is not exposed to client * This is internal function and is not exposed to client
* *
* @return Map where key is tag number and value is ExifEntry_t structure * @return Map where key is tag number and value is ExifEntry_t structure
......
...@@ -41,8 +41,8 @@ ...@@ -41,8 +41,8 @@
//M*/ //M*/
#ifndef _OPENCV_JPEG_EXIF_HPP_ #ifndef _OPENCV_EXIF_HPP_
#define _OPENCV_JPEG_EXIF_HPP_ #define _OPENCV_EXIF_HPP_
#include <cstdio> #include <cstdio>
#include <map> #include <map>
...@@ -131,21 +131,21 @@ struct ExifEntry_t ...@@ -131,21 +131,21 @@ struct ExifEntry_t
}; };
/** /**
* @brief Picture orientation which may be taken from JPEG's EXIF * @brief Picture orientation which may be taken from EXIF
* Orientation usually matters when the picture is taken by * Orientation usually matters when the picture is taken by
* smartphone or other camera with orientation sensor support * smartphone or other camera with orientation sensor support
* Corresponds to EXIF 2.3 Specification * Corresponds to EXIF 2.3 Specification
*/ */
enum JpegOrientation enum ImageOrientation
{ {
JPEG_ORIENTATION_TL = 1, ///< 0th row == visual top, 0th column == visual left-hand side IMAGE_ORIENTATION_TL = 1, ///< Horizontal (normal)
JPEG_ORIENTATION_TR = 2, ///< 0th row == visual top, 0th column == visual right-hand side IMAGE_ORIENTATION_TR = 2, ///< Mirrored horizontal
JPEG_ORIENTATION_BR = 3, ///< 0th row == visual bottom, 0th column == visual right-hand side IMAGE_ORIENTATION_BR = 3, ///< Rotate 180
JPEG_ORIENTATION_BL = 4, ///< 0th row == visual bottom, 0th column == visual left-hand side IMAGE_ORIENTATION_BL = 4, ///< Mirrored vertical
JPEG_ORIENTATION_LT = 5, ///< 0th row == visual left-hand side, 0th column == visual top IMAGE_ORIENTATION_LT = 5, ///< Mirrored horizontal & rotate 270 CW
JPEG_ORIENTATION_RT = 6, ///< 0th row == visual right-hand side, 0th column == visual top IMAGE_ORIENTATION_RT = 6, ///< Rotate 90 CW
JPEG_ORIENTATION_RB = 7, ///< 0th row == visual right-hand side, 0th column == visual bottom IMAGE_ORIENTATION_RB = 7, ///< Mirrored horizontal & rotate 90 CW
JPEG_ORIENTATION_LB = 8 ///< 0th row == visual left-hand side, 0th column == visual bottom IMAGE_ORIENTATION_LB = 8 ///< Rotate 270 CW
}; };
/** /**
...@@ -250,4 +250,4 @@ private: ...@@ -250,4 +250,4 @@ private:
} }
#endif /* JPEG_EXIF_HPP_ */ #endif /* _OPENCV_EXIF_HPP_ */
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
#include "precomp.hpp" #include "precomp.hpp"
#include "grfmt_jpeg.hpp" #include "grfmt_jpeg.hpp"
#include "jpeg_exif.hpp"
#ifdef HAVE_JPEG #ifdef HAVE_JPEG
...@@ -178,7 +177,6 @@ JpegDecoder::JpegDecoder() ...@@ -178,7 +177,6 @@ JpegDecoder::JpegDecoder()
m_state = 0; m_state = 0;
m_f = 0; m_f = 0;
m_buf_supported = true; m_buf_supported = true;
m_orientation = JPEG_ORIENTATION_TL;
} }
...@@ -255,71 +253,12 @@ bool JpegDecoder::readHeader() ...@@ -255,71 +253,12 @@ bool JpegDecoder::readHeader()
} }
} }
m_orientation = getOrientation();
if( !result ) if( !result )
close(); close();
return result; return result;
} }
int JpegDecoder::getOrientation()
{
int orientation = JPEG_ORIENTATION_TL;
if (m_filename.size() > 0)
{
ExifReader reader( m_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
}
}
}
return orientation;
}
void JpegDecoder::setOrientation(Mat& img)
{
switch( m_orientation )
{
case JPEG_ORIENTATION_TL: //0th row == visual top, 0th column == visual left-hand side
//do nothing, the image already has proper orientation
break;
case JPEG_ORIENTATION_TR: //0th row == visual top, 0th column == visual right-hand side
flip(img, img, 1); //flip horizontally
break;
case JPEG_ORIENTATION_BR: //0th row == visual bottom, 0th column == visual right-hand side
flip(img, img, -1);//flip both horizontally and vertically
break;
case JPEG_ORIENTATION_BL: //0th row == visual bottom, 0th column == visual left-hand side
flip(img, img, 0); //flip vertically
break;
case JPEG_ORIENTATION_LT: //0th row == visual left-hand side, 0th column == visual top
transpose(img, img);
break;
case JPEG_ORIENTATION_RT: //0th row == visual right-hand side, 0th column == visual top
transpose(img, img);
flip(img, img, 1); //flip horizontally
break;
case JPEG_ORIENTATION_RB: //0th row == visual right-hand side, 0th column == visual bottom
transpose(img, img);
flip(img, img, -1); //flip both horizontally and vertically
break;
case JPEG_ORIENTATION_LB: //0th row == visual left-hand side, 0th column == visual bottom
transpose(img, img);
flip(img, img, 0); //flip vertically
break;
default:
//by default the image read has normal (JPEG_ORIENTATION_TL) orientation
break;
}
}
/*************************************************************************** /***************************************************************************
* following code is for supporting MJPEG image files * following code is for supporting MJPEG image files
* based on a message of Laurent Pinchart on the video4linux mailing list * based on a message of Laurent Pinchart on the video4linux mailing list
...@@ -536,7 +475,6 @@ bool JpegDecoder::readData( Mat& img ) ...@@ -536,7 +475,6 @@ bool JpegDecoder::readData( Mat& img )
result = true; result = true;
jpeg_finish_decompress( cinfo ); jpeg_finish_decompress( cinfo );
setOrientation( img );
} }
} }
......
...@@ -70,12 +70,6 @@ protected: ...@@ -70,12 +70,6 @@ protected:
FILE* m_f; FILE* m_f;
void* m_state; void* m_state;
private:
//Support for handling exif orientation tag in Jpeg file
int m_orientation;
int getOrientation();
void setOrientation(Mat& img);
}; };
......
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
#include "precomp.hpp" #include "precomp.hpp"
#include "grfmts.hpp" #include "grfmts.hpp"
#include "utils.hpp"
#include "exif.hpp"
#undef min #undef min
#undef max #undef max
#include <iostream> #include <iostream>
...@@ -227,8 +229,11 @@ static ImageEncoder findEncoder( const String& _ext ) ...@@ -227,8 +229,11 @@ static ImageEncoder findEncoder( const String& _ext )
return ImageEncoder(); return ImageEncoder();
} }
enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 }; enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 };
void RotateImage(const String& filename, Mat& img);
/** /**
* Read an image into memory and return the information * Read an image into memory and return the information
* *
...@@ -403,6 +408,12 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats) ...@@ -403,6 +408,12 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
Mat mat(decoder->height(), decoder->width(), type); Mat mat(decoder->height(), decoder->width(), type);
if (!decoder->readData(mat)) if (!decoder->readData(mat))
{ {
// optionally rotate the data if EXIF' orientation flag says so
if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 )
{
RotateImage(filename, mat);
}
break; break;
} }
...@@ -416,6 +427,59 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats) ...@@ -416,6 +427,59 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
return !mats.empty(); return !mats.empty();
} }
void RotateImage(const String& filename, 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
//do nothing, the image already has proper orientation
break;
case IMAGE_ORIENTATION_TR: //0th row == visual top, 0th column == visual right-hand side
flip(img, img, 1); //flip horizontally
break;
case IMAGE_ORIENTATION_BR: //0th row == visual bottom, 0th column == visual right-hand side
flip(img, img, -1);//flip both horizontally and vertically
break;
case IMAGE_ORIENTATION_BL: //0th row == visual bottom, 0th column == visual left-hand side
flip(img, img, 0); //flip vertically
break;
case IMAGE_ORIENTATION_LT: //0th row == visual left-hand side, 0th column == visual top
transpose(img, img);
break;
case IMAGE_ORIENTATION_RT: //0th row == visual right-hand side, 0th column == visual top
transpose(img, img);
flip(img, img, 1); //flip horizontally
break;
case IMAGE_ORIENTATION_RB: //0th row == visual right-hand side, 0th column == visual bottom
transpose(img, img);
flip(img, img, -1); //flip both horizontally and vertically
break;
case IMAGE_ORIENTATION_LB: //0th row == visual left-hand side, 0th column == visual bottom
transpose(img, img);
flip(img, img, 0); //flip vertically
break;
default:
//by default the image read has normal (JPEG_ORIENTATION_TL) orientation
break;
}
}
/** /**
* Read an image * Read an image
* *
...@@ -432,6 +496,12 @@ Mat imread( const String& filename, int flags ) ...@@ -432,6 +496,12 @@ Mat imread( const String& filename, int flags )
/// load the data /// load the data
imread_( filename, flags, LOAD_MAT, &img ); imread_( filename, flags, LOAD_MAT, &img );
/// optionally rotate the data if EXIF' orientation flag says so
if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 )
{
RotateImage(filename, img);
}
/// return a reference to the data /// return a reference to the data
return img; return img;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment