upmerged pull req #2974 to master - added more jpeg options to imgcodecs
authorSergey Nikulov <snikulov@amt.ru>
Mon, 21 Jul 2014 14:56:35 +0000 (18:56 +0400)
committerSergey Nikulov <snikulov@amt.ru>
Mon, 21 Jul 2014 14:56:35 +0000 (18:56 +0400)
modules/imgcodecs/include/opencv2/imgcodecs.hpp
modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h
modules/imgcodecs/src/grfmt_jpeg.cpp
modules/imgcodecs/test/test_grfmt.cpp

index 81f8a45..9494852 100644 (file)
@@ -56,14 +56,17 @@ enum { IMREAD_UNCHANGED  = -1, // 8bit, color or not
        IMREAD_ANYCOLOR   = 4   // ?, any color
      };
 
-enum { IMWRITE_JPEG_QUALITY     = 1,
-       IMWRITE_JPEG_PROGRESSIVE = 2,
-       IMWRITE_JPEG_OPTIMIZE    = 3,
-       IMWRITE_PNG_COMPRESSION  = 16,
-       IMWRITE_PNG_STRATEGY     = 17,
-       IMWRITE_PNG_BILEVEL      = 18,
-       IMWRITE_PXM_BINARY       = 32,
-       IMWRITE_WEBP_QUALITY     = 64
+enum { IMWRITE_JPEG_QUALITY       = 1,
+       IMWRITE_JPEG_PROGRESSIVE   = 2,
+       IMWRITE_JPEG_OPTIMIZE      = 3,
+       IMWRITE_JPEG_RST_INTERVAL  = 4,
+       IMWRITE_JPEG_LUM_QUALITY   = 5,
+       IMWRITE_JPEG_CHROM_QUALITY = 6,
+       IMWRITE_PNG_COMPRESSION    = 16,
+       IMWRITE_PNG_STRATEGY       = 17,
+       IMWRITE_PNG_BILEVEL        = 18,
+       IMWRITE_PXM_BINARY         = 32,
+       IMWRITE_WEBP_QUALITY       = 64
      };
 
 enum { IMWRITE_PNG_STRATEGY_DEFAULT      = 0,
index f0c2ae1..a36b454 100644 (file)
@@ -76,6 +76,9 @@ enum
     CV_IMWRITE_JPEG_QUALITY =1,
     CV_IMWRITE_JPEG_PROGRESSIVE =2,
     CV_IMWRITE_JPEG_OPTIMIZE =3,
+    CV_IMWRITE_JPEG_RST_INTERVAL =4,
+    CV_IMWRITE_JPEG_LUM_QUALITY =5,
+    CV_IMWRITE_JPEG_CHROM_QUALITY =6,
     CV_IMWRITE_PNG_COMPRESSION =16,
     CV_IMWRITE_PNG_STRATEGY =17,
     CV_IMWRITE_PNG_BILEVEL =18,
index 147f185..3157ebf 100644 (file)
@@ -600,6 +600,9 @@ bool JpegEncoder::write( const Mat& img, const std::vector<int>& params )
         int quality = 95;
         int progressive = 0;
         int optimize = 0;
+        int rst_interval = 0;
+        int lum_quality = 100;
+        int chrom_quality = 100;
 
         for( size_t i = 0; i < params.size(); i += 2 )
         {
@@ -618,15 +621,49 @@ bool JpegEncoder::write( const Mat& img, const std::vector<int>& params )
             {
                 optimize = params[i+1];
             }
+
+            if( params[i] == CV_IMWRITE_JPEG_LUM_QUALITY )
+            {
+                lum_quality = params[i+1];
+                lum_quality = MIN(MAX(lum_quality, 0), 100);
+            }
+
+            if( params[i] == CV_IMWRITE_JPEG_CHROM_QUALITY )
+            {
+                chrom_quality = params[i+1];
+                chrom_quality = MIN(MAX(chrom_quality, 0), 100);
+            }
+
+            if( params[i] == CV_IMWRITE_JPEG_RST_INTERVAL )
+            {
+                rst_interval = params[i+1];
+                rst_interval = MIN(MAX(rst_interval, 0), 65535L);
+            }
         }
 
         jpeg_set_defaults( &cinfo );
+        cinfo.restart_interval = rst_interval;
         jpeg_set_quality( &cinfo, quality,
                           TRUE /* limit to baseline-JPEG values */ );
         if( progressive )
             jpeg_simple_progression( &cinfo );
         if( optimize )
             cinfo.optimize_coding = TRUE;
+
+#if JPEG_LIB_VERSION >= 70
+        cinfo.q_scale_factor[0] = jpeg_quality_scaling(lum_quality);
+        cinfo.q_scale_factor[1] = jpeg_quality_scaling(chrom_quality);
+        if ( lum_quality != chrom_quality )
+        {
+            /* disable subsampling - ref. Libjpeg.txt */
+            cinfo.comp_info[0].v_samp_factor = 1;
+            cinfo.comp_info[0].h_samp_factor = 1;
+            cinfo.comp_info[1].v_samp_factor = 1;
+            cinfo.comp_info[1].h_samp_factor = 1;
+        }
+        jpeg_default_qtables( &cinfo, TRUE );
+#endif // #if JPEG_LIB_VERSION >= 70
+
         jpeg_start_compress( &cinfo, TRUE );
 
         if( channels > 1 )
index 9b06c57..05bd122 100644 (file)
@@ -433,6 +433,31 @@ TEST(Imgcodecs_Jpeg, encode_decode_optimize_jpeg)
 
     remove(output_optimized.c_str());
 }
+
+TEST(Imgcodecs_Jpeg, encode_decode_rst_jpeg)
+{
+    cvtest::TS& ts = *cvtest::TS::ptr();
+    string input = string(ts.get_data_path()) + "../cv/shared/lena.png";
+    cv::Mat img = cv::imread(input);
+    ASSERT_FALSE(img.empty());
+
+    std::vector<int> params;
+    params.push_back(IMWRITE_JPEG_RST_INTERVAL);
+    params.push_back(1);
+
+    string output_rst = cv::tempfile(".jpg");
+    EXPECT_NO_THROW(cv::imwrite(output_rst, img, params));
+    cv::Mat img_jpg_rst = cv::imread(output_rst);
+
+    string output_normal = cv::tempfile(".jpg");
+    EXPECT_NO_THROW(cv::imwrite(output_normal, img));
+    cv::Mat img_jpg_normal = cv::imread(output_normal);
+
+    EXPECT_EQ(0, cvtest::norm(img_jpg_rst, img_jpg_normal, NORM_INF));
+
+    remove(output_optimized.c_str());
+}
+
 #endif