Added IMREAD_IGNORE_ORIENTATION flag
authorArkadiusz Raj <arek.raj@gmail.com>
Wed, 9 Nov 2016 17:09:22 +0000 (18:09 +0100)
committerArkadiusz Raj <arek.raj@gmail.com>
Wed, 9 Nov 2016 17:09:22 +0000 (18:09 +0100)
modules/imgcodecs/CMakeLists.txt
modules/imgcodecs/include/opencv2/imgcodecs.hpp
modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h
modules/imgcodecs/src/exif.cpp [moved from modules/imgcodecs/src/jpeg_exif.cpp with 99% similarity]
modules/imgcodecs/src/exif.hpp [moved from modules/imgcodecs/src/jpeg_exif.hpp with 90% similarity]
modules/imgcodecs/src/grfmt_jpeg.cpp
modules/imgcodecs/src/grfmt_jpeg.hpp
modules/imgcodecs/src/loadsave.cpp

index c614d79..5c709af 100644 (file)
@@ -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_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp)
 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_srcs ${CMAKE_CURRENT_LIST_DIR}/src/jpeg_exif.cpp)
+list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/exif.hpp)
+list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/exif.cpp)
 
 source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs})
 
index d551ae7..0b9cafa 100644 (file)
@@ -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_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_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
index 2e76f7f..3130710 100644 (file)
@@ -63,7 +63,9 @@ enum
 /* any depth, ? */
     CV_LOAD_IMAGE_ANYDEPTH   =2,
 /* ?, any color */
-    CV_LOAD_IMAGE_ANYCOLOR   =4
+    CV_LOAD_IMAGE_ANYCOLOR   =4,
+/* ?, no rotate */
+    CV_LOAD_IMAGE_IGNORE_ORIENTATION  =128
 };
 
 /* load image from file
similarity index 99%
rename from modules/imgcodecs/src/jpeg_exif.cpp
rename to modules/imgcodecs/src/exif.cpp
index 0704c2f..2708481 100644 (file)
@@ -40,7 +40,7 @@
 //
 //M*/
 
-#include "jpeg_exif.hpp"
+#include "exif.hpp"
 
 namespace {
 
@@ -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
  *          false in case of unsuccessful parsing
  */
@@ -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
  *
  *  @return Map where key is tag number and value is ExifEntry_t structure
similarity index 90%
rename from modules/imgcodecs/src/jpeg_exif.hpp
rename to modules/imgcodecs/src/exif.hpp
index c8502c5..43c2857 100644 (file)
@@ -41,8 +41,8 @@
 //M*/
 
 
-#ifndef _OPENCV_JPEG_EXIF_HPP_
-#define _OPENCV_JPEG_EXIF_HPP_
+#ifndef _OPENCV_EXIF_HPP_
+#define _OPENCV_EXIF_HPP_
 
 #include <cstdio>
 #include <map>
@@ -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
  *      smartphone or other camera with orientation sensor support
  *      Corresponds to EXIF 2.3 Specification
  */
-enum JpegOrientation
+enum ImageOrientation
 {
-    JPEG_ORIENTATION_TL = 1, ///< 0th row == visual top, 0th column == visual left-hand side
-    JPEG_ORIENTATION_TR = 2, ///< 0th row == visual top, 0th column == visual right-hand side
-    JPEG_ORIENTATION_BR = 3, ///< 0th row == visual bottom, 0th column == visual right-hand side
-    JPEG_ORIENTATION_BL = 4, ///< 0th row == visual bottom, 0th column == visual left-hand side
-    JPEG_ORIENTATION_LT = 5, ///< 0th row == visual left-hand side, 0th column == visual top
-    JPEG_ORIENTATION_RT = 6, ///< 0th row == visual right-hand side, 0th column == visual top
-    JPEG_ORIENTATION_RB = 7, ///< 0th row == visual right-hand side, 0th column == visual bottom
-    JPEG_ORIENTATION_LB = 8  ///< 0th row == visual left-hand side, 0th column == visual bottom
+    IMAGE_ORIENTATION_TL = 1, ///< Horizontal (normal)
+    IMAGE_ORIENTATION_TR = 2, ///< Mirrored horizontal
+    IMAGE_ORIENTATION_BR = 3, ///< Rotate 180
+    IMAGE_ORIENTATION_BL = 4, ///< Mirrored vertical
+    IMAGE_ORIENTATION_LT = 5, ///< Mirrored horizontal & rotate 270 CW
+    IMAGE_ORIENTATION_RT = 6, ///< Rotate 90 CW
+    IMAGE_ORIENTATION_RB = 7, ///< Mirrored horizontal & rotate 90 CW
+    IMAGE_ORIENTATION_LB = 8  ///< Rotate 270 CW
 };
 
 /**
@@ -250,4 +250,4 @@ private:
 
 }
 
-#endif /* JPEG_EXIF_HPP_ */
+#endif /* _OPENCV_EXIF_HPP_ */
index 093b88c..1f5f1e8 100644 (file)
@@ -41,7 +41,6 @@
 
 #include "precomp.hpp"
 #include "grfmt_jpeg.hpp"
-#include "jpeg_exif.hpp"
 
 #ifdef HAVE_JPEG
 
@@ -178,7 +177,6 @@ JpegDecoder::JpegDecoder()
     m_state = 0;
     m_f = 0;
     m_buf_supported = true;
-    m_orientation = JPEG_ORIENTATION_TL;
 }
 
 
@@ -255,71 +253,12 @@ bool  JpegDecoder::readHeader()
         }
     }
 
-    m_orientation = getOrientation();
-
     if( !result )
         close();
 
     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
  * based on a message of Laurent Pinchart on the video4linux mailing list
@@ -536,7 +475,6 @@ bool  JpegDecoder::readData( Mat& img )
 
             result = true;
             jpeg_finish_decompress( cinfo );
-            setOrientation( img );
         }
     }
 
index d0a0991..8455b19 100644 (file)
@@ -70,12 +70,6 @@ protected:
 
     FILE* m_f;
     void* m_state;
-
-private:
-    //Support for handling exif orientation tag in Jpeg file
-    int m_orientation;
-    int getOrientation();
-    void setOrientation(Mat& img);
 };
 
 
index 6cd3106..8c63933 100644 (file)
@@ -45,6 +45,8 @@
 
 #include "precomp.hpp"
 #include "grfmts.hpp"
+#include "utils.hpp"
+#include "exif.hpp"
 #undef min
 #undef max
 #include <iostream>
@@ -227,8 +229,11 @@ static ImageEncoder findEncoder( const String& _ext )
     return ImageEncoder();
 }
 
+
 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
  *
@@ -403,6 +408,12 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
         Mat mat(decoder->height(), decoder->width(), type);
         if (!decoder->readData(mat))
         {
+            // optionally rotate the data if EXIF' orientation flag says so
+            if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 )
+            {
+                RotateImage(filename, mat);
+            }
+
             break;
         }
 
@@ -416,6 +427,59 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
     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
  *
@@ -432,6 +496,12 @@ Mat imread( const String& filename, int flags )
     /// load the data
     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 img;
 }