Merged RTEngine enhancements from DEFAULT

This commit is contained in:
Oliver Duis
2011-04-07 17:04:24 +02:00
parent eefc675c99
commit d1ad6a85df
9 changed files with 148 additions and 171 deletions

View File

@@ -51,22 +51,22 @@ Crop::~Crop () {
}
void Crop::setListener (DetailedCropListener* il) {
// We can make reads in the IF, because the mProcessing lock is only needed for change
if (cropImageListener!=il) {
parent->mProcessing.lock();
Glib::Mutex::Lock lock(cropMutex);
cropImageListener = il;
parent->mProcessing.unlock();
}
}
void Crop::update (int todo, bool internal) {
void Crop::update (int todo) {
Glib::Mutex::Lock lock(cropMutex);
//flag for testing color accuracy
bool colortest = false;
if (!internal)
parent->mProcessing.lock ();
ProcParams& params = parent->params;
cropMutex.lock ();
parent->ipf.setScale (skip);
@@ -91,9 +91,10 @@ void Crop::update (int todo, bool internal) {
if (needsinitupdate)
todo = ALL;
/* Seems to be taken care of by calling improccoordinator::updatePreviewImage
if( regenHighDetail )
parent->updatePreviewImage (ALL,this); // We have just set skip to 1
*/
baseCrop = origCrop;
bool needstransform = parent->ipf.needsTransform();
@@ -243,11 +244,6 @@ void Crop::update (int todo, bool internal) {
delete final;
delete finaltrue;
}
cropMutex.unlock ();
if (!internal)
parent->mProcessing.unlock ();
}
void Crop::freeAll () {
@@ -392,15 +388,9 @@ bool Crop::tryUpdate() {
return needsFullUpdate;
}
// Full update, should be called via thread
void Crop::fullUpdate () {
if (updating) {
needsNext = true;
return;
}
updating = true;
parent->updaterThreadStart.lock ();
if (parent->updaterRunning && parent->thread) {
// Do NOT reset changes here, since in a long chain of events it will lead to chroma_scale not being updated,
@@ -410,19 +400,19 @@ void Crop::fullUpdate () {
}
if (parent->plistener)
parent->plistener->setProgressState (1);
parent->plistener->setProgressState (true);
needsNext = true;
while (needsNext) {
needsNext = false;
update (ALL, true);
update (ALL);
}
updating = false;
if (parent->plistener)
parent->plistener->setProgressState (0);
parent->updaterThreadStart.unlock ();
if (parent->plistener)
parent->plistener->setProgressState (false);
}
}

View File

@@ -68,7 +68,7 @@ class Crop : public DetailedCrop {
~Crop ();
bool hasListener () { return cropImageListener; }
void update (int todo, bool internal=false);
void update (int todo);
void setWindow (int cx, int cy, int cw, int ch, int skip) { setCropSizes (cx, cy, cw, ch, skip, false); }
bool tryUpdate (); // First try, only make fullUpdate if this returns false

View File

@@ -2,6 +2,7 @@
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
* Copyright (c) 2010 Oliver Duis <www.oliverduis.de>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,6 +46,22 @@ using namespace rtengine::procparams;
Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.","Error while reading header.","File reading error", "Image format not supported."};
// For only copying the raw input data
void ImageIO::setMetadata (const rtexif::TagDirectory* eroot) {
if (exifRoot!=NULL) { delete exifRoot; exifRoot = NULL; }
if (eroot) {
rtexif::TagDirectory* td = ((rtexif::TagDirectory*)eroot)->clone (NULL);
// make IPTC and XMP pass through
td->keepTag(0x83bb); // IPTC
td->keepTag(0x02bc); // XMP
exifRoot=td;
}
}
// For merging with RT specific data
void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const std::vector<ExifPair>& exif, const std::vector<IPTCPair>& iptcc) {
// store exif info
@@ -53,15 +70,13 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const std::vector<
exifChange[i].first = exif[i].field;
exifChange[i].second = exif[i].value;
}
delete exifRoot;
exifRoot = NULL;
if (exifRoot!=NULL) { delete exifRoot; exifRoot = NULL; }
if (eroot)
exifRoot = ((rtexif::TagDirectory*)eroot)->clone (NULL);
if (iptc)
iptc_data_free (iptc);
iptc = NULL;
if (iptc!=NULL) { iptc_data_free (iptc); iptc = NULL; }
// build iptc structures for libiptcdata
if (iptcc.size()==0)
@@ -136,7 +151,7 @@ int ImageIO::loadPNG (Glib::ustring fname) {
return IMIO_CANNOTREADFILE;
if (pl) {
pl->setProgressStr ("Loading PNG file...");
pl->setProgressStr ("PROGRESSBAR_LOADPNG");
pl->setProgress (0.0);
}
@@ -252,7 +267,7 @@ int ImageIO::loadPNG (Glib::ustring fname) {
delete [] row;
fclose(file);
if (pl) {
pl->setProgressStr ("Ready.");
pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0);
}
return IMIO_SUCCESS;
@@ -269,7 +284,7 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize)
if ( setjmp(((rt_jpeg_error_mgr*)cinfo.src)->error_jmp_buf) == 0 )
{
if (pl) {
pl->setProgressStr ("Loading JPEG file...");
pl->setProgressStr ("PROGRESSBAR_LOADJPEG");
pl->setProgress (0.0);
}
@@ -313,7 +328,7 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize)
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
if (pl) {
pl->setProgressStr ("Ready.");
pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0);
}
return IMIO_SUCCESS;
@@ -340,7 +355,7 @@ int ImageIO::loadJPEG (Glib::ustring fname) {
if ( setjmp(((rt_jpeg_error_mgr*)cinfo.src)->error_jmp_buf) == 0 )
{
if (pl) {
pl->setProgressStr ("Loading JPEG file...");
pl->setProgressStr ("PROGRESSBAR_LOADJPEG");
pl->setProgress (0.0);
}
@@ -385,7 +400,7 @@ int ImageIO::loadJPEG (Glib::ustring fname) {
jpeg_destroy_decompress(&cinfo);
fclose(file);
if (pl) {
pl->setProgressStr ("Ready.");
pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0);
}
return IMIO_SUCCESS;
@@ -409,7 +424,7 @@ int ImageIO::loadTIFF (Glib::ustring fname) {
return IMIO_CANNOTREADFILE;
if (pl) {
pl->setProgressStr ("Loading TIFF file...");
pl->setProgressStr ("PROGRESSBAR_LOADTIFF");
pl->setProgress (0.0);
}
@@ -467,7 +482,7 @@ int ImageIO::loadTIFF (Glib::ustring fname) {
delete [] linebuffer;
if (pl) {
pl->setProgressStr ("Ready.");
pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0);
}
@@ -502,17 +517,13 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s
int ImageIO::savePNG (Glib::ustring fname, int compression, int bps) {
// create a temporary file name that is opened in parallel by e.g. image viewers whilte RT is still writing
Glib::ustring tmpFname=fname;
tmpFname.append(".tmp");
FILE *file = safe_g_fopen (tmpFname, "wb");
FILE *file = safe_g_fopen_WriteBinLock (fname);
if (!file)
return IMIO_CANNOTREADFILE;
if (pl) {
pl->setProgressStr ("Saving PNG file...");
pl->setProgressStr ("PROGRESSBAR_SAVEPNG");
pl->setProgress (0.0);
}
@@ -573,11 +584,8 @@ int ImageIO::savePNG (Glib::ustring fname, int compression, int bps) {
delete [] row;
fclose (file);
// Rename temporary filename, practically atomic
safe_g_rename(tmpFname,fname);
if (pl) {
pl->setProgressStr ("Ready.");
pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0);
}
@@ -593,17 +601,13 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality) {
cinfo.err = jpeg_std_error (&jerr);
jpeg_create_compress (&cinfo);
// create a temporary file name that is opened in parallel by e.g. image viewers whilte RT is still writing
Glib::ustring tmpFname=fname;
tmpFname.append(".tmp");
FILE *file = safe_g_fopen (tmpFname, "wb");
FILE *file = safe_g_fopen_WriteBinLock (fname);
if (!file)
return IMIO_CANNOTREADFILE;
if (pl) {
pl->setProgressStr ("Saving JPEG file...");
pl->setProgressStr ("PROGRESSBAR_SAVEJPEG");
pl->setProgress (0.0);
}
@@ -689,11 +693,8 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality) {
fclose (file);
// Rename temporary filename, practically atomic
safe_g_rename(tmpFname,fname);
if (pl) {
pl->setProgressStr ("Ready.");
pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0);
}
@@ -712,13 +713,13 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) {
unsigned char* linebuffer = new unsigned char[lineWidth];
// TODO the following needs to be looked into - do we really need two ways to write a Tiff file ?
if (exifRoot && uncompressed) {
FILE *file = safe_g_fopen (fname, "wb");
FILE *file = safe_g_fopen_WriteBinLock (fname);
if (!file)
return IMIO_CANNOTREADFILE;
if (pl) {
pl->setProgressStr ("Saving TIFF file ...");
pl->setProgressStr ("PROGRESSBAR_SAVETIFF");
pl->setProgress (0.0);
}
@@ -771,7 +772,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) {
return IMIO_CANNOTREADFILE;
if (pl) {
pl->setProgressStr ("Saving TIFF file ...");
pl->setProgressStr ("PROGRESSBAR_SAVETIFF");
pl->setProgress (0.0);
}
@@ -842,7 +843,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) {
delete [] linebuffer;
if (pl) {
pl->setProgressStr ("Ready.");
pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0);
}
@@ -885,7 +886,8 @@ void png_flush(png_structp png_ptr) {
int ImageIO::load (Glib::ustring fname) {
int lastdot = fname.find_last_of ('.');
if( Glib::ustring::npos == lastdot )
return IMIO_FILETYPENOTSUPPORTED;
if (!fname.casefold().compare (lastdot, 4, ".png"))
return loadPNG (fname);
else if (!fname.casefold().compare (lastdot, 4, ".jpg"))
@@ -898,7 +900,8 @@ int ImageIO::load (Glib::ustring fname) {
int ImageIO::save (Glib::ustring fname) {
int lastdot = fname.find_last_of ('.');
if( Glib::ustring::npos == lastdot )
return IMIO_FILETYPENOTSUPPORTED;
if (!fname.casefold().compare (lastdot, 4, ".png"))
return savePNG (fname);
else if (!fname.casefold().compare (lastdot, 4, ".jpg"))

View File

@@ -83,6 +83,8 @@ DetailedCrop* ImProcCoordinator::createCrop () {
return new Crop (this);
}
// todo: bitmask containing desired actions, taken from changesSinceLast
// cropCall: calling crop, used to prevent self-updates
void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
mProcessing.lock ();
@@ -92,6 +94,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
ipf.setScale (scale);
// Check if any detail crops need high detail. If not, take a fast path short cut
bool highDetailNeeded=false;
for (int i=0; i<crops.size(); i++)
if (crops[i]->get_skip() == 1 ){
@@ -109,14 +112,12 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if ( todo & M_PREPROC)
imgsrc->preprocess( rp );
if( todo & M_RAW){
if( !highDetailNeeded ){
fineDetailsProcessed = false;
}else
fineDetailsProcessed = true;
fineDetailsProcessed = highDetailNeeded;
imgsrc->demosaic( rp );
}
if (todo & M_INIT) {
minit.lock ();
Glib::Mutex::Lock lock(minit);
if (settings->verbose) printf ("Applying white balance, color correction & sRBG conversion...\n");
currWB = ColorTemp (params.wb.temperature, params.wb.green);
if (params.wb.method=="Camera")
@@ -140,15 +141,15 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
imgsrc->getFullSize (fw, fh, tr);
PreviewProps pp (0, 0, fw, fh, scale);
setScale (scale, true);
setScale (scale);
imgsrc->getImage (currWB, tr, orig_prev, pp, params.hlrecovery, params.icm, params.raw);
ipf.firstAnalysis (orig_prev, &params, vhist16, imgsrc->getGamma());
minit.unlock ();
}
readyphase++;
progress ("Rotate / Distortion...",100*readyphase/numofphases);
bool needstransform = ipf.needsTransform();
// Remove transformation if unneeded
if (!needstransform && orig_prev!=oprevi) {
delete oprevi;
oprevi = orig_prev;
@@ -237,7 +238,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
// process crop, if needed
for (int i=0; i<crops.size(); i++)
if (crops[i]->hasListener () && cropCall != crops[i] )
crops[i]->update (todo, true);
crops[i]->update (todo); // may call outselves
progress ("Conversion to RGB...",100*readyphase/numofphases);
if (todo!=CROP) {
@@ -249,6 +250,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
catch(char * str)
{
progress ("Error converting file...",0);
previmg->getMutex().unlock();
mProcessing.unlock ();
return;
}
@@ -304,13 +306,10 @@ void ImProcCoordinator::freeAll () {
allocated = false;
}
void ImProcCoordinator::setScale (int prevscale, bool internal) {
void ImProcCoordinator::setScale (int prevscale) {
if (settings->verbose) printf ("setscale before lock\n");
if (!internal)
mProcessing.lock ();
tr = TR_NONE;
if (params.coarse.rotate==90) tr |= TR_R90;
if (params.coarse.rotate==180) tr |= TR_R180;
@@ -356,8 +355,6 @@ if (settings->verbose) printf ("setscale before lock\n");
sizeListeners[i]->sizeChanged (fullw, fullh, fw, fh);
if (settings->verbose) printf ("setscale ends2\n");
if (!internal)
mProcessing.unlock ();
}
@@ -479,51 +476,6 @@ void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &
mProcessing.unlock ();
}
void ImProcCoordinator::fullUpdatePreviewImage () {
if (destroying)
return;
updaterThreadStart.lock ();
if (updaterRunning && thread) {
changeSinceLast = 0;
thread->join ();
}
if (plistener)
plistener->setProgressState (1);
updatePreviewImage (ALL);
if (plistener)
plistener->setProgressState (0);
updaterThreadStart.unlock ();
}
void ImProcCoordinator::fullUpdateDetailedCrops () {
if (destroying)
return;
updaterThreadStart.lock ();
if (updaterRunning && thread) {
changeSinceLast = 0;
thread->join ();
}
if (plistener)
plistener->setProgressState (1);
for (int i=0; i<crops.size(); i++)
crops[i]->update (ALL, true);
if (plistener)
plistener->setProgressState (0);
updaterThreadStart.unlock ();
}
void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) {
@@ -593,7 +545,7 @@ void ImProcCoordinator::startProcessing () {
void ImProcCoordinator::process () {
if (plistener)
plistener->setProgressState (1);
plistener->setProgressState (true);
paramsUpdateMutex.lock ();
while (changeSinceLast) {
@@ -609,7 +561,7 @@ void ImProcCoordinator::process () {
updaterRunning = false;
if (plistener)
plistener->setProgressState (0);
plistener->setProgressState (false);
}
ProcParams* ImProcCoordinator::getParamsForUpdate (ProcEvent change) {

View File

@@ -34,6 +34,8 @@ using namespace procparams;
class Crop;
// Manages the image processing, espc. of the preview windows
// There is one ImProcCoordinator per edit panel
class ImProcCoordinator : public StagedImageProcessor {
friend class Crop;
@@ -95,7 +97,7 @@ class ImProcCoordinator : public StagedImageProcessor {
void progress (Glib::ustring str, int pr);
void reallocAll ();
void updateHistograms (int x1, int y1, int x2, int y2);
void setScale (int prevscale, bool internal=false);
void setScale (int prevscale);
void updatePreviewImage (int todo, Crop* cropCall= NULL);
Glib::Mutex mProcessing;
@@ -129,8 +131,7 @@ class ImProcCoordinator : public StagedImageProcessor {
void setPreviewScale (int scale) { setScale (scale); }
int getPreviewScale () { return scale; }
void fullUpdatePreviewImage ();
void fullUpdateDetailedCrops ();
//void fullUpdatePreviewImage ();
int getFullWidth () { return fullw; }
int getFullHeight () { return fullh; }

View File

@@ -105,8 +105,8 @@ namespace rtengine {
* @param str is the textual information corresponding to the progress */
virtual void setProgressStr (Glib::ustring str) {}
/** This member function is called when the state of the processing has been changed.
* @param state =1 if the processing has been started, =0 if it has been stopped */
virtual void setProgressState (int state) {}
* @param inProcessing =true if the processing has been started, =false if it has been stopped */
virtual void setProgressState (bool inProcessing) {}
/** This member function is called when an error occurs during the operation.
* @param descr is the error message */
virtual void error (Glib::ustring descr) {}
@@ -261,10 +261,6 @@ namespace rtengine {
/** Returns the scale of the preview image.
* @return the current scale of the preview image */
virtual int getPreviewScale () =0;
/** Performs a full update on the preview image. The resulting image is passed to the listener. */
virtual void fullUpdatePreviewImage () =0;
/** Performs a full update on the detailed crops corresponding to the image. The resulting images are passed to the listeners of the crops. */
virtual void fullUpdateDetailedCrops () =0;
/** Returns the full width of the resulting image (in 1:1 scale).
* @return the width of the final image */
virtual int getFullWidth () =0;
@@ -354,6 +350,7 @@ namespace rtengine {
* @param job the ProcessingJob to cancel.
* @param errorCode is the error code if an error occured (e.g. the input image could not be loaded etc.)
* @param pl is an optional ProgressListener if you want to keep track of the progress
* @param tunnelMetaData tunnels IPTC and XMP to output without change
* @return the resulting image, with the output profile applied, exif and iptc data set. You have to save it or you can access the pixel data directly. */
IImage16* processImage (ProcessingJob* job, int& errorCode, ProgressListener* pl = NULL, bool tunnelMetaData=false);

View File

@@ -22,6 +22,12 @@
#include <safegtk.h>
#include <guiutils.h>
#include <glib/gstdio.h>
#include <fcntl.h>
#ifdef WIN32
#include <windows.h>
#else
#include <stdio.h>
#endif
Glib::RefPtr<Gdk::Pixbuf> safe_create_from_file(const std::string& filename)
@@ -113,6 +119,9 @@ void safe_build_subdir_list (Glib::RefPtr<Gio::File> &dir, std::vector<Glib::ust
Glib::RefPtr<Gio::FileEnumerator> dirList;
if (dir)
{
// CD-ROMs with no drive inserted are reported, but do not exist, causing RT to crash
if (!safe_file_test(dir->get_path(),Glib::FILE_TEST_EXISTS)) return;
SAFE_ENUMERATOR_CODE_START
if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || add_hidden))
subDirs.push_back (info->get_name());
@@ -162,27 +171,6 @@ std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str)
return str;
}
std::string safe_filename_from_utf8 (const Glib::ustring& utf8_str)
{
std::string str;
#ifdef GLIBMM_EXCEPTIONS_ENABLED
try {
str = Glib::filename_from_utf8 (utf8_str);
}
catch (const Glib::ConvertError& e) {
//str = Glib::convert_with_fallback(utf8_str, "LATIN1", "UTF8", "?");
}
#else
{
std::auto_ptr<Glib::Error> error;
str = Glib::filename_from_utf8 (utf8_str, error);
/*if (error.get())
{str = Glib::convert_with_fallback(utf8_str, "LATIN1", "UTF8", "?", error);}*/
}
#endif //GLIBMM_EXCEPTIONS_ENABLED
return str;
}
bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8)
{
std::string cmd;
@@ -190,8 +178,8 @@ bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8)
#ifdef GLIBMM_EXCEPTIONS_ENABLED
try {
cmd = Glib::filename_from_utf8(cmd_utf8);
printf ("command line: |%s|\n", cmd.c_str());
Glib::spawn_command_line_async (cmd);
printf ("command line: %s\n", cmd.c_str());
Glib::spawn_command_line_async (cmd.c_str());
success = true;
} catch (Glib::Exception& ex) {
printf ("%s\n", ex.what().c_str());
@@ -200,7 +188,7 @@ bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8)
std::auto_ptr<Glib::Error> error;
cmd = Glib::filename_from_utf8(cmd_utf8, error);
if (!error.get()) {
printf ("command line: |%s|\n", cmd.c_str());
printf ("command line: %s\n", cmd.c_str());
Glib::spawn_command_line_async (cmd, error);
}
if (error.get())
@@ -221,38 +209,81 @@ bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8)
int exitStatus=-1;
try {
cmd = Glib::filename_from_utf8(cmd_utf8);
printf ("command line: |%s|\n", cmd.c_str());
//cmd = Glib::filename_from_utf8(cmd_utf8);
printf ("command line: %s\n", cmd_utf8.c_str());
// if it crashes here on windows, make sure you have the GTK runtime files gspawn-win32-helper*.exe files in RT directory
Glib::spawn_command_line_sync (cmd,NULL,NULL, &exitStatus);
Glib::spawn_command_line_sync (cmd_utf8, NULL, NULL, &exitStatus);
} catch (Glib::Exception& ex) {
printf ("%s\n", ex.what().c_str());
}
return (exitStatus==0);
}
// Opens a file for binary writing and request exclusive lock (cases were you need "wb" mode plus locking)
// (Important on Windows to prevent Explorer to crash RT when parallel scanning e.g. a currently written image file)
FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname) {
FILE* f=NULL;
#ifdef WIN32
// g_fopen just uses _wfopen internally on Windows, does not lock access and has no options to set this
// so use a native function to work around this problem
wchar_t *wFname = (wchar_t*)g_utf8_to_utf16 (fname.c_str(), -1, NULL, NULL, NULL);
HANDLE hFile = CreateFileW(wFname, GENERIC_READ | GENERIC_WRITE, 0 /* no sharing allowed */, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
g_free(wFname);
if (hFile==INVALID_HANDLE_VALUE)
f=NULL;
else
f=_fdopen( _open_osfhandle((intptr_t)hFile, 0) , "wb");
#else
f = safe_g_fopen(fname, "wb");
#endif
return f;
}
// Covers old UNIX ::open, which expects ANSI instead of UTF8 on Windows
int safe_open_ReadOnly(const char *fname) {
int fd=-1;
#ifdef WIN32
// First convert UTF8 to UTF16, then use Windows function to open
wchar_t *wFname = (wchar_t*)g_utf8_to_utf16 (fname, -1, NULL, NULL, NULL);
HANDLE hFile = CreateFileW(wFname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
g_free(wFname);
// convert back to old file descriptor format
if (hFile!=INVALID_HANDLE_VALUE) fd = _open_osfhandle((intptr_t)hFile, 0);
#else
fd = ::open(fname, O_RDONLY);
#endif
return fd;
}
FILE * safe_g_fopen(const Glib::ustring& src,const gchar *mode)
{
return g_fopen(safe_filename_from_utf8(src).c_str(),mode);
return g_fopen(src.c_str(),mode);
}
bool safe_file_test (const Glib::ustring& filename, Glib::FileTest test)
{
return Glib::file_test (safe_filename_from_utf8(filename), test);
return Glib::file_test (filename, test);
}
int safe_g_remove(const Glib::ustring& filename)
{
return ::g_remove(safe_filename_from_utf8(filename).c_str());
return ::g_remove(filename.c_str());
}
int safe_g_rename(const Glib::ustring& oldFilename, const Glib::ustring& newFilename)
{
return ::g_rename(safe_filename_from_utf8(oldFilename).c_str(), safe_filename_from_utf8(newFilename).c_str());
return ::g_rename(oldFilename.c_str(), newFilename.c_str());
}
int safe_g_mkdir_with_parents(const Glib::ustring& dirName, int mode)
{
return ::g_mkdir_with_parents(safe_filename_from_utf8(dirName).c_str(), mode);
return ::g_mkdir_with_parents(dirName.c_str(), mode);
}

View File

@@ -31,6 +31,9 @@ std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str);
std::string safe_filename_from_utf8 (const Glib::ustring& utf8_str);
FILE * safe_g_fopen(const Glib::ustring& src,const gchar *mode);
FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname);
int safe_open_ReadOnly(const char *fname);
bool safe_file_test (const Glib::ustring& filename, Glib::FileTest test);
int safe_g_remove(const Glib::ustring& filename);
int safe_g_rename(const Glib::ustring& oldFilename, const Glib::ustring& newFilename);

View File

@@ -275,9 +275,9 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
}
//if (tunnelMetaData)
// readyImg->setMetadata (ii->getMetaData()->getExifData ());
//else
if (tunnelMetaData)
readyImg->setMetadata (ii->getMetaData()->getExifData ());
else
readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);