[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    playground/graphics/darkroom
From:       Cyrille Berger <cyb () lepi ! org>
Date:       2008-08-24 12:25:41
Message-ID: 1219580741.675984.22385.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 851722 by berger:

allow to export to JPEG

 M  +1 -0      CMakeLists.txt  
 M  +2 -1      src/CMakeLists.txt  
 M  +186 -1    src/codecs/JpegExportCodec.cpp  
 M  +2 -2      src/codecs/PngExportCodec.cpp  
 A             src/codecs/iccjpeg.c   [License: BSD X11 (BSD like)]
 A             src/codecs/iccjpeg.h   [License: BSD X11 (BSD like)]


--- trunk/playground/graphics/darkroom/CMakeLists.txt #851721:851722
@@ -2,6 +2,7 @@
 
 find_package(KDE4 REQUIRED)
 find_package(PNG REQUIRED)
+find_package(JPEG REQUIRED)
 find_package(Kdcraw REQUIRED)
 find_package(Kexiv2 REQUIRED)
 find_package(LCMS REQUIRED)
--- trunk/playground/graphics/darkroom/src/CMakeLists.txt #851721:851722
@@ -20,6 +20,7 @@
    ExportCodec.cpp
    codecs/PngExportCodec.cpp
    codecs/JpegExportCodec.cpp
+   codecs/iccjpeg.c
 # External widgets
    ImageHistogram.cpp
    HistogramWidget.cpp
@@ -47,7 +48,7 @@
 
 kde4_add_executable(darkroom ${darkroom_SRCS})
 
-target_link_libraries(darkroom ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} \
${KDCRAW_LIBRARIES} ${KEXIV2_LIBRARIES} ${KDE4_THREADWEAVER_LIBRARIES} \
${LCMS_LIBRARIES} ${OPENCTL_LIBRARIES} ) +target_link_libraries(darkroom \
${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDCRAW_LIBRARIES} ${KEXIV2_LIBRARIES} \
${KDE4_THREADWEAVER_LIBRARIES} ${LCMS_LIBRARIES} ${OPENCTL_LIBRARIES} jpeg )  
 install(TARGETS darkroom DESTINATION ${BIN_INSTALL_DIR} )
 
--- trunk/playground/graphics/darkroom/src/codecs/JpegExportCodec.cpp #851721:851722
@@ -16,6 +16,19 @@
 
 #include "codecs/JpegExportCodec.h"
 
+extern "C" {
+#include <codecs/iccjpeg.h>
+}
+
+#include <QFileInfo>
+#include <qendian.h>
+
+#include <KMessageBox>
+
+#include <libkexiv2/kexiv2.h>
+
+#include "ColorManager.h"
+#include "PostProcessor.h"
 #include "ProcessingOptions.h"
 
 #include "ui_JpegOptions.h"
@@ -56,6 +69,178 @@
   
 }
 
-bool JpegExportCodec::writeFile( RawImageInfoSP rawImageInfo, const QString& \
_fileName, const QByteArray& _data, int width, int height, const ProcessingOptions& \
processingOptions ) +#define TELL_ERROR( msg ) \
+  KMessageBox::error( 0, msg, i18n("An error has occured while saving.")); \
+  return false;
+
+#define COND_TELL_ERROR( cond, msg ) \
+  if( not (cond ) ) \
+  { \
+    TELL_ERROR( msg ); \
+  }
+
+#define ICC_MARKER  (JPEG_APP0 + 2) /* JPEG marker code for ICC */
+#define ICC_OVERHEAD_LEN  14    /* size of non-profile data in APP2 */
+#define MAX_BYTES_IN_MARKER  65533  /* maximum data len of a JPEG marker */
+#define MAX_DATA_BYTES_IN_MARKER  (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
+
+bool JpegExportCodec::writeFile( RawImageInfoSP rawImageInfo, const QString& \
_fileName, const QByteArray& _imageData, int width, int height, const \
ProcessingOptions& _processingOptions )  {
+  FILE *fp = fopen(_fileName.toLatin1(), "wb");
+  COND_TELL_ERROR( fp, "Can't open file: " + _fileName);
+  
+  // Initialize structure
+  struct jpeg_compress_struct cinfo;
+  jpeg_create_compress(&cinfo);
+  // Initialize error output
+  struct jpeg_error_mgr jerr;
+  cinfo.err = jpeg_std_error(&jerr);
+  // Initialize output stream
+  jpeg_stdio_dest(&cinfo, fp);
+  
+  cinfo.image_width = width;  // image width and height, in pixels
+  cinfo.image_height = height;
+  cinfo.input_components = 3;
+  cinfo.in_color_space = JCS_RGB;
+  
+  // Set default compression parameters
+  jpeg_set_defaults(&cinfo);
+  // Customize them
+  jpeg_set_quality(&cinfo,  _processingOptions.asInteger( "JpegQuality" ), true );
+  
+  if(_processingOptions.asBool( "JpegProgressive" ))
+  {
+      jpeg_simple_progression (&cinfo);
+  }
+  
+  // Optimize ?
+  cinfo.optimize_coding = _processingOptions.asBool( "JpegOptimize" );
+  
+  // Smoothing
+  cinfo.smoothing_factor = _processingOptions.asInteger( "JpegSmooth" );
+  
+  // Subsampling
+  switch(_processingOptions.asInteger( "JpegSubsampling" ))
+  {
+      default:
+      case 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;
+          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 1:
+      {
+          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:
+      {
+          cinfo.comp_info[0].h_samp_factor = 1;
+          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;
+      case 3:
+      {
+          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;
+  }
+  
+  // Start compression
+  jpeg_start_compress(&cinfo, true);
+  
+  // Save profile
+  if( _processingOptions.asBool("ConvertToSRGB") )
+  {
+    QByteArray profile = ColorManager::instance()->sRGBLinearProfile();
+    write_icc_profile(& cinfo, (uchar*)profile.data(), profile.size());
+  }
+  
+  // Save metadata  
+  KExiv2Iface::KExiv2 exiv2;
+  if(exiv2.load( rawImageInfo->fileInfo().absoluteFilePath()))
+  {
+    // Save exif
+    if(exiv2.hasExif()) {
+      QByteArray exifArray = exiv2.getExif(true);
+      if (exifArray.size() < MAX_DATA_BYTES_IN_MARKER)
+      {
+        jpeg_write_marker(&cinfo, JPEG_APP0 + 1, (const JOCTET*)exifArray.data(), \
exifArray.size()); +      }
+    }
+    // Save IPTC
+    if(exiv2.hasIptc()) {
+      QByteArray exifArray = exiv2.getIptc(true);
+      if (exifArray.size() < MAX_DATA_BYTES_IN_MARKER)
+      {
+        jpeg_write_marker(&cinfo, JPEG_APP0 + 13, (const JOCTET*)exifArray.data(), \
exifArray.size()); +      }
+    }
+    // Save XMP
+    if(exiv2.hasXmp()) {
+      QByteArray exifArray = exiv2.getXmp();
+      if (exifArray.size() < MAX_DATA_BYTES_IN_MARKER)
+      {
+        jpeg_write_marker(&cinfo, JPEG_APP0 + 14, (const JOCTET*)exifArray.data(), \
exifArray.size()); // TODO check which marker is suppose to host XMP data +      }
+    }
+  }
+  // Save data
+  int pixelSize = sizeof( quint16 ) * 3;
+  int lineWidth = pixelSize * width;
+  
+  QByteArray line;
+  line.resize( lineWidth);
+  
+  PostProcessor processor(_processingOptions);
+  JSAMPROW row_pointer = new JSAMPLE[width*cinfo.input_components];
+  for (; cinfo.next_scanline < height;) {
+    memcpy( line.data(), (_imageData.data() + cinfo.next_scanline * lineWidth ), \
lineWidth ); +    for(int i = 0; i < width; ++i)
+    {
+      quint16* ptr = (quint16*)(line.data() + i * pixelSize );
+      for( int i = 0; i < 3; ++i)
+      {
+        ptr[i] = qFromBigEndian(ptr[i]);
+      }
+    }
+    processor.apply16( line );
+    {
+      quint16* srcIt = (quint16*)line.data();
+      quint8* dstIt = (quint8*)row_pointer;
+      for( int i = 0; i < 3 * width; ++i)
+      {
+        dstIt[ i ] = srcIt[ i ] / 0xFF;
+      }
+    }
+    jpeg_write_scanlines(&cinfo, &row_pointer, 1);
+  }
+  // Writing is over
+  jpeg_finish_compress(&cinfo);
+  fclose(fp);
+
+  delete [] row_pointer;
+  // Free memory
+  jpeg_destroy_compress(&cinfo);
+  return true;
 }
--- trunk/playground/graphics/darkroom/src/codecs/PngExportCodec.cpp #851721:851722
@@ -189,7 +189,7 @@
   
   // Save ICC profile
   
-  if(sixteenBitsImage and not processingOptions.asBool("ConvertToSRGB") )
+  if( processingOptions.asBool("ConvertToSRGB") )
   {
     QByteArray profile = ColorManager::instance()->sRGBLinearProfile();
     png_set_iCCP( png_ptr, info_ptr, "icc", PNG_COMPRESSION_TYPE_BASE, \
profile.data(), profile.size()); @@ -220,7 +220,7 @@
   png_write_info(png_ptr, info_ptr);
   
   // Save data
-  int pixelSize = ( sixteenBitsImage ? sizeof( quint16 ) : sizeof( quint8 ) ) * 3;
+  int pixelSize = sizeof( quint16 ) * 3;
   int lineWidth = pixelSize * width;
   
   QByteArray line;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic