diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais
index 279c5e423..860e99fc7 100644
--- a/rtdata/languages/Francais
+++ b/rtdata/languages/Francais
@@ -597,6 +597,7 @@ MAIN_TAB_EXPORT;Export Rapide
MAIN_TAB_EXPOSURE;Exposition
MAIN_TAB_EXPOSURE_TOOLTIP;Raccourci:Alt-e
MAIN_TAB_FILTER; Filtrer
+MAIN_TAB_INSPECT; Inspecter
MAIN_TAB_IPTC;IPTC
MAIN_TAB_METADATA;Métadonnées
MAIN_TAB_METADATA_TOOLTIP;Raccourci:Alt-m
@@ -796,6 +797,9 @@ PREFERENCES_INTENT_RELATIVE;Colorimétrie relative
PREFERENCES_INTENT_SATURATION;Saturation
PREFERENCES_INTERNALTHUMBIFUNTOUCHED;Afficher vignette incluse dans fichier RAW si non édité
PREFERENCES_LANGAUTODETECT;Utiliser les paramètres linguistiques de l'OS
+PREFERENCES_INSPECT_LABEL;Inspecter
+PREFERENCES_INSPECT_MAXBUFFERS_LABEL;Nombre maxi de mémoire tampon
+PREFERENCES_INSPECT_MAXBUFFERS_TOOLTIP;Règle le nombre maximum d'images mis en cache lors de leur survol dans le Navigateur de Fichier ; les systèmes avec peu de mémoire RAM (2 Go) devraient garder cette valeur à 1 ou 2.
PREFERENCES_MENUGROUPEXTPROGS;Groupe "Ouvrir avec"
PREFERENCES_MENUGROUPFILEOPERATIONS;Opérations sur les fichiers
PREFERENCES_MENUGROUPLABEL;Label
diff --git a/rtdata/languages/default b/rtdata/languages/default
index 7dd6b7b4b..144f44144 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -607,6 +607,7 @@ MAIN_TAB_EXPORT; Fast Export
MAIN_TAB_EXPOSURE;Exposure
MAIN_TAB_EXPOSURE_TOOLTIP;Shortcut: Alt-e
MAIN_TAB_FILTER; Filter
+MAIN_TAB_INSPECT; Inspect
MAIN_TAB_IPTC;IPTC
MAIN_TAB_METADATA;Metadata
MAIN_TAB_METADATA_TOOLTIP;Shortcut: Alt-m
@@ -816,6 +817,9 @@ PREFERENCES_LEVAUTDN;Denoising level
PREFERENCES_LEVDN;Cell size
PREFERENCES_LISS;Auto multi-zone smoothing
PREFERENCES_MAX;Maxi (Tile)
+PREFERENCES_INSPECT_LABEL;Inspect
+PREFERENCES_INSPECT_MAXBUFFERS_LABEL;Maximum number of buffer
+PREFERENCES_INSPECT_MAXBUFFERS_TOOLTIP;Set the maximum number of images set in cache when hovering them in the File Browser ; systems with few RAM memory (2 Gb) should keep this value set to 1 ot 2.
PREFERENCES_MED;Medium (Tile/2)
PREFERENCES_MENUGROUPEXTPROGS;Group "Open with"
PREFERENCES_MENUGROUPFILEOPERATIONS;Group "File operations"
diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index b2699a9ef..72a238273 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -16,7 +16,7 @@ set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagona
iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc ipvibrance.cc
imagedimensions.cc jpeg_memsrc.cc jdatasrc.cc iimage.cc
EdgePreservingDecomposition.cc cplx_wavelet_dec.cc FTblockDN.cc
- PF_correct_RT.cc
+ PF_correct_RT.cc previewimage.cc
dirpyr_equalizer.cc
calc_distort.cc lcp.cc dcp.cc
cJSON.c camconst.cc
diff --git a/rtengine/color.cc b/rtengine/color.cc
index 3203642e2..c0e6bdb0f 100644
--- a/rtengine/color.cc
+++ b/rtengine/color.cc
@@ -126,7 +126,7 @@ namespace rtengine {
int maxindex = 65536;
cachef(maxindex,LUT_CLIP_BELOW);
- gamma2curve(maxindex,0);
+ gamma2curve(maxindex,LUT_CLIP_BELOW|LUT_CLIP_ABOVE);
for (int i=0; ieps_max) {
diff --git a/rtengine/iimage.h b/rtengine/iimage.h
index c460b00ee..562aead75 100644
--- a/rtengine/iimage.h
+++ b/rtengine/iimage.h
@@ -93,23 +93,23 @@ namespace rtengine {
};
template <>
- inline void ImageDatas::convertTo (unsigned short srcValue, unsigned char &dstValue) {
+ inline void ImageDatas::convertTo (const unsigned short srcValue, unsigned char &dstValue) {
dstValue = (unsigned char)(srcValue >> 8);
}
template <>
- inline void ImageDatas::convertTo (unsigned char srcValue, int &dstValue) {
+ inline void ImageDatas::convertTo (const unsigned char srcValue, int &dstValue) {
dstValue = (int)(srcValue) << 8;
}
template <>
- inline void ImageDatas::convertTo (unsigned char srcValue, unsigned short &dstValue) {
+ inline void ImageDatas::convertTo (const unsigned char srcValue, unsigned short &dstValue) {
dstValue = (unsigned short)(srcValue) << 8;
}
template <>
- inline void ImageDatas::convertTo (float srcValue, unsigned char &dstValue) {
+ inline void ImageDatas::convertTo (const float srcValue, unsigned char &dstValue) {
dstValue = (unsigned char)( (unsigned short)(srcValue) >> 8 );
}
template <>
- inline void ImageDatas::convertTo (unsigned char srcValue, float &dstValue) {
+ inline void ImageDatas::convertTo (const unsigned char srcValue, float &dstValue) {
dstValue = float( (unsigned short)(srcValue) << 8 );
}
@@ -350,7 +350,15 @@ namespace rtengine {
template
void resizeImgTo (int nw, int nh, TypeInterpolation interp, PlanarWhateverData *imgPtr) {
//printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height);
- if (interp == TI_Nearest) {
+ if (width==nw && height==nh) {
+ // special case where no resizing is necessary, just type conversion....
+ for (int i=0; iv(i,j));
+ }
+ }
+ }
+ else if (interp == TI_Nearest) {
for (int i=0; i
void resizeImgTo (int nw, int nh, TypeInterpolation interp, IC *imgPtr) {
//printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height);
- if (interp == TI_Nearest) {
+ if (width==nw && height==nh) {
+ // special case where no resizing is necessary, just type conversion....
+ for (int i=0; ir(i,j));
+ convertTo(g(i,j), imgPtr->g(i,j));
+ convertTo(b(i,j), imgPtr->b(i,j));
+ }
+ }
+ }
+ else if (interp == TI_Nearest) {
for (int i=0; i
void resizeImgTo (int nw, int nh, TypeInterpolation interp, IC *imgPtr) {
//printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height);
- if (interp == TI_Nearest) {
+ if (width==nw && height==nh) {
+ // special case where no resizing is necessary, just type conversion....
+ for (int i=0; ir(i,j));
+ convertTo(g(i,j), imgPtr->g(i,j));
+ convertTo(b(i,j), imgPtr->b(i,j));
+ }
+ }
+ }
+ else if (interp == TI_Nearest) {
for (int i=0; i
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+
+#include "previewimage.h"
+#include "iimage.h"
+#include "utils.h"
+#include "iimage.h"
+#include "rtthumbnail.h"
+#include "rawimagesource.h"
+#include "StopWatch.h"
+
+using namespace rtengine;
+using namespace procparams;
+
+PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext, const PreviewImageMode mode) {
+ rtengine::Thumbnail* tpp=NULL;
+
+ if (mode==PIM_EmbeddedPreviewOnly || mode==PIM_EmbeddedOrRaw) {
+
+ const unsigned char *data = NULL;
+
+ int width=-1, height=-1;
+ if (ext.lowercase()=="jpg" || ext.lowercase()=="jpeg") {
+ // int deg = infoFromImage (fname);
+ tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true);
+ if (tpp)
+ data = tpp->getImage8Data();
+ }
+ else if (ext.lowercase()=="png") {
+ tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true);
+ if (tpp)
+ data = tpp->getImage8Data();
+ }
+ else if (ext.lowercase()=="tif" || ext.lowercase()=="tiff") {
+ // int deg = infoFromImage (fname);
+ tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true);
+ if (tpp)
+ data = tpp->getImage8Data();
+ }
+ else {
+ rtengine::RawMetaDataLocation ri;
+ tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, width, height, 1, true, true);
+ if (tpp)
+ data = tpp->getImage8Data();
+ }
+
+ if (tpp) {
+ if (data) {
+ int w, h;
+ double scale = 1.;
+ if (tpp)
+ tpp->getDimensions(w, h, scale);
+ previewImage = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h);
+ previewImage->flush();
+
+#pragma omp parallel
+{
+ const unsigned char *src;
+ unsigned char *dst;
+#pragma omp for schedule(static,10)
+ for (unsigned int i=0; i<(unsigned int)(h); i++) {
+ src = data + i*w*3;
+ dst = previewImage->get_data() + i*w*4;
+ for (unsigned int j=0; j<(unsigned int)(w); j++) {
+ unsigned char r = *(src++);
+ unsigned char g = *(src++);
+ unsigned char b = *(src++);
+
+#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
+ *(dst++) = b;
+ *(dst++) = g;
+ *(dst++) = r;
+ *(dst++) = 0;
+#else
+ *(dst++) = 0;
+ *(dst++) = r;
+ *(dst++) = g;
+ *(dst++) = b;
+#endif
+ }
+ }
+}
+ previewImage->mark_dirty();
+ }
+ }
+ }
+
+ if ((mode==PIM_EmbeddedOrRaw && !tpp) || mode==PIM_ForceRaw) {
+ RawImageSource rawImage;
+ int error = rawImage.load(fname, true);
+ if (!error) {
+ rtengine::Image8 *output = NULL;
+ const unsigned char *data = NULL;
+ int fw, fh;
+ procparams::ProcParams params;
+ /*rtengine::RAWParams raw;
+ rtengine::LensProfParams lensProf;
+ rtengine::procparams::ToneCurveParams toneCurve;
+ rtengine::procparams::ColorManagementParams icm;
+ rtengine::CoarseTransformParams coarse;*/
+ ColorTemp wb = rawImage.getWB ();
+ rawImage.getFullSize (fw, fh, TR_NONE);
+ PreviewProps pp (0, 0, fw, fh, 1);
+ params.icm.input = Glib::ustring("(embedded)");
+ params.raw.bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast];
+ params.raw.deadPixelFilter = false;
+ params.raw.ca_autocorrect = false;
+ params.raw.xtranssensor.method = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::fast];
+ rawImage.preprocess(params.raw, params.lensProf, params.coarse);
+ rawImage.demosaic(params.raw);
+ Imagefloat* image = new rtengine::Imagefloat (fw, fh);
+ rawImage.getImage (wb, TR_NONE, image, pp, params.toneCurve, params.icm, params.raw);
+ output = new Image8(fw, fh);
+ rawImage.convertColorSpace(image, params.icm, wb, params.raw);
+ StopWatch Stop1("inspector loop");
+#pragma omp parallel for schedule(dynamic, 10)
+ for (int i=0; ir(i,j) = Color::gamma2curve[image->r(i,j)];
+ image->g(i,j) = Color::gamma2curve[image->g(i,j)];
+ image->b(i,j) = Color::gamma2curve[image->b(i,j)];
+ }
+ Stop1.stop();
+
+ image->resizeImgTo(fw, fh, TI_Nearest, output);
+ data = output->getData();
+
+
+ if (data) {
+ int w, h;
+ double scale = 1.;
+ w = output->getWidth();
+ h = output->getHeight();
+ previewImage = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h);
+ previewImage->flush();
+
+#pragma omp parallel
+{
+ const unsigned char *src;
+ unsigned char *dst;
+#pragma omp for schedule(static,10)
+ for (unsigned int i=0; i<(unsigned int)(h); i++) {
+ src = data + i*w*3;
+ dst = previewImage->get_data() + i*w*4;
+ for (unsigned int j=0; j<(unsigned int)(w); j++) {
+ unsigned char r = *(src++);
+ unsigned char g = *(src++);
+ unsigned char b = *(src++);
+#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
+ *(dst++) = b;
+ *(dst++) = g;
+ *(dst++) = r;
+ *(dst++) = 0;
+#else
+ *(dst++) = 0;
+ *(dst++) = r;
+ *(dst++) = g;
+ *(dst++) = b;
+#endif
+ }
+ }
+}
+ if (output)
+ delete output;
+ previewImage->mark_dirty();
+ }
+ }
+ }
+
+ if (tpp)
+ delete tpp;
+
+}
+
+Cairo::RefPtr PreviewImage::getImage() {
+ return previewImage;
+}
diff --git a/rtengine/previewimage.h b/rtengine/previewimage.h
new file mode 100644
index 000000000..6f78dc960
--- /dev/null
+++ b/rtengine/previewimage.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#ifndef _PREVIEWIMAGE_
+#define _PREVIEWIMAGE_
+
+#include
+#include "cairomm/cairomm.h"
+
+namespace rtengine {
+
+/** @brief Get a quick preview image out of a raw or standard file
+ *
+ * This class reads the full size preview image (at least the biggest one available) from the raw file,
+ * or the fast demosaiced version if no suitable embedded preview is found.
+ *
+ * For standard image, it simply read it with fast conversion for 32 bits images
+ */
+class PreviewImage {
+
+private:
+ Cairo::RefPtr previewImage;
+
+public:
+ typedef enum mode {
+ PIM_EmbeddedPreviewOnly, /// Get the embedded image only, fail if doesn't exist
+ PIM_EmbeddedOrRaw, /// Get the embedded image if it exist, or use the raw file otherwise
+ PIM_ForceRaw /// Get a preview of the raw file, even if an embedded image exist
+ } PreviewImageMode;
+
+ PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext, const PreviewImageMode mode);
+
+ Cairo::RefPtr getImage();
+
+};
+
+}
+
+#endif
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 145ea04b3..e47c4c8e2 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -112,7 +112,7 @@ void CropParams::mapToResized(int resizedWidth, int resizedHeight, int scale, in
}
ColorToningParams::ColorToningParams () : hlColSat(60, 80, false), shadowsColSat(80, 208, false) {
- setDefault();
+ setDefaults();
}
void ColorToningParams::getDefaultColorCurve(std::vector &curve) {
@@ -158,7 +158,7 @@ void ColorToningParams::getDefaultCL2Curve(std::vector &curve) {
curve.at(i) = v[i-1];
}
-void ColorToningParams::setDefault() {
+void ColorToningParams::setDefaults() {
enabled = false;
autosat=true;
method = "Lab";
@@ -416,7 +416,7 @@ void ColorToningParams::getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurv
DirPyrDenoiseParams::DirPyrDenoiseParams () {
- setDefault ();
+ setDefaults ();
}
void DirPyrDenoiseParams::getDefaultNoisCurve(std::vector &curve) {
@@ -433,7 +433,7 @@ void DirPyrDenoiseParams::getDefaultCCCurve(std::vector &curve) {
// 0.60, 0.05,0.35,0.35};
double v[8]= { 0.05, 0.50,0.35,0.35,
0.35, 0.05,0.35,0.35};
-
+
curve.resize(9);
curve.at(0 ) = double(FCT_MinMaxCPoints);
for (size_t i=1; i &curve) {
}
-void DirPyrDenoiseParams::setDefault() {
+void DirPyrDenoiseParams::setDefaults() {
- getDefaultNoisCurve(lcurve);
- getDefaultCCCurve(cccurve);
-
- enabled = false;
- enhance = false;
- median = false;
- autochroma = false;
- luma = 0;
- passes = 1;
- dmethod = "Lab";
- Lmethod = "CUR";
- Cmethod = "MAN";
- C2method = "AUTO";
- smethod = "shal";
- medmethod = "soft";
- methodmed = "none";
- rgbmethod = "soft";
- Ldetail = 50;
- chroma = 15;
- redchro = 0;
- bluechro = 0;
- gamma = 1.7;
+ getDefaultNoisCurve(lcurve);
+ getDefaultCCCurve(cccurve);
+
+ enabled = false;
+ enhance = false;
+ median = false;
+ autochroma = false;
+ luma = 0;
+ passes = 1;
+ dmethod = "Lab";
+ Lmethod = "CUR";
+ Cmethod = "MAN";
+ C2method = "AUTO";
+ smethod = "shal";
+ medmethod = "soft";
+ methodmed = "none";
+ rgbmethod = "soft";
+ Ldetail = 50;
+ chroma = 15;
+ redchro = 0;
+ bluechro = 0;
+ gamma = 1.7;
}
void DirPyrDenoiseParams::getCurves(NoiseCurve &lCurve, NoiseCurve &cCurve) const {
- lCurve.Set(this->lcurve);
- cCurve.Set(this->cccurve);
+ lCurve.Set(this->lcurve);
+ cCurve.Set(this->cccurve);
}
+void ToneCurveParams::setDefaults() {
+ autoexp = false;
+ clip = 0.02;
+ expcomp = 0;
+ brightness = 0;
+ contrast = 0;
+ saturation = 0;
+ black = 0;
+ hlcompr = 0;
+ hlcomprthresh = 33;
+ shcompr = 50;
+ curve.clear ();
+ curve.push_back(DCT_Linear);
+ curve2.clear ();
+ curve2.push_back(DCT_Linear);
+ curveMode = ToneCurveParams::TC_MODE_STD;
+ curveMode2 = ToneCurveParams::TC_MODE_STD;
+ hrenabled = false;
+ method = "Blend";
+}
+void LensProfParams::setDefaults() {
+ lcpFile="";
+ useDist=useVign=true;
+ useCA=false;
+}
+
+void CoarseTransformParams::setDefaults() {
+ rotate = 0;
+ hflip = false;
+ vflip = false;
+}
+
+void RAWParams::setDefaults() {
+ bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze];
+ bayersensor.ccSteps = 0;
+ bayersensor.dcb_iterations = 2;
+ bayersensor.dcb_enhance = false;
+ //bayersensor.all_enhance = false;
+ bayersensor.lmmse_iterations = 2;
+ bayersensor.black0 = 0.0;
+ bayersensor.black1 = 0.0;
+ bayersensor.black2 = 0.0;
+ bayersensor.black3 = 0.0;
+ bayersensor.twogreen = true;
+ bayersensor.linenoise = 0;
+ bayersensor.greenthresh = 0;
+
+ xtranssensor.method = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::threePass];
+ xtranssensor.ccSteps = 0;
+ xtranssensor.blackred = 0.0;
+ xtranssensor.blackgreen = 0.0;
+ xtranssensor.blackblue = 0.0;
+
+ expos=1.0;
+ preser=0.0;
+ df_autoselect = false;
+ ff_AutoSelect = false;
+ ff_BlurRadius = 32;
+ ff_BlurType = RAWParams::ff_BlurTypestring[RAWParams::area_ff];
+ ff_AutoClipControl = false;
+ ff_clipControl = 0;
+ cared = 0;
+ cablue = 0;
+ ca_autocorrect = false;
+ hotPixelFilter = false;
+ deadPixelFilter = false;
+ hotdeadpix_thresh = 40;
+}
+
+void ColorManagementParams::setDefaults() {
+ input = "(cameraICC)";
+ blendCMSMatrix = false;
+ toneCurve = false;
+ dcpIlluminant = 0;
+ working = "ProPhoto";
+ output = "RT_sRGB";
+ gamma = "default";
+ gampos =2.22;
+ slpos=4.5;
+ freegamma = false;
+}
ProcParams::ProcParams () {
@@ -501,30 +582,13 @@ void ProcParams::destroy (ProcParams* pp) {
void ProcParams::setDefaults () {
- toneCurve.autoexp = false;
- toneCurve.clip = 0.02;
- toneCurve.expcomp = 0;
- toneCurve.brightness = 0;
- toneCurve.contrast = 0;
- toneCurve.saturation = 0;
- toneCurve.black = 0;
- toneCurve.hlcompr = 0;
- toneCurve.hlcomprthresh = 33;
- toneCurve.shcompr = 50;
- toneCurve.curve.clear ();
- toneCurve.curve.push_back(DCT_Linear);
- toneCurve.curve2.clear ();
- toneCurve.curve2.push_back(DCT_Linear);
- toneCurve.curveMode = ToneCurveParams::TC_MODE_STD;
- toneCurve.curveMode2 = ToneCurveParams::TC_MODE_STD;
- toneCurve.hrenabled = false;
- toneCurve.method = "Blend";
+ toneCurve.setDefaults();
+
labCurve.brightness = 0;
labCurve.contrast = 0;
labCurve.chromaticity = 0;
labCurve.avoidcolorshift = false;
labCurve.lcredsk = true;
-
labCurve.rstprotection = 0;
labCurve.lcurve.clear ();
labCurve.lcurve.push_back(DCT_Linear);
@@ -554,7 +618,7 @@ void ProcParams::setDefaults () {
rgbCurves.bcurve.clear ();
rgbCurves.bcurve.push_back(DCT_Linear);
- colorToning.setDefault();
+ colorToning.setDefaults();
sharpenEdge.enabled = false;
sharpenEdge.passes = 2;
@@ -662,26 +726,9 @@ void ProcParams::setDefaults () {
defringe.huecurve.at(22) = 0.;
defringe.huecurve.at(23) = 0.35;
defringe.huecurve.at(24) = 0.35;
-/*
- dirpyrDenoise.enabled = false;
- dirpyrDenoise.enhance = false;
- // dirpyrDenoise.perform = false;
- dirpyrDenoise.median = true;
- dirpyrDenoise.luma = 0;
- dirpyrDenoise.lcurve.clear ();
- dirpyrDenoise.lcurve.push_back(DCT_Linear);
- dirpyrDenoise.Ldetail = 50;
- dirpyrDenoise.chroma = 15;
- dirpyrDenoise.redchro = 0;
- dirpyrDenoise.bluechro = 0;
- dirpyrDenoise.gamma = 1.7;
- dirpyrDenoise.passes = 1;
- dirpyrDenoise.dmethod = "RGB";
- dirpyrDenoise.smethod = "shal";
- dirpyrDenoise.medmethod = "soft";
- dirpyrDenoise.methodmed = "none";
- dirpyrDenoise.rgbmethod = "soft";
-*/
+
+ dirpyrDenoise.setDefaults();
+
epd.enabled = false;
epd.strength = 0.25;
epd.edgeStopping = 1.4;
@@ -707,9 +754,7 @@ void ProcParams::setDefaults () {
crop.orientation= "Landscape";
crop.guide = "Rule of thirds";
- coarse.rotate = 0;
- coarse.hflip = false;
- coarse.vflip = false;
+ coarse.setDefaults();
commonTrans.autofill = true;
@@ -742,9 +787,7 @@ void ProcParams::setDefaults () {
vignetting.centerX = 0;
vignetting.centerY = 0;
- lensProf.lcpFile="";
- lensProf.useDist=lensProf.useVign=true;
- lensProf.useCA=false;
+ lensProf.setDefaults();
chmixer.red[0] = 100;
chmixer.red[1] = 0;
@@ -791,16 +834,7 @@ void ProcParams::setDefaults () {
resize.width = 900;
resize.height = 900;
- icm.input = "(cameraICC)";
- icm.blendCMSMatrix = false;
- icm.toneCurve = false;
- icm.dcpIlluminant = 0;
- icm.working = "ProPhoto";
- icm.output = "RT_sRGB";
- icm.gamma = "default";
- icm.gampos =2.22;
- icm.slpos=4.5;
- icm.freegamma = false;
+ icm.setDefaults();
dirpyrequalizer.enabled = false;
dirpyrequalizer.gamutlab = false;
@@ -822,40 +856,8 @@ void ProcParams::setDefaults () {
filmSimulation.setDefaults();
- raw.bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze];
- raw.bayersensor.ccSteps = 0;
- raw.bayersensor.dcb_iterations = 2;
- raw.bayersensor.dcb_enhance = false;
- //raw.bayersensor.all_enhance = false;
- raw.bayersensor.lmmse_iterations = 2;
- raw.bayersensor.black0 = 0.0;
- raw.bayersensor.black1 = 0.0;
- raw.bayersensor.black2 = 0.0;
- raw.bayersensor.black3 = 0.0;
- raw.bayersensor.twogreen = true;
- raw.bayersensor.linenoise = 0;
- raw.bayersensor.greenthresh = 0;
+ raw.setDefaults();
- raw.xtranssensor.method = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::threePass];
- raw.xtranssensor.ccSteps = 0;
- raw.xtranssensor.blackred = 0.0;
- raw.xtranssensor.blackgreen = 0.0;
- raw.xtranssensor.blackblue = 0.0;
-
- raw.expos=1.0;
- raw.preser=0.0;
- raw.df_autoselect = false;
- raw.ff_AutoSelect = false;
- raw.ff_BlurRadius = 32;
- raw.ff_BlurType = RAWParams::ff_BlurTypestring[RAWParams::area_ff];
- raw.ff_AutoClipControl = false;
- raw.ff_clipControl = 0;
- raw.cared = 0;
- raw.cablue = 0;
- raw.ca_autocorrect = false;
- raw.hotPixelFilter = false;
- raw.deadPixelFilter = false;
- raw.hotdeadpix_thresh = 40;
exif.clear ();
iptc.clear ();
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 2105d8a23..95751ffc4 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -211,6 +211,10 @@ class ToneCurveParams {
int hlcompr; // Highlight Recovery's compression
int hlcomprthresh; // Highlight Recovery's threshold
+ ToneCurveParams () {
+ setDefaults();
+ }
+ void setDefaults();
static bool HLReconstructionNecessary(LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw);
};
@@ -301,7 +305,7 @@ class ColorToningParams {
bool lumamode;
ColorToningParams ();
- void setDefault(); // SHOULD BE GENERALIZED TO ALL CLASSES!
+ void setDefaults(); // SHOULD BE GENERALIZED TO ALL CLASSES!
/// @brief Transform the mixer values to their curve equivalences
void mixerToCurve(std::vector &colorCurve, std::vector &opacityCurve) const;
/// @brief Specifically transform the sliders values to their curve equivalences
@@ -568,7 +572,7 @@ class DirPyrDenoiseParams {
int passes;
DirPyrDenoiseParams ();
- void setDefault(); // SHOULD BE GENERALIZED TO ALL CLASSES!
+ void setDefaults(); // SHOULD BE GENERALIZED TO ALL CLASSES!
void getCurves(NoiseCurve &lCurve, NoiseCurve &cCurve) const;
static void getDefaultNoisCurve(std::vector &curve);
@@ -631,6 +635,11 @@ class CoarseTransformParams {
int rotate;
bool hflip;
bool vflip;
+
+ CoarseTransformParams() {
+ setDefaults();
+ }
+ void setDefaults();
};
/**
@@ -666,6 +675,11 @@ class LensProfParams {
public:
Glib::ustring lcpFile;
bool useDist, useVign, useCA;
+
+ LensProfParams() {
+ setDefaults();
+ }
+ void setDefaults();
};
/**
@@ -818,6 +832,11 @@ class ColorManagementParams {
double gampos;
double slpos;
bool freegamma;
+
+ ColorManagementParams() {
+ setDefaults();
+ }
+ void setDefaults();
};
/**
@@ -956,6 +975,11 @@ class RAWParams {
bool hotPixelFilter;
bool deadPixelFilter;
int hotdeadpix_thresh;
+
+ RAWParams() {
+ setDefaults();
+ }
+ void setDefaults();
};
/**
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 2c5fd2c85..8f178ee73 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -46,7 +46,7 @@ extern Options options;
namespace rtengine {
using namespace procparams;
-Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq) {
+Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode) {
StdImageSource imgSrc;
if (imgSrc.load(fname)) {
@@ -73,60 +73,88 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
tpp->colorMatrix[1][1] = 1.0;
tpp->colorMatrix[2][2] = 1.0;
- if (fixwh==1) {
- w = h * img->width / img->height;
- tpp->scale = (double)img->height / h;
+ if (inspectorMode) {
+ // Special case, meaning that we want a full sized thumbnail image (e.g. for the Inspector feature)
+ w = img->width;
+ h = img->height;
+ tpp->scale = 1.;
}
else {
- h = w * img->height / img->width;
- tpp->scale = (double)img->width / w;
+ if (fixwh==1) {
+ w = h * img->width / img->height;
+ tpp->scale = (double)img->height / h;
+ }
+ else {
+ h = w * img->height / img->width;
+ tpp->scale = (double)img->width / w;
+ }
}
-
// bilinear interpolation
- if (tpp->thumbImg) delete tpp->thumbImg; tpp->thumbImg = NULL;
- tpp->thumbImg = resizeToSameType(w, h, TI_Bilinear, img);
-
- // histogram computation
- tpp->aeHistCompression = 3;
- tpp->aeHistogram(65536>>tpp->aeHistCompression);
-
- double avg_r = 0;
- double avg_g = 0;
- double avg_b = 0;
- int n = 0;
-
- if (img->getType() == rtengine::sImage8) {
- Image8 *image = static_cast(img);
- image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression);
+ if (tpp->thumbImg) {
+ delete tpp->thumbImg;
+ tpp->thumbImg = NULL;
}
- else if (img->getType() == sImage16) {
- Image16 *image = static_cast(img);
- image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression);
- }
- else if (img->getType() == sImagefloat) {
- Imagefloat *image = static_cast(img);
- image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression);
+ if (inspectorMode) {
+ // we want an Image8
+ if (img->getType() == rtengine::sImage8) {
+ // copy the image
+ Image8 *srcImg = static_cast(img);
+ Image8 *thImg = new Image8 (w, h);
+ srcImg->copyData(thImg);
+ tpp->thumbImg = thImg;
+ }
+ else {
+ // copy the image with a conversion
+ tpp->thumbImg = resizeTo(w, h, TI_Bilinear, img);
+ }
}
else {
- printf("loadFromImage: Unsupported image type \"%s\"!\n", img->getType());
+ // we want the same image type than the source file
+ tpp->thumbImg = resizeToSameType(w, h, TI_Bilinear, img);
+
+ // histogram computation
+ tpp->aeHistCompression = 3;
+ tpp->aeHistogram(65536>>tpp->aeHistCompression);
+
+ double avg_r = 0;
+ double avg_g = 0;
+ double avg_b = 0;
+ int n = 0;
+
+ if (img->getType() == rtengine::sImage8) {
+ Image8 *image = static_cast(img);
+ image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression);
+ }
+ else if (img->getType() == sImage16) {
+ Image16 *image = static_cast(img);
+ image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression);
+ }
+ else if (img->getType() == sImagefloat) {
+ Imagefloat *image = static_cast(img);
+ image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression);
+ }
+ else {
+ printf("loadFromImage: Unsupported image type \"%s\"!\n", img->getType());
+ }
+
+ if (n>0) {
+ ColorTemp cTemp;
+
+ tpp->redAWBMul = avg_r/double(n);
+ tpp->greenAWBMul = avg_g/double(n);
+ tpp->blueAWBMul = avg_b/double(n);
+ tpp->wbEqual = wbEq;
+
+ cTemp.mul2temp (tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen);
+ }
+
+ tpp->init ();
}
- if (n>0) {
- ColorTemp cTemp;
-
- tpp->redAWBMul = avg_r/double(n);
- tpp->greenAWBMul = avg_g/double(n);
- tpp->blueAWBMul = avg_b/double(n);
- tpp->wbEqual = wbEq;
-
- cTemp.mul2temp (tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen);
- }
-
- tpp->init ();
return tpp;
}
-Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate)
+Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode)
{
RawImage *ri= new RawImage(fname);
int r = ri->loadRaw(false,false);
@@ -188,18 +216,34 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
tpp->colorMatrix[1][1] = 1.0;
tpp->colorMatrix[2][2] = 1.0;
- if (fixwh==1) {
- w = h * img->width / img->height;
- tpp->scale = (double)img->height / h;
+ if (inspectorMode) {
+ // Special case, meaning that we want a full sized thumbnail image (e.g. for the Inspector feature)
+ w = img->width;
+ h = img->height;
+ tpp->scale = 1.;
}
else {
- h = w * img->height / img->width;
- tpp->scale = (double)img->width / w;
+ if (fixwh==1) {
+ w = h * img->width / img->height;
+ tpp->scale = (double)img->height / h;
+ }
+ else {
+ h = w * img->height / img->width;
+ tpp->scale = (double)img->width / w;
+ }
}
- if (tpp->thumbImg) delete tpp->thumbImg; tpp->thumbImg = NULL;
- tpp->thumbImg = resizeTo(w, h, TI_Nearest, img);
- delete img;
+ if (tpp->thumbImg) {
+ delete tpp->thumbImg;
+ tpp->thumbImg = NULL;
+ }
+ if (inspectorMode) {
+ tpp->thumbImg = img;
+ }
+ else {
+ tpp->thumbImg = resizeTo(w, h, TI_Nearest, img);
+ delete img;
+ }
if (rotate && ri->get_rotateDegree() > 0) {
std::string fname = ri->get_filename();
@@ -214,7 +258,9 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
}
}
- tpp->init ();
+ if (!inspectorMode)
+ tpp->init ();
+
delete ri;
return tpp;
@@ -1614,4 +1660,14 @@ bool Thumbnail::writeAEHistogram (const Glib::ustring& fname) {
return false;
}
+unsigned char* Thumbnail::getImage8Data() {
+ if (thumbImg && thumbImg->getType()==rtengine::sImage8) {
+ Image8* img8 = static_cast(thumbImg);
+ return img8->data;
+ }
+ return NULL;
+}
+
+
+
}
diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h
index 669b33083..393241eb7 100644
--- a/rtengine/rtthumbnail.h
+++ b/rtengine/rtthumbnail.h
@@ -80,9 +80,9 @@ namespace rtengine {
int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio);
void getDimensions (int& w, int& h, double& scaleFac);
- static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate);
+ static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode=false);
static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate);
- static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq);
+ static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode=false);
static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname);
void getCamWB (double& temp, double& green);
@@ -104,6 +104,7 @@ namespace rtengine {
bool readAEHistogram (const Glib::ustring& fname);
bool writeAEHistogram (const Glib::ustring& fname);
+ unsigned char* getImage8Data(); // accessor to the 8bit image if it is one, which should be the case for the "Inspector" mode.
// Hombre: ... let's hope that proper template can make this cleaner
diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt
index fa13d78ef..e394c6626 100644
--- a/rtgui/CMakeLists.txt
+++ b/rtgui/CMakeLists.txt
@@ -14,7 +14,7 @@ set (BASESOURCEFILES
crophandler.cc dirbrowser.cc
curveeditor.cc curveeditorgroup.cc diagonalcurveeditorsubgroup.cc flatcurveeditorsubgroup.cc
filecatalog.cc extprog.cc
- previewloader.cc rtimage.cc
+ previewloader.cc rtimage.cc inspector.cc
histogrampanel.cc history.cc imagearea.cc
imageareapanel.cc iptcpanel.cc labcurve.cc main.cc
multilangmgr.cc mycurve.cc myflatcurve.cc mydiagonalcurve.cc options.cc
diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc
index 77bd3f690..983474ae5 100644
--- a/rtgui/batchqueuepanel.cc
+++ b/rtgui/batchqueuepanel.cc
@@ -179,12 +179,15 @@ BatchQueuePanel::BatchQueuePanel () {
}
}
-
-void BatchQueuePanel::updateTab (int qsize)
+// it is expected to have a non null forceOrientation value on Preferences update only. In this case, qsize is ingored and computed automatically
+void BatchQueuePanel::updateTab (int qsize, int forceOrientation)
{
Gtk::Notebook *nb =(Gtk::Notebook *)(this->get_parent());
- if (options.mainNBVertical) {
+ if (forceOrientation > 0)
+ qsize = batchQueue->getEntries().size();
+
+ if ((forceOrientation==0 && options.mainNBVertical) || (forceOrientation==2)) {
Gtk::VBox* vbb = Gtk::manage (new Gtk::VBox ());
Gtk::Label* l;
diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h
index 1adb3c3be..033960894 100644
--- a/rtgui/batchqueuepanel.h
+++ b/rtgui/batchqueuepanel.h
@@ -69,7 +69,7 @@ class BatchQueuePanel : public Gtk::VBox,
void pathFolderChanged ();
void pathFolderButtonPressed ();
void formatChanged (Glib::ustring f);
- void updateTab (int qsize);
+ void updateTab (int qsize, int forceOrientation=0); // forceOrientation=0: base on options / 1: horizontal / 2: vertical
bool handleShortcutKey (GdkEventKey* event);
};
diff --git a/rtgui/coloredbar.cc b/rtgui/coloredbar.cc
index 2e48034c8..de41b8312 100644
--- a/rtgui/coloredbar.cc
+++ b/rtgui/coloredbar.cc
@@ -26,9 +26,9 @@ ColoredBar::ColoredBar (eRTOrientation orient) {
}
/*
- * Redraw the bar to a Cairo::Surface
+ * Redraw the bar to a Cairo::ImageSurface
*/
-void ColoredBar::expose(Cairo::RefPtr destSurface) {
+void ColoredBar::expose(Cairo::RefPtr destSurface) {
// look out if the Surface has to be redrawn
if (!surfaceCreated() || !destSurface)
return;
diff --git a/rtgui/coloredbar.h b/rtgui/coloredbar.h
index 657896abd..8e62e20ed 100644
--- a/rtgui/coloredbar.h
+++ b/rtgui/coloredbar.h
@@ -39,7 +39,7 @@ class ColoredBar : public BackBuffer, public ColorCaller {
ColoredBar (eRTOrientation orient);
void expose(Glib::RefPtr destWindow);
- void expose(Cairo::RefPtr destSurface);
+ void expose(Cairo::RefPtr destSurface);
void expose(BackBuffer *backBuffer);
bool canGetColors();
diff --git a/rtgui/coord.h b/rtgui/coord.h
new file mode 100644
index 000000000..91fc40562
--- /dev/null
+++ b/rtgui/coord.h
@@ -0,0 +1,163 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#ifndef _COORD_H_
+#define _COORD_H_
+
+class PolarCoord;
+
+// Do not confuse with rtengine::Coord2D, Coord is for the GUI
+class Coord {
+public:
+ int x;
+ int y;
+
+ Coord() : x(-1), y(-1) {}
+ Coord(int x, int y) : x(x), y(y) {}
+
+ void set (int x, int y) {
+ this->x = x;
+ this->y = y;
+ }
+
+ void setFromPolar(PolarCoord polar);
+
+ /// @brief Clip the coord to stay in the width x height bounds
+ /// @return true if the x or y coordinate has changed
+ bool clip(int width, int height) {
+ int trimmedX = rtengine::LIM(x, 0, width);
+ int trimmedY = rtengine::LIM(y, 0, height);
+ bool retval = trimmedX!=x || trimmedY!=y;
+ x = trimmedX;
+ y = trimmedY;
+ return retval;
+ }
+
+ void operator+=(const Coord & rhs) {
+ x += rhs.x;
+ y += rhs.y;
+ }
+ void operator-=(const Coord & rhs) {
+ x -= rhs.x;
+ y -= rhs.y;
+ }
+ void operator*=(double scale) {
+ x *= scale;
+ y *= scale;
+ }
+ Coord operator+(Coord & rhs) {
+ Coord result(x+rhs.x, y+rhs.y);
+ return result;
+ }
+ Coord operator-(Coord & rhs) {
+ Coord result(x-rhs.x, y-rhs.y);
+ return result;
+ }
+ Coord operator*(double scale) {
+ Coord result(x*scale, y*scale);
+ return result;
+ }
+};
+
+class PolarCoord {
+public:
+ double radius;
+ double angle; // degree
+
+ PolarCoord() : radius(1.), angle(0.) {}
+ PolarCoord(double radius, double angle) : radius(radius), angle(angle) {}
+
+ void set (double radius, double angle) {
+ this->radius = radius;
+ this->angle = angle;
+ }
+
+ void setFromCartesian(Coord start, Coord end) {
+ Coord delta(end.x-start.x, end.y-start.y);
+ setFromCartesian(delta);
+ }
+
+ void setFromCartesian(Coord delta) {
+ if (!delta.x && !delta.y) {
+ // null vector, we set to a default value
+ radius = 1.;
+ angle = 0.;
+ return;
+ }
+ double x_ = double(delta.x);
+ double y_ = double(delta.y);
+ radius = sqrt(x_*x_+y_*y_);
+ if (delta.x>0.) {
+ if (delta.y>=0.)
+ angle = atan(y_/x_)/(2*M_PI)*360.;
+ else if (delta.y<0.)
+ angle = (atan(y_/x_)+2*M_PI)/(2*M_PI)*360.;
+ }
+ else if (delta.x<0.)
+ angle = (atan(y_/x_)+M_PI)/(2*M_PI)*360.;
+ else if (delta.x==0.) {
+ if (delta.y>0.)
+ angle = 90.;
+ else
+ angle = 270.;
+ }
+ }
+
+ void operator+=(const PolarCoord & rhs) {
+ Coord thisCoord, rhsCoord;
+ thisCoord.setFromPolar(*this);
+ rhsCoord.setFromPolar(rhs);
+ thisCoord += rhsCoord;
+ setFromCartesian(thisCoord);
+ }
+ void operator-=(const PolarCoord & rhs) {
+ Coord thisCoord, rhsCoord;
+ thisCoord.setFromPolar(*this);
+ rhsCoord.setFromPolar(rhs);
+ thisCoord -= rhsCoord;
+ setFromCartesian(thisCoord);
+ }
+ void operator*=(double scale) {
+ radius *= scale;
+ }
+ PolarCoord operator+(PolarCoord & rhs) {
+ Coord thisCoord, rhsCoord;
+ thisCoord.setFromPolar(*this);
+ rhsCoord.setFromPolar(rhs);
+ thisCoord += rhsCoord;
+ PolarCoord result;
+ result.setFromCartesian(thisCoord);
+ return result;
+ }
+ PolarCoord operator-(PolarCoord & rhs) {
+ Coord thisCoord, rhsCoord;
+ thisCoord.setFromPolar(*this);
+ rhsCoord.setFromPolar(rhs);
+ thisCoord -= rhsCoord;
+ PolarCoord result;
+ result.setFromCartesian(thisCoord);
+ return result;
+ }
+ Coord operator*(double scale) {
+ Coord result(radius*scale, angle);
+ return result;
+ }
+
+};
+
+#endif
diff --git a/rtgui/edit.h b/rtgui/edit.h
index 37b876907..1e7159384 100644
--- a/rtgui/edit.h
+++ b/rtgui/edit.h
@@ -24,6 +24,7 @@
#include "editid.h"
#include "cursormanager.h"
#include "../rtengine/rt_math.h"
+#include "coord.h"
class EditDataProvider;
@@ -60,146 +61,6 @@ class EditBuffer;
*
*/
-class PolarCoord;
-
-// Do not confuse with rtengine::Coord2D, this one is for the GUI
-class Coord {
-public:
- int x;
- int y;
-
- Coord() : x(-1), y(-1) {}
- Coord(int x, int y) : x(x), y(y) {}
-
- void set (int x, int y) {
- this->x = x;
- this->y = y;
- }
-
- void setFromPolar(PolarCoord polar);
-
- /// @brief Clip the coord to stay in the width x height bounds
- /// @return true if the x or y coordinate has changed
- bool clip(int width, int height) {
- int trimmedX = rtengine::LIM(x, 0, width);
- int trimmedY = rtengine::LIM(y, 0, height);
- bool retval = trimmedX!=x || trimmedY!=y;
- x = trimmedX;
- y = trimmedY;
- return retval;
- }
-
- void operator+=(const Coord & rhs) {
- x += rhs.x;
- y += rhs.y;
- }
- void operator-=(const Coord & rhs) {
- x -= rhs.x;
- y -= rhs.y;
- }
- void operator*=(double scale) {
- x *= scale;
- y *= scale;
- }
- Coord operator+(Coord & rhs) {
- Coord result(x+rhs.x, y+rhs.y);
- return result;
- }
- Coord operator-(Coord & rhs) {
- Coord result(x-rhs.x, y-rhs.y);
- return result;
- }
- Coord operator*(double scale) {
- Coord result(x*scale, y*scale);
- return result;
- }
-};
-
-class PolarCoord {
-public:
- double radius;
- double angle; // degree
-
- PolarCoord() : radius(1.), angle(0.) {}
- PolarCoord(double radius, double angle) : radius(radius), angle(angle) {}
-
- void set (double radius, double angle) {
- this->radius = radius;
- this->angle = angle;
- }
-
- void setFromCartesian(Coord start, Coord end) {
- Coord delta(end.x-start.x, end.y-start.y);
- setFromCartesian(delta);
- }
-
- void setFromCartesian(Coord delta) {
- if (!delta.x && !delta.y) {
- // null vector, we set to a default value
- radius = 1.;
- angle = 0.;
- return;
- }
- double x_ = double(delta.x);
- double y_ = double(delta.y);
- radius = sqrt(x_*x_+y_*y_);
- if (delta.x>0.) {
- if (delta.y>=0.)
- angle = atan(y_/x_)/(2*M_PI)*360.;
- else if (delta.y<0.)
- angle = (atan(y_/x_)+2*M_PI)/(2*M_PI)*360.;
- }
- else if (delta.x<0.)
- angle = (atan(y_/x_)+M_PI)/(2*M_PI)*360.;
- else if (delta.x==0.) {
- if (delta.y>0.)
- angle = 90.;
- else
- angle = 270.;
- }
- }
-
- void operator+=(const PolarCoord & rhs) {
- Coord thisCoord, rhsCoord;
- thisCoord.setFromPolar(*this);
- rhsCoord.setFromPolar(rhs);
- thisCoord += rhsCoord;
- setFromCartesian(thisCoord);
- }
- void operator-=(const PolarCoord & rhs) {
- Coord thisCoord, rhsCoord;
- thisCoord.setFromPolar(*this);
- rhsCoord.setFromPolar(rhs);
- thisCoord -= rhsCoord;
- setFromCartesian(thisCoord);
- }
- void operator*=(double scale) {
- radius *= scale;
- }
- PolarCoord operator+(PolarCoord & rhs) {
- Coord thisCoord, rhsCoord;
- thisCoord.setFromPolar(*this);
- rhsCoord.setFromPolar(rhs);
- thisCoord += rhsCoord;
- PolarCoord result;
- result.setFromCartesian(thisCoord);
- return result;
- }
- PolarCoord operator-(PolarCoord & rhs) {
- Coord thisCoord, rhsCoord;
- thisCoord.setFromPolar(*this);
- rhsCoord.setFromPolar(rhs);
- thisCoord -= rhsCoord;
- PolarCoord result;
- result.setFromCartesian(thisCoord);
- return result;
- }
- Coord operator*(double scale) {
- Coord result(radius*scale, angle);
- return result;
- }
-
-};
/** @brief Coordinate system where the widgets will be drawn
*
diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h
index a939f38ed..7e51866b0 100644
--- a/rtgui/filebrowser.h
+++ b/rtgui/filebrowser.h
@@ -45,6 +45,7 @@ class FileBrowserListener {
virtual void copyMoveRequested (std::vector tbe, bool moveRequested) {}
virtual void selectionChanged (std::vector tbe) {}
virtual void clearFromCacheRequested(std::vector tbe, bool leavenotrace) {}
+ virtual bool isInTabMode () { return false; }
};
struct FileBrowserIdleHelper {
@@ -166,6 +167,8 @@ class FileBrowser : public ThumbBrowserBase,
void saveThumbnailHeight (int height);
int getThumbnailHeight ();
+ bool isInTabMode() { return tbl ? tbl->isInTabMode() : false; }
+
void openNextImage ();
void openPrevImage ();
void copyProfile ();
diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc
index c98c57cbe..1e3976019 100644
--- a/rtgui/filebrowserentry.cc
+++ b/rtgui/filebrowserentry.cc
@@ -23,6 +23,7 @@
#include "guiutils.h"
#include "threadutils.h"
#include "../rtengine/safegtk.h"
+#include "inspector.h"
#include
@@ -34,7 +35,7 @@ Glib::RefPtr FileBrowserEntry::recentlySavedIcon;
Glib::RefPtr FileBrowserEntry::enqueuedIcon;
FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname)
- : ThumbBrowserEntryBase (fname), iatlistener(NULL), cropgl(NULL), state(SNormal) {
+ : ThumbBrowserEntryBase (fname), wasInside(false), iatlistener(NULL), cropgl(NULL), state(SNormal) {
thumbnail=thm;
feih = new FileBrowserEntryIdleHelper;
@@ -261,6 +262,25 @@ bool FileBrowserEntry::motionNotify (int x, int y) {
int ix = x - startx - ofsX;
int iy = y - starty - ofsY;
+ Inspector* inspector = parent->getInspector();
+ if (inspector && inspector->isActive() && !parent->isInTabMode()) {
+ rtengine::Coord2D coord(-1.,-1.);
+ getPosInImgSpace(x, y, coord);
+ if (coord.x != -1.) {
+ if (!wasInside) {
+ inspector->switchImage(filename);
+ }
+ wasInside = true;
+ inspector->mouseMove(coord, 0);
+ }
+ else {
+ if (wasInside) {
+ wasInside = false;
+ rtengine::Coord2D coord(-1,-1);
+ }
+ }
+ }
+
if (inside (x,y))
updateCursor (ix, iy);
diff --git a/rtgui/filebrowserentry.h b/rtgui/filebrowserentry.h
index 4f5a559e5..bc52273a0 100644
--- a/rtgui/filebrowserentry.h
+++ b/rtgui/filebrowserentry.h
@@ -45,6 +45,7 @@ class FileBrowserEntry : public ThumbBrowserEntryBase,
double scale;
static bool iconsLoaded;
+ bool wasInside;
ImageAreaToolListener* iatlistener;
int press_x, press_y, action_x, action_y;
double rot_deg;
diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h
index 9d25c55ba..7a0558e6b 100644
--- a/rtgui/filecatalog.h
+++ b/rtgui/filecatalog.h
@@ -60,7 +60,7 @@ class FilePanel;
class FileCatalog : public Gtk::VBox,
public DirSelectionListener,
public PreviewLoaderListener,
- public FilterPanelListener,
+ public FilterPanelListener,
public FileBrowserListener,
public ExportPanelListener
#ifdef WIN32
@@ -181,6 +181,10 @@ class FileCatalog : public Gtk::VBox,
void previewsFinishedUI ();
void _refreshProgressBar ();
+ void setInspector(Inspector* inspector) { if (fileBrowser) fileBrowser->setInspector(inspector); }
+ void disableInspector() { if (fileBrowser) fileBrowser->disableInspector(); }
+ void enableInspector() { if (fileBrowser) fileBrowser->enableInspector(); }
+
// filterpanel interface
void exifFilterChanged ();
@@ -245,6 +249,8 @@ class FileCatalog : public Gtk::VBox,
bool handleShortcutKey (GdkEventKey* event);
+ bool isInTabMode() { return inTabMode; }
+
bool CheckSidePanelsVisibility();
void toggleSidePanels();
void toggleLeftPanel();
diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc
index 21118327f..22988d8e8 100644
--- a/rtgui/filepanel.cc
+++ b/rtgui/filepanel.cc
@@ -20,6 +20,7 @@
#include "filepanel.h"
#include "rtwindow.h"
#include "../rtengine/safegtk.h"
+#include "inspector.h"
int FilePanelInitUI (void* data) {
(static_cast(data))->init ();
@@ -68,6 +69,7 @@ FilePanel::FilePanel () : parent(NULL) {
rightBox = Gtk::manage ( new Gtk::HBox () );
rightBox->set_size_request(50,100);
rightNotebook = Gtk::manage ( new Gtk::Notebook () );
+ rightNotebook->signal_switch_page().connect_notify( sigc::mem_fun(*this, &FilePanel::on_NB_switch_page) );
//Gtk::VBox* taggingBox = Gtk::manage ( new Gtk::VBox () );
history = Gtk::manage ( new History (false) );
@@ -80,6 +82,9 @@ FilePanel::FilePanel () : parent(NULL) {
sFilterPanel->add (*filterPanel);
sFilterPanel->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+ inspectorPanel = new Inspector();
+ fileCatalog->setInspector(inspectorPanel);
+
Gtk::ScrolledWindow* sExportPanel = Gtk::manage ( new Gtk::ScrolledWindow() );
exportPanel = Gtk::manage ( new ExportPanel () );
sExportPanel->add (*exportPanel);
@@ -96,6 +101,8 @@ FilePanel::FilePanel () : parent(NULL) {
Gtk::Label* devLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_DEVELOP")) );
devLab->set_angle (90);
+ Gtk::Label* inspectLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_INSPECT")) );
+ inspectLab->set_angle (90);
Gtk::Label* filtLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_FILTER")) );
filtLab->set_angle (90);
//Gtk::Label* tagLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_TAGGING")) );
@@ -108,6 +115,7 @@ FilePanel::FilePanel () : parent(NULL) {
tpcPaned->pack2 (*history, true, true);
rightNotebook->append_page (*tpcPaned, *devLab);
+ rightNotebook->append_page (*inspectorPanel, *inspectLab);
rightNotebook->append_page (*sFilterPanel, *filtLab);
//rightNotebook->append_page (*taggingBox, *tagLab); commented out: currently the tab is empty ...
rightNotebook->append_page (*sExportPanel, *exportLab);
@@ -125,6 +133,11 @@ FilePanel::FilePanel () : parent(NULL) {
show_all ();
}
+FilePanel::~FilePanel () {
+ if (inspectorPanel)
+ delete inspectorPanel;
+}
+
void FilePanel::setAspect () {
int winW, winH;
parent->get_size(winW, winH);
@@ -160,7 +173,18 @@ void FilePanel::init () {
}
}
}
-}
+}
+
+void FilePanel::on_NB_switch_page(GtkNotebookPage* page, guint page_num) {
+ if (page_num == 1) {
+ // switching the inspector "on"
+ fileCatalog->enableInspector();
+ }
+ else {
+ // switching the inspector "off"
+ fileCatalog->disableInspector();
+ }
+}
bool FilePanel::fileSelected (Thumbnail* thm) {
diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h
index d38aa3d7d..aab1d7168 100755
--- a/rtgui/filepanel.h
+++ b/rtgui/filepanel.h
@@ -44,11 +44,12 @@ class FilePanel : public Gtk::HPaned,
RecentBrowser* recentBrowser;
// FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it
+ Inspector* inspectorPanel;
Gtk::VPaned* tpcPaned;
BatchToolPanelCoordinator* tpc;
History* history;
- //FilterPanel* filterPanel;
- RTWindow* parent;
+ //FilterPanel* filterPanel;
+ RTWindow* parent;
Gtk::Notebook* rightNotebook;
struct pendingLoad {
@@ -56,12 +57,16 @@ class FilePanel : public Gtk::HPaned,
ProgressConnector *pc;
Thumbnail *thm;
};
- MyMutex pendingLoadMutex;
+ MyMutex pendingLoadMutex;
std::vector pendingLoads;
int error;
+
+ void on_NB_switch_page(GtkNotebookPage* page, guint page_num);
+
public:
FilePanel ();
+ ~FilePanel ();
Gtk::Paned* placespaned;
Gtk::HPaned* dirpaned;
@@ -80,10 +85,10 @@ class FilePanel : public Gtk::HPaned,
void open (const Glib::ustring& d); // open a file or a directory
void refreshEditedState (const std::set& efiles) { fileCatalog->refreshEditedState (efiles); }
void loadingThumbs(Glib::ustring str, double rate);
-
- // call this before closeing rt: it saves file browser relating things into options
+
+ // call this before closing RT: it saves file browser's related things into options
void saveOptions ();
-
+
// interface fileselectionlistener
bool fileSelected (Thumbnail* thm);
bool addBatchQueueJobs ( std::vector &entries );
diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc
index e8d09045e..27dbc031e 100644
--- a/rtgui/guiutils.cc
+++ b/rtgui/guiutils.cc
@@ -19,6 +19,7 @@
#include "guiutils.h"
#include "options.h"
+#include "../rtengine/rt_math.h"
#include "../rtengine/utils.h"
#include "../rtengine/safegtk.h"
#include "rtimage.h"
@@ -540,12 +541,18 @@ void TextOrIcon::switchTo(TOITypes type) {
show_all();
}
-BackBuffer::BackBuffer() {
- x = y = w = h = 0;
- dirty = true;
+BackBuffer::BackBuffer() : x(0), y(0), w(0), h(0), offset(0,0), dirty(true) {}
+
+void BackBuffer::setSrcOffset(int x, int y) {
+ // values will be clamped when used...
+ offset.x = x;
+ offset.y = y;
}
-bool BackBuffer::setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH) {
+// Note: newW & newH must be > 0
+bool BackBuffer::setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH, bool updateBackBufferSize) {
+ assert(newW && newH);
+
bool newSize = w!=newW || h!=newH;
x = newX;
@@ -554,17 +561,31 @@ bool BackBuffer::setDrawRectangle(Glib::RefPtr window, int newX, in
h = newH;
// WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!?
- if (newSize && window) {
+ if (updateBackBufferSize && newSize && window) {
// allocate a new Surface
- if (newW>0 && newH>0) {
- surface = window->create_similar_surface(Cairo::CONTENT_COLOR, w, h);
- }
- else {
- // at least one dimension is null, so we delete the Surface
- surface.clear();
- // and we reset all dimensions
- x = y = w = h = 0;
- }
+ surface.clear(); // ... don't know if this is necessary?
+ surface = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h);
+ dirty = true;
+ }
+ return dirty;
+}
+
+// Note: newW & newH must be > 0
+bool BackBuffer::setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize) {
+ assert(!newW && !newH);
+
+ bool newSize = w!=newW || h!=newH;
+
+ x = newX;
+ y = newY;
+ w = newW;
+ h = newH;
+
+ // WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!?
+ if (updateBackBufferSize && newSize) {
+ // allocate a new Surface
+ surface.clear(); // ... don't know if this is necessary?
+ surface = Cairo::ImageSurface::create(format, w, h);
dirty = true;
}
return dirty;
@@ -579,9 +600,13 @@ void BackBuffer::copySurface(Glib::RefPtr window, GdkRectangle *rec
Cairo::RefPtr crSrc = window->create_cairo_context();
Cairo::RefPtr destSurface = crSrc->get_target();
+ // compute the source offset
+ int offsetX = rtengine::LIM(offset.x,0, surface->get_width());
+ int offsetY = rtengine::LIM(offset.y,0, surface->get_height());
+
// now copy the off-screen Surface to the destination Surface
Cairo::RefPtr crDest = Cairo::Context::create(destSurface);
- crDest->set_source(surface, x, y);
+ crDest->set_source(surface, x-offsetX, y-offsetY);
crDest->set_line_width(0.);
if (rectangle)
crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height);
@@ -596,9 +621,13 @@ void BackBuffer::copySurface(Glib::RefPtr window, GdkRectangle *rec
*/
void BackBuffer::copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle) {
if (surface && destBackBuffer) {
+ // compute the source offset
+ int offsetX = rtengine::LIM(offset.x,0, surface->get_width());
+ int offsetY = rtengine::LIM(offset.y,0, surface->get_height());
+
// now copy the off-screen Surface to the destination Surface
Cairo::RefPtr crDest = Cairo::Context::create(destBackBuffer->getSurface());
- crDest->set_source(surface, x, y);
+ crDest->set_source(surface, x-offsetX, y-offsetY);
crDest->set_line_width(0.);
if (rectangle)
crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height);
@@ -611,11 +640,15 @@ void BackBuffer::copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle
/*
* Copy the BackBuffer to another Cairo::Surface
*/
-void BackBuffer::copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle) {
+void BackBuffer::copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle) {
if (surface && destSurface) {
+ // compute the source offset
+ int offsetX = rtengine::LIM(offset.x,0, surface->get_width());
+ int offsetY = rtengine::LIM(offset.y,0, surface->get_height());
+
// now copy the off-screen Surface to the destination Surface
Cairo::RefPtr crDest = Cairo::Context::create(destSurface);
- crDest->set_source(surface, x, y);
+ crDest->set_source(surface, x-offsetX, y-offsetY);
crDest->set_line_width(0.);
if (rectangle)
crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height);
diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h
index 3dae41d1e..41a2d99cc 100644
--- a/rtgui/guiutils.h
+++ b/rtgui/guiutils.h
@@ -265,29 +265,34 @@ class BackBuffer {
protected:
int x, y, w, h; // Rectangle where the colored bar has to be drawn
- Cairo::RefPtr surface;
+ Point offset; // Offset of the source region to draw, relative to the top left corner
+ Cairo::RefPtr surface;
bool dirty; // mean that the Surface has to be (re)allocated
public:
BackBuffer();
// set the destination drawing rectangle; return true if the dimensions are different
- bool setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH);
+ // Note: newW & newH must be > 0
+ bool setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH, bool updateBackBufferSize=true);
+ bool setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize=true);
+ void setSrcOffset(int x, int y);
void copySurface(Glib::RefPtr window, GdkRectangle *rectangle=NULL);
void copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle=NULL);
- void copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle=NULL);
+ void copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle=NULL);
void setDirty(bool isDirty) { dirty = isDirty; if (!dirty && !surface) dirty = true; }
bool isDirty() { return dirty; }
// you have to check if the surface is created thanks to surfaceCreated before starting to draw on it
bool surfaceCreated() { return surface; }
- Cairo::RefPtr getSurface() { return surface; }
- void deleteSurface() { surface.clear(); dirty=true; }
+ Cairo::RefPtr getSurface() { return surface; }
+ void setSurface(Cairo::RefPtr surf) { surface = surf; }
+ void deleteSurface() { if (surface) surface.clear(); dirty=true; }
// will let you get a Cairo::Context for Cairo drawing operations
Cairo::RefPtr getContext() { return Cairo::Context::create(surface); }
- int getWidth() { return w; }
- int getHeight() { return h; }
+ int getWidth() { return surface ? surface->get_width() : 0; }
+ int getHeight() { return surface ? surface->get_height() : 0; }
};
diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc
new file mode 100644
index 000000000..00ae1f5cb
--- /dev/null
+++ b/rtgui/inspector.cc
@@ -0,0 +1,262 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#include "inspector.h"
+#include "guiutils.h"
+#include
+#include "cursormanager.h"
+#include "guiutils.h"
+#include "options.h"
+#include "../rtengine/safegtk.h"
+#include "../rtengine/previewimage.h"
+
+extern Options options;
+
+InspectorBuffer::InspectorBuffer(const Glib::ustring &imagePath) : currTransform(0), fromRaw(false) {
+ if (!imagePath.empty() && safe_file_test(imagePath, Glib::FILE_TEST_EXISTS) && !safe_file_test(imagePath, Glib::FILE_TEST_IS_DIR)) {
+ imgPath = imagePath;
+
+ // generate thumbnail image
+ Glib::ustring ext = getExtension (imagePath);
+ if (ext=="") {
+ imgPath.clear();
+ return;
+ }
+
+ rtengine::PreviewImage pi(imagePath, ext, rtengine::PreviewImage::PIM_EmbeddedOrRaw);
+ Cairo::RefPtr imageSurface = pi.getImage();
+
+ if (imageSurface) {
+ imgBuffer.setSurface(imageSurface);
+ fromRaw = true;
+ }
+ else {
+ imgPath.clear();
+ }
+ }
+}
+
+/*
+InspectorBuffer::~InspectorBuffer() {
+}
+*/
+
+int InspectorBuffer::infoFromImage (const Glib::ustring& fname) {
+
+ rtengine::ImageMetaData* idata = rtengine::ImageMetaData::fromFile (fname, NULL);
+ if (!idata)
+ return 0;
+
+ int deg = 0;
+ if (idata->hasExif()) {
+ if (idata->getOrientation()=="Rotate 90 CW" ) deg = 90;
+ else if (idata->getOrientation()=="Rotate 180" ) deg = 180;
+ else if (idata->getOrientation()=="Rotate 270 CW") deg = 270;
+ }
+ delete idata;
+ return deg;
+}
+
+Inspector::Inspector () : currImage(NULL), zoom(0.0), active(false) {}
+
+Inspector::~Inspector() {
+ deleteBuffers();
+}
+
+bool Inspector::on_expose_event (GdkEventExpose* event) {
+
+ Glib::RefPtr win = get_window();
+ if (!win)
+ return false;
+
+ if (!active) {
+ active = true;
+ }
+
+
+ // cleanup the region
+
+
+ if (currImage && currImage->imgBuffer.surfaceCreated()) {
+ // this will eventually create/update the off-screen pixmap
+
+ // compute the displayed area
+ Coord availableSize;
+ Coord topLeft;
+ Coord displayedSize;
+ Coord dest(0, 0);
+ win->get_size(availableSize.x, availableSize.y);
+ int imW = currImage->imgBuffer.getWidth();
+ int imH = currImage->imgBuffer.getHeight();
+
+ if (imW < availableSize.x) {
+ // center the image in the available space along X
+ topLeft.x = 0;
+ displayedSize.x = availableSize.x;
+ dest.x = (availableSize.x - imW) / 2;
+ }
+ else {
+ // partial image display
+ // double clamp
+ topLeft.x = center.x + availableSize.x/2;
+ topLeft.x = rtengine::min(topLeft.x, imW);
+ topLeft.x -= availableSize.x;
+ topLeft.x = rtengine::max(topLeft.x, 0);
+ }
+
+ if (imH < availableSize.y) {
+ // center the image in the available space along Y
+ topLeft.y = 0;
+ displayedSize.y = availableSize.y;
+ dest.y = (availableSize.y - imH) / 2;
+ }
+ else {
+ // partial image display
+ // double clamp
+ topLeft.y = center.y + availableSize.y/2;
+ topLeft.y = rtengine::min(topLeft.y, imH);
+ topLeft.y -= availableSize.y;
+ topLeft.y = rtengine::max(topLeft.y, 0);
+ }
+
+ //printf("center: %d, %d (img: %d, %d) (availableSize: %d, %d) (topLeft: %d, %d)\n", center.x, center.y, imW, imH, availableSize.x, availableSize.y, topLeft.x, topLeft.y);
+
+ // define the destination area
+ currImage->imgBuffer.setDrawRectangle(win, dest.x, dest.y, rtengine::min(availableSize.x-dest.x, imW), rtengine::min(availableSize.y-dest.y,imH), false);
+ currImage->imgBuffer.setSrcOffset(topLeft.x, topLeft.y);
+
+ if (!currImage->imgBuffer.surfaceCreated()) {
+ return false;
+ }
+
+ // Draw!
+
+ Gdk::Color c;
+ Cairo::RefPtr cr = win->create_cairo_context();
+ Glib::RefPtr style = get_style();
+
+ // draw the background
+ c = style->get_bg (Gtk::STATE_NORMAL);
+ cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
+ cr->set_line_width (0);
+ cr->rectangle (0, 0, availableSize.x, availableSize.y);
+ cr->fill ();
+
+ currImage->imgBuffer.copySurface(win);
+
+ // draw the frame
+ c = style->get_fg (Gtk::STATE_NORMAL);
+ cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
+ cr->set_line_width (1);
+ cr->rectangle (0.5, 0.5, availableSize.x-1, availableSize.y-1);
+ cr->stroke ();
+ }
+ return true;
+}
+
+void Inspector::mouseMove (rtengine::Coord2D pos, int transform) {
+ if (!active)
+ return;
+
+ if (currImage)
+ center.set(int(rtengine::LIM01(pos.x)*double(currImage->imgBuffer.getWidth())), int(rtengine::LIM01(pos.y)*double(currImage->imgBuffer.getHeight())));
+ else
+ center.set(0,0);
+ queue_draw();
+}
+
+void Inspector::switchImage (const Glib::ustring &fullPath) {
+ if (!active)
+ return;
+
+ // we first check the size of the list, it may have been changed in Preference
+ if (images.size() > size_t(options.maxInspectorBuffers)) {
+ // deleting the last entries
+ for (size_t i=images.size()-1; i>size_t(options.maxInspectorBuffers-1); --i) {
+ delete images.at(i);
+ images.at(i) = NULL;
+ }
+ // resizing down
+ images.resize(options.maxInspectorBuffers);
+ }
+
+ if (fullPath.empty()) {
+ currImage = NULL;
+ queue_draw();
+ return;
+ }
+ else {
+ bool found = false;
+ for (size_t i=0; iimgPath==fullPath) {
+ currImage = images.at(i);
+
+ // rolling the list 1 step to the beginning
+ for (size_t j=i; jimgPath.empty()) {
+ images.push_back(iBuffer);
+ currImage = images.at(images.size()-1);
+ }
+ else {
+ currImage = NULL;
+ }
+ }
+ }
+}
+
+void Inspector::deleteBuffers () {
+ for (size_t i=0; i
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#ifndef _INSPECTOR_
+#define _INSPECTOR_
+
+#include
+#include "guiutils.h"
+#include "coord.h"
+
+class InspectorBuffer {
+ private:
+ int infoFromImage (const Glib::ustring& fname);
+
+ public:
+ BackBuffer imgBuffer;
+ Glib::ustring imgPath;
+ int currTransform; // coarse rotation from RT, not from shot orientation
+ bool fromRaw;
+
+ InspectorBuffer(const Glib::ustring &imgagePath);
+ //~InspectorBuffer();
+};
+
+class Inspector : public Gtk::DrawingArea {
+
+ private:
+ Coord center;
+ std::vector images;
+ InspectorBuffer* currImage;
+ double zoom;
+ bool active;
+
+ bool on_expose_event (GdkEventExpose* event);
+ void deleteBuffers();
+
+ public:
+ Inspector();
+ ~Inspector();
+
+ /** @brief Mouse movement to a new position
+ * @param pos Location of the mouse, in percentage (i.e. [0;1] range) relative to the full size image ; -1,-1 == out of the image
+ * @param transform H/V flip and coarse rotation transformation
+ */
+ void mouseMove (rtengine::Coord2D pos, int transform);
+
+ /** @brief A new image is being flown over
+ * @param fullPath Full path of the image that is being hovered inspect, or an empty string if out of any image.
+ */
+ void switchImage (const Glib::ustring &fullPath);
+
+ /** @brief Set the new coarse rotation transformation
+ * @param transform A semi-bitfield coarse transformation using #defines from iimage.h
+ */
+ void setTransformation (int transform);
+
+ /** @brief Use this method to flush all image buffer whenever the Inspector panel is hidden
+ */
+ void flushBuffers ();
+
+ /** @brief Set the inspector on/off
+ * @param state true if to activate the Inspector, false to disable it and flush the buffers
+ */
+ void setActive(bool state);
+
+ /** @brief Get the on/off state
+ */
+ bool isActive() { return active; };
+};
+
+#endif
diff --git a/rtgui/options.cc b/rtgui/options.cc
index 400d99ce2..f350af0a4 100644
--- a/rtgui/options.cc
+++ b/rtgui/options.cc
@@ -360,11 +360,12 @@ void Options::setDefaults () {
rgbDenoiseThreadLimit = 0;
#if defined( _OPENMP ) && defined( __x86_64__ )
- clutCacheSize = omp_get_num_procs();
+ clutCacheSize = omp_get_num_procs();
#else
- clutCacheSize = 1;
+ clutCacheSize = 1;
#endif
- filledProfile = false;
+ filledProfile = false;
+ maxInspectorBuffers = 2; // a rather conservative value for low specced systems...
showProfileSelector = true;
FileBrowserToolbarSingleRow = false;
@@ -735,17 +736,18 @@ if (keyFile.has_group ("Clipping Indication")) {
}
if (keyFile.has_group ("Performance")) {
- if (keyFile.has_key ("Performance", "RgbDenoiseThreadLimit")) rgbDenoiseThreadLimit = keyFile.get_integer ("Performance", "RgbDenoiseThreadLimit");
- if( keyFile.has_key ("Performance", "NRauto")) rtSettings.nrauto = keyFile.get_double("Performance", "NRauto");
- if( keyFile.has_key ("Performance", "NRautomax")) rtSettings.nrautomax = keyFile.get_double("Performance", "NRautomax");
- if( keyFile.has_key ("Performance", "NRhigh")) rtSettings.nrhigh = keyFile.get_double("Performance", "NRhigh");
- if( keyFile.has_key ("Performance", "NRWavlevel")) rtSettings.nrwavlevel = keyFile.get_integer("Performance", "NRWavlevel");
- if (keyFile.has_key ("Performance", "LevNR")) rtSettings.leveldnv = keyFile.get_integer("Performance", "LevNR");
- if (keyFile.has_key ("Performance", "LevNRTI")) rtSettings.leveldnti = keyFile.get_integer("Performance", "LevNRTI");
- if (keyFile.has_key ("Performance", "LevNRAUT")) rtSettings.leveldnaut = keyFile.get_integer("Performance", "LevNRAUT");
- if (keyFile.has_key ("Performance", "LevNRLISS")) rtSettings.leveldnliss = keyFile.get_integer("Performance", "LevNRLISS");
- if (keyFile.has_key ("Performance", "SIMPLNRAUT")) rtSettings.leveldnautsimpl = keyFile.get_integer("Performance", "SIMPLNRAUT");
- if (keyFile.has_key ("Performance", "ClutCacheSize")) clutCacheSize = keyFile.get_integer ("Performance", "ClutCacheSize");
+ if (keyFile.has_key ("Performance", "RgbDenoiseThreadLimit")) rgbDenoiseThreadLimit = keyFile.get_integer ("Performance", "RgbDenoiseThreadLimit");
+ if( keyFile.has_key ("Performance", "NRauto")) rtSettings.nrauto = keyFile.get_double ("Performance", "NRauto");
+ if( keyFile.has_key ("Performance", "NRautomax")) rtSettings.nrautomax = keyFile.get_double ("Performance", "NRautomax");
+ if( keyFile.has_key ("Performance", "NRhigh")) rtSettings.nrhigh = keyFile.get_double ("Performance", "NRhigh");
+ if( keyFile.has_key ("Performance", "NRWavlevel")) rtSettings.nrwavlevel = keyFile.get_integer ("Performance", "NRWavlevel");
+ if (keyFile.has_key ("Performance", "LevNR")) rtSettings.leveldnv = keyFile.get_integer ("Performance", "LevNR");
+ if (keyFile.has_key ("Performance", "LevNRTI")) rtSettings.leveldnti = keyFile.get_integer ("Performance", "LevNRTI");
+ if (keyFile.has_key ("Performance", "LevNRAUT")) rtSettings.leveldnaut = keyFile.get_integer ("Performance", "LevNRAUT");
+ if (keyFile.has_key ("Performance", "LevNRLISS")) rtSettings.leveldnliss = keyFile.get_integer ("Performance", "LevNRLISS");
+ if (keyFile.has_key ("Performance", "SIMPLNRAUT")) rtSettings.leveldnautsimpl = keyFile.get_integer ("Performance", "SIMPLNRAUT");
+ if (keyFile.has_key ("Performance", "ClutCacheSize")) clutCacheSize = keyFile.get_integer ("Performance", "ClutCacheSize");
+ if (keyFile.has_key ("Performance", "MaxInspectorBuffers")) maxInspectorBuffers = keyFile.get_integer ("Performance", "MaxInspectorBuffers");
}
if (keyFile.has_group ("GUI")) {
@@ -811,12 +813,12 @@ if (keyFile.has_group ("Color Management")) {
if (keyFile.has_key ("Color Management", "Intent")) rtSettings.colorimetricIntent = keyFile.get_integer("Color Management", "Intent");
if (keyFile.has_key ("Color Management", "CRI")) rtSettings.CRI_color = keyFile.get_integer("Color Management", "CRI");
- if (keyFile.has_key ("Color Management", "DenoiseLabgamma"))rtSettings.denoiselabgamma = keyFile.get_integer("Color Management", "DenoiseLabgamma");
+ if (keyFile.has_key ("Color Management", "DenoiseLabgamma"))rtSettings.denoiselabgamma = keyFile.get_integer("Color Management", "DenoiseLabgamma");
if (keyFile.has_key ("Color Management", "view")) rtSettings.viewingdevice = keyFile.get_integer("Color Management", "view");
if (keyFile.has_key ("Color Management", "grey")) rtSettings.viewingdevicegrey = keyFile.get_integer("Color Management", "grey");
- if (keyFile.has_key ("Color Management", "greySc")) rtSettings.viewinggreySc = keyFile.get_integer("Color Management", "greySc");
+ if (keyFile.has_key ("Color Management", "greySc")) rtSettings.viewinggreySc = keyFile.get_integer("Color Management", "greySc");
if (keyFile.has_key ("Color Management", "CBDLArtif")) rtSettings.artifact_cbdl = keyFile.get_double("Color Management", "CBDLArtif");
- if (keyFile.has_key ("Color Management", "CBDLlevel0")) rtSettings.level0_cbdl = keyFile.get_double("Color Management", "CBDLlevel0");
+ if (keyFile.has_key ("Color Management", "CBDLlevel0")) rtSettings.level0_cbdl = keyFile.get_double("Color Management", "CBDLlevel0");
if (keyFile.has_key ("Color Management", "CBDLlevel123")) rtSettings.level123_cbdl = keyFile.get_double("Color Management", "CBDLlevel123");
// if (keyFile.has_key ("Color Management", "Colortoningab")) rtSettings.colortoningab = keyFile.get_double("Color Management", "Colortoningab");
// if (keyFile.has_key ("Color Management", "Decaction")) rtSettings.decaction = keyFile.get_double("Color Management", "Decaction");
@@ -1017,17 +1019,18 @@ int Options::saveToFile (Glib::ustring fname) {
keyFile.set_integer ("Clipping Indication", "ShadowThreshold", shadowThreshold);
keyFile.set_boolean ("Clipping Indication", "BlinkClipped", blinkClipped);
- keyFile.set_integer ("Performance", "RgbDenoiseThreadLimit", rgbDenoiseThreadLimit);
+ keyFile.set_integer ("Performance", "RgbDenoiseThreadLimit", rgbDenoiseThreadLimit);
keyFile.set_double ("Performance", "NRauto", rtSettings.nrauto);
keyFile.set_double ("Performance", "NRautomax", rtSettings.nrautomax);
keyFile.set_double ("Performance", "NRhigh", rtSettings.nrhigh);
- keyFile.set_integer ("Performance", "NRWavlevel", rtSettings.nrwavlevel);
- keyFile.set_integer ("Performance", "LevNR", rtSettings.leveldnv);
- keyFile.set_integer ("Performance", "LevNRTI", rtSettings.leveldnti);
- keyFile.set_integer ("Performance", "LevNRAUT", rtSettings.leveldnaut);
- keyFile.set_integer ("Performance", "LevNRLISS", rtSettings.leveldnliss);
- keyFile.set_integer ("Performance", "SIMPLNRAUT", rtSettings.leveldnautsimpl);
+ keyFile.set_integer ("Performance", "NRWavlevel", rtSettings.nrwavlevel);
+ keyFile.set_integer ("Performance", "LevNR", rtSettings.leveldnv);
+ keyFile.set_integer ("Performance", "LevNRTI", rtSettings.leveldnti);
+ keyFile.set_integer ("Performance", "LevNRAUT", rtSettings.leveldnaut);
+ keyFile.set_integer ("Performance", "LevNRLISS", rtSettings.leveldnliss);
+ keyFile.set_integer ("Performance", "SIMPLNRAUT", rtSettings.leveldnautsimpl);
keyFile.set_integer ("Performance", "ClutCacheSize", clutCacheSize);
+ keyFile.set_integer ("Performance", "MaxInspectorBuffers", maxInspectorBuffers);
keyFile.set_string ("Output", "Format", saveFormat.format);
keyFile.set_integer ("Output", "JpegQuality", saveFormat.jpegQuality);
@@ -1128,8 +1131,8 @@ int Options::saveToFile (Glib::ustring fname) {
keyFile.set_boolean ("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut);
keyFile.set_integer ("Color Management", "Intent", rtSettings.colorimetricIntent);
keyFile.set_integer ("Color Management", "view", rtSettings.viewingdevice);
- keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey);
- keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc);
+ keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey);
+ keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc);
keyFile.set_string ("Color Management", "AdobeRGB", rtSettings.adobe);
keyFile.set_string ("Color Management", "ProPhoto", rtSettings.prophoto);
diff --git a/rtgui/options.h b/rtgui/options.h
index 79d30ded6..52422eec2 100644
--- a/rtgui/options.h
+++ b/rtgui/options.h
@@ -219,7 +219,8 @@ class Options {
// Performance options
int rgbDenoiseThreadLimit; // maximum number of threads for the denoising tool ; 0 = use the maximum available
- int clutCacheSize;
+ int maxInspectorBuffers; // maximum number of buffers (i.e. images) for the Inspector feature
+ int clutCacheSize;
bool filledProfile; // Used as reminder for the ProfilePanel "mode"
bool menuGroupRank;
diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc
index 9d87ddb31..93d631c62 100644
--- a/rtgui/preferences.cc
+++ b/rtgui/preferences.cc
@@ -493,14 +493,14 @@ Gtk::Widget* Preferences::getProcParamsPanel () {
}
Gtk::Widget* Preferences::getPerformancePanel () {
- Gtk::VBox* mvbsd = Gtk::manage( new Gtk::VBox () );
+ Gtk::VBox* vbdenoise = Gtk::manage( new Gtk::VBox () );
Gtk::Frame* fdenoise = Gtk::manage( new Gtk::Frame (M("PREFERENCES_NOISE")) );
- Gtk::VBox* mainContainer = Gtk::manage( new Gtk::VBox () );
+ Gtk::VBox* mainContainer = Gtk::manage( new Gtk::VBox () );
mainContainer->set_border_width (4);
-
- mainContainer->set_spacing(4);
+
+ mainContainer->set_spacing(4);
Gtk::HBox* threadLimitHB = Gtk::manage( new Gtk::HBox () );
threadLimitHB->set_border_width(4);
@@ -579,9 +579,13 @@ Gtk::Widget* Preferences::getPerformancePanel () {
colon->attach (*dnwavlab, 0, 1, 5, 6, Gtk::FILL, Gtk::SHRINK, 2, 2);
colon->attach (*dnwavlev, 1, 2, 5, 6, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
colon->attach (*restartNeeded7, 2, 3, 5, 6, Gtk::FILL, Gtk::SHRINK, 2, 2);
-
- mainContainer->pack_start (*colon, Gtk::PACK_SHRINK, 4);
-
+
+ vbdenoise->pack_start (*colon, Gtk::PACK_SHRINK, 4);
+
+ vbdenoise->pack_start(*threadLimitHB, Gtk::PACK_SHRINK, 4);
+ fdenoise->add (*vbdenoise);
+ mainContainer->pack_start (*fdenoise, Gtk::PACK_SHRINK, 4);
+
/* Gtk::Label* dntilab = Gtk::manage (new Gtk::Label (M("PREFERENCES_TINB")+":", Gtk::ALIGN_LEFT));
dnti = Gtk::manage (new Gtk::ComboBoxText ());
@@ -591,14 +595,9 @@ Gtk::Widget* Preferences::getPerformancePanel () {
colon2->attach (*dntilab, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
colon2->attach (*dnti, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
colon2->attach (*restartNeeded4, 2, 3, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
- mainContainer->pack_start (*colon2, Gtk::PACK_SHRINK, 4);
+ vbdenoise->pack_start (*colon2, Gtk::PACK_SHRINK, 4);
*/
-
- mainContainer->pack_start(*threadLimitHB, Gtk::PACK_SHRINK, 4);
- fdenoise->add (*mainContainer);
- mvbsd->pack_start (*fdenoise, Gtk::PACK_SHRINK, 4);
-
-
+
Gtk::Frame* fclut = Gtk::manage( new Gtk::Frame (M("PREFERENCES_CLUTSCACHE")) );
Gtk::HBox* clutCacheSizeHB = Gtk::manage( new Gtk::HBox () );
@@ -619,14 +618,29 @@ Gtk::Widget* Preferences::getPerformancePanel () {
clutCacheSizeHB->pack_start (*CLUTLl, Gtk::PACK_SHRINK, 0);
clutCacheSizeHB->pack_end (*clutCacheSizeSB, Gtk::PACK_SHRINK, 0);
- fclut->add (*clutCacheSizeHB);
-
-
- mvbsd->pack_start (*fclut, Gtk::PACK_SHRINK, 4);
- // return mainContainer;
- return mvbsd;
-
+ fclut->add (*clutCacheSizeHB);
+ mainContainer->pack_start (*fclut, Gtk::PACK_SHRINK, 4);
+
+ Gtk::Frame* finspect = Gtk::manage( new Gtk::Frame (M("PREFERENCES_INSPECT_LABEL")) );
+
+ Gtk::HBox* maxIBuffersHB = Gtk::manage( new Gtk::HBox () );
+ maxIBuffersHB->set_border_width(4);
+ maxIBuffersHB->set_spacing(4);
+ maxIBuffersHB->set_tooltip_text(M("PREFERENCES_INSPECT_MAXBUFFERS_TOOLTIP"));
+ Gtk::Label* maxIBufferLbl = Gtk::manage( new Gtk::Label (M("PREFERENCES_INSPECT_MAXBUFFERS_LABEL") + ":", Gtk::ALIGN_LEFT));
+ maxInspectorBuffersSB = Gtk::manage( new Gtk::SpinButton () );
+ maxInspectorBuffersSB->set_digits (0);
+ maxInspectorBuffersSB->set_increments (1, 5);
+ maxInspectorBuffersSB->set_max_length(2);
+ maxInspectorBuffersSB->set_range (1, 12); // ... we have to set a limit, 12 seem to be enough even for systems with tons of RAM
+ maxIBuffersHB->pack_start (*maxIBufferLbl, Gtk::PACK_SHRINK, 0);
+ maxIBuffersHB->pack_end (*maxInspectorBuffersSB, Gtk::PACK_SHRINK, 0);
+ finspect->add(*maxIBuffersHB);
+
+ mainContainer->pack_start(*finspect, Gtk::PACK_SHRINK, 4);
+
+ return mainContainer;
}
Gtk::Widget* Preferences::getColorManagementPanel () {
@@ -1405,8 +1419,9 @@ void Preferences::storePreferences () {
moptions.overwriteOutputFile = chOverwriteOutputFile->get_active ();
moptions.UseIconNoText = ckbUseIconNoText->get_active();
- moptions.rgbDenoiseThreadLimit = rgbDenoiseTreadLimitSB->get_value_as_int();
+ moptions.rgbDenoiseThreadLimit = rgbDenoiseTreadLimitSB->get_value_as_int();
moptions.clutCacheSize = clutCacheSizeSB->get_value_as_int();
+ moptions.maxInspectorBuffers = maxInspectorBuffersSB->get_value_as_int();
// Sounds only on Windows and Linux
#if defined(WIN32) || defined(__linux__)
@@ -1552,7 +1567,9 @@ void Preferences::fillPreferences () {
ckbUseIconNoText->set_active(moptions.UseIconNoText);
rgbDenoiseTreadLimitSB->set_value(moptions.rgbDenoiseThreadLimit);
- clutCacheSizeSB->set_value(moptions.clutCacheSize);
+ clutCacheSizeSB->set_value(moptions.clutCacheSize);
+ maxInspectorBuffersSB->set_value(moptions.maxInspectorBuffers);
+
//darkFrameDir->set_filename( moptions.rtSettings.darkFramesPath );
//updateDFinfos();
darkFrameDir->set_current_folder( moptions.rtSettings.darkFramesPath );
diff --git a/rtgui/preferences.h b/rtgui/preferences.h
index 4c0f58bd0..7893f2efe 100644
--- a/rtgui/preferences.h
+++ b/rtgui/preferences.h
@@ -125,6 +125,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener {
Gtk::SpinButton* rgbDenoiseTreadLimitSB;
Gtk::SpinButton* clutCacheSizeSB;
+ Gtk::SpinButton* maxInspectorBuffersSB;
Gtk::CheckButton* ckbmenuGroupRank;
Gtk::CheckButton* ckbmenuGroupLabel;
diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc
index 057db0bf9..76fb49a9e 100644
--- a/rtgui/rtwindow.cc
+++ b/rtgui/rtwindow.cc
@@ -75,9 +75,9 @@ RTWindow::RTWindow ()
:mainNB(NULL)
,bpanel(NULL)
,splash(NULL)
+,btn_fullscreen(NULL)
,epanel(NULL)
,fpanel(NULL)
-,btn_fullscreen(NULL)
{
cacheMgr->init ();
@@ -284,6 +284,8 @@ RTWindow::~RTWindow()
#if defined(__APPLE__)
g_object_unref (osxApp);
#endif
+ if (fpanel)
+ delete fpanel;
}
void RTWindow::findVerNumbers(int* numbers, Glib::ustring versionStr) {
@@ -705,6 +707,7 @@ void RTWindow::MoveFileBrowserToEditor()
{
FileCatalog *fCatalog = fpanel->fileCatalog;
fpanel->ribbonPane->remove(*fCatalog);
+ fCatalog->disableInspector();
epanel->catalogPane->add(*fCatalog);
epanel->showTopPanel(options.editorFilmStripOpened);
fCatalog->enableTabMode(true);
@@ -783,4 +786,4 @@ bool RTWindow::isEditorPanel(Widget* panel) {
bool RTWindow::isEditorPanel(guint pageNum) {
return isEditorPanel(mainNB->get_nth_page(pageNum));
-}
\ No newline at end of file
+}
diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc
index cf7cde8d7..ceb566b22 100644
--- a/rtgui/thumbbrowserbase.cc
+++ b/rtgui/thumbbrowserbase.cc
@@ -25,7 +25,7 @@
using namespace std;
ThumbBrowserBase::ThumbBrowserBase ()
- : lastClicked(NULL), previewHeight(options.thumbSize), numOfCols(1) {
+ : lastClicked(NULL), previewHeight(options.thumbSize), numOfCols(1), inspector(NULL), isInspectorActive(false) {
location = THLOC_FILEBROWSER;
inW = -1; inH = -1;
@@ -546,6 +546,15 @@ void ThumbBrowserBase::arrangeFiles () {
}
}
+void ThumbBrowserBase::disableInspector() {
+ if (inspector)
+ inspector->setActive(false);
+}
+
+void ThumbBrowserBase::enableInspector() {
+ if (inspector)
+ inspector->setActive(true);
+}
void ThumbBrowserBase::Internal::on_realize() {
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
diff --git a/rtgui/thumbbrowserbase.h b/rtgui/thumbbrowserbase.h
index 81458de7d..046afda22 100644
--- a/rtgui/thumbbrowserbase.h
+++ b/rtgui/thumbbrowserbase.h
@@ -24,6 +24,7 @@
#include
#include "options.h"
#include "guiutils.h"
+#include "inspector.h"
/*
* Class handling the list of ThumbBrowserEntry objects and their position in it's allocated space
@@ -48,7 +49,7 @@ class ThumbBrowserBase : public Gtk::VBox {
bool on_key_press_event (GdkEventKey* event);
bool on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
void setPosition (int x, int y);
-
+
void setDirty () { dirty = true; }
bool isDirty () { return dirty; }
};
@@ -72,12 +73,20 @@ class ThumbBrowserBase : public Gtk::VBox {
int inW, inH;
+ Inspector *inspector;
+ bool isInspectorActive;
+
+
void resizeThumbnailArea (int w, int h);
void internalAreaResized (Gtk::Allocation& req);
void buttonPressed (int x, int y, int button, GdkEventType type, int state, int clx, int cly, int clw, int clh);
public:
+ void setInspector(Inspector* inspector) { this->inspector = inspector; }
+ Inspector* getInspector() { return inspector; }
+ void disableInspector();
+ void enableInspector();
enum Arrangement {TB_Horizontal, TB_Vertical};
void configScrollBars ();
void scrollChanged ();
@@ -89,6 +98,8 @@ class ThumbBrowserBase : public Gtk::VBox {
void selectFirst (bool enlarge);
void selectLast (bool enlarge);
+ virtual bool isInTabMode() { return false; }
+
eLocation getLocation() { return location; }
protected:
diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc
index 271947a05..59d669c4f 100644
--- a/rtgui/thumbbrowserentrybase.cc
+++ b/rtgui/thumbbrowserentrybase.cc
@@ -459,7 +459,20 @@ void ThumbBrowserEntryBase::setOffset (int x, int y) {
bool ThumbBrowserEntryBase::inside (int x, int y) {
return x>ofsX+startx && xofsY+starty && y=prex && x<=prex+prew && y>=prey && y<=prey+preh) {
+ coord.x = double(x-prex)/double(prew);
+ coord.y = double(y-prey)/double(preh);
+ }
+ }
+}
bool ThumbBrowserEntryBase::insideWindow (int x, int y, int w, int h) {
diff --git a/rtgui/thumbbrowserentrybase.h b/rtgui/thumbbrowserentrybase.h
index d5fede9d3..fad7f4daa 100644
--- a/rtgui/thumbbrowserentrybase.h
+++ b/rtgui/thumbbrowserentrybase.h
@@ -127,6 +127,7 @@ protected:
int getY () const { return ofsY+starty; }
bool inside (int x, int y);
+ void getPosInImgSpace (int x, int y, rtengine::Coord2D &coord);
bool insideWindow (int x, int y, int w, int h);
void setPosition (int x, int y, int w, int h);
void setOffset (int x, int y);