[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