Merge pull request #16309 from ganesh-k13:bugfix/imdecode-resize
authorGanesh Kathiresan <ganesh3597@gmail.com>
Mon, 20 Jan 2020 11:00:45 +0000 (16:30 +0530)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Mon, 20 Jan 2020 11:00:45 +0000 (14:00 +0300)
* Added flag handlers for imread and imdecode | Issue 16203

Undo imread change

Added Imread resize tests

Added imdecode flags check

Added imdecode tests for resize

Removed trailing whitespace

Removed IMREAD_IGNORE_ORIENTATION check

Added else condition

Removed IMREAD_IGNORE_ORIENTATION check in decode

Added HAVE_JPEG guards

Added static_cast for Win32

Added resize for non jpegs

Added tests for non jpeg resize case

Fixed resize value in assert

Changed tests to Value-Parameterized Tests

Changed tests to Value-Parameterized Tests | handled >> in cpp

Changed tests to Value-Parameterized Tests | removed trailing whitespace

* imgcodecs: update test

modules/imgcodecs/src/loadsave.cpp
modules/imgcodecs/test/test_precomp.hpp
modules/imgcodecs/test/test_read_write.cpp

index 0c22118..55008aa 100644 (file)
@@ -423,12 +423,12 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 )
     int scale_denom = 1;
     if( flags > IMREAD_LOAD_GDAL )
     {
-    if( flags & IMREAD_REDUCED_GRAYSCALE_2 )
-        scale_denom = 2;
-    else if( flags & IMREAD_REDUCED_GRAYSCALE_4 )
-        scale_denom = 4;
-    else if( flags & IMREAD_REDUCED_GRAYSCALE_8 )
-        scale_denom = 8;
+        if( flags & IMREAD_REDUCED_GRAYSCALE_2 )
+            scale_denom = 2;
+        else if( flags & IMREAD_REDUCED_GRAYSCALE_4 )
+            scale_denom = 4;
+        else if( flags & IMREAD_REDUCED_GRAYSCALE_8 )
+            scale_denom = 8;
     }
 
     /// set the scale_denom in the driver
@@ -766,6 +766,20 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )
     if( !decoder )
         return 0;
 
+    int scale_denom = 1;
+    if( flags > IMREAD_LOAD_GDAL )
+    {
+        if( flags & IMREAD_REDUCED_GRAYSCALE_2 )
+            scale_denom = 2;
+        else if( flags & IMREAD_REDUCED_GRAYSCALE_4 )
+            scale_denom = 4;
+        else if( flags & IMREAD_REDUCED_GRAYSCALE_8 )
+            scale_denom = 8;
+    }
+
+    /// set the scale_denom in the driver
+    decoder->setScale( scale_denom );
+
     if( !decoder->setSource(buf_row) )
     {
         filename = tempfile();
@@ -861,7 +875,7 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )
     {
         std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
     }
-    decoder.release();
+
     if (!filename.empty())
     {
         if (0 != remove(filename.c_str()))
@@ -879,6 +893,13 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )
         return 0;
     }
 
+    if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1
+    {
+        resize( *mat, *mat, Size( size.width / scale_denom, size.height / scale_denom ), 0, 0, INTER_LINEAR_EXACT);
+    }
+
+    decoder.release();
+
     return hdrtype == LOAD_CVMAT ? (void*)matrix :
         hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
 }
index 4fc692c..3bd4221 100644 (file)
@@ -8,4 +8,68 @@
 #include "opencv2/imgcodecs.hpp"
 #include "opencv2/imgproc/imgproc_c.h"
 
+namespace cv {
+
+static inline
+void PrintTo(const ImreadModes& val, std::ostream* os)
+{
+    int v = val;
+    if (v == IMREAD_UNCHANGED && (v & IMREAD_IGNORE_ORIENTATION) != 0)
+    {
+        CV_Assert(IMREAD_UNCHANGED == -1);
+        *os << "IMREAD_UNCHANGED";
+        return;
+    }
+    if ((v & IMREAD_COLOR) != 0)
+    {
+        CV_Assert(IMREAD_COLOR == 1);
+        v &= ~IMREAD_COLOR;
+        *os << "IMREAD_COLOR" << (v == 0 ? "" : " | ");
+    }
+    else
+    {
+        CV_Assert(IMREAD_GRAYSCALE == 0);
+        *os << "IMREAD_GRAYSCALE" << (v == 0 ? "" : " | ");
+    }
+    if ((v & IMREAD_ANYDEPTH) != 0)
+    {
+        v &= ~IMREAD_ANYDEPTH;
+        *os << "IMREAD_ANYDEPTH" << (v == 0 ? "" : " | ");
+    }
+    if ((v & IMREAD_ANYCOLOR) != 0)
+    {
+        v &= ~IMREAD_ANYCOLOR;
+        *os << "IMREAD_ANYCOLOR" << (v == 0 ? "" : " | ");
+    }
+    if ((v & IMREAD_LOAD_GDAL) != 0)
+    {
+        v &= ~IMREAD_LOAD_GDAL;
+        *os << "IMREAD_LOAD_GDAL" << (v == 0 ? "" : " | ");
+    }
+    if ((v & IMREAD_IGNORE_ORIENTATION) != 0)
+    {
+        v &= ~IMREAD_IGNORE_ORIENTATION;
+        *os << "IMREAD_IGNORE_ORIENTATION" << (v == 0 ? "" : " | ");
+    }
+    switch (v)
+    {
+        case IMREAD_UNCHANGED: return;
+        case IMREAD_GRAYSCALE: return;
+        case IMREAD_COLOR: return;
+        case IMREAD_ANYDEPTH: return;
+        case IMREAD_ANYCOLOR: return;
+        case IMREAD_LOAD_GDAL: return;
+        case IMREAD_REDUCED_GRAYSCALE_2: // fallthru
+        case IMREAD_REDUCED_COLOR_2: *os << "REDUCED_2"; return;
+        case IMREAD_REDUCED_GRAYSCALE_4: // fallthru
+        case IMREAD_REDUCED_COLOR_4: *os << "REDUCED_4"; return;
+        case IMREAD_REDUCED_GRAYSCALE_8: // fallthru
+        case IMREAD_REDUCED_COLOR_8: *os << "REDUCED_8"; return;
+        case IMREAD_IGNORE_ORIENTATION: return;
+    } // don't use "default:" to emit compiler warnings
+    *os << "IMREAD_UNKNOWN(" << (int)v << ")";
+}
+
+} // namespace
+
 #endif
index f0f4139..6396200 100644 (file)
@@ -5,6 +5,95 @@
 
 namespace opencv_test { namespace {
 
+/* < <file_name, image_size>, <imread mode, scale> > */
+typedef tuple< tuple<string, Size>, tuple<ImreadModes, int> > Imgcodecs_Resize_t;
+
+typedef testing::TestWithParam< Imgcodecs_Resize_t > Imgcodecs_Resize;
+
+/* resize_flag_and_dims = <imread_flag, scale>*/
+const tuple <ImreadModes, int> resize_flag_and_dims[] =
+{
+    make_tuple(IMREAD_UNCHANGED, 1),
+    make_tuple(IMREAD_REDUCED_GRAYSCALE_2, 2),
+    make_tuple(IMREAD_REDUCED_GRAYSCALE_4, 4),
+    make_tuple(IMREAD_REDUCED_GRAYSCALE_8, 8),
+    make_tuple(IMREAD_REDUCED_COLOR_2, 2),
+    make_tuple(IMREAD_REDUCED_COLOR_4, 4),
+    make_tuple(IMREAD_REDUCED_COLOR_8, 8)
+};
+
+const tuple<string, Size> images[] =
+{
+#ifdef HAVE_JPEG
+    make_tuple<string, Size>("../cv/imgproc/stuff.jpg", Size(640, 480)),
+#endif
+#ifdef HAVE_PNG
+    make_tuple<string, Size>("../cv/shared/pic1.png", Size(400, 300)),
+#endif
+};
+
+TEST_P(Imgcodecs_Resize, imread_reduce_flags)
+{
+    const string file_name = findDataFile(get<0>(get<0>(GetParam())));
+    const Size imageSize = get<1>(get<0>(GetParam()));
+
+    const int imread_flag = get<0>(get<1>(GetParam()));
+    const int scale = get<1>(get<1>(GetParam()));
+
+    const int cols = imageSize.width / scale;
+    const int rows = imageSize.height / scale;
+    {
+        Mat img = imread(file_name, imread_flag);
+        ASSERT_FALSE(img.empty());
+        EXPECT_EQ(cols, img.cols);
+        EXPECT_EQ(rows, img.rows);
+    }
+}
+
+//==================================================================================================
+
+TEST_P(Imgcodecs_Resize, imdecode_reduce_flags)
+{
+    const string file_name = findDataFile(get<0>(get<0>(GetParam())));
+    const Size imageSize = get<1>(get<0>(GetParam()));
+
+    const int imread_flag = get<0>(get<1>(GetParam()));
+    const int scale = get<1>(get<1>(GetParam()));
+
+    const int cols = imageSize.width / scale;
+    const int rows = imageSize.height / scale;
+
+    const std::ios::openmode mode = std::ios::in | std::ios::binary;
+    std::ifstream ifs(file_name.c_str(), mode);
+    ASSERT_TRUE(ifs.is_open());
+
+    ifs.seekg(0, std::ios::end);
+    const size_t sz = static_cast<size_t>(ifs.tellg());
+    ifs.seekg(0, std::ios::beg);
+
+    std::vector<char> content(sz);
+    ifs.read((char*)content.data(), sz);
+    ASSERT_FALSE(ifs.fail());
+
+    {
+        Mat img = imdecode(Mat(content), imread_flag);
+        ASSERT_FALSE(img.empty());
+        EXPECT_EQ(cols, img.cols);
+        EXPECT_EQ(rows, img.rows);
+    }
+}
+
+//==================================================================================================
+
+INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Resize,
+        testing::Combine(
+            testing::ValuesIn(images),
+            testing::ValuesIn(resize_flag_and_dims)
+            )
+        );
+
+//==================================================================================================
+
 TEST(Imgcodecs_Image, read_write_bmp)
 {
     const size_t IMAGE_COUNT = 10;