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) { 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; 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 //flag for testing color accuracy
bool colortest = false; bool colortest = false;
if (!internal)
parent->mProcessing.lock ();
ProcParams& params = parent->params; ProcParams& params = parent->params;
cropMutex.lock ();
parent->ipf.setScale (skip); parent->ipf.setScale (skip);
@@ -91,9 +91,10 @@ void Crop::update (int todo, bool internal) {
if (needsinitupdate) if (needsinitupdate)
todo = ALL; todo = ALL;
/* Seems to be taken care of by calling improccoordinator::updatePreviewImage
if( regenHighDetail ) if( regenHighDetail )
parent->updatePreviewImage (ALL,this); // We have just set skip to 1 parent->updatePreviewImage (ALL,this); // We have just set skip to 1
*/
baseCrop = origCrop; baseCrop = origCrop;
bool needstransform = parent->ipf.needsTransform(); bool needstransform = parent->ipf.needsTransform();
@@ -243,11 +244,6 @@ void Crop::update (int todo, bool internal) {
delete final; delete final;
delete finaltrue; delete finaltrue;
} }
cropMutex.unlock ();
if (!internal)
parent->mProcessing.unlock ();
} }
void Crop::freeAll () { void Crop::freeAll () {
@@ -392,15 +388,9 @@ bool Crop::tryUpdate() {
return needsFullUpdate; return needsFullUpdate;
} }
// Full update, should be called via thread
void Crop::fullUpdate () { void Crop::fullUpdate () {
if (updating) {
needsNext = true;
return;
}
updating = true;
parent->updaterThreadStart.lock (); parent->updaterThreadStart.lock ();
if (parent->updaterRunning && parent->thread) { 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, // 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) if (parent->plistener)
parent->plistener->setProgressState (1); parent->plistener->setProgressState (true);
needsNext = true; needsNext = true;
while (needsNext) { while (needsNext) {
needsNext = false; needsNext = false;
update (ALL, true); update (ALL);
} }
updating = false; updating = false;
if (parent->plistener)
parent->plistener->setProgressState (0);
parent->updaterThreadStart.unlock (); parent->updaterThreadStart.unlock ();
if (parent->plistener)
parent->plistener->setProgressState (false);
} }
} }

View File

@@ -68,7 +68,7 @@ class Crop : public DetailedCrop {
~Crop (); ~Crop ();
bool hasListener () { return cropImageListener; } 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); } 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 bool tryUpdate (); // First try, only make fullUpdate if this returns false

View File

@@ -2,6 +2,7 @@
* This file is part of RawTherapee. * This file is part of RawTherapee.
* *
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com> * 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 * RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * 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."}; 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) { void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const std::vector<ExifPair>& exif, const std::vector<IPTCPair>& iptcc) {
// store exif info // 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].first = exif[i].field;
exifChange[i].second = exif[i].value; exifChange[i].second = exif[i].value;
} }
delete exifRoot;
exifRoot = NULL; if (exifRoot!=NULL) { delete exifRoot; exifRoot = NULL; }
if (eroot) if (eroot)
exifRoot = ((rtexif::TagDirectory*)eroot)->clone (NULL); exifRoot = ((rtexif::TagDirectory*)eroot)->clone (NULL);
if (iptc) if (iptc!=NULL) { iptc_data_free (iptc); iptc = NULL; }
iptc_data_free (iptc);
iptc = NULL;
// build iptc structures for libiptcdata // build iptc structures for libiptcdata
if (iptcc.size()==0) if (iptcc.size()==0)
@@ -136,7 +151,7 @@ int ImageIO::loadPNG (Glib::ustring fname) {
return IMIO_CANNOTREADFILE; return IMIO_CANNOTREADFILE;
if (pl) { if (pl) {
pl->setProgressStr ("Loading PNG file..."); pl->setProgressStr ("PROGRESSBAR_LOADPNG");
pl->setProgress (0.0); pl->setProgress (0.0);
} }
@@ -252,7 +267,7 @@ int ImageIO::loadPNG (Glib::ustring fname) {
delete [] row; delete [] row;
fclose(file); fclose(file);
if (pl) { if (pl) {
pl->setProgressStr ("Ready."); pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0); pl->setProgress (1.0);
} }
return IMIO_SUCCESS; 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 ( setjmp(((rt_jpeg_error_mgr*)cinfo.src)->error_jmp_buf) == 0 )
{ {
if (pl) { if (pl) {
pl->setProgressStr ("Loading JPEG file..."); pl->setProgressStr ("PROGRESSBAR_LOADJPEG");
pl->setProgress (0.0); pl->setProgress (0.0);
} }
@@ -313,7 +328,7 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize)
jpeg_finish_decompress(&cinfo); jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
if (pl) { if (pl) {
pl->setProgressStr ("Ready."); pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0); pl->setProgress (1.0);
} }
return IMIO_SUCCESS; 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 ( setjmp(((rt_jpeg_error_mgr*)cinfo.src)->error_jmp_buf) == 0 )
{ {
if (pl) { if (pl) {
pl->setProgressStr ("Loading JPEG file..."); pl->setProgressStr ("PROGRESSBAR_LOADJPEG");
pl->setProgress (0.0); pl->setProgress (0.0);
} }
@@ -385,7 +400,7 @@ int ImageIO::loadJPEG (Glib::ustring fname) {
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
fclose(file); fclose(file);
if (pl) { if (pl) {
pl->setProgressStr ("Ready."); pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0); pl->setProgress (1.0);
} }
return IMIO_SUCCESS; return IMIO_SUCCESS;
@@ -409,7 +424,7 @@ int ImageIO::loadTIFF (Glib::ustring fname) {
return IMIO_CANNOTREADFILE; return IMIO_CANNOTREADFILE;
if (pl) { if (pl) {
pl->setProgressStr ("Loading TIFF file..."); pl->setProgressStr ("PROGRESSBAR_LOADTIFF");
pl->setProgress (0.0); pl->setProgress (0.0);
} }
@@ -467,7 +482,7 @@ int ImageIO::loadTIFF (Glib::ustring fname) {
delete [] linebuffer; delete [] linebuffer;
if (pl) { if (pl) {
pl->setProgressStr ("Ready."); pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0); 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) { 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 FILE *file = safe_g_fopen_WriteBinLock (fname);
Glib::ustring tmpFname=fname;
tmpFname.append(".tmp");
FILE *file = safe_g_fopen (tmpFname, "wb");
if (!file) if (!file)
return IMIO_CANNOTREADFILE; return IMIO_CANNOTREADFILE;
if (pl) { if (pl) {
pl->setProgressStr ("Saving PNG file..."); pl->setProgressStr ("PROGRESSBAR_SAVEPNG");
pl->setProgress (0.0); pl->setProgress (0.0);
} }
@@ -573,11 +584,8 @@ int ImageIO::savePNG (Glib::ustring fname, int compression, int bps) {
delete [] row; delete [] row;
fclose (file); fclose (file);
// Rename temporary filename, practically atomic
safe_g_rename(tmpFname,fname);
if (pl) { if (pl) {
pl->setProgressStr ("Ready."); pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0); pl->setProgress (1.0);
} }
@@ -593,17 +601,13 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality) {
cinfo.err = jpeg_std_error (&jerr); cinfo.err = jpeg_std_error (&jerr);
jpeg_create_compress (&cinfo); jpeg_create_compress (&cinfo);
// create a temporary file name that is opened in parallel by e.g. image viewers whilte RT is still writing FILE *file = safe_g_fopen_WriteBinLock (fname);
Glib::ustring tmpFname=fname;
tmpFname.append(".tmp");
FILE *file = safe_g_fopen (tmpFname, "wb");
if (!file) if (!file)
return IMIO_CANNOTREADFILE; return IMIO_CANNOTREADFILE;
if (pl) { if (pl) {
pl->setProgressStr ("Saving JPEG file..."); pl->setProgressStr ("PROGRESSBAR_SAVEJPEG");
pl->setProgress (0.0); pl->setProgress (0.0);
} }
@@ -689,11 +693,8 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality) {
fclose (file); fclose (file);
// Rename temporary filename, practically atomic
safe_g_rename(tmpFname,fname);
if (pl) { if (pl) {
pl->setProgressStr ("Ready."); pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0); 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]; 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 ? // TODO the following needs to be looked into - do we really need two ways to write a Tiff file ?
if (exifRoot && uncompressed) { if (exifRoot && uncompressed) {
FILE *file = safe_g_fopen (fname, "wb"); FILE *file = safe_g_fopen_WriteBinLock (fname);
if (!file) if (!file)
return IMIO_CANNOTREADFILE; return IMIO_CANNOTREADFILE;
if (pl) { if (pl) {
pl->setProgressStr ("Saving TIFF file ..."); pl->setProgressStr ("PROGRESSBAR_SAVETIFF");
pl->setProgress (0.0); pl->setProgress (0.0);
} }
@@ -771,7 +772,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) {
return IMIO_CANNOTREADFILE; return IMIO_CANNOTREADFILE;
if (pl) { if (pl) {
pl->setProgressStr ("Saving TIFF file ..."); pl->setProgressStr ("PROGRESSBAR_SAVETIFF");
pl->setProgress (0.0); pl->setProgress (0.0);
} }
@@ -842,7 +843,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) {
delete [] linebuffer; delete [] linebuffer;
if (pl) { if (pl) {
pl->setProgressStr ("Ready."); pl->setProgressStr ("PROGRESSBAR_READY");
pl->setProgress (1.0); pl->setProgress (1.0);
} }
@@ -885,7 +886,8 @@ void png_flush(png_structp png_ptr) {
int ImageIO::load (Glib::ustring fname) { int ImageIO::load (Glib::ustring fname) {
int lastdot = fname.find_last_of ('.'); int lastdot = fname.find_last_of ('.');
if( Glib::ustring::npos == lastdot )
return IMIO_FILETYPENOTSUPPORTED;
if (!fname.casefold().compare (lastdot, 4, ".png")) if (!fname.casefold().compare (lastdot, 4, ".png"))
return loadPNG (fname); return loadPNG (fname);
else if (!fname.casefold().compare (lastdot, 4, ".jpg")) 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 ImageIO::save (Glib::ustring fname) {
int lastdot = fname.find_last_of ('.'); int lastdot = fname.find_last_of ('.');
if( Glib::ustring::npos == lastdot )
return IMIO_FILETYPENOTSUPPORTED;
if (!fname.casefold().compare (lastdot, 4, ".png")) if (!fname.casefold().compare (lastdot, 4, ".png"))
return savePNG (fname); return savePNG (fname);
else if (!fname.casefold().compare (lastdot, 4, ".jpg")) else if (!fname.casefold().compare (lastdot, 4, ".jpg"))

View File

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

View File

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

View File

@@ -105,8 +105,8 @@ namespace rtengine {
* @param str is the textual information corresponding to the progress */ * @param str is the textual information corresponding to the progress */
virtual void setProgressStr (Glib::ustring str) {} virtual void setProgressStr (Glib::ustring str) {}
/** This member function is called when the state of the processing has been changed. /** 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 */ * @param inProcessing =true if the processing has been started, =false if it has been stopped */
virtual void setProgressState (int state) {} virtual void setProgressState (bool inProcessing) {}
/** This member function is called when an error occurs during the operation. /** This member function is called when an error occurs during the operation.
* @param descr is the error message */ * @param descr is the error message */
virtual void error (Glib::ustring descr) {} virtual void error (Glib::ustring descr) {}
@@ -261,10 +261,6 @@ namespace rtengine {
/** Returns the scale of the preview image. /** Returns the scale of the preview image.
* @return the current scale of the preview image */ * @return the current scale of the preview image */
virtual int getPreviewScale () =0; 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). /** Returns the full width of the resulting image (in 1:1 scale).
* @return the width of the final image */ * @return the width of the final image */
virtual int getFullWidth () =0; virtual int getFullWidth () =0;
@@ -354,6 +350,7 @@ namespace rtengine {
* @param job the ProcessingJob to cancel. * @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 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 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. */ * @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); IImage16* processImage (ProcessingJob* job, int& errorCode, ProgressListener* pl = NULL, bool tunnelMetaData=false);

View File

@@ -22,6 +22,12 @@
#include <safegtk.h> #include <safegtk.h>
#include <guiutils.h> #include <guiutils.h>
#include <glib/gstdio.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) 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; Glib::RefPtr<Gio::FileEnumerator> dirList;
if (dir) 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 SAFE_ENUMERATOR_CODE_START
if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || add_hidden)) if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || add_hidden))
subDirs.push_back (info->get_name()); subDirs.push_back (info->get_name());
@@ -162,27 +171,6 @@ std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str)
return 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) bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8)
{ {
std::string cmd; std::string cmd;
@@ -190,8 +178,8 @@ bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8)
#ifdef GLIBMM_EXCEPTIONS_ENABLED #ifdef GLIBMM_EXCEPTIONS_ENABLED
try { try {
cmd = Glib::filename_from_utf8(cmd_utf8); cmd = Glib::filename_from_utf8(cmd_utf8);
printf ("command line: |%s|\n", cmd.c_str()); printf ("command line: %s\n", cmd.c_str());
Glib::spawn_command_line_async (cmd); Glib::spawn_command_line_async (cmd.c_str());
success = true; success = true;
} catch (Glib::Exception& ex) { } catch (Glib::Exception& ex) {
printf ("%s\n", ex.what().c_str()); 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; std::auto_ptr<Glib::Error> error;
cmd = Glib::filename_from_utf8(cmd_utf8, error); cmd = Glib::filename_from_utf8(cmd_utf8, error);
if (!error.get()) { 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); Glib::spawn_command_line_async (cmd, error);
} }
if (error.get()) if (error.get())
@@ -221,38 +209,81 @@ bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8)
int exitStatus=-1; int exitStatus=-1;
try { try {
cmd = Glib::filename_from_utf8(cmd_utf8); //cmd = Glib::filename_from_utf8(cmd_utf8);
printf ("command line: |%s|\n", cmd.c_str()); 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 // 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) { } catch (Glib::Exception& ex) {
printf ("%s\n", ex.what().c_str()); printf ("%s\n", ex.what().c_str());
} }
return (exitStatus==0); 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) 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) 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) 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) 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) 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); 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(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); bool safe_file_test (const Glib::ustring& filename, Glib::FileTest test);
int safe_g_remove(const Glib::ustring& filename); int safe_g_remove(const Glib::ustring& filename);
int safe_g_rename(const Glib::ustring& oldFilename, const Glib::ustring& newFilename); 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) if (tunnelMetaData)
// readyImg->setMetadata (ii->getMetaData()->getExifData ()); readyImg->setMetadata (ii->getMetaData()->getExifData ());
//else else
readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);