Bug 358848

Summary: Chroma subsampling incorrectly described
Product: [Applications] digikam Reporter: DrSlony <bugs>
Component: Setup-ImageEditorAssignee: Digikam Developers <digikam-bugs-null>
Status: RESOLVED FIXED    
Severity: normal CC: bugs, caulier.gilles
Priority: NOR    
Version: 5.0.0   
Target Milestone: ---   
Platform: Other   
OS: Linux   
Latest Commit: Version Fixed In: 5.0.0
Sentry Crash Report:

Description DrSlony 2016-01-31 22:46:21 UTC
Continuation of https://plus.google.com/u/0/+digikam/posts/SExHL5iCt8f

https://quickgit.kde.org/?p=digikam.git&a=blob&h=f33c15ca92309ff6e8ec2e7a296bd88df0682c63&hb=b5be6c56a43af98a639e2668ff99d8a47fd6504a&f=libs%2Fdimg%2Floaders%2Fjpegloader.cpp

Case 1: 2x1 1x1 1x1 = 4:2:2
Chroma halved horizontally.
You call it "low".

Case 2: 2x2 1x1 1x1 = 4:2:0
Chroma quartered in 2x2 blocks.
You call it "medium".

Case 3: 4x1 1x1 1x1 = 4:1:1
Chroma quartered in 4x1 blocks.
You call it "high".

Tooltip:
https://quickgit.kde.org/?p=digikam.git&a=blob&h=afa4beb83a6173345f516261ec442c199557738e&hb=b5be6c56a43af98a639e2668ff99d8a47fd6504a&f=libs%2Fdimg%2Floaders%2Fjpegsettings.cpp

4:2:0 and 4:1:1 both quarter the chroma resolution, but in different ways. 4:1:1 is uncommon, but if you want to have it then I think it is misleading to call 4:1:1 "high" and 4:2:0 "medium", as they both destroy 3/4 of the color but in different ways.

Just saying "little to no visual difference" is not good, because the difference can be the opposite of "little" depending on the image, and this explanation does nothing to prepare the user for what sort of difference to expect. I would not call this "little to no" http://i.imgur.com/zfvnrML.png

Saying that only 4:1:1 "tends to alter colors" leads the user to think the other options don't when in fact they all butcher colors.

Lastly, 4:2:0 and 4:1:1 both quarter the resolution, so I wouldn't call one "high" and the other "medium".

Here is my proposal:

    d->subSamplingCB->setWhatsThis(i18n("<p>Chroma subsampling reduces file size by taking advantage of the eye's lesser sensitivity to color resolution. How perceptible the difference is depends on the image - real-life full-sized photos will generally show no difference, while sharp, down-scaled photos and pixel-fine colorful watermarks and text may lose fine color detail.</p>"
"<p><b>None</b><br>J:a:b 4:4:4, h/v 1/1<br>No chroma subsampling, highest quality but lowest compression.</p>"
"<p><b>Medium</b><br>J:a:b 4:2:2, h/v 2/1<br>Chroma halved horizontally, average compression, average quality.</p>"
"<p><b>High 2x1</b><br>J:a:b 4:2:0, h/v 2/2<br>Chroma quartered in 2x2 blocks, high compression but low quality.</p>"
"<p><b>High 4x1</b><br>J:a:b 4:1:1, h/v 4/1<br>Chroma quartered in 4x1 blocks, high compression but low quality.</p>"));
Comment 1 caulier.gilles 2016-02-01 07:37:25 UTC
Git commit b5be6c56a43af98a639e2668ff99d8a47fd6504a by Maik Qualmann.
Committed on 31/01/2016 at 20:01.
Pushed by mqualmann into branch 'master'.

correct chroma subsampling in JPEGLoader and adds a chroma subsampling mode

M  +16   -4    libs/dimg/loaders/jpegloader.cpp
M  +12   -8    libs/dimg/loaders/jpegsettings.cpp

http://commits.kde.org/digikam/b5be6c56a43af98a639e2668ff99d8a47fd6504a

diff --git a/libs/dimg/loaders/jpegloader.cpp b/libs/dimg/loaders/jpegloader.cpp
index c33d785..f33c15c 100644
--- a/libs/dimg/loaders/jpegloader.cpp
+++ b/libs/dimg/loaders/jpegloader.cpp
@@ -736,9 +736,9 @@ bool JPEGLoader::save(const QString& filePath, DImgLoaderObserver* const observe

     switch (subsampling)
     {
-        case 1:  // 2x1, 1x1, 1x1 (4:2:2) : Medium
+        case 1:  // 2x1, 1x1, 1x1 (4:2:2) : Low
         {
-            qCDebug(DIGIKAM_DIMG_LOG_JPEG) << "Using LibJPEG medium chroma-subsampling (4:2:2)";
+            qCDebug(DIGIKAM_DIMG_LOG_JPEG) << "Using LibJPEG low chroma-subsampling (4:2:2)";
             cinfo.comp_info[0].h_samp_factor = 2;
             cinfo.comp_info[0].v_samp_factor = 1;
             cinfo.comp_info[1].h_samp_factor = 1;
@@ -748,9 +748,9 @@ bool JPEGLoader::save(const QString& filePath, DImgLoaderObserver* const observe
             break;
         }

-        case 2:  // 2x2, 1x1, 1x1 (4:1:1) : High
+        case 2:  // 2x2, 1x1, 1x1 (4:2:0) : Medium
         {
-            qCDebug(DIGIKAM_DIMG_LOG_JPEG) << "Using LibJPEG high chroma-subsampling (4:1:1)";
+            qCDebug(DIGIKAM_DIMG_LOG_JPEG) << "Using LibJPEG medium chroma-subsampling (4:2:0)";
             cinfo.comp_info[0].h_samp_factor = 2;
             cinfo.comp_info[0].v_samp_factor = 2;
             cinfo.comp_info[1].h_samp_factor = 1;
@@ -760,6 +760,18 @@ bool JPEGLoader::save(const QString& filePath, DImgLoaderObserver* const observe
             break;
         }

+        case 3:  // 4x1, 1x1, 1x1 (4:1:1) : High
+        {
+            qCDebug(DIGIKAM_DIMG_LOG_JPEG) << "Using LibJPEG high chroma-subsampling (4:1:1)";
+            cinfo.comp_info[0].h_samp_factor = 4;
+            cinfo.comp_info[0].v_samp_factor = 1;
+            cinfo.comp_info[1].h_samp_factor = 1;
+            cinfo.comp_info[1].v_samp_factor = 1;
+            cinfo.comp_info[2].h_samp_factor = 1;
+            cinfo.comp_info[2].v_samp_factor = 1;
+            break;
+        }
+
         default:  // 1x1 1x1 1x1 (4:4:4) : None
         {
             qCDebug(DIGIKAM_DIMG_LOG_JPEG) << "Using LibJPEG none chroma-subsampling (4:4:4)";
diff --git a/libs/dimg/loaders/jpegsettings.cpp b/libs/dimg/loaders/jpegsettings.cpp
index b93bfba..afa4beb 100644
--- a/libs/dimg/loaders/jpegsettings.cpp
+++ b/libs/dimg/loaders/jpegsettings.cpp
@@ -108,18 +108,22 @@ JPEGSettings::JPEGSettings(QWidget* const parent)

     d->subSamplingCB = new QComboBox(this);
     d->subSamplingCB->insertItem(0, i18n("None"));    // 1x1, 1x1, 1x1 (4:4:4)
-    d->subSamplingCB->insertItem(1, i18n("Medium"));  // 2x1, 1x1, 1x1 (4:2:2)
-    d->subSamplingCB->insertItem(2, i18n("High"));    // 2x2, 1x1, 1x1 (4:1:1)
+    d->subSamplingCB->insertItem(1, i18n("Low"));     // 2x1, 1x1, 1x1 (4:2:2)
+    d->subSamplingCB->insertItem(2, i18n("Medium"));  // 2x2, 1x1, 1x1 (4:2:0)
+    d->subSamplingCB->insertItem(3, i18n("High"));    // 4x1, 1x1, 1x1 (4:1:1)
     d->subSamplingCB->setWhatsThis(i18n("<p>JPEG Chroma subsampling level \n(color is saved with less resolution "
                                         "than luminance):</p>"
                                         "<p><b>None</b>=best: uses 4:4:4 ratio. Does not employ chroma "
                                         "subsampling at all. This preserves edges and contrasting "
-                                        "colors, whilst adding no additional compression</p>"
-                                        "<p><b>Medium</b>: uses 4:2:2 ratio. Medium compression: reduces "
-                                        "the color resolution by one-third with little to "
-                                        "no visual difference</p>"
-                                        "<p><b>High</b>: use 4:1:1 ratio. High compression: suits "
-                                        "images with soft edges but tends to alter colors</p>"
+                                        "colors, whilst adding no additional compression.</p>"
+                                        "<p><b>Low</b>: uses 4:2:2 ratio. Low compression: reduces "
+                                        "the horizontal color resolution by half with little to "
+                                        "no visual difference.</p>"
+                                        "<p><b>Medium</b>: uses 4:2:0 ratio. Medium compression: reduces "
+                                        "the horizontal and vertical color resolution by half.</p>"
+                                        "<p><b>High</b>: use 4:1:1 ratio. High compression: reduces "
+                                        "the horizontal color resolution by one quarter. Created "
+                                        "images with soft edges but tends to alter colors.</p>"
                                         "<p><b>Note: JPEG always uses lossy compression.</b></p>"));

     d->JPEGGrid->addWidget(d->labelJPEGcompression, 0, 0, 1, 2);
Comment 2 Maik Qualmann 2016-02-01 19:02:10 UTC
Git commit 64db6a9dff56d2b0cf5678c98bfc5e2c88ce8992 by Maik Qualmann.
Committed on 01/02/2016 at 19:00.
Pushed by mqualmann into branch 'master'.

remove rating Low, Medium High from the chroma subsampling settings

M  +8    -8    libs/dimg/loaders/jpegloader.cpp
M  +17   -17   libs/dimg/loaders/jpegsettings.cpp

http://commits.kde.org/digikam/64db6a9dff56d2b0cf5678c98bfc5e2c88ce8992
Comment 3 DrSlony 2016-02-01 19:24:13 UTC
+1 for Maik's commit, in my opinion it is now much clearer now to the users.
P.S. It would also be nice if we spoke in English and not only in diffs.