[Digikam-devel] [Bug 149578] libjpeg JPEG subsampling setting is not user-controlable

Gilles Caulier caulier.gilles at gmail.com
Fri Sep 7 15:36:41 BST 2007


------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
         
http://bugs.kde.org/show_bug.cgi?id=149578         
caulier.gilles gmail com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |FIXED



------- Additional Comments From caulier.gilles gmail com  2007-09-07 16:36 -------
SVN commit 709455 by cgilles:

digiKam from trunk (KDE4) : provide settings to adjust JPEG subsampling factor when new JPEG file is created by editor.
BUG: 149578 


 M  +42 -4     libs/dimg/loaders/jpegloader.cpp  
 M  +39 -4     libs/dimg/loaders/jpegsettings.cpp  
 M  +3 -0      libs/dimg/loaders/jpegsettings.h  
 M  +2 -1      libs/widgets/common/filesaveoptionsbox.cpp  
 M  +2 -0      project/project.kdevelop  
 M  +5 -2      utilities/imageeditor/canvas/dimginterface.cpp  
 M  +4 -0      utilities/imageeditor/canvas/iofilesettingscontainer.h  
 M  +2 -0      utilities/imageeditor/editor/editorwindow.cpp  
 M  +2 -0      utilities/setup/setupiofiles.cpp  


--- trunk/extragear/graphics/digikam/libs/dimg/loaders/jpegloader.cpp #709454:709455
 @ -532,13 +532,51  @
     if (quality > 100)
         quality = 100;
     
+    QVariant subSamplingAttr = imageGetAttribute("subsampling");
+    int subsampling = subSamplingAttr.isValid() ? subSamplingAttr.toInt() : 1;  // Medium    
+
     jpeg_set_defaults(&cinfo);
 
-    // B.K.O #130996: set horizontal and vertical Subsampling factor to 1 for a best 
-    // quality of color picture compression. 
-    cinfo.comp_info[0].h_samp_factor = 1;
-    cinfo.comp_info[0].v_samp_factor = 1; 
+    // B.K.O #149578: set horizontal and vertical chroma subsampling factor to encoder.
+    // See this page for details: http://en.wikipedia.org/wiki/Chroma_subsampling
 
+    switch (subsampling)
+    {
+        case 1:  // 2x1, 1x1, 1x1 (4:2:2) : Medium
+        {
+            DDebug() << "Using LibJPEG medium chroma-subsampling (4:2:2)" << endl;
+            cinfo.comp_info[0].h_samp_factor = 2;
+            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;
+        }
+        case 2:  // 2x2, 1x1, 1x1 (4:1:1) : High
+        {
+            DDebug() << "Using LibJPEG high chroma-subsampling (4:1:1)" << endl;
+            cinfo.comp_info[0].h_samp_factor = 2;
+            cinfo.comp_info[0].v_samp_factor = 2;
+            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
+        {
+            DDebug() << "Using LibJPEG none chroma-subsampling (4:4:4)" << endl;
+            cinfo.comp_info[0].h_samp_factor = 1;
+            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;
+        }
+    }
+
     jpeg_set_quality(&cinfo, quality, true);
     jpeg_start_compress(&cinfo, true);
 
--- trunk/extragear/graphics/digikam/libs/dimg/loaders/jpegsettings.cpp #709454:709455
 @ -28,6 +28,7  @
 #include <QLayout>
 #include <QFrame>
 #include <QGridLayout>
+#include <QComboBox>
 
 // KDE includes.
 
 @ -54,14 +55,18  @
         labelJPEGcompression = 0;
         JPEGcompression      = 0;
         labelWarning         = 0;
+        labelSubSampling     = 0;
+        subSamplingCB        = 0;
     }
 
     QGridLayout   *JPEGGrid;
 
     QLabel        *labelJPEGcompression;
-
     QLabel        *labelWarning;
+    QLabel        *labelSubSampling;
 
+    QComboBox     *subSamplingCB;
+
     KIntNumInput  *JPEGcompression;
 };
 
 @ -96,11 +101,31  @
     d->labelWarning->setLineWidth(1);
     d->labelWarning->setFrameShape(QFrame::Box);
 
+    d->labelSubSampling = new QLabel(i18n("Chroma subsampling:"), this);
+
+    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->setWhatsThis( i18n("<p>The level of chroma subsampling for JPEG images:<p>"
+                                         "<b>None</b>: use 4:4:4 ratio. It does not have any chroma "
+                                         "subsampling at all. This preserves borders and contrasting "
+                                         "colors, but compression is less<p>"
+                                         "<b>Medium</b>: use 4:2:2 ratio. Medium compression; reduces "
+                                         "the bandwidth for the picture by one-third with little to "
+                                         "no visual difference<p>"
+                                         "<b>High</b>: use 4:1:1 ratio. Important compression; suits "
+                                         "images with weak borders but tends to denature colors<p>"
+                                         "<b>Note: JPEG use a lossy compression image algorithm.</b>"));
+
+
     d->JPEGGrid->addWidget(d->labelJPEGcompression, 0, 0, 1, 1);
-    d->JPEGGrid->addWidget(d->JPEGcompression, 0, 1, 1, 1);
-    d->JPEGGrid->addWidget(d->labelWarning, 0, 2, 1, 1);    
+    d->JPEGGrid->addWidget(d->JPEGcompression,      0, 1, 1, 1);
+    d->JPEGGrid->addWidget(d->labelSubSampling,     1, 0, 1, 1);    
+    d->JPEGGrid->addWidget(d->subSamplingCB,        1, 1, 1, 1);    
+    d->JPEGGrid->addWidget(d->labelWarning,         0, 2, 1, 1);    
     d->JPEGGrid->setColumnStretch(1, 10);
-    d->JPEGGrid->setRowStretch(1, 10);
+    d->JPEGGrid->setRowStretch(2, 10);
     d->JPEGGrid->setAlignment(d->JPEGcompression, Qt::AlignCenter);
     d->JPEGGrid->setMargin(KDialog::spacingHint());
     d->JPEGGrid->setSpacing(KDialog::spacingHint());
 @ -121,4 +146,14  @
     return d->JPEGcompression->value();
 }
 
+void JPEGSettings::setSubSamplingValue(int val)
+{
+    d->subSamplingCB->setCurrentIndex(val);
+}
+
+int JPEGSettings::getSubSamplingValue()
+{
+    return d->subSamplingCB->currentIndex();
+}
+
 }  // namespace Digikam
--- trunk/extragear/graphics/digikam/libs/dimg/loaders/jpegsettings.h #709454:709455
 @ -49,6 +49,9  @
     void setCompressionValue(int val);
     int  getCompressionValue();
 
+    void setSubSamplingValue(int val);
+    int  getSubSamplingValue();
+
 private:
 
     JPEGSettingsPriv* d;
--- trunk/extragear/graphics/digikam/libs/widgets/common/filesaveoptionsbox.cpp #709454:709455
 @ -164,6 +164,7  @
     KSharedConfig::Ptr config = KGlobal::config();
     KConfigGroup group = config->group("ImageViewer Settings");
     group.writeEntry("JPEGCompression", d->JPEGOptions->getCompressionValue());
+    group.writeEntry("JPEGSubSampling", d->JPEGOptions->getSubSamplingValue());
     group.writeEntry("PNGCompression", d->PNGOptions->getCompressionValue());
     group.writeEntry("TIFFCompression", d->TIFFOptions->getCompression());
     group.writeEntry("JPEG2000Compression", d->JPEG2000Options->getCompressionValue());
 @ -176,6 +177,7  @
     KSharedConfig::Ptr config = KGlobal::config();
     KConfigGroup group = config->group("ImageViewer Settings");
     d->JPEGOptions->setCompressionValue( group.readEntry("JPEGCompression", 75) );
+    d->JPEGOptions->setCompressionValue( group.readEntry("JPEGSubSampling", 1) );  // Medium subsampling
     d->PNGOptions->setCompressionValue( group.readEntry("PNGCompression", 9) );
     d->TIFFOptions->setCompression( group.readEntry("TIFFCompression", false) );
     d->JPEG2000Options->setCompressionValue( group.readEntry("JPEG2000Compression", 75) );
 @ -183,4 +185,3  @
 }
 
 }  // namespace Digikam
-
--- trunk/extragear/graphics/digikam/project/project.kdevelop #709454:709455
 @ -158,6 +158,8  @
     <projectname>project</projectname>
     <projectname>project</projectname>
     <projectname>project</projectname>
+    <projectname>project</projectname>
+    <projectname>project</projectname>
   </general>
   <kdevfileview>
     <groups>
--- trunk/extragear/graphics/digikam/utilities/imageeditor/canvas/dimginterface.cpp #709454:709455
 @ -3,7 +3,7  @
  * This file is a part of digiKam project
  * http://www.digikam.org
  *
- * Date   : 2003-01-15
+ * Date        : 2003-01-15
  * Description : DImg interface for image editor
  *
  * Copyright (C) 2004-2005 by Renchi Raju <renchi pooh tam uiuc edu>
 @ -552,7 +552,10  @
     // JPEG file format.
     if ( mimeType.toUpper() == QString("JPG") || mimeType.toUpper() == QString("JPEG") || 
          mimeType.toUpper() == QString("JPE")) 
-       d->image.setAttribute("quality", iofileSettings->JPEGCompression);
+    {
+       d->image.setAttribute("quality",     iofileSettings->JPEGCompression);
+       d->image.setAttribute("subsampling", iofileSettings->JPEGSubSampling);
+    }
 
     // PNG file format.
     if ( mimeType.toUpper() == QString("PNG") ) 
--- trunk/extragear/graphics/digikam/utilities/imageeditor/canvas/iofilesettingscontainer.h #709454:709455
 @ -43,6 +43,7  @
     IOFileSettingsContainer()
     {
         JPEGCompression     = 75;
+        JPEGSubSampling     = 1;    // Medium subsampling
         PNGCompression      = 9;
         TIFFCompression     = false;
         JPEG2000Compression = 75;
 @ -56,6 +57,9  @
     // JPEG quality value.
     int  JPEGCompression;
 
+    // JPEG chroma subsampling value.
+    int  JPEGSubSampling;
+
     // PNG compression value.
     int  PNGCompression;
 
--- trunk/extragear/graphics/digikam/utilities/imageeditor/editor/editorwindow.cpp #709454:709455
 @ -818,6 +818,8  @
                                                  (float)group.readEntry("JPEGCompression", 75)
                                                  + 26.0 - (75.0/100.0));
 
+    m_IOFileSettings->JPEGSubSampling     = group.readEntry("JPEGSubSampling", 1);  // Medium subsampling
+
     // PNG compression slider settings : 1 - 9 ==> libpng settings : 100 - 1.
     m_IOFileSettings->PNGCompression      = (int)(((1.0-100.0)/8.0)*
                                                  (float)group.readEntry("PNGCompression", 1)
--- trunk/extragear/graphics/digikam/utilities/setup/setupiofiles.cpp #709454:709455
 @ -118,6 +118,7  @
     KSharedConfig::Ptr config = KGlobal::config();
     KConfigGroup group = config->group(QString("ImageViewer Settings"));
     group.writeEntry("JPEGCompression", d->JPEGOptions->getCompressionValue());
+    group.writeEntry("JPEGSubSampling", d->JPEGOptions->getSubSamplingValue());
     group.writeEntry("PNGCompression", d->PNGOptions->getCompressionValue());
     group.writeEntry("TIFFCompression", d->TIFFOptions->getCompression());
     group.writeEntry("JPEG2000Compression", d->JPEG2000Options->getCompressionValue());
 @ -130,6 +131,7  @
     KSharedConfig::Ptr config = KGlobal::config();
     KConfigGroup group = config->group(QString("ImageViewer Settings"));
     d->JPEGOptions->setCompressionValue(group.readEntry("JPEGCompression", 75) );
+    d->JPEGOptions->setCompressionValue(group.readEntry("JPEGSubSampling", 1) ); // Medium subsampling
     d->PNGOptions->setCompressionValue(group.readEntry("PNGCompression", 9) );
     d->TIFFOptions->setCompression(group.readEntry("TIFFCompression", false));
     d->JPEG2000Options->setCompressionValue( group.readEntry("JPEG2000Compression", 75) );



More information about the Digikam-devel mailing list