From bf5aecab31ff53536c5802f5746c674186f25ec3 Mon Sep 17 00:00:00 2001 From: torger Date: Sat, 21 Mar 2015 21:11:36 +0100 Subject: [PATCH] Added possibility to export profiling reference image without WB to make it possible to generate DNG profiles; also apply transform and scaling on profiling reference image --- rtdata/languages/default | 1 + rtengine/improccoordinator.cc | 58 ++++++++++++++++++++------------ rtengine/improccoordinator.h | 2 +- rtengine/improcfun.h | 1 + rtengine/ipresize.cc | 59 ++++++++++++++++++++++++++++++++ rtengine/rawimagesource.cc | 15 ++++++--- rtengine/rtengine.h | 2 +- rtengine/simpleprocess.cc | 63 ++++------------------------------- rtgui/icmpanel.cc | 10 +++++- rtgui/icmpanel.h | 2 +- rtgui/toolpanelcoord.cc | 4 +-- rtgui/toolpanelcoord.h | 2 +- 12 files changed, 131 insertions(+), 88 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 31bc73b18..aefd1be2c 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1410,6 +1410,7 @@ TP_ICM_NOICM;No ICM: sRGB Output TP_ICM_OUTPUTPROFILE;Output Profile TP_ICM_SAVEREFERENCE;Save Reference Image for Profiling TP_ICM_SAVEREFERENCE_TOOLTIP;Save the linear TIFF image before the input profile is applied. The result can be used for calibration purposes and generation of a camera profile. +TP_ICM_SAVEREFERENCE_APPLYWB;Apply white balance TP_ICM_TONECURVE;Use DCP's tone curve TP_ICM_TONECURVE_TOOLTIP;Employ the embedded DCP tone curve. The setting is only enabled if the selected DCP has a tone curve. TP_ICM_WORKINGPROFILE;Working Profile diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 9c9627aaa..6d14fe2c5 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -956,7 +956,7 @@ void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int & } -void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) { +void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb) { MyMutex::MyLock lock(mProcessing); @@ -969,7 +969,6 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) { Imagefloat* im = new Imagefloat (fW, fH); imgsrc->preprocess( ppar.raw, ppar.lensProf, ppar.coarse ); imgsrc->demosaic(ppar.raw ); - //imgsrc->getImage (imgsrc->getWB(), 0, im, pp, ppar.toneCurve, ppar.icm, ppar.raw); ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method); if (params.wb.method=="Camera") currWB = imgsrc->getWB (); @@ -988,29 +987,46 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) { } currWB = autoWB; } - params.wb.temperature = currWB.getTemp (); - params.wb.green = currWB.getGreen (); + if (!apply_wb) { + currWB = ColorTemp(); // = no white balance + } imgsrc->getImage (currWB, 0, im, pp, ppar.toneCurve, ppar.icm, ppar.raw); - imgsrc->convertColorSpace(im, ppar.icm, currWB, params.raw); - if (params.crop.enabled) { - Imagefloat *tmpim = new Imagefloat (params.crop.w, params.crop.h); - int cx = params.crop.x; - int cy = params.crop.y; - int cw = params.crop.w; - int ch = params.crop.h; + ImProcFunctions ipf (&ppar, true); + if (ipf.needsTransform()) { + Imagefloat* trImg = new Imagefloat (fW, fH); + ipf.transform (im, trImg, 0, 0, 0, 0, fW, fH, fW, fH, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), + imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true); + delete im; + im = trImg; + } + if (params.crop.enabled) { + Imagefloat *tmpim = new Imagefloat (params.crop.w, params.crop.h); + int cx = params.crop.x; + int cy = params.crop.y; + int cw = params.crop.w; + int ch = params.crop.h; #pragma omp parallel for - for (int i=cy; ir(i-cy, j-cx) = im->r(i, j); - tmpim->g(i-cy, j-cx) = im->g(i, j); - tmpim->b(i-cy, j-cx) = im->b(i, j); - } - } - delete im; - im = tmpim; - } + for (int i=cy; ir(i-cy, j-cx) = im->r(i, j); + tmpim->g(i-cy, j-cx) = im->g(i, j); + tmpim->b(i-cy, j-cx) = im->b(i, j); + } + } + delete im; + im = tmpim; + } Image16* im16 = im->to16(); delete im; + + int imw, imh; + double tmpScale = ipf.resizeScale(¶ms, fW, fH, imw, imh); + if (tmpScale != 1.0) { + Image16* tempImage = new Image16 (imw, imh); + ipf.resize (im16, tempImage, tmpScale); + delete im16; + im16 = tempImage; + } im16->saveTIFF (fname,16,true); delete im16; //im->saveJPEG (fname, 85); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index e3ccecb66..d3ed9da0e 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -233,7 +233,7 @@ class ImProcCoordinator : public StagedImageProcessor { void setAutoChromaListener (AutoChromaListener* adn) {adnListener = adn; } void setWaveletListener (WaveletListener* awa) {awavListener = awa; } - void saveInputICCReference (const Glib::ustring& fname); + void saveInputICCReference (const Glib::ustring& fname, bool apply_wb); InitialImage* getInitialImage () { return imgsrc; } }; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index f2fc34bc5..9da2e2876 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -250,6 +250,7 @@ class ImProcFunctions { void sharpeningcam (CieImage* ncie, float** buffer); void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, double focalLen, double focalLen35mm, float focusDist, int rawRotationDeg, bool fullImage); + float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb (LabImage* lab, Image8* image); void resize (Image16* src, Image16* dst, float dScale); // void Lanczoslab (LabImage* src, LabImage* dst, float scale); diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index c5ee0bcb5..b3ad7785f 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -333,6 +333,65 @@ SSEFUNCTION static void Lanczos(const LabImage* src, LabImage* dst, float scale) } } +float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh) { + imw = fw; + imh = fh; + if (!params || !params->resize.enabled) { + return 1.0; + } + + // get the resize parameters + int refw, refh; + double dScale; + if (params->crop.enabled && params->resize.appliesTo == "Cropped area") { + // the resize values applies to the crop dimensions + refw = params->crop.w; + refh = params->crop.h; + } + else { + // the resize values applies to the image dimensions + // if a crop exists, it will be resized to the calculated scale + refw = fw; + refh = fh; + } + + switch(params->resize.dataspec) { + case (1): + // Width + dScale = (double)params->resize.width/(double)refw; + break; + case (2): + // Height + dScale = (double)params->resize.height/(double)refh; + break; + case (3): + // FitBox + if ((double)refw/(double)refh > (double)params->resize.width/(double)params->resize.height) + dScale = (double)params->resize.width/(double)refw; + else + dScale = (double)params->resize.height/(double)refh; + break; + default: + // Scale + dScale = params->resize.scale; + break; + } + + if (fabs(dScale-1.0)<=1e-5) { + return 1.0; + } + if (params->crop.enabled && params->resize.appliesTo == "Full image") { + imw = params->crop.w; + imh = params->crop.h; + } + else { + imw = refw; + imh = refh; + } + imw = (int)( (double)imw * dScale + 0.5 ); + imh = (int)( (double)imh * dScale + 0.5 ); + return (float)dScale; +} void ImProcFunctions::resize (Image16* src, Image16* dst, float dScale) { #ifdef PROFILE diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index b30d769d2..92540708d 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -236,10 +236,17 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre // compute channel multipliers double r, g, b; float rm, gm, bm; - ctemp.getMultipliers (r, g, b); - rm = imatrices.cam_rgb[0][0]*r + imatrices.cam_rgb[0][1]*g + imatrices.cam_rgb[0][2]*b; - gm = imatrices.cam_rgb[1][0]*r + imatrices.cam_rgb[1][1]*g + imatrices.cam_rgb[1][2]*b; - bm = imatrices.cam_rgb[2][0]*r + imatrices.cam_rgb[2][1]*g + imatrices.cam_rgb[2][2]*b; + if (ctemp.getTemp() < 0) { + // no white balance, ie revert the pre-process white balance to restore original unbalanced raw camera color + rm = ri->get_pre_mul(0); + gm = ri->get_pre_mul(1); + bm = ri->get_pre_mul(2); + } else { + ctemp.getMultipliers (r, g, b); + rm = imatrices.cam_rgb[0][0]*r + imatrices.cam_rgb[0][1]*g + imatrices.cam_rgb[0][2]*b; + gm = imatrices.cam_rgb[1][0]*r + imatrices.cam_rgb[1][1]*g + imatrices.cam_rgb[1][2]*b; + bm = imatrices.cam_rgb[2][0]*r + imatrices.cam_rgb[2][1]*g + imatrices.cam_rgb[2][2]*b; + } if (true) { // adjust gain so the maximum raw value of the least scaled channel just hits max diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index dbd54063d..46a8a0d6b 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -368,7 +368,7 @@ namespace rtengine { virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) =0; virtual void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) =0; - virtual void saveInputICCReference (const Glib::ustring& fname) =0; + virtual void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) =0; virtual void setProgressListener (ProgressListener* l) =0; virtual void setSizeListener (SizeListener* l) =0; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index c576e6efe..1c843f8b5 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1045,63 +1045,14 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p } if (pl) pl->setProgress (0.70); - if (params.resize.enabled) { - - // get the resize parameters - int refw, refh; - double tmpScale; - if (params.crop.enabled && params.resize.appliesTo == "Cropped area") { - // the resize values applies to the crop dimensions - refw = cw; - refh = ch; - } - else { - // the resize values applies to the image dimensions - // if a crop exists, it will be resized to the calculated scale - refw = fw; - refh = fh; - } - - switch(params.resize.dataspec) { - case (1): - // Width - tmpScale = (double)params.resize.width/(double)refw; - break; - case (2): - // Height - tmpScale = (double)params.resize.height/(double)refh; - break; - case (3): - // FitBox - if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height) - tmpScale = (double)params.resize.width/(double)refw; - else - tmpScale = (double)params.resize.height/(double)refh; - break; - default: - // Scale - tmpScale = params.resize.scale; - break; - } - + int imw, imh; + double tmpScale = ipf.resizeScale(¶ms, fw, fh, imw, imh); + if (tmpScale != 1.0) { // resize image - if (fabs(tmpScale-1.0)>1e-5) { - int imw, imh; - if (params.crop.enabled && params.resize.appliesTo == "Full image") { - imw = cw; - imh = ch; - } - else { - imw = refw; - imh = refh; - } - imw = (int)( (double)imw * tmpScale + 0.5 ); - imh = (int)( (double)imh * tmpScale + 0.5 ); - Image16* tempImage = new Image16 (imw, imh); - ipf.resize (readyImg, tempImage, tmpScale); - delete readyImg; - readyImg = tempImage; - } + Image16* tempImage = new Image16 (imw, imh); + ipf.resize (readyImg, tempImage, tmpScale); + delete readyImg; + readyImg = tempImage; } diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index b9a7d7e81..5864fa23e 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -693,6 +693,13 @@ void ICMPanel::saveReferencePressed () { dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK); + Gtk::CheckButton applyWB(M("TP_ICM_SAVEREFERENCE_APPLYWB")); + applyWB.set_active(true); + Gtk::HBox* hbox = Gtk::manage( new Gtk::HBox() ); + hbox->pack_end(applyWB, Gtk::PACK_SHRINK, 2); + Gtk::VBox *vbox = dialog.get_vbox(); + vbox->pack_end(*hbox, Gtk::PACK_SHRINK, 2); + Gtk::FileFilter filter_tif; filter_tif.set_name(M("SAVEDLG_TIFFFILTER")); filter_tif.add_pattern("*.tif"); @@ -704,6 +711,7 @@ void ICMPanel::saveReferencePressed () { filter_any.add_pattern("*"); dialog.add_filter(filter_any); + dialog.show_all_children(); //dialog.set_do_overwrite_confirmation (true); bool done = false; @@ -717,7 +725,7 @@ void ICMPanel::saveReferencePressed () { if (ext != "tif" && ext != "tiff") fname += ".tif"; if (confirmOverwrite(dialog, fname)) { - icmplistener->saveInputICCReference (fname); + icmplistener->saveInputICCReference (fname, applyWB.get_active()); lastRefFilename = Glib::path_get_basename (fname); done = true; } diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 045e670cf..99dc96533 100755 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -31,7 +31,7 @@ class ICMPanelListener { public: virtual ~ICMPanelListener() {} - virtual void saveInputICCReference (Glib::ustring fname) {} + virtual void saveInputICCReference (Glib::ustring fname, bool apply_wb) {} }; class ICMPanel : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 8dd861ef8..77e54aa28 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -580,10 +580,10 @@ void ToolPanelCoordinator::cropSelectRequested () { toolBar->setTool (TMCropSelect); } -void ToolPanelCoordinator::saveInputICCReference (Glib::ustring fname) { +void ToolPanelCoordinator::saveInputICCReference (Glib::ustring fname, bool apply_wb) { if (ipc) - ipc->saveInputICCReference (fname); + ipc->saveInputICCReference (fname, apply_wb); } int ToolPanelCoordinator::getSpotWBRectSize () { diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 98301c36f..3453b10a9 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -265,7 +265,7 @@ class ToolPanelCoordinator : public ToolPanelListener, void cropSelectRequested (); // icmpanellistener interface - void saveInputICCReference (Glib::ustring fname); + void saveInputICCReference (Glib::ustring fname, bool apply_wb); // imageareatoollistener interface void spotWBselected (int x, int y, Thumbnail* thm=NULL);