diff --git a/README.md b/README.md
index bd30ae4df..62a91a2bb 100644
--- a/README.md
+++ b/README.md
@@ -40,5 +40,5 @@ http://rawpedia.rawtherapee.com/Linux
Windows:
http://rawpedia.rawtherapee.com/Windows
-OS X:
+macOS:
http://rawpedia.rawtherapee.com/macOS
diff --git a/rtdata/dcpprofiles/NIKON D300.dcp b/rtdata/dcpprofiles/NIKON D300.dcp
new file mode 100644
index 000000000..6aafdc616
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D300.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D80.dcp b/rtdata/dcpprofiles/NIKON D80.dcp
new file mode 100644
index 000000000..965c358aa
Binary files /dev/null and b/rtdata/dcpprofiles/NIKON D80.dcp differ
diff --git a/rtdata/dcpprofiles/NIKON D810.dcp b/rtdata/dcpprofiles/NIKON D810.dcp
index 58f90c983..a946c1be2 100644
Binary files a/rtdata/dcpprofiles/NIKON D810.dcp and b/rtdata/dcpprofiles/NIKON D810.dcp differ
diff --git a/rtdata/dcpprofiles/Nikon D300.dcp b/rtdata/dcpprofiles/Nikon D300.dcp
deleted file mode 100644
index 3b1100b9d..000000000
Binary files a/rtdata/dcpprofiles/Nikon D300.dcp and /dev/null differ
diff --git a/rtdata/dcpprofiles/OLYMPUS E-M1MarkII.dcp b/rtdata/dcpprofiles/OLYMPUS E-M1MarkII.dcp
new file mode 100644
index 000000000..f32d01302
Binary files /dev/null and b/rtdata/dcpprofiles/OLYMPUS E-M1MarkII.dcp differ
diff --git a/rtdata/dcpprofiles/Panasonic DMC-GX85.dcp b/rtdata/dcpprofiles/Panasonic DMC-GX85.dcp
new file mode 100644
index 000000000..82d722a8c
Binary files /dev/null and b/rtdata/dcpprofiles/Panasonic DMC-GX85.dcp differ
diff --git a/rtdata/languages/default b/rtdata/languages/default
index 8a52cf990..2a9ed318a 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -741,6 +741,7 @@ HISTORY_MSG_506;Local - Denoise
HISTORY_MSG_507;Local - LH Curve
HISTORY_MSG_508;Local - Enable super
HISTORY_MSG_509;Local - CC curve
+HISTORY_MSG_510;Local - curve method
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc
index 8623d26cd..3b6d98133 100644
--- a/rtengine/dcraw.cc
+++ b/rtengine/dcraw.cc
@@ -11,6 +11,7 @@
/*RT*/#define DJGPP
#include "opthelper.h"
+
/*
dcraw.c -- Dave Coffin's raw photo decoder
Copyright 1997-2016 by Dave Coffin, dcoffin a cybercom o net
@@ -6264,6 +6265,7 @@ void CLASS apply_tiff()
tile_width = tiff_ifd[i].tile_width;
tile_length = tiff_ifd[i].tile_length;
shutter = tiff_ifd[i].shutter;
+ raw_size = tiff_ifd[i].bytes;
raw = i;
}
}
@@ -9016,6 +9018,9 @@ canon_a5:
if (filters == 9)
FORC(36) ((char *)xtrans)[c] =
xtrans_abs[(c/6+top_margin) % 6][(c+left_margin) % 6];
+ if(filters == 9 && raw_height * raw_width * 2 != raw_size) {
+ xtransCompressed = true;
+ }
} else if (!strcmp(model,"KD-400Z")) {
height = 1712;
width = 2312;
@@ -9865,6 +9870,8 @@ struct tiff_hdr {
char desc[512], make[64], model[64], soft[32], date[20], artist[64];
};
+#include "xtranscompressed.cc"
+
/* RT: Delete from here */
/*RT*/#undef SQR
/*RT*/#undef MAX
diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h
index 0a68b02cc..1ea938cc7 100644
--- a/rtengine/dcraw.h
+++ b/rtengine/dcraw.h
@@ -89,8 +89,51 @@ protected:
unsigned black, cblack[4102], maximum, mix_green, raw_color, zero_is_bad;
unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error;
unsigned tile_width, tile_length, gpsdata[32], load_flags;
+ bool xtransCompressed = false;
+ struct xtrans_params
+ {
+ char *q_table; /* quantization table */
+ int q_point[5]; /* quantization points */
+ int max_bits;
+ int min_value;
+ int raw_bits;
+ int total_values;
+ int maxDiff;
+ ushort line_width;
+ };
+
+ struct int_pair {
+ int value1;
+ int value2;
+ };
+
+ enum _xt_lines
+ {
+ _R0=0,_R1,_R2,_R3,_R4,
+ _G0,_G1,_G2,_G3,_G4,_G5,_G6,_G7,
+ _B0,_B1,_B2,_B3,_B4,
+ _ltotal
+ };
+
+ struct xtrans_block {
+ int cur_bit; // current bit being read (from left to right)
+ int cur_pos; // current position in a buffer
+ INT64 cur_buf_offset; // offset of this buffer in a file
+ unsigned max_read_size; // Amount of data to be read
+ int cur_buf_size; // buffer size
+ uchar *cur_buf; // currently read block
+ IMFILE *input;
+ struct int_pair grad_even[3][41]; // tables of gradients
+ struct int_pair grad_odd[3][41];
+ ushort *linealloc;
+ ushort *linebuf[_ltotal];
+ };
+
+ int fuji_total_lines, fuji_total_blocks, fuji_block_width, fuji_bits;
+
ushort raw_height, raw_width, height, width, top_margin, left_margin;
ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height;
+ unsigned raw_size;
ushort *raw_image;
float * float_raw_image;
ushort white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4];
@@ -226,6 +269,25 @@ void adobe_copy_pixel (unsigned row, unsigned col, ushort **rp);
void lossless_dng_load_raw();
void packed_dng_load_raw();
void deflate_dng_load_raw();
+void init_xtrans(struct xtrans_params* info);
+void fuji_fill_buffer(struct xtrans_block *info);
+void init_xtrans_block(struct xtrans_block* info, const struct xtrans_params *params, INT64 raw_offset, unsigned dsize);
+void copy_line_to_xtrans(struct xtrans_block* info, int cur_line, int cur_block, int cur_block_width);
+void fuji_zerobits(struct xtrans_block* info, int *count);
+void fuji_read_code(struct xtrans_block* info, int *data, int bits_to_read);
+int bitDiff(int value1, int value2);
+int fuji_decode_sample_even(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads);
+int fuji_decode_sample_odd(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads);
+void fuji_decode_interpolation_even(int line_width, ushort* line_buf, int pos);
+void xtrans_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end);
+void xtrans_extend_red(ushort *linebuf[_ltotal], int line_width);
+void xtrans_extend_green(ushort *linebuf[_ltotal], int line_width);
+void xtrans_extend_blue(ushort *linebuf[_ltotal], int line_width);
+void xtrans_decode_block(struct xtrans_block* info, const struct xtrans_params *params, int cur_line);
+void xtrans_decode_strip(const struct xtrans_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize);
+void xtrans_compressed_load_raw();
+void xtrans_decode_loop(const struct xtrans_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes);
+void parse_xtrans_header();
void pentax_load_raw();
void nikon_load_raw();
int nikon_is_compressed();
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index 7cbd443ea..47fa302b8 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -28,7 +28,19 @@
#include
//#include
// "ceil" rounding
-#define SKIPS(a,b) ((a) / (b) + ((a) % (b) > 0))
+//#define SKIPS(a,b) ((a) / (b) + ((a) % (b) > 0))
+
+namespace
+{
+
+// "ceil" rounding
+template
+constexpr T skips (T a, T b)
+{
+ return a / b + static_cast (a % b);
+}
+
+}
namespace rtengine
{
@@ -37,8 +49,8 @@ extern const Settings* settings;
Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow)
: PipetteBuffer (editDataProvider), origCrop (nullptr), laboCrop (nullptr), labnCrop (nullptr),
- cropImg (nullptr), cbuf_real (nullptr), shbuf_real (nullptr), cshmap (nullptr), transCrop (nullptr), cieCrop (nullptr), cbuffer (nullptr), shbuffer (nullptr),
- updating (false), newUpdatePending (false), skip (10), padding (0),
+ cropImg (nullptr), cbuf_real (nullptr), shbuf_real (nullptr), cshmap (nullptr), transCrop (nullptr), cieCrop (nullptr), cbuffer (nullptr), shbuffer (nullptr),
+ updating (false), newUpdatePending (false), skip (10),
cropx (0), cropy (0), cropw (-1), croph (-1),
trafx (0), trafy (0), trafw (-1), trafh (-1),
rqcropx (0), rqcropy (0), rqcropw (-1), rqcroph (-1),
@@ -116,6 +128,12 @@ void Crop::setEditSubscriber (EditSubscriber* newSubscriber)
// If oldSubscriber == NULL && newSubscriber != NULL && newSubscriber->getEditingType() == ET_PIPETTE-> the image will be allocated when necessary
}
+bool Crop::hasListener()
+{
+ MyMutex::MyLock cropLock (cropMutex);
+ return cropImageListener;
+}
+
void Crop::update (int todo)
{
MyMutex::MyLock cropLock (cropMutex);
@@ -690,7 +708,7 @@ void Crop::update (int todo)
}
if (needstransform)
- parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, SKIPS (parent->fw, skip), SKIPS (parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(),
+ parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, skips (parent->fw, skip), skips (parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(),
parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(),
parent->imgsrc->getMetaData()->getFocusDist(), parent->imgsrc->getRotateDegree(), false);
else {
@@ -721,7 +739,7 @@ void Crop::update (int todo)
// blurmap for shadow & highlights
if ((todo & M_BLURMAP) && params.sh.enabled) {
- double radius = sqrt (double (SKIPS (parent->fw, skip) * SKIPS (parent->fw, skip) + SKIPS (parent->fh, skip) * SKIPS (parent->fh, skip))) / 2.0;
+ double radius = sqrt (double (skips (parent->fw, skip) * skips (parent->fw, skip) + skips (parent->fh, skip) * skips (parent->fh, skip))) / 2.0;
double shradius = params.sh.radius;
if (!params.sh.hq) {
@@ -817,7 +835,8 @@ void Crop::update (int todo)
if (needslocal ) {
// if (tyty ) {
//Glib::ustring datalab2 = parent->imgsrc->getFileName() + ".mip";
- Glib::ustring pop = options.getUserProfilePath() + "/";
+ // Glib::ustring pop = options.getUserProfilePath() + "/";
+ Glib::ustring pop = options.cacheBaseDir + "/mip/";
Glib::ustring datalab;
@@ -1011,7 +1030,7 @@ void Crop::update (int todo)
params.locallab.chromaref = parent->chromarefs[sp];
params.locallab.lumaref = parent->lumarefs[sp];
- parent->ipf.Lab_Local (1, sp, (float**)shbuffer, labnCrop, labnCrop, trafx / skip, trafy / skip, cropx / skip, cropy / skip, SKIPS (parent->fw, skip), SKIPS (parent->fh, skip), parent->fw, parent->fh, locutili, skip, locRETgainCurve, locallutili, lllocalcurve2, loclhCurve, cclocalcurve2, params.locallab.hueref, params.locallab.chromaref, params.locallab.lumaref);
+ parent->ipf.Lab_Local (1, sp, (float**)shbuffer, labnCrop, labnCrop, trafx / skip, trafy / skip, cropx / skip, cropy / skip, skips (parent->fw, skip), skips (parent->fh, skip), parent->fw, parent->fh, locutili, skip, locRETgainCurve, locallutili, lllocalcurve2, loclhCurve, cclocalcurve2, params.locallab.hueref, params.locallab.chromaref, params.locallab.lumaref);
lllocalcurve2.clear();
cclocalcurve2.clear();
@@ -1247,7 +1266,7 @@ void Crop::update (int todo)
params.locallab.chromaref = parent->chromarefs[sp];
params.locallab.lumaref = parent->lumarefs[sp];
- parent->ipf.Lab_Local (1, sp, (float**)shbuffer, labnCrop, labnCrop, trafx / skip, trafy / skip, cropx / skip, cropy / skip, SKIPS (parent->fw, skip), SKIPS (parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(), locutili2, skip, locRETgainCurve, locallutili, lllocalcurve2, loclhCurve, cclocalcurve2, params.locallab.hueref, params.locallab.chromaref, params.locallab.lumaref);
+ parent->ipf.Lab_Local (1, sp, (float**)shbuffer, labnCrop, labnCrop, trafx / skip, trafy / skip, cropx / skip, cropy / skip, skips (parent->fw, skip), skips (parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(), locutili2, skip, locRETgainCurve, locallutili, lllocalcurve2, loclhCurve, cclocalcurve2, params.locallab.hueref, params.locallab.chromaref, params.locallab.lumaref);
lllocalcurve2.clear();
cclocalcurve2.clear();
@@ -1590,12 +1609,11 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
PreviewProps cp (orx, ory, orw, orh, skip);
int orW, orH;
parent->imgsrc->getSize (cp, orW, orH);
+ int cw = skips (bw, skip);
+ int ch = skips (bh, skip);
- int cw = SKIPS (bw, skip);
- int ch = SKIPS (bh, skip);
-
- leftBorder = SKIPS (rqx1 - bx1, skip);
- upperBorder = SKIPS (rqy1 - by1, skip);
+ leftBorder = skips (rqx1 - bx1, skip);
+ upperBorder = skips (rqy1 - by1, skip);
if (settings->verbose) {
printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh, cw, ch);
@@ -1787,5 +1805,22 @@ void Crop::fullUpdate ()
parent->updaterThreadStart.unlock ();
}
+int Crop::get_skip()
+{
+ MyMutex::MyLock lock (cropMutex);
+ return skip;
}
+int Crop::getLeftBorder()
+{
+ MyMutex::MyLock lock (cropMutex);
+ return leftBorder;
+}
+
+int Crop::getUpperBorder()
+{
+ MyMutex::MyLock lock (cropMutex);
+ return upperBorder;
+}
+
+}
diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h
index c2fcc2a63..7fc165008 100644
--- a/rtengine/dcrop.h
+++ b/rtengine/dcrop.h
@@ -16,8 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
*/
-#ifndef _CROP_H_
-#define _CROP_H_
+#pragma once
#include "improccoordinator.h"
#include "rtengine.h"
@@ -59,19 +58,18 @@ protected:
bool updating; /// Flag telling if an updater thread is currently processing
bool newUpdatePending; /// Flag telling the updater thread that a new update is pending
int skip;
- int padding; /// Minimum space allowed around image in the display area
int cropx, cropy, cropw, croph; /// size of the detail crop image ('skip' taken into account), with border
int trafx, trafy, trafw, trafh; /// the size and position to get from the imagesource that is transformed to the requested crop area
int rqcropx, rqcropy, rqcropw, rqcroph; /// size of the requested detail crop image (the image might be smaller) (without border)
- int borderRequested; /// requested extra border size for image processing
+ const int borderRequested; /// requested extra border size for image processing
int upperBorder, leftBorder; /// extra border size really allocated for image processing
bool cropAllocated;
DetailedCropListener* cropImageListener;
MyMutex cropMutex;
- ImProcCoordinator* parent;
- bool isDetailWindow;
+ ImProcCoordinator* const parent;
+ const bool isDetailWindow;
EditUniqueID getCurrEditID();
bool setCropSizes (int cropX, int cropY, int cropW, int cropH, int skip, bool internal);
void freeAll ();
@@ -80,20 +78,8 @@ public:
Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow);
virtual ~Crop ();
// MyMutex* locMutex;
-
- void mLock ()
- {
- cropMutex.lock();
- }
- void mUnlock ()
- {
- cropMutex.lock();
- }
void setEditSubscriber (EditSubscriber* newSubscriber);
- bool hasListener ()
- {
- return cropImageListener;
- }
+ bool hasListener();
void update (int todo);
void setWindow (int cropX, int cropY, int cropW, int cropH, int skip)
{
@@ -109,22 +95,8 @@ public:
void setListener (DetailedCropListener* il);
void destroy ();
- int get_skip ()
- {
- return skip;
- }
- int getPadding ()
- {
- return padding;
- }
- int getLeftBorder ()
- {
- return leftBorder;
- }
- int getUpperBorder ()
- {
- return upperBorder;
- }
+ int get_skip();
+ int getLeftBorder();
+ int getUpperBorder();
};
}
-#endif
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 48342087b..a32e574d9 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -739,7 +739,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
// printf("mip file=%s \n", datalab.c_str());
- Glib::ustring pop = options.getUserProfilePath() + "/";
+ // Glib::ustring pop = options.getUserProfilePath() + "/";
+ Glib::ustring pop = options.cacheBaseDir + "/mip/";
+
Glib::ustring datal;
diff --git a/rtengine/opthelper.h b/rtengine/opthelper.h
index bee97f6b2..4b34fc58f 100644
--- a/rtengine/opthelper.h
+++ b/rtengine/opthelper.h
@@ -69,7 +69,7 @@
#define ALIGNED64
#define ALIGNED16
#endif
- #if !defined(__clang__) && defined _OPENMP
+ #if defined _OPENMP
#define _RT_NESTED_OPENMP
#endif
#endif
diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc
index dc91da64d..bfe7092f2 100644
--- a/rtengine/rawimage.cc
+++ b/rtengine/rawimage.cc
@@ -435,6 +435,10 @@ int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistene
return 2;
}
+ if(xtransCompressed) {
+ parse_xtrans_header();
+ }
+
if (flip == 5) {
this->rotate_deg = 270;
} else if (flip == 3) {
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 0e61c8086..da6f139b6 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -949,7 +949,9 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
//Glib::ustring datalab = imgsrc->getFileName() + ".mip";
- Glib::ustring pop = options.getUserProfilePath() + "/";
+ // Glib::ustring pop = options.getUserProfilePath() + "/";
+ Glib::ustring pop = options.cacheBaseDir + "/mip/";
+
Glib::ustring datalab;
if (options.mip == MI_opt) {
diff --git a/rtengine/xtranscompressed.cc b/rtengine/xtranscompressed.cc
new file mode 100644
index 000000000..854ffec2f
--- /dev/null
+++ b/rtengine/xtranscompressed.cc
@@ -0,0 +1,800 @@
+/* -*- C++ -*-
+ * File: xtranscompressed.cpp
+ * Copyright (C) 2016 Alexey Danilchenko
+ *
+ * Adopted to LibRaw by Alex Tutubalin, lexa@lexa.ru
+ * LibRaw Fujifilm/compressed decoder
+
+LibRaw is free software; you can redistribute it and/or modify
+it under the terms of the one of three licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+ (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+ * Adopted to RawTherapee by Ingo Weyrich
+
+ */
+
+void CLASS init_xtrans (struct xtrans_params* info)
+{
+ int cur_val, i;
+ char *qt;
+
+ if (fuji_block_width % 3) {
+ derror();
+ }
+
+ info->q_table = (char *) malloc (32768);
+ merror (info->q_table, "init_xtrans()");
+
+ info->line_width = (fuji_block_width * 2) / 3;
+
+ info->q_point[0] = 0;
+ info->q_point[1] = 0x12;
+ info->q_point[2] = 0x43;
+ info->q_point[3] = 0x114;
+ info->q_point[4] = (1 << fuji_bits) - 1;
+ info->min_value = 0x40;
+
+ cur_val = -info->q_point[4];
+
+ for (qt = info->q_table; cur_val <= info->q_point[4]; ++qt, ++cur_val) {
+ if (cur_val <= -info->q_point[3]) {
+ *qt = -4;
+ } else if (cur_val <= -info->q_point[2]) {
+ *qt = -3;
+ } else if (cur_val <= -info->q_point[1]) {
+ *qt = -2;
+ } else if (cur_val < 0) {
+ *qt = -1;
+ } else if (cur_val == 0) {
+ *qt = 0;
+ } else if (cur_val < info->q_point[1]) {
+ *qt = 1;
+ } else if (cur_val < info->q_point[2]) {
+ *qt = 2;
+ } else if (cur_val < info->q_point[3]) {
+ *qt = 3;
+ } else {
+ *qt = 4;
+ }
+ }
+
+ // populting gradients
+ if (info->q_point[4] == 0x3FFF) {
+ info->total_values = 0x4000;
+ info->raw_bits = 14;
+ info->max_bits = 56;
+ info->maxDiff = 256;
+ } else if (info->q_point[4] == 0xFFF) {
+ info->total_values = 4096;
+ info->raw_bits = 12;
+ info->max_bits = 48;
+ info->maxDiff = 64;
+ } else {
+ derror();
+ }
+}
+
+#define XTRANS_BUF_SIZE 0x10000u
+
+void CLASS fuji_fill_buffer (struct xtrans_block *info)
+{
+ if (info->cur_pos >= info->cur_buf_size) {
+ info->cur_pos = 0;
+ info->cur_buf_offset += info->cur_buf_size;
+#ifdef _OPENMP
+ #pragma omp critical
+#endif
+ {
+ fseek (info->input, info->cur_buf_offset, SEEK_SET);
+ info->cur_buf_size = fread (info->cur_buf, 1, std::min (info->max_read_size, XTRANS_BUF_SIZE), info->input);
+ }
+ if (info->cur_buf_size < 1) // nothing read
+ ;//throw LIBRAW_EXCEPTION_IO_EOF;
+
+ info->max_read_size -= info->cur_buf_size;
+ }
+}
+
+void CLASS init_xtrans_block (struct xtrans_block* info, const struct xtrans_params *params, INT64 raw_offset, unsigned dsize)
+{
+ info->linealloc = (ushort*)calloc (sizeof (ushort), _ltotal * (params->line_width + 2));
+ merror (info->linealloc, "init_xtrans_block()");
+
+ info->input = ifp;
+ INT64 fsize = info->input->size;
+ info->max_read_size = std::min (unsigned (fsize - raw_offset), dsize + 16); // Data size may be incorrect?
+
+ info->linebuf[_R0] = info->linealloc;
+
+ for (int i = _R1; i <= _B4; i++) {
+ info->linebuf[i] = info->linebuf[i - 1] + params->line_width + 2;
+ }
+
+ // init buffer
+ info->cur_buf = (uchar*)malloc (XTRANS_BUF_SIZE);
+ merror (info->cur_buf, "init_xtrans_block()");
+ info->cur_bit = 0;
+ info->cur_pos = 0;
+ info->cur_buf_offset = raw_offset;
+
+ for (int j = 0; j < 3; j++)
+ for (int i = 0; i < 41; i++) {
+ info->grad_even[j][i].value1 = params->maxDiff;
+ info->grad_even[j][i].value2 = 1;
+ info->grad_odd[j][i].value1 = params->maxDiff;
+ info->grad_odd[j][i].value2 = 1;
+ }
+
+ info->cur_buf_size = 0;
+ fuji_fill_buffer (info);
+}
+
+void CLASS copy_line_to_xtrans (struct xtrans_block* info, int cur_line, int cur_block, int cur_block_width)
+{
+ ushort *lineBufB[3];
+ ushort *lineBufG[6];
+ ushort *lineBufR[3];
+ unsigned pixel_count;
+ ushort* line_buf;
+ int index;
+
+ int offset = fuji_block_width * cur_block + 6 * raw_width * cur_line;
+ ushort* raw_block_data = raw_image + offset;
+ int row_count = 0;
+
+ for (int i = 0; i < 3; i++) {
+ lineBufR[i] = info->linebuf[_R2 + i] + 1;
+ lineBufB[i] = info->linebuf[_B2 + i] + 1;
+ }
+
+ for (int i = 0; i < 6; i++) {
+ lineBufG[i] = info->linebuf[_G2 + i] + 1;
+ }
+
+ while (row_count < 6) {
+ pixel_count = 0;
+
+ while (pixel_count < cur_block_width) {
+ switch (xtrans_abs[row_count][ (pixel_count % 6)]) {
+ case 0: // red
+ line_buf = lineBufR[row_count >> 1];
+ break;
+
+ case 1: // green
+ line_buf = lineBufG[row_count];
+ break;
+
+ case 2: // blue
+ line_buf = lineBufB[row_count >> 1];
+ break;
+ }
+
+ index = (((pixel_count * 2 / 3) & 0x7FFFFFFE) | (pixel_count % 3) & 1) + ((pixel_count % 3) >> 1);
+ raw_block_data[pixel_count] = line_buf[index];
+
+ ++pixel_count;
+ }
+
+ ++row_count;
+ raw_block_data += raw_width;
+ }
+}
+
+#define fuji_quant_gradient(i,v1,v2) (9*i->q_table[i->q_point[4]+(v1)] + i->q_table[i->q_point[4]+(v2)])
+
+void CLASS fuji_zerobits (struct xtrans_block* info, int *count)
+{
+ uchar zero = 0;
+ *count = 0;
+
+ while (zero == 0) {
+ zero = (info->cur_buf[info->cur_pos] >> (7 - info->cur_bit)) & 1;
+ info->cur_bit++;
+ info->cur_bit &= 7;
+
+ if (!info->cur_bit) {
+ ++info->cur_pos;
+ fuji_fill_buffer (info);
+ }
+
+ if (zero) {
+ break;
+ }
+
+ ++*count;
+ }
+}
+
+void CLASS fuji_read_code (struct xtrans_block* info, int *data, int bits_to_read)
+{
+ uchar bits_left = bits_to_read;
+ uchar bits_left_in_byte = 8 - (info->cur_bit & 7);
+ *data = 0;
+
+ if (!bits_to_read) {
+ return;
+ }
+
+ if (bits_to_read >= bits_left_in_byte) {
+ do {
+ *data <<= bits_left_in_byte;
+ bits_left -= bits_left_in_byte;
+ *data |= info->cur_buf[info->cur_pos] & ((1 << bits_left_in_byte) - 1);
+ ++info->cur_pos;
+ fuji_fill_buffer (info);
+ bits_left_in_byte = 8;
+ } while (bits_left >= 8);
+ }
+
+ if (!bits_left) {
+ info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7;
+ return;
+ }
+
+ *data <<= bits_left;
+ bits_left_in_byte -= bits_left;
+ *data |= ((1 << bits_left) - 1) & ((unsigned)info->cur_buf[info->cur_pos] >> bits_left_in_byte);
+ info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7;
+}
+
+int CLASS bitDiff (int value1, int value2)
+{
+ int decBits = 0;
+
+ if ( value2 < value1 )
+ while (decBits <= 12 && (value2 << ++decBits) < value1)
+ ;
+
+ return decBits;
+}
+
+int CLASS fuji_decode_sample_even (struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads)
+{
+ int interp_val = 0;
+ int errcnt = 0;
+
+ int sample = 0, code = 0;
+ ushort* line_buf_cur = line_buf + pos;
+ int Rb = line_buf_cur[-2 - params->line_width];
+ int Rc = line_buf_cur[-3 - params->line_width];
+ int Rd = line_buf_cur[-1 - params->line_width];
+ int Rf = line_buf_cur[-4 - 2 * params->line_width];
+
+ int grad, gradient, diffRcRb, diffRfRb, diffRdRb;
+
+ grad = fuji_quant_gradient (params, Rb - Rf, Rc - Rb);
+ gradient = std::abs (grad);
+ diffRcRb = std::abs (Rc - Rb);
+ diffRfRb = std::abs (Rf - Rb);
+ diffRdRb = std::abs (Rd - Rb);
+
+ if ( diffRcRb > diffRfRb && diffRcRb > diffRdRb ) {
+ interp_val = Rf + Rd + 2 * Rb;
+ } else if ( diffRdRb > diffRcRb && diffRdRb > diffRfRb ) {
+ interp_val = Rf + Rc + 2 * Rb;
+ } else {
+ interp_val = Rd + Rc + 2 * Rb;
+ }
+
+
+ fuji_zerobits (info, &sample);
+
+ if (sample < params->max_bits - params->raw_bits - 1) {
+ int decBits = bitDiff (grads[gradient].value1, grads[gradient].value2);
+ fuji_read_code (info, &code, decBits);
+ code += sample << decBits;
+ } else {
+ fuji_read_code (info, &code, params->raw_bits);
+ code++;
+ }
+
+ if (code < 0 || code >= params->total_values) {
+ errcnt++;
+ }
+
+ if (code & 1) {
+ code = -1 - code / 2;
+ } else {
+ code /= 2;
+ }
+
+ grads[gradient].value1 += std::abs (code);
+
+ if (grads[gradient].value2 == params->min_value ) {
+ grads[gradient].value1 >>= 1;
+ grads[gradient].value2 >>= 1;
+ }
+
+ grads[gradient].value2++;
+
+ if (grad < 0) {
+ interp_val = (interp_val >> 2) - code;
+ } else {
+ interp_val = (interp_val >> 2) + code;
+ }
+
+ if ( interp_val < 0 ) {
+ interp_val += params->total_values;
+ } else if (interp_val > params->q_point[4]) {
+ interp_val -= params->total_values;
+ }
+
+ if ( interp_val >= 0 ) {
+ line_buf_cur[0] = std::min (interp_val, params->q_point[4]);
+ } else {
+ line_buf_cur[0] = 0;
+ }
+
+ return errcnt;
+}
+
+int CLASS fuji_decode_sample_odd (struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads)
+{
+ int interp_val = 0;
+ int errcnt = 0;
+
+ int sample = 0, code = 0;
+ ushort* line_buf_cur = line_buf + pos;
+ int Ra = line_buf_cur[-1];
+ int Rb = line_buf_cur[-2 - params->line_width];
+ int Rc = line_buf_cur[-3 - params->line_width];
+ int Rd = line_buf_cur[-1 - params->line_width];
+ int Rg = line_buf_cur[1];
+
+ int grad, gradient;
+
+ grad = fuji_quant_gradient (params, Rb - Rc, Rc - Ra);
+ gradient = std::abs (grad);
+
+ if ((Rb > Rc && Rb > Rd) || (Rb < Rc && Rb < Rd)) {
+ interp_val = (Rg + Ra + 2 * Rb) >> 2;
+ } else {
+ interp_val = (Ra + Rg) >> 1;
+ }
+
+ fuji_zerobits (info, &sample);
+
+ if (sample < params->max_bits - params->raw_bits - 1) {
+ int decBits = bitDiff (grads[gradient].value1, grads[gradient].value2);
+ fuji_read_code (info, &code, decBits);
+ code += sample << decBits;
+ } else {
+ fuji_read_code (info, &code, params->raw_bits);
+ code++;
+ }
+
+ if (code < 0 || code >= params->total_values) {
+ errcnt++;
+ }
+
+ if (code & 1) {
+ code = -1 - code / 2;
+ } else {
+ code /= 2;
+ }
+
+ grads[gradient].value1 += std::abs (code);
+
+ if (grads[gradient].value2 == params->min_value) {
+ grads[gradient].value1 >>= 1;
+ grads[gradient].value2 >>= 1;
+ }
+
+ grads[gradient].value2++;
+
+ if (grad < 0) {
+ interp_val -= code;
+ } else {
+ interp_val += code;
+ }
+
+ if ( interp_val < 0 ) {
+ interp_val += params->total_values;
+ } else if (interp_val > params->q_point[4]) {
+ interp_val -= params->total_values;
+ }
+
+ if ( interp_val >= 0 ) {
+ line_buf_cur[0] = std::min(interp_val, params->q_point[4]);
+ } else {
+ line_buf_cur[0] = 0;
+ }
+
+ return errcnt;
+}
+
+void CLASS fuji_decode_interpolation_even (int line_width, ushort* line_buf, int pos)
+{
+ ushort* line_buf_cur = line_buf + pos;
+ int Rb = line_buf_cur[-2 - line_width];
+ int Rc = line_buf_cur[-3 - line_width];
+ int Rd = line_buf_cur[-1 - line_width];
+ int Rf = line_buf_cur[-4 - 2 * line_width];
+ int diffRcRb = std::abs (Rc - Rb);
+ int diffRfRb = std::abs (Rf - Rb);
+ int diffRdRb = std::abs (Rd - Rb);
+
+ if ( diffRcRb > diffRfRb && diffRcRb > diffRdRb ) {
+ *line_buf_cur = (Rf + Rd + 2 * Rb) >> 2;
+ } else if ( diffRdRb > diffRcRb && diffRdRb > diffRfRb ) {
+ *line_buf_cur = (Rf + Rc + 2 * Rb) >> 2;
+ } else {
+ *line_buf_cur = (Rd + Rc + 2 * Rb) >> 2;
+ }
+}
+
+void CLASS xtrans_extend_generic (ushort *linebuf[_ltotal], int line_width, int start, int end)
+{
+ for (int i = start; i <= end; i++) {
+ linebuf[i][0] = linebuf[i - 1][1];
+ linebuf[i][line_width + 1] = linebuf[i - 1][line_width];
+ }
+}
+
+void CLASS xtrans_extend_red (ushort *linebuf[_ltotal], int line_width)
+{
+ xtrans_extend_generic (linebuf, line_width, _R2, _R4);
+}
+
+void CLASS xtrans_extend_green (ushort *linebuf[_ltotal], int line_width)
+{
+ xtrans_extend_generic (linebuf, line_width, _G2, _G7);
+}
+
+void CLASS xtrans_extend_blue (ushort *linebuf[_ltotal], int line_width)
+{
+ xtrans_extend_generic (linebuf, line_width, _B2, _B4);
+}
+
+void CLASS xtrans_decode_block (struct xtrans_block* info, const struct xtrans_params *params, int cur_line)
+{
+ int r_even_pos = 0, r_odd_pos = 1;
+ int g_even_pos = 0, g_odd_pos = 1;
+ int b_even_pos = 0, b_odd_pos = 1;
+
+ int errcnt = 0;
+
+ const int line_width = params->line_width;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width) {
+ if (g_even_pos < line_width) {
+ fuji_decode_interpolation_even (line_width, info->linebuf[_R2] + 1, r_even_pos);
+ r_even_pos += 2;
+ errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G2] + 1, g_even_pos, info->grad_even[0]);
+ g_even_pos += 2;
+ }
+
+ if (g_even_pos > 8) {
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_R2] + 1, r_odd_pos, info->grad_odd[0]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G2] + 1, g_odd_pos, info->grad_odd[0]);
+ g_odd_pos += 2;
+ }
+ }
+
+ xtrans_extend_red (info->linebuf, line_width);
+ xtrans_extend_green (info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width) {
+ if (g_even_pos < line_width) {
+ errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G3] + 1, g_even_pos, info->grad_even[1]);
+ g_even_pos += 2;
+ fuji_decode_interpolation_even (line_width, info->linebuf[_B2] + 1, b_even_pos);
+ b_even_pos += 2;
+ }
+
+ if (g_even_pos > 8) {
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G3] + 1, g_odd_pos, info->grad_odd[1]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_B2] + 1, b_odd_pos, info->grad_odd[1]);
+ b_odd_pos += 2;
+ }
+ }
+
+ xtrans_extend_green (info->linebuf, line_width);
+ xtrans_extend_blue (info->linebuf, line_width);
+
+ r_even_pos = 0, r_odd_pos = 1;
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width) {
+ if (g_even_pos < line_width) {
+ if (r_even_pos & 3) {
+ errcnt += fuji_decode_sample_even (info, params, info->linebuf[_R3] + 1, r_even_pos, info->grad_even[2]);
+ } else {
+ fuji_decode_interpolation_even (line_width, info->linebuf[_R3] + 1, r_even_pos);
+ }
+
+ r_even_pos += 2;
+ fuji_decode_interpolation_even (line_width, info->linebuf[_G4] + 1, g_even_pos);
+ g_even_pos += 2;
+ }
+
+ if (g_even_pos > 8) {
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_R3] + 1, r_odd_pos, info->grad_odd[2]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G4] + 1, g_odd_pos, info->grad_odd[2]);
+ g_odd_pos += 2;
+ }
+ }
+
+ xtrans_extend_red (info->linebuf, line_width);
+ xtrans_extend_green (info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+ b_even_pos = 0, b_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width) {
+ if (g_even_pos < line_width) {
+ errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G5] + 1, g_even_pos, info->grad_even[0]);
+ g_even_pos += 2;
+
+ if ((b_even_pos & 3) == 2) {
+ fuji_decode_interpolation_even (line_width, info->linebuf[_B3] + 1, b_even_pos);
+ } else {
+ errcnt += fuji_decode_sample_even (info, params, info->linebuf[_B3] + 1, b_even_pos, info->grad_even[0]);
+ }
+
+ b_even_pos += 2;
+ }
+
+ if (g_even_pos > 8) {
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G5] + 1, g_odd_pos, info->grad_odd[0]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_B3] + 1, b_odd_pos, info->grad_odd[0]);
+ b_odd_pos += 2;
+ }
+ }
+
+ xtrans_extend_green (info->linebuf, line_width);
+ xtrans_extend_blue (info->linebuf, line_width);
+
+ r_even_pos = 0, r_odd_pos = 1;
+ g_even_pos = 0, g_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width) {
+ if (g_even_pos < line_width) {
+ if ((r_even_pos & 3) == 2) {
+ fuji_decode_interpolation_even (line_width, info->linebuf[_R4] + 1, r_even_pos);
+ } else {
+ errcnt += fuji_decode_sample_even (info, params, info->linebuf[_R4] + 1, r_even_pos, info->grad_even[1]);
+ }
+
+ r_even_pos += 2;
+ errcnt += fuji_decode_sample_even (info, params, info->linebuf[_G6] + 1, g_even_pos, info->grad_even[1]);
+ g_even_pos += 2;
+ }
+
+ if (g_even_pos > 8) {
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_R4] + 1, r_odd_pos, info->grad_odd[1]);
+ r_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G6] + 1, g_odd_pos, info->grad_odd[1]);
+ g_odd_pos += 2;
+ }
+ }
+
+ xtrans_extend_red (info->linebuf, line_width);
+ xtrans_extend_green (info->linebuf, line_width);
+
+ g_even_pos = 0, g_odd_pos = 1;
+ b_even_pos = 0, b_odd_pos = 1;
+
+ while (g_even_pos < line_width || g_odd_pos < line_width) {
+ if (g_even_pos < line_width) {
+ fuji_decode_interpolation_even (line_width, info->linebuf[_G7] + 1, g_even_pos);
+ g_even_pos += 2;
+
+ if (b_even_pos & 3) {
+ errcnt += fuji_decode_sample_even (info, params, info->linebuf[_B4] + 1, b_even_pos, info->grad_even[2]);
+ } else {
+ fuji_decode_interpolation_even (line_width, info->linebuf[_B4] + 1, b_even_pos);
+ }
+
+ b_even_pos += 2;
+ }
+
+ if (g_even_pos > 8) {
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_G7] + 1, g_odd_pos, info->grad_odd[2]);
+ g_odd_pos += 2;
+ errcnt += fuji_decode_sample_odd (info, params, info->linebuf[_B4] + 1, b_odd_pos, info->grad_odd[2]);
+ b_odd_pos += 2;
+ }
+ }
+
+ xtrans_extend_green (info->linebuf, line_width);
+ xtrans_extend_blue (info->linebuf, line_width);
+
+ if (errcnt) {
+ derror();
+ }
+}
+
+void CLASS xtrans_decode_strip (const struct xtrans_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize)
+{
+ int cur_block_width, cur_line;
+ unsigned line_size;
+ struct xtrans_block info;
+
+ init_xtrans_block (&info, info_common, raw_offset, dsize);
+ line_size = sizeof (ushort) * (info_common->line_width + 2);
+
+ cur_block_width = fuji_block_width;
+
+ if (cur_block + 1 == fuji_total_blocks) {
+ cur_block_width = raw_width % fuji_block_width;
+ }
+
+ struct i_pair {
+ int a, b;
+ };
+
+ const i_pair mtable[6] = { {_R0, _R3}, {_R1, _R4}, {_G0, _G6}, {_G1, _G7}, {_B0, _B3}, {_B1, _B4}},
+ ztable[3] = {{_R2, 3}, {_G2, 6}, {_B2, 3}};
+
+ for (cur_line = 0; cur_line < fuji_total_lines; cur_line++) {
+ xtrans_decode_block (&info, info_common, cur_line);
+
+ // copy data from line buffers and advance
+ for (int i = 0; i < 6; i++) {
+ memcpy (info.linebuf[mtable[i].a], info.linebuf[mtable[i].b], line_size);
+ }
+
+ copy_line_to_xtrans (&info, cur_line, cur_block, cur_block_width);
+
+ for (int i = 0; i < 3; i++) {
+ memset (info.linebuf[ztable[i].a], 0, ztable[i].b * line_size);
+ info.linebuf[ztable[i].a][0] = info.linebuf[ztable[i].a - 1][1];
+ info.linebuf[ztable[i].a][info_common->line_width + 1] = info.linebuf[ztable[i].a - 1][info_common->line_width];
+ }
+ }
+
+ // release data
+ free (info.linealloc);
+ free (info.cur_buf);
+}
+
+static unsigned sgetn (int n, uchar *s)
+{
+ unsigned result = 0;
+
+ while (n-- > 0) {
+ result = (result << 8) | (*s++);
+ }
+
+ return result;
+}
+
+void CLASS xtrans_compressed_load_raw()
+{
+ struct xtrans_params common_info;
+ int cur_block;
+ unsigned line_size, *block_sizes;
+ INT64 raw_offset, *raw_block_offsets;
+ //struct xtrans_block info;
+
+ init_xtrans (&common_info);
+ line_size = sizeof (ushort) * (common_info.line_width + 2);
+
+ // read block sizes
+ block_sizes = (unsigned*) malloc (sizeof (unsigned) * fuji_total_blocks);
+ merror (block_sizes, "xtrans_load_raw()");
+ raw_block_offsets = (INT64*) malloc (sizeof (INT64) * fuji_total_blocks);
+ merror (raw_block_offsets, "xtrans_load_raw()");
+
+ raw_offset = sizeof (unsigned) * fuji_total_blocks;
+
+ if (raw_offset & 0xC) {
+ raw_offset += 0x10 - (raw_offset & 0xC);
+ }
+
+ raw_offset += data_offset;
+
+ fseek (ifp, data_offset, SEEK_SET);
+ fread (block_sizes, 1, sizeof (unsigned)*fuji_total_blocks, ifp);
+
+ raw_block_offsets[0] = raw_offset;
+
+ // calculating raw block offsets
+ for (cur_block = 0; cur_block < fuji_total_blocks; cur_block++) {
+ unsigned bsize = sgetn (4, (uchar *) (block_sizes + cur_block));
+ block_sizes[cur_block] = bsize;
+ }
+
+ for (cur_block = 1; cur_block < fuji_total_blocks; cur_block++) {
+ raw_block_offsets[cur_block] = raw_block_offsets[cur_block - 1] + block_sizes[cur_block - 1] ;
+ }
+
+ xtrans_decode_loop (&common_info, fuji_total_blocks, raw_block_offsets, block_sizes);
+
+ free (block_sizes);
+ free (raw_block_offsets);
+ free (common_info.q_table);
+}
+
+void CLASS xtrans_decode_loop (const struct xtrans_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes)
+{
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int cur_block = 0; cur_block < count ; cur_block++) {
+ xtrans_decode_strip (common_info, cur_block, raw_block_offsets[cur_block], block_sizes[cur_block]);
+ }
+}
+
+
+void CLASS parse_xtrans_header()
+{
+
+ uchar header[16];
+
+ ushort signature;
+ uchar version;
+ uchar h_raw_type;
+ uchar h_raw_bits;
+ ushort h_raw_height;
+ ushort h_raw_rounded_width;
+ ushort h_raw_width;
+ ushort h_block_size;
+ uchar h_blocks_in_row;
+ ushort h_total_lines;
+
+ fseek (ifp, data_offset, SEEK_SET);
+ fread (header, 1, sizeof (header), ifp);
+
+ signature = sgetn (2, header);
+ version = header[2];
+ h_raw_type = header[3];
+ h_raw_bits = header[4];
+ h_raw_height = sgetn (2, header + 5);
+ h_raw_rounded_width = sgetn (2, header + 7);
+ h_raw_width = sgetn (2, header + 9);
+ h_block_size = sgetn (2, header + 11);
+ h_blocks_in_row = header[13];
+ h_total_lines = sgetn (2, header + 14);
+
+
+ // general validation
+ if (signature != 0x4953
+ || version != 1
+ || h_raw_height > 0x3000
+ || h_raw_height < 6
+ || h_raw_height % 6
+ || h_raw_width > 0x3000
+ || h_raw_width < 0x300
+ || h_raw_width % 24
+ || h_raw_rounded_width > 0x3000
+ || h_raw_rounded_width < h_block_size
+ || h_raw_rounded_width % h_block_size
+ || h_raw_rounded_width - h_raw_width >= h_block_size
+ || h_block_size != 0x300
+ || h_blocks_in_row > 0x10
+ || h_blocks_in_row == 0
+ || h_blocks_in_row != h_raw_rounded_width / h_block_size
+ || h_total_lines > 0x800
+ || h_total_lines == 0
+ || h_total_lines != h_raw_height / 6
+ || (h_raw_bits != 12 && h_raw_bits != 14)
+ || h_raw_type != 16) {
+ xtransCompressed = false;
+ return;
+ }
+
+ // modify data
+ fuji_total_lines = h_total_lines;
+ fuji_total_blocks = h_blocks_in_row;
+ fuji_block_width = h_block_size;
+ fuji_bits = h_raw_bits;
+ raw_width = h_raw_width;
+ raw_height = h_raw_height;
+ data_offset += 16;
+ load_raw = &CLASS xtrans_compressed_load_raw;
+}
diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc
index fbe2be4c6..7bd53c444 100644
--- a/rtgui/batchqueue.cc
+++ b/rtgui/batchqueue.cc
@@ -85,6 +85,8 @@ BatchQueue::BatchQueue (FileCatalog* aFileCatalog) : processing(nullptr), fileCa
BatchQueue::~BatchQueue ()
{
+ idle_register.destroy();
+
MYWRITERLOCK(l, entryRW);
// The listener merges parameters with old values, so delete afterwards
@@ -937,7 +939,7 @@ void BatchQueue::notifyListener (bool queueEmptied)
}
params->queueEmptied = queueEmptied;
params->queueError = false;
- add_idle (bqnotifylistenerUI, params);
+ idle_register.add(bqnotifylistenerUI, params);
}
}
@@ -967,6 +969,6 @@ void BatchQueue::error (Glib::ustring msg)
params->queueEmptied = false;
params->queueError = true;
params->queueErrorMessage = msg;
- add_idle (bqnotifylistenerUI, params);
+ idle_register.add(bqnotifylistenerUI, params);
}
}
diff --git a/rtgui/batchqueue.h b/rtgui/batchqueue.h
index f7376680b..68373838e 100644
--- a/rtgui/batchqueue.h
+++ b/rtgui/batchqueue.h
@@ -36,37 +36,12 @@ public:
};
class FileCatalog;
-class BatchQueue : public ThumbBrowserBase,
+
+class BatchQueue final :
+ public ThumbBrowserBase,
public rtengine::BatchProcessingListener,
public LWButtonListener
{
-
-protected:
- int getMaxThumbnailHeight() const;
- void saveThumbnailHeight (int height);
- int getThumbnailHeight ();
-
- BatchQueueEntry* processing; // holds the currently processed image
- FileCatalog* fileCatalog;
- int sequence; // holds the current sequence index
-
- Glib::ustring nameTemplate;
-
- MyImageMenuItem* cancel;
- MyImageMenuItem* head;
- MyImageMenuItem* tail;
- Gtk::MenuItem* selall;
- Gtk::MenuItem* open;
- Glib::RefPtr pmaccelgroup;
- Gtk::Menu pmenu;
-
- BatchQueueListener* listener;
-
- Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format);
- Glib::ustring getTempFilenameForParams( const Glib::ustring &filename );
- bool saveBatchQueue ();
- void notifyListener (bool queueEmptied);
-
public:
explicit BatchQueue (FileCatalog* aFileCatalog);
~BatchQueue ();
@@ -106,6 +81,34 @@ public:
static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName, int sequence = 0);
static int calcMaxThumbnailHeight();
+
+protected:
+ int getMaxThumbnailHeight() const;
+ void saveThumbnailHeight (int height);
+ int getThumbnailHeight ();
+
+ Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format);
+ Glib::ustring getTempFilenameForParams( const Glib::ustring &filename );
+ bool saveBatchQueue ();
+ void notifyListener (bool queueEmptied);
+
+ BatchQueueEntry* processing; // holds the currently processed image
+ FileCatalog* fileCatalog;
+ int sequence; // holds the current sequence index
+
+ Glib::ustring nameTemplate;
+
+ MyImageMenuItem* cancel;
+ MyImageMenuItem* head;
+ MyImageMenuItem* tail;
+ Gtk::MenuItem* selall;
+ Gtk::MenuItem* open;
+ Glib::RefPtr pmaccelgroup;
+ Gtk::Menu pmenu;
+
+ BatchQueueListener* listener;
+
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc
index dab459a14..67dd9f64a 100644
--- a/rtgui/blackwhite.cc
+++ b/rtgui/blackwhite.cc
@@ -364,23 +364,25 @@ BlackWhite::BlackWhite (): FoldableToolPanel(this, "blackwhite", M("TP_BWMIX_LAB
}
BlackWhite::~BlackWhite ()
{
+ idle_register.destroy();
+
delete luminanceCEG;
delete beforeCurveCEG;
delete afterCurveCEG;
}
-int BWChangedUI (void* data)
-{
- (static_cast(data))->BWComputed_ ();
- return 0;
-}
-
void BlackWhite::BWChanged (double redbw, double greenbw, double bluebw)
{
nextredbw = redbw;
nextgreenbw = greenbw;
nextbluebw = bluebw;
- add_idle (BWChangedUI, this);
+
+ const auto func = [](gpointer data) -> gboolean {
+ static_cast(data)->BWComputed_();
+ return FALSE;
+ };
+
+ idle_register.add(func, this);
}
bool BlackWhite::BWComputed_ ()
diff --git a/rtgui/blackwhite.h b/rtgui/blackwhite.h
index e38258b04..5f0ffec44 100644
--- a/rtgui/blackwhite.h
+++ b/rtgui/blackwhite.h
@@ -28,10 +28,64 @@
#include "mycurve.h"
#include "colorprovider.h"
-class BlackWhite : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoBWListener, public CurveListener, public ColorProvider
+class BlackWhite final :
+ public ToolParamBlock,
+ public AdjusterListener,
+ public FoldableToolPanel,
+ public rtengine::AutoBWListener,
+ public CurveListener,
+ public ColorProvider
{
+public:
+
+ BlackWhite ();
+ ~BlackWhite ();
+
+ void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
+ void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
+ void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
+ void setBatchMode (bool batchMode);
+ void autoOpenCurve ();
+ void setEditProvider (EditDataProvider *provider);
+
+ void autoch_toggled ();
+ void neutral_pressed ();
+
+ void updateRGBLabel ();
+ void adjusterChanged (Adjuster* a, double newval);
+ void setAdjusterBehavior (bool bwadd, bool bwgadd);
+ void trimValues (rtengine::procparams::ProcParams* pp);
+ void enabledcc_toggled ();
+ void enabledChanged ();
+ void methodChanged ();
+ void filterChanged ();
+ void settingChanged ();
+ virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller);
+ void BWChanged (double redbw, double greenbw, double bluebw);
+ bool BWComputed_ ();
+ void curveChanged (CurveEditor* ce);
+ void curveMode1Changed ();
+ bool curveMode1Changed_ ();
+ void curveMode1Changed2 ();
+ bool curveMode1Changed2_ ();
+ void algoChanged ();
+
+ Glib::ustring getSettingString ();
+ Glib::ustring getFilterString ();
+ Glib::ustring getalgoString ();
+
+private:
+ void showLuminance();
+ void hideLuminance();
+ void showFilter();
+ void hideFilter();
+ void showEnabledCC();
+ void hideEnabledCC();
+ void showMixer(int nChannels, bool RGBIsSensitive = true);
+ void hideMixer();
+ void showGamma();
+ void hideGamma();
-protected:
FlatCurveEditor* luminanceCurve;
Gtk::HSeparator* luminanceSep;
CurveEditorGroup* luminanceCEG;
@@ -85,55 +139,7 @@ protected:
double nextgreenbw;
double nextbluebw;
- void showLuminance();
- void hideLuminance();
- void showFilter();
- void hideFilter();
- void showEnabledCC();
- void hideEnabledCC();
- void showMixer(int nChannels, bool RGBIsSensitive = true);
- void hideMixer();
- void showGamma();
- void hideGamma();
-
-public:
-
- BlackWhite ();
- ~BlackWhite ();
-
- void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
- void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
- void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
- void setBatchMode (bool batchMode);
- void autoOpenCurve ();
- void setEditProvider (EditDataProvider *provider);
-
- void autoch_toggled ();
- void neutral_pressed ();
-
- void updateRGBLabel ();
- void adjusterChanged (Adjuster* a, double newval);
- void setAdjusterBehavior (bool bwadd, bool bwgadd);
- void trimValues (rtengine::procparams::ProcParams* pp);
- void enabledcc_toggled ();
- void enabledChanged ();
- void methodChanged ();
- void filterChanged ();
- void settingChanged ();
- virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller);
- void BWChanged (double redbw, double greenbw, double bluebw);
- bool BWComputed_ ();
- void curveChanged (CurveEditor* ce);
- void curveMode1Changed ();
- bool curveMode1Changed_ ();
- void curveMode1Changed2 ();
- bool curveMode1Changed2_ ();
- void algoChanged ();
-
- Glib::ustring getSettingString ();
- Glib::ustring getFilterString ();
- Glib::ustring getalgoString ();
-
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc
index 7421711eb..081db2b76 100644
--- a/rtgui/cachemanager.cc
+++ b/rtgui/cachemanager.cc
@@ -19,6 +19,7 @@
#include "cachemanager.h"
#include
+#include
#include
#include
@@ -35,8 +36,8 @@
namespace
{
-constexpr auto cacheDirMode = 511;
-constexpr auto cacheDirs = { "profiles", "images", "aehistograms", "embprofiles", "data" };
+constexpr int cacheDirMode = 0777;
+constexpr const char* cacheDirs[] = { "profiles", "images", "aehistograms", "embprofiles", "data", "mip" };
}
@@ -60,7 +61,7 @@ void CacheManager::init ()
}
if (error != 0 && options.rtSettings.verbose) {
- std::cerr << "Failed to create all cache directories: " << g_strerror(errno) << std::endl;
+ std::cerr << "Failed to create all cache directories: " << g_strerror (errno) << std::endl;
}
}
@@ -76,6 +77,7 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname)
// if it is open, return it
const auto iterator = openEntries.find (fname);
+
if (iterator != openEntries.end ()) {
auto cachedThumbnail = iterator->second;
@@ -99,9 +101,11 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname)
CacheImageData imageData;
const auto error = imageData.load (cacheName);
+
if (error == 0 && imageData.supported) {
thumbnail.reset (new Thumbnail (this, fname, &imageData));
+
if (!thumbnail->isSupported ()) {
thumbnail.reset ();
}
@@ -112,6 +116,7 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname)
if (!thumbnail) {
thumbnail.reset (new Thumbnail (this, fname, md5));
+
if (!thumbnail->isSupported ()) {
thumbnail.reset ();
}
@@ -123,6 +128,7 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname)
MyMutex::MyLock lock (mutex);
const auto iterator = openEntries.find (fname);
+
if (iterator != openEntries.end ()) {
auto cachedThumbnail = iterator->second;
@@ -145,6 +151,7 @@ void CacheManager::deleteEntry (const Glib::ustring& fname)
// check if it is opened
auto iterator = openEntries.find (fname);
+
if (iterator == openEntries.end ()) {
deleteFiles (fname, getMD5 (fname), true, true);
return;
@@ -190,12 +197,13 @@ void CacheManager::renameEntry (const std::string& oldfilename, const std::strin
error |= g_rename (getCacheFileName ("data", oldfilename, ".txt", oldmd5).c_str (), getCacheFileName ("data", newfilename, ".txt", newmd5).c_str ());
if (error != 0 && options.rtSettings.verbose) {
- std::cerr << "Failed to rename all files for cache entry '" << oldfilename << "': " << g_strerror(errno) << std::endl;
+ std::cerr << "Failed to rename all files for cache entry '" << oldfilename << "': " << g_strerror (errno) << std::endl;
}
// check if it is opened
// if it is open, update md5
const auto iterator = openEntries.find (oldfilename);
+
if (iterator == openEntries.end ()) {
return;
}
@@ -256,12 +264,13 @@ void CacheManager::deleteDir (const Glib::ustring& dirName) const
Glib::Dir dir (Glib::build_filename (baseDir, dirName));
auto error = 0;
+
for (auto entry = dir.begin (); entry != dir.end (); ++entry) {
error |= g_remove (Glib::build_filename (baseDir, dirName, *entry).c_str ());
}
if (error != 0 && options.rtSettings.verbose) {
- std::cerr << "Failed to delete all entries in cache directory '" << dirName << "': " << g_strerror(errno) << std::endl;
+ std::cerr << "Failed to delete all entries in cache directory '" << dirName << "': " << g_strerror (errno) << std::endl;
}
} catch (Glib::Error&) {}
@@ -289,7 +298,7 @@ void CacheManager::deleteFiles (const Glib::ustring& fname, const std::string& m
}
if (error != 0 && options.rtSettings.verbose) {
- std::cerr << "Failed to delete all files for cache entry '" << fname << "': " << g_strerror(errno) << std::endl;
+ std::cerr << "Failed to delete all files for cache entry '" << fname << "': " << g_strerror (errno) << std::endl;
}
}
@@ -302,9 +311,10 @@ std::string CacheManager::getMD5 (const Glib::ustring& fname)
#ifdef WIN32
- std::unique_ptr wfname (reinterpret_cast(g_utf8_to_utf16 (fname.c_str (), -1, NULL, NULL, NULL)), g_free);
+ std::unique_ptr wfname (reinterpret_cast (g_utf8_to_utf16 (fname.c_str (), -1, NULL, NULL, NULL)), g_free);
WIN32_FILE_ATTRIBUTE_DATA fileAttr;
+
if (GetFileAttributesExW (wfname.get (), GetFileExInfoStandard, &fileAttr)) {
// We use name, size and creation time to identify a file.
const auto identifier = Glib::ustring::compose ("%1-%2-%3-%4", fileAttr.nFileSizeLow, fileAttr.ftCreationTime.dwHighDateTime, fileAttr.ftCreationTime.dwLowDateTime, fname);
@@ -313,8 +323,7 @@ std::string CacheManager::getMD5 (const Glib::ustring& fname)
#else
- try
- {
+ try {
if (auto info = file->query_info ()) {
// We only use name and size to identify a file.
@@ -322,7 +331,7 @@ std::string CacheManager::getMD5 (const Glib::ustring& fname)
return Glib::Checksum::compute_checksum (Glib::Checksum::CHECKSUM_MD5, identifier);
}
- } catch(Gio::Error&) {}
+ } catch (Gio::Error&) {}
#endif
@@ -332,9 +341,9 @@ std::string CacheManager::getMD5 (const Glib::ustring& fname)
}
Glib::ustring CacheManager::getCacheFileName (const Glib::ustring& subDir,
- const Glib::ustring& fname,
- const Glib::ustring& fext,
- const Glib::ustring& md5) const
+ const Glib::ustring& fname,
+ const Glib::ustring& fext,
+ const Glib::ustring& md5) const
{
const auto dirName = Glib::build_filename (baseDir, subDir);
const auto baseName = Glib::path_get_basename (fname) + "." + md5;
@@ -363,8 +372,7 @@ void CacheManager::applyCacheSizeLimitation () const
return;
}
- std::sort (files.begin (), files.end (), [] (const FNameMTime& lhs, const FNameMTime& rhs)
- {
+ std::sort (files.begin (), files.end (), [] (const FNameMTime & lhs, const FNameMTime & rhs) {
return lhs.second < rhs.second;
});
diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc
index 528047a22..a198dd1f5 100644
--- a/rtgui/colorappearance.cc
+++ b/rtgui/colorappearance.cc
@@ -424,6 +424,8 @@ ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance",
ColorAppearance::~ColorAppearance ()
{
+ idle_register.destroy();
+
delete curveEditorG;
delete curveEditorG2;
delete curveEditorG3;
@@ -1002,15 +1004,17 @@ void ColorAppearance::setDefaults (const ProcParams* defParams, const ParamsEdit
}
}
-int autoCamChangedUI (void* data)
-{
- (static_cast(data))->autoCamComputed_ ();
- return 0;
-}
+
void ColorAppearance::autoCamChanged (double ccam)
{
nextCcam = ccam;
- add_idle (autoCamChangedUI, this);
+
+ const auto func = [](gpointer data) -> gboolean {
+ static_cast(data)->autoCamComputed_();
+ return FALSE;
+ };
+
+ idle_register.add(func, this);
}
bool ColorAppearance::autoCamComputed_ ()
@@ -1023,15 +1027,17 @@ bool ColorAppearance::autoCamComputed_ ()
return false;
}
-int adapCamChangedUI (void* data)
-{
- (static_cast(data))->adapCamComputed_ ();
- return 0;
-}
+
void ColorAppearance::adapCamChanged (double cadap)
{
nextCadap = cadap;
- add_idle (adapCamChangedUI, this);
+
+ const auto func = [](gpointer data) -> gboolean {
+ static_cast(data)->adapCamComputed_();
+ return FALSE;
+ };
+
+ idle_register.add(func, this);
}
bool ColorAppearance::adapCamComputed_ ()
diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h
index 1560e275e..e7b7e072d 100644
--- a/rtgui/colorappearance.h
+++ b/rtgui/colorappearance.h
@@ -28,10 +28,61 @@
#include "guiutils.h"
#include "colorprovider.h"
-class ColorAppearance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoCamListener, public CurveListener, public ColorProvider
+class ColorAppearance final :
+ public ToolParamBlock,
+ public AdjusterListener,
+ public FoldableToolPanel,
+ public rtengine::AutoCamListener,
+ public CurveListener,
+ public ColorProvider
{
+public:
+ ColorAppearance ();
+ ~ColorAppearance ();
+
+ void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
+ void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
+ void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
+ void setBatchMode (bool batchMode);
+ void adjusterChanged (Adjuster* a, double newval);
+ void adjusterAutoToggled (Adjuster* a, bool newval);
+// void adjusterAdapToggled (Adjuster* a, bool newval);
+ void enabledChanged ();
+ void surroundChanged ();
+ void wbmodelChanged ();
+ void algoChanged ();
+ void surrsource_toggled ();
+ void gamut_toggled ();
+// void badpix_toggled ();
+ void datacie_toggled ();
+ void tonecie_toggled ();
+// void sharpcie_toggled ();
+ void autoCamChanged (double ccam);
+ bool autoCamComputed_ ();
+ void adapCamChanged (double cadap);
+ bool adapCamComputed_ ();
+
+ void curveChanged (CurveEditor* ce);
+ void curveMode1Changed ();
+ bool curveMode1Changed_ ();
+ void curveMode2Changed ();
+ bool curveMode2Changed_ ();
+ void curveMode3Changed ();
+ bool curveMode3Changed_ ();
+
+ void expandCurve (bool isExpanded);
+ bool isCurveExpanded ();
+ void autoOpenCurve ();
+
+ void setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd);
+ void trimValues (rtengine::procparams::ProcParams* pp);
+ void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histLRETI);
+ virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller);
+
+private:
+ bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
+ bool srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
-protected:
Glib::RefPtr bgTTips;
Glib::RefPtr srTTips;
Glib::RefPtr bgPixbuf;
@@ -83,56 +134,10 @@ protected:
bool lastAutoAdapscen;
bool lastsurr;
bool lastgamut;
-// bool lastbadpix;
bool lastdatacie;
bool lasttonecie;
-// bool lastsharpcie;
- bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
- bool srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip);
-public:
-
- ColorAppearance ();
- ~ColorAppearance ();
-
- void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
- void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
- void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
- void setBatchMode (bool batchMode);
- void adjusterChanged (Adjuster* a, double newval);
- void adjusterAutoToggled (Adjuster* a, bool newval);
-// void adjusterAdapToggled (Adjuster* a, bool newval);
- void enabledChanged ();
- void surroundChanged ();
- void wbmodelChanged ();
- void algoChanged ();
- void surrsource_toggled ();
- void gamut_toggled ();
-// void badpix_toggled ();
- void datacie_toggled ();
- void tonecie_toggled ();
-// void sharpcie_toggled ();
- void autoCamChanged (double ccam);
- bool autoCamComputed_ ();
- void adapCamChanged (double cadap);
- bool adapCamComputed_ ();
-
- void curveChanged (CurveEditor* ce);
- void curveMode1Changed ();
- bool curveMode1Changed_ ();
- void curveMode2Changed ();
- bool curveMode2Changed_ ();
- void curveMode3Changed ();
- bool curveMode3Changed_ ();
-
- void expandCurve (bool isExpanded);
- bool isCurveExpanded ();
- void autoOpenCurve ();
-
- void setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd);
- void trimValues (rtengine::procparams::ProcParams* pp);
- void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histLRETI);
- virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller);
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc
index ceec0092f..d471ef787 100644
--- a/rtgui/colortoning.cc
+++ b/rtgui/colortoning.cc
@@ -324,6 +324,8 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR
ColorToning::~ColorToning()
{
+ idle_register.destroy();
+
delete colorCurveEditorG;
delete opacityCurveEditorG;
delete clCurveEditorG;
@@ -650,19 +652,18 @@ void ColorToning::adjusterChanged (ThresholdAdjuster* a, double newBottom, doubl
Glib::ustring::compose(Glib::ustring(M("TP_COLORTONING_HUE") + ": %1" + "\n" + M("TP_COLORTONING_STRENGTH") + ": %2"), int(newTop), int(newBottom)));
}
-int CTChanged_UI (void* data)
-{
- (static_cast(data))->CTComp_ ();
- return 0;
-}
-
-
void ColorToning::autoColorTonChanged(int bwct, int satthres, int satprot)
{
nextbw = bwct;
nextsatth = satthres;
nextsatpr = satprot;
- add_idle (CTChanged_UI, this);
+
+ const auto func = [](gpointer data) -> gboolean {
+ static_cast(data)->CTComp_();
+ return FALSE;
+ };
+
+ idle_register.add(func, this);
}
bool ColorToning::CTComp_ ()
diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h
index e34447301..7f1290bf6 100644
--- a/rtgui/colortoning.h
+++ b/rtgui/colortoning.h
@@ -13,12 +13,43 @@
#include "thresholdadjuster.h"
#include "colorprovider.h"
-class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rtengine::AutoColorTonListener, public CurveListener, public ColorProvider,
- public ThresholdAdjusterListener, public AdjusterListener
+class ColorToning final :
+ public ToolParamBlock,
+ public FoldableToolPanel,
+ public rtengine::AutoColorTonListener,
+ public CurveListener,
+ public ColorProvider,
+ public ThresholdAdjusterListener,
+ public AdjusterListener
{
+public:
+ ColorToning ();
+ ~ColorToning();
+ void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
+ void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
+ void setBatchMode (bool batchMode);
+ void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
+ void trimValues (rtengine::procparams::ProcParams* pp);
+ void adjusterChanged (Adjuster* a, double newval);
+ void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop);
+ void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd);
+ void neutral_pressed ();
+ //void neutralCurves_pressed ();
+ void autoColorTonChanged (int bwct, int satthres, int satprot);
+ bool CTComp_ ();
-protected:
- //Gtk::HSeparator* splitSep;
+ void enabledChanged ();
+ void curveChanged (CurveEditor* ce);
+ void autosatChanged ();
+ void autoOpenCurve ();
+ void methodChanged ();
+ void twocolorChanged (bool changedbymethod);
+ void twoColorChangedByGui ();
+ void lumamodeChanged ();
+
+ void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller);
+
+private:
Gtk::HSeparator* satLimiterSep;
Gtk::HSeparator* colorSep;
CurveEditorGroup* colorCurveEditorG;
@@ -57,7 +88,6 @@ protected:
Gtk::Image* irg;
Gtk::Button* neutral;
- //Gtk::Button* neutralCurves;
Gtk::HBox* neutrHBox;
Gtk::HBox* chromaHbox;
Gtk::Label* chroLabel;
@@ -75,32 +105,7 @@ protected:
bool lastLumamode;
sigc::connection lumamodeConn;
-public:
- ColorToning ();
- ~ColorToning();
- void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
- void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
- void setBatchMode (bool batchMode);
- void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
- void trimValues (rtengine::procparams::ProcParams* pp);
- void adjusterChanged (Adjuster* a, double newval);
- void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop);
- void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd);
- void neutral_pressed ();
- //void neutralCurves_pressed ();
- void autoColorTonChanged (int bwct, int satthres, int satprot);
- bool CTComp_ ();
-
- void enabledChanged ();
- void curveChanged (CurveEditor* ce);
- void autosatChanged ();
- void autoOpenCurve ();
- void methodChanged ();
- void twocolorChanged (bool changedbymethod);
- void twoColorChangedByGui ();
- void lumamodeChanged ();
-
- void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller);
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/crop.cc b/rtgui/crop.cc
index a69c71ed8..83efb6a37 100644
--- a/rtgui/crop.cc
+++ b/rtgui/crop.cc
@@ -25,6 +25,9 @@ using namespace rtengine::procparams;
extern Options options;
+namespace
+{
+
class RefreshSpinHelper
{
@@ -35,6 +38,22 @@ public:
: crop(_crop), notify(_notify) {}
};
+int refreshSpinsUI (void* data)
+{
+ RefreshSpinHelper* rsh = static_cast(data);
+ rsh->crop->refreshSpins (rsh->notify);
+ delete rsh;
+ return 0;
+}
+
+int notifyListenerUI (void* data)
+{
+ static_cast(data)->notifyListener();
+ return 0;
+}
+
+}
+
Crop::Crop (): FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true)
{
@@ -252,6 +271,11 @@ Crop::Crop (): FoldableToolPanel(this, "crop", M("TP_CROP_LABEL"), false, true)
show_all ();
}
+Crop::~Crop()
+{
+ idle_register.destroy();
+}
+
void Crop::writeOptions ()
{
@@ -508,32 +532,18 @@ void Crop::enabledChanged ()
}
}
-int notifyListenerUI (void* data)
-{
- (static_cast(data))->notifyListener ();
- return 0;
-}
-
-int refreshSpinsUI (void* data)
-{
- RefreshSpinHelper* rsh = static_cast(data);
- rsh->crop->refreshSpins (rsh->notify);
- delete rsh;
- return 0;
-}
-
void Crop::hFlipCrop ()
{
nx = maxw - nx - nw;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::vFlipCrop ()
{
ny = maxh - ny - nh;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::rotateCrop (int deg, bool hflip, bool vflip)
@@ -573,7 +583,7 @@ void Crop::rotateCrop (int deg, bool hflip, bool vflip)
}
lastRotationDeg = deg;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::positionChanged ()
@@ -587,7 +597,7 @@ void Crop::positionChanged ()
int W = nw;
int H = nh;
cropMoved (X, Y, W, H);
- add_idle (notifyListenerUI, this);
+ idle_register.add(notifyListenerUI, this);
}
void Crop::widthChanged ()
@@ -600,7 +610,7 @@ void Crop::widthChanged ()
int W = (int)w->get_value ();
int H = nh;
cropWidth2Resized (X, Y, W, H);
- add_idle (notifyListenerUI, this);
+ idle_register.add(notifyListenerUI, this);
}
void Crop::heightChanged ()
@@ -613,7 +623,7 @@ void Crop::heightChanged ()
int W = nw;
int H = (int)h->get_value ();
cropHeight2Resized (X, Y, W, H);
- add_idle (notifyListenerUI, this);
+ idle_register.add(notifyListenerUI, this);
}
// Fixed ratio toggle button
@@ -665,7 +675,7 @@ void Crop::adjustCropToRatio()
}
// This will save the options
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, true));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, true));
}
void Crop::refreshSize ()
@@ -737,28 +747,28 @@ void Crop::setDimensions (int mw, int mh)
refreshSize ();
}
-struct setdimparams {
- Crop* crop;
- int x;
- int y;
-};
-
-int sizeChangedUI (void* data)
-{
- setdimparams* params = static_cast(data);
- params->crop->setDimensions (params->x, params->y);
- delete params;
- return 0;
-}
-
void Crop::sizeChanged (int x, int y, int ow, int oh)
{
+ struct Params {
+ Crop* crop;
+ int x;
+ int y;
+ };
- setdimparams* params = new setdimparams;
- params->x = x;
- params->y = y;
- params->crop = this;
- add_idle (sizeChangedUI, params);
+ Params* const params = new Params{
+ this,
+ x,
+ y
+ };
+
+ const auto func = [](gpointer data) -> gboolean {
+ Params* const params = static_cast(data);
+ params->crop->setDimensions(params->x, params->y);
+ delete params;
+ return FALSE;
+ };
+
+ idle_register.add(func, params);
}
bool Crop::refreshSpins (bool notify)
@@ -822,7 +832,7 @@ void Crop::cropMoved (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
}
@@ -866,7 +876,7 @@ void Crop::cropWidth1Resized (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H)
@@ -906,7 +916,7 @@ void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H)
@@ -949,7 +959,7 @@ void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H)
@@ -989,7 +999,7 @@ void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H)
@@ -1031,7 +1041,7 @@ void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H)
@@ -1071,7 +1081,7 @@ void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H)
@@ -1111,7 +1121,7 @@ void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H)
@@ -1148,7 +1158,7 @@ void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropInit (int &x, int &y, int &w, int &h)
@@ -1266,13 +1276,12 @@ void Crop::cropResized (int &x, int &y, int& x2, int& y2)
nw = W;
nh = H;
- add_idle (refreshSpinsUI, new RefreshSpinHelper (this, false));
+ idle_register.add(refreshSpinsUI, new RefreshSpinHelper(this, false));
}
void Crop::cropManipReady ()
{
-
- add_idle (notifyListenerUI, this);
+ idle_register.add(notifyListenerUI, this);
}
double Crop::getRatio ()
diff --git a/rtgui/crop.h b/rtgui/crop.h
index 077903836..e0bad8b36 100644
--- a/rtgui/crop.h
+++ b/rtgui/crop.h
@@ -33,44 +33,20 @@ public:
virtual void cropSelectRequested() = 0;
};
-class CropRatio
-{
-
-public:
+struct CropRatio {
Glib::ustring label;
double value;
};
-class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolPanel, public rtengine::SizeListener
+class Crop final :
+ public ToolParamBlock,
+ public CropGUIListener,
+ public FoldableToolPanel,
+ public rtengine::SizeListener
{
-protected:
- Gtk::CheckButton* fixr;
- MyComboBoxText* ratio;
- MyComboBoxText* orientation;
- MyComboBoxText* guide;
- Gtk::Button* selectCrop;
- CropPanelListener* clistener;
- int opt;
- MySpinButton* x;
- MySpinButton* y;
- MySpinButton* w;
- MySpinButton* h;
- MySpinButton* ppi;
- Gtk::Label* sizecm;
- Gtk::Label* sizein;
- Gtk::VBox* ppibox;
- Gtk::VBox* sizebox;
- int maxw, maxh;
- double nx, ny;
- int nw, nh;
- int lastRotationDeg;
- sigc::connection xconn, yconn, wconn, hconn, fconn, rconn, oconn, gconn;
- bool wDirty, hDirty, xDirty, yDirty, lastFixRatio;
- void adjustCropToRatio();
- std::vector cropratio;
-
public:
- Crop ();
+ Crop();
+ ~Crop();
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
@@ -116,6 +92,34 @@ public:
void hFlipCrop ();
void vFlipCrop ();
void rotateCrop (int deg, bool hflip, bool vflip);
+
+private:
+ Gtk::CheckButton* fixr;
+ MyComboBoxText* ratio;
+ MyComboBoxText* orientation;
+ MyComboBoxText* guide;
+ Gtk::Button* selectCrop;
+ CropPanelListener* clistener;
+ int opt;
+ MySpinButton* x;
+ MySpinButton* y;
+ MySpinButton* w;
+ MySpinButton* h;
+ MySpinButton* ppi;
+ Gtk::Label* sizecm;
+ Gtk::Label* sizein;
+ Gtk::VBox* ppibox;
+ Gtk::VBox* sizebox;
+ int maxw, maxh;
+ double nx, ny;
+ int nw, nh;
+ int lastRotationDeg;
+ sigc::connection xconn, yconn, wconn, hconn, fconn, rconn, oconn, gconn;
+ bool wDirty, hDirty, xDirty, yDirty, lastFixRatio;
+ void adjustCropToRatio();
+ std::vector cropratio;
+
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc
index bb59efe13..42c6eb756 100644
--- a/rtgui/crophandler.cc
+++ b/rtgui/crophandler.cc
@@ -38,14 +38,15 @@ CropHandler::CropHandler ()
displayHandler(nullptr)
{
- chi = new CropHandlerIdleHelper;
- chi->destroyed = false;
- chi->pending = 0;
- chi->cropHandler = this;
+ idle_helper = new IdleHelper;
+ idle_helper->destroyed = false;
+ idle_helper->pending = 0;
+ idle_helper->cropHandler = this;
}
CropHandler::~CropHandler ()
{
+ idle_register.destroy();
if (ipc) {
ipc->delSizeListener (this);
@@ -61,10 +62,10 @@ CropHandler::~CropHandler ()
cimg.lock ();
- if (chi->pending) {
- chi->destroyed = true;
+ if (idle_helper->pending) {
+ idle_helper->destroyed = true;
} else {
- delete chi;
+ delete idle_helper;
}
cimg.unlock ();
@@ -292,83 +293,6 @@ void CropHandler::getPosition (int& x, int& y)
}
-int createpixbufs (void* data)
-{
-
- CropHandlerIdleHelper* chi = static_cast(data);
-
- if (chi->destroyed) {
- if (chi->pending == 1) {
- delete chi;
- } else {
- chi->pending--;
- }
-
- return 0;
- }
-
- CropHandler* ch = chi->cropHandler;
-
- ch->cimg.lock ();
- ch->cropPixbuf.clear ();
-
- if (!ch->enabled) {
- delete [] ch->cropimg;
- ch->cropimg = nullptr;
- delete [] ch->cropimgtrue;
- ch->cropimgtrue = nullptr;
- ch->cimg.unlock ();
- return 0;
- }
-
- if (ch->cropimg) {
- if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom)) {
- // calculate final image size
- int czoom = ch->zoom < 1000 ? 1000 : ch->zoom;
- int imw = ch->cropimg_width * czoom / 1000;
- int imh = ch->cropimg_height * czoom / 1000;
-
- if (imw > ch->ww) {
- imw = ch->ww;
- }
-
- if (imh > ch->wh) {
- imh = ch->wh;
- }
-
- Glib::RefPtr tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width);
- ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
- tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST);
- tmpPixbuf.clear ();
-
- Glib::RefPtr tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width);
- ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
- tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST);
- tmpPixbuftrue.clear ();
- }
-
- delete [] ch->cropimg;
- ch->cropimg = nullptr;
- delete [] ch->cropimgtrue;
- ch->cropimgtrue = nullptr;
- }
-
- ch->cimg.unlock ();
-
- if (ch->displayHandler) {
- ch->displayHandler->cropImageUpdated ();
-
- if (ch->initial) {
- ch->displayHandler->initialImageArrived ();
- ch->initial = false;
- }
- }
-
- chi->pending--;
-
- return 0;
-}
-
void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procparams::ColorManagementParams cmp,
rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip)
{
@@ -408,8 +332,84 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp
ciw = aw;
cih = ah;
cis = askip;
- chi->pending++;
- add_idle (createpixbufs, chi);
+ idle_helper->pending++;
+
+ const auto func = [](gpointer data) -> gboolean {
+ IdleHelper* const idle_helper = static_cast(data);
+
+ if (idle_helper->destroyed) {
+ if (idle_helper->pending == 1) {
+ delete idle_helper;
+ } else {
+ idle_helper->pending--;
+ }
+
+ return FALSE;
+ }
+
+ CropHandler* ch = idle_helper->cropHandler;
+
+ ch->cimg.lock ();
+ ch->cropPixbuf.clear ();
+
+ if (!ch->enabled) {
+ delete [] ch->cropimg;
+ ch->cropimg = nullptr;
+ delete [] ch->cropimgtrue;
+ ch->cropimgtrue = nullptr;
+ ch->cimg.unlock ();
+ return FALSE;
+ }
+
+ if (ch->cropimg) {
+ if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom)) {
+ // calculate final image size
+ int czoom = ch->zoom < 1000 ? 1000 : ch->zoom;
+ int imw = ch->cropimg_width * czoom / 1000;
+ int imh = ch->cropimg_height * czoom / 1000;
+
+ if (imw > ch->ww) {
+ imw = ch->ww;
+ }
+
+ if (imh > ch->wh) {
+ imh = ch->wh;
+ }
+
+ Glib::RefPtr tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width);
+ ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
+ tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST);
+ tmpPixbuf.clear ();
+
+ Glib::RefPtr tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width);
+ ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
+ tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST);
+ tmpPixbuftrue.clear ();
+ }
+
+ delete [] ch->cropimg;
+ ch->cropimg = nullptr;
+ delete [] ch->cropimgtrue;
+ ch->cropimgtrue = nullptr;
+ }
+
+ ch->cimg.unlock ();
+
+ if (ch->displayHandler) {
+ ch->displayHandler->cropImageUpdated ();
+
+ if (ch->initial) {
+ ch->displayHandler->initialImageArrived ();
+ ch->initial = false;
+ }
+ }
+
+ idle_helper->pending--;
+
+ return FALSE;
+ };
+
+ idle_register.add(func, idle_helper);
}
cimg.unlock ();
diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h
index 3bf7e58da..0492aea2a 100644
--- a/rtgui/crophandler.h
+++ b/rtgui/crophandler.h
@@ -36,56 +36,15 @@ public:
virtual void setDisplayPosition (int x, int y) {}
};
-class CropHandler;
-struct CropHandlerIdleHelper {
- CropHandler* cropHandler;
- bool destroyed;
- int pending;
-};
-
/**
* This class handle the displayed part of the image, ask for the initial data and process it so it can display it.
* Its position on the preview is handled not set by this class but by the CropHandlerListener (i.e. CropWindow) with which it works closely.
*/
-class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener
+class CropHandler final :
+ public rtengine::DetailedCropListener,
+ public rtengine::SizeListener
{
-
- friend int createpixbufs (void* data);
-
-protected:
- int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...)
- int ww, wh; // size of the crop's canvas on the screen ; might be bigger than the displayed image, but not smaller
- int imx, imy, imw, imh; // this is a copy of the cropwindow's parameters
- int cax, cay; // clamped crop anchor's coordinate, i.e. point of the image that coincide to the center of the display area, expressed in image coordinates; cannot be outside the image's bounds; but if cax==cay==-1, designate the center of the image
- int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size
- int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds
- bool enabled;
- unsigned char* cropimg;
- unsigned char* cropimgtrue;
- int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis;
- bool initial;
- bool isLowUpdatePriority;
-
- rtengine::StagedImageProcessor* ipc;
- rtengine::DetailedCrop* crop;
-
- CropDisplayHandler* displayHandler;
- CropHandlerIdleHelper* chi;
-
- void compDim ();
-
public:
-
- void update ();
-
-
- rtengine::procparams::CropParams cropParams;
- rtengine::procparams::ColorManagementParams colorParams;
- Glib::RefPtr cropPixbuf;
- Glib::RefPtr cropPixbuftrue;
-
- MyMutex cimg;
-
CropHandler ();
~CropHandler ();
@@ -127,6 +86,46 @@ public:
bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip);
// SizeListener interface
void sizeChanged (int w, int h, int ow, int oh);
+
+ void update ();
+
+
+ rtengine::procparams::CropParams cropParams;
+ rtengine::procparams::ColorManagementParams colorParams;
+ Glib::RefPtr cropPixbuf;
+ Glib::RefPtr cropPixbuftrue;
+
+ MyMutex cimg;
+
+private:
+ struct IdleHelper {
+ CropHandler* cropHandler;
+ bool destroyed;
+ int pending;
+ };
+
+ void compDim ();
+
+ int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...)
+ int ww, wh; // size of the crop's canvas on the screen ; might be bigger than the displayed image, but not smaller
+ int imx, imy, imw, imh; // this is a copy of the cropwindow's parameters
+ int cax, cay; // clamped crop anchor's coordinate, i.e. point of the image that coincide to the center of the display area, expressed in image coordinates; cannot be outside the image's bounds; but if cax==cay==-1, designate the center of the image
+ int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size
+ int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds
+ bool enabled;
+ unsigned char* cropimg;
+ unsigned char* cropimgtrue;
+ int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis;
+ bool initial;
+ bool isLowUpdatePriority;
+
+ rtengine::StagedImageProcessor* ipc;
+ rtengine::DetailedCrop* crop;
+
+ CropDisplayHandler* displayHandler;
+ IdleHelper* idle_helper;
+
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc
index eafaa477a..7b5adade2 100644
--- a/rtgui/dirbrowser.cc
+++ b/rtgui/dirbrowser.cc
@@ -18,6 +18,7 @@
*/
#include "dirbrowser.h"
+#include
#include
#ifdef WIN32
diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc
index a5611cc45..bd673e5c3 100644
--- a/rtgui/dirpyrdenoise.cc
+++ b/rtgui/dirpyrdenoise.cc
@@ -327,22 +327,24 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP
DirPyrDenoise::~DirPyrDenoise ()
{
+ idle_register.destroy();
+
delete NoiscurveEditorG;
delete CCcurveEditorG;
+}
-}
-int chromaChangedUI (void* data)
-{
- (static_cast(data))->chromaComputed_ ();
- return 0;
-}
void DirPyrDenoise::chromaChanged (double autchroma, double autred, double autblue)
{
nextchroma = autchroma;
-// printf("CHROM=%f\n",nextchroma);
nextred = autred;
nextblue = autblue;
- add_idle(chromaChangedUI, this);
+
+ const auto func = [](gpointer data) -> gboolean {
+ static_cast(data)->chromaComputed_();
+ return false;
+ };
+
+ idle_register.add(func, this);
}
bool DirPyrDenoise::chromaComputed_ ()
@@ -356,12 +358,6 @@ bool DirPyrDenoise::chromaComputed_ ()
updateNoiseLabel ();
return false;
}
-int TilePrevChangedUI (void* data)
-{
- (static_cast(data))->TilePrevComputed_ ();
- return 0;
-}
-
void DirPyrDenoise::noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP)
{
@@ -372,10 +368,14 @@ void DirPyrDenoise::noiseTilePrev (int tileX, int tileY, int prevX, int prevY, i
nextsizeT = sizeT;
nextsizeP = sizeP;
- add_idle(TilePrevChangedUI, this);
-
+ const auto func = [](gpointer data) -> gboolean {
+ static_cast(data)->TilePrevComputed_();
+ return false;
+ };
+ idle_register.add(func, this);
}
+
bool DirPyrDenoise::TilePrevComputed_ ()
{
@@ -385,6 +385,7 @@ bool DirPyrDenoise::TilePrevComputed_ ()
updatePrevLabel ();
return false;
}
+
void DirPyrDenoise::updateTileLabel ()
{
if (!batchMode) {
@@ -422,19 +423,17 @@ void DirPyrDenoise::updatePrevLabel ()
}
}
-
-int noiseChangedUI (void* data)
-{
- (static_cast(data))->noiseComputed_ ();
- return 0;
-}
-
-
void DirPyrDenoise::noiseChanged (double nresid, double highresid)
{
nextnresid = nresid;
nexthighresid = highresid;
- add_idle(noiseChangedUI, this);
+
+ const auto func = [](gpointer data) -> gboolean {
+ static_cast(data)->noiseComputed_();
+ return false;
+ };
+
+ idle_register.add(func, this);
}
bool DirPyrDenoise::noiseComputed_ ()
diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h
index e81bf263e..9745b374b 100644
--- a/rtgui/dirpyrdenoise.h
+++ b/rtgui/dirpyrdenoise.h
@@ -28,10 +28,58 @@
#include "guiutils.h"
#include "options.h"
-class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoChromaListener, public CurveListener, public ColorProvider
+class DirPyrDenoise final :
+ public ToolParamBlock,
+ public AdjusterListener,
+ public FoldableToolPanel,
+ public rtengine::AutoChromaListener,
+ public CurveListener,
+ public ColorProvider
{
+public:
+ DirPyrDenoise ();
+ ~DirPyrDenoise ();
-protected:
+ void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
+ void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
+ void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
+ void setBatchMode (bool batchMode);
+ void curveChanged (CurveEditor* ce);
+ void setEditProvider (EditDataProvider *provider);
+ void autoOpenCurve ();
+
+ void adjusterChanged (Adjuster* a, double newval);
+ void enabledChanged ();
+ void enhanceChanged ();
+ void medianChanged ();
+ void autochromaChanged ();
+ void chromaChanged (double autchroma, double autred, double autblue);
+ bool chromaComputed_ ();
+ void noiseChanged (double nresid, double highresid);
+ bool noiseComputed_ ();
+ void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP);
+ bool TilePrevComputed_ ();
+
+// void perform_toggled ();
+ void updateNoiseLabel ();
+ void LmethodChanged ();
+ void CmethodChanged ();
+ void C2methodChanged ();
+ void updateTileLabel ();
+ void updatePrevLabel ();
+
+ void dmethodChanged ();
+ void medmethodChanged ();
+ void methodmedChanged ();
+ void rgbmethodChanged ();
+ void smethodChanged ();
+ virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller);
+
+ void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd);
+ void trimValues (rtengine::procparams::ProcParams* pp);
+ Glib::ustring getSettingString ();
+
+private:
CurveEditorGroup* NoiscurveEditorG;
CurveEditorGroup* CCcurveEditorG;
Adjuster* luma;
@@ -92,50 +140,7 @@ protected:
int nextsizeT;
int nextsizeP;
-public:
-
- DirPyrDenoise ();
- ~DirPyrDenoise ();
-
- void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr);
- void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr);
- void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
- void setBatchMode (bool batchMode);
- void curveChanged (CurveEditor* ce);
- void setEditProvider (EditDataProvider *provider);
- void autoOpenCurve ();
-
- void adjusterChanged (Adjuster* a, double newval);
- void enabledChanged ();
- void enhanceChanged ();
- void medianChanged ();
- void autochromaChanged ();
- void chromaChanged (double autchroma, double autred, double autblue);
- bool chromaComputed_ ();
- void noiseChanged (double nresid, double highresid);
- bool noiseComputed_ ();
- void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP);
- bool TilePrevComputed_ ();
-
-// void perform_toggled ();
- void updateNoiseLabel ();
- void LmethodChanged ();
- void CmethodChanged ();
- void C2methodChanged ();
- void updateTileLabel ();
- void updatePrevLabel ();
-
- void dmethodChanged ();
- void medmethodChanged ();
- void methodmedChanged ();
- void rgbmethodChanged ();
- void smethodChanged ();
- virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller);
-
- void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd);
- void trimValues (rtengine::procparams::ProcParams* pp);
- Glib::ustring getSettingString ();
-
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc
index 0783efe14..8da176fc3 100644
--- a/rtgui/editorpanel.cc
+++ b/rtgui/editorpanel.cc
@@ -35,6 +35,44 @@
using namespace rtengine::procparams;
+namespace
+{
+
+struct spparams {
+ double val;
+ Glib::ustring str;
+ MyProgressBar *pProgress;
+ Glib::RefPtr cssProvider;
+};
+
+int setprogressStrUI ( void *p )
+{
+ spparams *s = static_cast (p);
+
+ if ( ! s->str.empty() ) {
+ s->pProgress->set_text ( M (s->str) );
+ }
+
+ if ( s->val >= 0 ) {
+ s->pProgress->set_fraction ( s->val );
+
+ if (s->cssProvider) {
+ if ( s->val < 1.0 ) {
+ s->cssProvider->load_from_data ("ProgressBar { background-color: red }");
+ } else {
+ s->cssProvider->load_from_data ("ProgressBar { background-color: grey }");
+ }
+
+ s->pProgress->get_style_context()->set_background (s->pProgress->get_window());
+ }
+ }
+
+ delete s;
+ return FALSE;
+}
+
+}
+
class EditorPanel::ColorManagementToolbar
{
private:
@@ -683,6 +721,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
EditorPanel::~EditorPanel ()
{
+ idle_register.destroy();
history->setHistoryBeforeLineListener (nullptr);
// the order is important!
@@ -1017,46 +1056,12 @@ void EditorPanel::setProgressState (bool inProcessing)
g_idle_add (setProgressStateUIThread, p);
}
-struct spparams {
- double val;
- Glib::ustring str;
- MyProgressBar *pProgress;
- Glib::RefPtr cssProvider;
-
-};
-
-int setprogressStrUI ( void *p )
-{
- spparams *s = static_cast (p);
-
- if ( ! s->str.empty() ) {
- s->pProgress->set_text ( M (s->str) );
- }
-
- if ( s->val >= 0 ) {
- s->pProgress->set_fraction ( s->val );
-
- if (s->cssProvider) {
- if ( s->val < 1.0 ) {
- s->cssProvider->load_from_data ("ProgressBar { background-color: red }");
- } else {
- s->cssProvider->load_from_data ("ProgressBar { background-color: grey }");
- }
-
- s->pProgress->get_style_context()->set_background (s->pProgress->get_window());
- }
- }
-
- delete s;
- return 0;
-}
-
void EditorPanel::setProgress (double p)
{
spparams *s = new spparams;
s->val = p;
s->pProgress = progressLabel;
- add_idle (setprogressStrUI, s);
+ idle_register.add(setprogressStrUI, s);
}
void EditorPanel::setProgressStr (Glib::ustring str)
@@ -1065,7 +1070,7 @@ void EditorPanel::setProgressStr (Glib::ustring str)
s->str = str;
s->val = -1;
s->pProgress = progressLabel;
- add_idle (setprogressStrUI, s);
+ idle_register.add(setprogressStrUI, s);
}
// This is only called from the ThreadUI, so within the gtk thread
diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h
index d87f12c23..609df5236 100644
--- a/rtgui/editorpanel.h
+++ b/rtgui/editorpanel.h
@@ -45,102 +45,17 @@ struct EditorPanelIdleHelper {
};
class RTWindow;
-class EditorPanel : public Gtk::VBox,
+class EditorPanel final :
+ public Gtk::VBox,
public PParamsChangeListener,
public rtengine::ProgressListener,
public ThumbnailListener,
public HistoryBeforeLineListener,
public rtengine::HistogramListener
{
-private:
-
- Glib::ustring lastSaveAsFileName;
- bool realized;
-
-protected:
- MyProgressBar *progressLabel;
- Gtk::ToggleButton* info;
- Gtk::ToggleButton* hidehp;
- Gtk::ToggleButton* tbShowHideSidePanels;
- Gtk::ToggleButton* tbTopPanel_1;
- Gtk::ToggleButton* tbRightPanel_1;
- Gtk::ToggleButton* tbBeforeLock;
- //bool bAllSidePanelsVisible;
- Gtk::ToggleButton* beforeAfter;
- Gtk::Paned* hpanedl;
- Gtk::Paned* hpanedr;
- Gtk::Image *iHistoryShow, *iHistoryHide;
- Gtk::Image *iTopPanel_1_Show, *iTopPanel_1_Hide;
- Gtk::Image *iRightPanel_1_Show, *iRightPanel_1_Hide;
- Gtk::Image *iShowHideSidePanels;
- Gtk::Image *iShowHideSidePanels_exit;
- Gtk::Image *iBeforeLockON, *iBeforeLockOFF;
- Gtk::VBox *leftbox;
- Gtk::VBox *vboxright;
-
- Gtk::Button* queueimg;
- Gtk::Button* saveimgas;
- Gtk::Button* sendtogimp;
- Gtk::Button* navSync;
- Gtk::Button* navNext;
- Gtk::Button* navPrev;
-
- class ColorManagementToolbar;
- std::unique_ptr colorMgmtToolBar;
-
- ImageAreaPanel* iareapanel;
- PreviewHandler* previewHandler;
- PreviewHandler* beforePreviewHandler; // for the before-after view
- Navigator* navigator;
- ImageAreaPanel* beforeIarea; // for the before-after view
- Gtk::VBox* beforeBox;
- Gtk::VBox* afterBox;
- Gtk::Label* beforeLabel;
- Gtk::Label* afterLabel;
- Gtk::HBox* beforeAfterBox;
- Gtk::HBox* beforeHeaderBox;
- Gtk::HBox* afterHeaderBox;
-
- Gtk::Frame* ppframe;
- ProfilePanel* profilep;
- History* history;
- HistogramPanel* histogramPanel;
- ToolPanelCoordinator* tpc;
- RTWindow* parent;
- //SaveAsDialog* saveAsDialog;
- BatchToolPanelCoordinator* btpCoordinator;
- FilePanel* fPanel;
-
- bool firstProcessingDone;
-
- Thumbnail* openThm; // may get invalid on external delete event
- Glib::ustring fname; // must be saved separately
-
- rtengine::InitialImage* isrc;
- rtengine::StagedImageProcessor* ipc;
- rtengine::StagedImageProcessor* beforeIpc; // for the before-after view
-
- EditorPanelIdleHelper* epih;
-
- void close ();
-
- BatchQueueEntry* createBatchQueueEntry ();
- bool idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf);
- bool idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf);
- bool idle_sendToGimp ( ProgressConnector *pc, Glib::ustring fname);
- bool idle_sentToGimp (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename);
- int err;
-
- time_t processingStartedTime;
-
- sigc::connection ShowHideSidePanelsconn;
-
- bool isProcessing;
-
-
public:
explicit EditorPanel (FilePanel* filePanel = nullptr);
- virtual ~EditorPanel ();
+ ~EditorPanel ();
void open (Thumbnail* tmb, rtengine::InitialImage* isrc);
void setAspect ();
@@ -214,7 +129,93 @@ public:
void updateTabsUsesIcons (bool useIcons);
void updateHistogramPosition (int oldPosition, int newPosition);
- Gtk::Paned *catalogPane;
+ Gtk::Paned* catalogPane;
+
+private:
+ void close ();
+
+ BatchQueueEntry* createBatchQueueEntry ();
+ bool idle_imageSaved (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf);
+ bool idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf);
+ bool idle_sendToGimp ( ProgressConnector *pc, Glib::ustring fname);
+ bool idle_sentToGimp (ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename);
+
+ Glib::ustring lastSaveAsFileName;
+ bool realized;
+
+ MyProgressBar *progressLabel;
+ Gtk::ToggleButton* info;
+ Gtk::ToggleButton* hidehp;
+ Gtk::ToggleButton* tbShowHideSidePanels;
+ Gtk::ToggleButton* tbTopPanel_1;
+ Gtk::ToggleButton* tbRightPanel_1;
+ Gtk::ToggleButton* tbBeforeLock;
+ //bool bAllSidePanelsVisible;
+ Gtk::ToggleButton* beforeAfter;
+ Gtk::Paned* hpanedl;
+ Gtk::Paned* hpanedr;
+ Gtk::Image *iHistoryShow, *iHistoryHide;
+ Gtk::Image *iTopPanel_1_Show, *iTopPanel_1_Hide;
+ Gtk::Image *iRightPanel_1_Show, *iRightPanel_1_Hide;
+ Gtk::Image *iShowHideSidePanels;
+ Gtk::Image *iShowHideSidePanels_exit;
+ Gtk::Image *iBeforeLockON, *iBeforeLockOFF;
+ Gtk::VBox *leftbox;
+ Gtk::VBox *vboxright;
+
+ Gtk::Button* queueimg;
+ Gtk::Button* saveimgas;
+ Gtk::Button* sendtogimp;
+ Gtk::Button* navSync;
+ Gtk::Button* navNext;
+ Gtk::Button* navPrev;
+
+ class ColorManagementToolbar;
+ std::unique_ptr colorMgmtToolBar;
+
+ ImageAreaPanel* iareapanel;
+ PreviewHandler* previewHandler;
+ PreviewHandler* beforePreviewHandler; // for the before-after view
+ Navigator* navigator;
+ ImageAreaPanel* beforeIarea; // for the before-after view
+ Gtk::VBox* beforeBox;
+ Gtk::VBox* afterBox;
+ Gtk::Label* beforeLabel;
+ Gtk::Label* afterLabel;
+ Gtk::HBox* beforeAfterBox;
+ Gtk::HBox* beforeHeaderBox;
+ Gtk::HBox* afterHeaderBox;
+
+ Gtk::Frame* ppframe;
+ ProfilePanel* profilep;
+ History* history;
+ HistogramPanel* histogramPanel;
+ ToolPanelCoordinator* tpc;
+ RTWindow* parent;
+ //SaveAsDialog* saveAsDialog;
+ BatchToolPanelCoordinator* btpCoordinator;
+ FilePanel* fPanel;
+
+ bool firstProcessingDone;
+
+ Thumbnail* openThm; // may get invalid on external delete event
+ Glib::ustring fname; // must be saved separately
+
+ rtengine::InitialImage* isrc;
+ rtengine::StagedImageProcessor* ipc;
+ rtengine::StagedImageProcessor* beforeIpc; // for the before-after view
+
+ EditorPanelIdleHelper* epih;
+
+ int err;
+
+ time_t processingStartedTime;
+
+ sigc::connection ShowHideSidePanelsconn;
+
+ bool isProcessing;
+
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc
index 8c7bae0fa..ed9b70e8d 100644
--- a/rtgui/filepanel.cc
+++ b/rtgui/filepanel.cc
@@ -22,12 +22,6 @@
#include "inspector.h"
#include "placesbrowser.h"
-int FilePanelInitUI (void* data)
-{
- (static_cast(data))->init ();
- return 0;
-}
-
FilePanel::FilePanel () : parent(nullptr)
{
@@ -143,13 +137,21 @@ FilePanel::FilePanel () : parent(nullptr)
fileCatalog->setFileSelectionChangeListener (tpc);
fileCatalog->setFileSelectionListener (this);
- add_idle (FilePanelInitUI, this);
+
+ const auto func = [](gpointer data) -> gboolean {
+ static_cast(data)->init();
+ return FALSE;
+ };
+
+ idle_register.add(func, this);
show_all ();
}
FilePanel::~FilePanel ()
{
+ idle_register.destroy();
+
rightNotebookSwitchConn.disconnect();
if (inspectorPanel) {
diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h
index 68f021043..d54f5f75a 100644
--- a/rtgui/filepanel.h
+++ b/rtgui/filepanel.h
@@ -33,38 +33,12 @@
#include "progressconnector.h"
class RTWindow;
-class FilePanel : public Gtk::HPaned,
+
+class FilePanel final :
+ public Gtk::HPaned,
public FileSelectionListener,
public PParamsChangeListener
{
-
-protected:
- //DirBrowser* dirBrowser;
- PlacesBrowser* placesBrowser;
- 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;
- Gtk::Notebook* rightNotebook;
- sigc::connection rightNotebookSwitchConn;
-
- struct pendingLoad {
- bool complete;
- ProgressConnector *pc;
- Thumbnail *thm;
- };
- MyMutex pendingLoadMutex;
- std::vector pendingLoads;
-
- int error;
-
- void on_NB_switch_page(Gtk::Widget* page, guint page_num);
-
public:
FilePanel ();
~FilePanel ();
@@ -107,6 +81,32 @@ public:
bool handleShortcutKey (GdkEventKey* event);
void updateTPVScrollbar (bool hide);
void updateTabsUsesIcons (bool useIcons);
+
+private:
+ void on_NB_switch_page(Gtk::Widget* page, guint page_num);
+
+ PlacesBrowser* placesBrowser;
+ RecentBrowser* recentBrowser;
+
+ Inspector* inspectorPanel;
+ Gtk::VPaned* tpcPaned;
+ BatchToolPanelCoordinator* tpc;
+ History* history;
+ RTWindow* parent;
+ Gtk::Notebook* rightNotebook;
+ sigc::connection rightNotebookSwitchConn;
+
+ struct pendingLoad {
+ bool complete;
+ ProgressConnector *pc;
+ Thumbnail *thm;
+ };
+ MyMutex pendingLoadMutex;
+ std::vector pendingLoads;
+
+ int error;
+
+ IdleRegister idle_register;
};
#endif
diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc
index 43bfc11b0..e8310ff0e 100644
--- a/rtgui/guiutils.cc
+++ b/rtgui/guiutils.cc
@@ -43,6 +43,53 @@ guint add_idle (GSourceFunc function, gpointer data)
//gtk_main_iteration_do(false);
}
+IdleRegister::~IdleRegister()
+{
+ destroy();
+}
+
+void IdleRegister::add(GSourceFunc function, gpointer data)
+{
+ struct DataWrapper {
+ IdleRegister* const self;
+ GSourceFunc function;
+ gpointer data;
+ };
+
+ const auto dispatch = [](gpointer data) -> gboolean {
+ DataWrapper* const data_wrapper = static_cast(data);
+
+ if (!data_wrapper->function(data_wrapper->data)) {
+ data_wrapper->self->mutex.lock();
+ data_wrapper->self->ids.erase(data_wrapper);
+ data_wrapper->self->mutex.unlock();
+
+ delete data_wrapper;
+ return FALSE;
+ }
+
+ return TRUE;
+ };
+
+ DataWrapper* const data_wrapper = new DataWrapper{
+ this,
+ function,
+ data
+ };
+
+ mutex.lock();
+ ids[data_wrapper] = add_idle(dispatch, data_wrapper);
+ mutex.unlock();
+}
+
+void IdleRegister::destroy()
+{
+ mutex.lock();
+ for (const auto id : ids) {
+ g_source_remove(id.second);
+ }
+ mutex.unlock();
+}
/*
gboolean giveMeAGo(void* data) {
diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h
index e5919c9e4..12370a571 100644
--- a/rtgui/guiutils.h
+++ b/rtgui/guiutils.h
@@ -19,13 +19,17 @@
#ifndef __GUI_UTILS_
#define __GUI_UTILS_
+#include