From bd144cfa64094966e9fdf95c18e6ea594c34fe82 Mon Sep 17 00:00:00 2001 From: Sergey Nikulov Date: Mon, 21 Jul 2014 18:56:35 +0400 Subject: [PATCH 1/3] upmerged pull req #2974 to master - added more jpeg options to imgcodecs --- .../imgcodecs/include/opencv2/imgcodecs.hpp | 19 ++++++---- .../include/opencv2/imgcodecs/imgcodecs_c.h | 3 ++ modules/imgcodecs/src/grfmt_jpeg.cpp | 37 +++++++++++++++++++ modules/imgcodecs/test/test_grfmt.cpp | 25 +++++++++++++ 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 81f8a45f65..94948525c9 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -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, diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h index f0c2ae13fe..a36b454058 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h +++ b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h @@ -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, diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index 147f185e4c..3157ebfcb1 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -600,6 +600,9 @@ bool JpegEncoder::write( const Mat& img, const std::vector& 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& 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 ) diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 9b06c5744c..05bd1227ff 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -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 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 From 9d107fb2d5c0fdfe27273f4de1c9669517a82346 Mon Sep 17 00:00:00 2001 From: Sergey Nikulov Date: Mon, 21 Jul 2014 19:26:26 +0400 Subject: [PATCH 2/3] fixed test compilation --- modules/imgcodecs/test/test_grfmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 05bd1227ff..09b0bdc89e 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -455,7 +455,7 @@ TEST(Imgcodecs_Jpeg, encode_decode_rst_jpeg) EXPECT_EQ(0, cvtest::norm(img_jpg_rst, img_jpg_normal, NORM_INF)); - remove(output_optimized.c_str()); + remove(output_rst.c_str()); } #endif From eaec13209135bd28c73d15017645ee065c9ca003 Mon Sep 17 00:00:00 2001 From: Sergei Nikulov Date: Wed, 30 Jul 2014 00:03:41 +0400 Subject: [PATCH 3/3] #2992: update after review --- .../imgcodecs/include/opencv2/imgcodecs.hpp | 22 ++++----- .../include/opencv2/imgcodecs/imgcodecs_c.h | 4 +- modules/imgcodecs/src/grfmt_jpeg.cpp | 49 ++++++++++++------- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 94948525c9..97fff83e14 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -56,17 +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_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_JPEG_QUALITY = 1, + IMWRITE_JPEG_PROGRESSIVE = 2, + IMWRITE_JPEG_OPTIMIZE = 3, + IMWRITE_JPEG_RST_INTERVAL = 4, + IMWRITE_JPEG_LUMA_QUALITY = 5, + IMWRITE_JPEG_CHROMA_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, diff --git a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h index a36b454058..ccd29a7c1c 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h +++ b/modules/imgcodecs/include/opencv2/imgcodecs/imgcodecs_c.h @@ -77,8 +77,8 @@ enum 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_JPEG_LUMA_QUALITY =5, + CV_IMWRITE_JPEG_CHROMA_QUALITY =6, CV_IMWRITE_PNG_COMPRESSION =16, CV_IMWRITE_PNG_STRATEGY =17, CV_IMWRITE_PNG_BILEVEL =18, diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index 3157ebfcb1..ec1793287f 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -601,8 +601,8 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) int progressive = 0; int optimize = 0; int rst_interval = 0; - int lum_quality = 100; - int chrom_quality = 100; + int luma_quality = -1; + int chroma_quality = -1; for( size_t i = 0; i < params.size(); i += 2 ) { @@ -622,16 +622,27 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) optimize = params[i+1]; } - if( params[i] == CV_IMWRITE_JPEG_LUM_QUALITY ) + if( params[i] == CV_IMWRITE_JPEG_LUMA_QUALITY ) { - lum_quality = params[i+1]; - lum_quality = MIN(MAX(lum_quality, 0), 100); + if (params[i+1] >= 0) + { + luma_quality = MIN(MAX(params[i+1], 0), 100); + + quality = luma_quality; + + if (chroma_quality < 0) + { + chroma_quality = luma_quality; + } + } } - if( params[i] == CV_IMWRITE_JPEG_CHROM_QUALITY ) + if( params[i] == CV_IMWRITE_JPEG_CHROMA_QUALITY ) { - chrom_quality = params[i+1]; - chrom_quality = MIN(MAX(chrom_quality, 0), 100); + if (params[i+1] >= 0) + { + chroma_quality = MIN(MAX(params[i+1], 0), 100); + } } if( params[i] == CV_IMWRITE_JPEG_RST_INTERVAL ) @@ -643,6 +654,7 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) jpeg_set_defaults( &cinfo ); cinfo.restart_interval = rst_interval; + jpeg_set_quality( &cinfo, quality, TRUE /* limit to baseline-JPEG values */ ); if( progressive ) @@ -651,17 +663,20 @@ bool JpegEncoder::write( const Mat& img, const std::vector& params ) 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 ) + if (luma_quality >= 0 && chroma_quality >= 0) { - /* 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; + cinfo.q_scale_factor[0] = jpeg_quality_scaling(luma_quality); + cinfo.q_scale_factor[1] = jpeg_quality_scaling(chroma_quality); + if ( luma_quality != chroma_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 ); } - jpeg_default_qtables( &cinfo, TRUE ); #endif // #if JPEG_LIB_VERSION >= 70 jpeg_start_compress( &cinfo, TRUE );