From c3c3ceac7962dffbfeeac97715b682912de4b9f9 Mon Sep 17 00:00:00 2001 From: "luz.paz" Date: Wed, 14 Feb 2018 14:03:38 -0500 Subject: [PATCH] Misc. typos Found via `codespell` + removed rtengine/dcraw.patch per discussion in https://github.com/Beep6581/RawTherapee/pull/4395 --- AUTHORS.txt | 2 +- rtdata/options/options.lin | 2 +- rtdata/options/options.osx | 4 +- rtdata/options/options.win | 4 +- rtengine/CA_correct_RT.cc | 2 +- rtengine/EdgePreservingDecomposition.cc | 2 +- rtengine/EdgePreservingDecomposition.h | 4 +- rtengine/amaze_demosaic_RT.cc | 2 +- rtengine/cJSON.h | 2 +- rtengine/camconst.json | 8 +- rtengine/color.h | 4 +- rtengine/colortemp.cc | 6 +- rtengine/curves.cc | 4 +- rtengine/dcraw.cc | 6 +- rtengine/dcraw.patch | 4218 ----------------------- rtengine/dcrop.cc | 6 +- rtengine/dfmanager.cc | 4 +- rtengine/diagonalcurves.cc | 4 +- rtengine/ex1simple.cc | 2 +- rtengine/fast_demo.cc | 2 +- rtengine/ffmanager.cc | 4 +- rtengine/image16.cc | 2 +- rtengine/imagedata.cc | 2 +- rtengine/imagefloat.cc | 2 +- rtengine/imageio.cc | 2 +- rtengine/improccoordinator.cc | 2 +- rtengine/improcfun.cc | 28 +- rtengine/iplab2rgb.cc | 2 +- rtengine/ipsharpen.cc | 4 +- rtengine/ipwavelet.cc | 6 +- rtengine/procparams.cc | 2 +- rtengine/procparams.h | 2 +- rtengine/rawimagesource.cc | 2 +- rtengine/rtengine.h | 10 +- rtengine/simpleprocess.cc | 6 +- rtengine/tmo_fattal02.cc | 4 +- rtexif/rtexif.h | 2 +- rtgui/batchqueuepanel.cc | 2 +- rtgui/batchtoolpanelcoord.cc | 2 +- rtgui/cacheimagedata.h | 2 +- rtgui/edit.h | 2 +- rtgui/filecatalog.cc | 6 +- rtgui/filepanel.cc | 2 +- rtgui/filepanel.h | 2 +- rtgui/guiutils.cc | 2 +- rtgui/histogrampanel.cc | 2 +- rtgui/lensprofile.cc | 2 +- rtgui/lwbutton.cc | 2 +- rtgui/mydiagonalcurve.cc | 4 +- rtgui/options.cc | 2 +- rtgui/ppversion.h | 2 +- rtgui/soundman.cc | 2 +- rtgui/splash.cc | 2 +- rtgui/thumbimageupdater.cc | 2 +- rtgui/tonecurve.cc | 2 +- rtgui/toolpanelcoord.cc | 6 +- rtgui/wavelet.cc | 2 +- tools/RTProfileBuilderSample.cs | 4 +- tools/benchmarkRT | 6 +- tools/win/readme.txt | 2 +- 60 files changed, 107 insertions(+), 4325 deletions(-) delete mode 100644 rtengine/dcraw.patch diff --git a/AUTHORS.txt b/AUTHORS.txt index 0ad8438eb..11eee1da9 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -3,7 +3,7 @@ Project initiator: Gábor Horváth -Developement contributors, in last name alphabetical order: +Development contributors, in last name alphabetical order: Martin Burri Javier Celaya diff --git a/rtdata/options/options.lin b/rtdata/options/options.lin index 4ff90246d..924e8b9a2 100644 --- a/rtdata/options/options.lin +++ b/rtdata/options/options.lin @@ -6,7 +6,7 @@ [General] # Setting MultiUser to false will use the application's installation directory as cache directory, -# which can be usefull if you want to keep the application and all the cache datas in a single place, +# which can be useful if you want to keep the application and all the cache datas in a single place, # an external HD for example MultiUser=true diff --git a/rtdata/options/options.osx b/rtdata/options/options.osx index 9130ef9ad..4decccb6d 100644 --- a/rtdata/options/options.osx +++ b/rtdata/options/options.osx @@ -2,11 +2,11 @@ # After the first run, all the parameters will be available in this global option file # or in a new local option file, depending on the MultiUser value below -# Most ot the options are modifiable through the Preference window +# Most of the options are modifiable through the Preference window [General] # Setting MultiUser to false will use the application's installation directory as cache directory, -# which can be usefull if you want to keep the application and all the cache datas in a single place, +# which can be useful if you want to keep the application and all the cache datas in a single place, # an external HD for example MultiUser=true diff --git a/rtdata/options/options.win b/rtdata/options/options.win index 33ab499be..40e73aacc 100644 --- a/rtdata/options/options.win +++ b/rtdata/options/options.win @@ -2,11 +2,11 @@ # After the first run, all the parameters will be available in this global option file # or in a new local option file, depending on the MultiUser value below -# Most ot the options are modifiable through the Preference window +# Most of the options are modifiable through the Preference window [General] # Setting MultiUser to false will use the application's installation directory as cache directory, -# which can be usefull if you want to keep the application and all the cache datas in a single place, +# which can be useful if you want to keep the application and all the cache datas in a single place, # an external HD for example MultiUser=true # Windows users should not use the system theme : some composed widget won't be usable diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc index bfd56cc0a..cc527a891 100644 --- a/rtengine/CA_correct_RT.cc +++ b/rtengine/CA_correct_RT.cc @@ -38,7 +38,7 @@ bool LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution) // pfMatr - matrix with coefficients // pfVect - vector with free members // pfSolution - vector with system solution -// pfMatr becames trianglular after function call +// pfMatr becomes triangular after function call // pfVect changes after function call // // Developer: Henry Guennadi Levkin diff --git a/rtengine/EdgePreservingDecomposition.cc b/rtengine/EdgePreservingDecomposition.cc index 21514978b..eac42ffaa 100644 --- a/rtengine/EdgePreservingDecomposition.cc +++ b/rtengine/EdgePreservingDecomposition.cc @@ -789,7 +789,7 @@ float *EdgePreservingDecomposition::CreateBlur(float *Source, float Scale, float // checked for race condition here -// a0[] is read and write but adressed by i only +// a0[] is read and write but addressed by i only // a[] is read only // a_w_1 is write only // a_w is write only diff --git a/rtengine/EdgePreservingDecomposition.h b/rtengine/EdgePreservingDecomposition.h index 1eca7b2c8..c90123ed3 100644 --- a/rtengine/EdgePreservingDecomposition.h +++ b/rtengine/EdgePreservingDecomposition.h @@ -11,7 +11,7 @@ Anyway. Basically, this is an implementation of what's presented in the following papers: - Edge-Preserving Decompositions for Multi-Scale Tone and Detail Manipulation - An Iterative Solution Method for Linear Systems of Which the Coefficient - Matrix is a Symetric M-Matrix + Matrix is a Symmetric M-Matrix - Color correction for tone mapping - Wikipedia, the free encyclopedia @@ -89,7 +89,7 @@ public: and StartRows must strictly increase with its index. The main diagonal for example has start row 0, its subdiagonal has 1, etc. Then, Diagonal[j] is the matrix entry on the diagonal at column j. For efficiency, you're expected to learn this and fill in public Diagonals manually. Symmetric matrices are represented by this class, and all symmetry is handled internally, you - only every worry or think about the lower trianglular (including main diagonal) part of the matrix. + only every worry or think about the lower triangular (including main diagonal) part of the matrix. */ float **Diagonals; char *buffer; diff --git a/rtengine/amaze_demosaic_RT.cc b/rtengine/amaze_demosaic_RT.cc index bdb798a06..4fe0bee69 100644 --- a/rtengine/amaze_demosaic_RT.cc +++ b/rtengine/amaze_demosaic_RT.cc @@ -105,7 +105,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, a }; //gaussian on 5x5 alt quincunx, sigma=1.5 constexpr float gausseven[2] = {0.13719494435797422f, 0.05640252782101291f}; - //guassian on quincunx grid + //gaussian on quincunx grid constexpr float gquinc[4] = {0.169917f, 0.108947f, 0.069855f, 0.0287182f}; typedef struct { diff --git a/rtengine/cJSON.h b/rtengine/cJSON.h index b32b6792e..e701d8397 100644 --- a/rtengine/cJSON.h +++ b/rtengine/cJSON.h @@ -104,7 +104,7 @@ extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); -/* Remove/Detatch items from Arrays/Objects. */ +/* Remove/Detach items from Arrays/Objects. */ extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which); extern void cJSON_DeleteItemFromArray(cJSON *array, int which); extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string); diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 610a22310..95d9606fa 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -512,7 +512,7 @@ Camera constants: { // Quality B, some missing scaling factors are safely guessed "make_model": "Canon EOS 6D Mark II", "dcraw_matrix": [ 6875,-970,-932,-4691,12459,2501,-874,1953,5809 ], // DNG v_9.12 D65 - "raw_crop": [ 120, 44, 6264, 4180 ], // fullraw size 6384x4224 usefull 120,44,6264x4180 + "raw_crop": [ 120, 44, 6264, 4180 ], // fullraw size 6384x4224 useful 120,44,6264x4180 // "raw_crop": [ 128, 52, 6248, 4168 ], // official jpeg crop 120+12,44+12,6240x4160 "masked_areas": [ 44, 4, 4220, 116 ], "ranges": { @@ -1209,7 +1209,7 @@ Camera constants: "make_model": "FUJIFILM GFX 50S", "dcraw_matrix": [ 11756,-4754,-874,-3056,11045,2305,-381,1457,6006 ], // DNGv9.9 D65 //"dcraw_matrix": [ 12407,-5222,-1086,-2971,11116,2120,-294,1029,5284 ], // copy from X-A3 DNGv9.8 D65 - "raw_crop": [ 0, 0, 8280, 6208 ], // full raw 9216X6210 - usefull 8280x6208 + "raw_crop": [ 0, 0, 8280, 6208 ], // full raw 9216X6210 - useful 8280x6208 //"raw_crop": [ 6, 6, 8264, 6200 ], // fuji official JPEG 8256X6192 10,11,9,8 - experimental crop to match with official "ranges": { "white": 16000 } }, @@ -1996,7 +1996,7 @@ Camera constants: "make_model": [ "RICOH PENTAX K-70", "PENTAX K-70" ], //"dcraw_matrix": [ 8050,-2061,-1264,-4359,12953,1515,-1096,1965,6075 ], // PENTAX DNG D65 "dcraw_matrix": [ 8766,-3149,-747,-3976,11943,2292,-517,1259,5552 ], // Adobe DNGv9.8 D65 - "raw_crop": [ 58, 28, 6022, 4020 ], // full frame 6080x4064, usefull raw frame 56,28,6080,4049, official DNG raw_crop 58,28,6080,4052, official jpeg crop 58+8,28+4 6000x4000 + "raw_crop": [ 58, 28, 6022, 4020 ], // full frame 6080x4064, useful raw frame 56,28,6080,4049, official DNG raw_crop 58,28,6080,4052, official jpeg crop 58+8,28+4 6000x4000 //"raw_crop": [ 62, 28, 6000, 4000 ], // matched to official jpeg crop 58+8,28+4 6000x4000 "ranges": { "white": [ @@ -2015,7 +2015,7 @@ Camera constants: { // Quality B, Intemediate ISO samples missing. Pentax_DNG WLtags are after BL sutraction and not valid "make_model": [ "RICOH PENTAX KP", "PENTAX KP" ], "dcraw_matrix": [ 7357,-2031,-1320,-4842,13555,1349,-1538,2416,5736 ], // Adobe DNGv9.12 D65 - "raw_crop": [ 52, 28, 6032, 4030 ], // full frame 6112x4060, usefull raw frame 52,28,6084,4049, official DNG raw_crop 54,28,6082,4060 + "raw_crop": [ 52, 28, 6032, 4030 ], // full frame 6112x4060, useful raw frame 52,28,6084,4049, official DNG raw_crop 54,28,6082,4060 "ranges": { "white": [ { "iso": 100, "levels": 16300 }, // 16383 diff --git a/rtengine/color.h b/rtengine/color.h index 4b865f1d9..9775e0ecb 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -1372,7 +1372,7 @@ public: * @param CC chroma before [0 ; 180] * @param corectionHuechroma hue correction depending on chromaticity (saturation), in radians [0 ; 0.45] (return value) * @param correctlum hue correction depending on luminance (brightness, contrast,...), in radians [0 ; 0.45] (return value) - * @param munsDbgInfo (Debug target only) object to collect informations + * @param munsDbgInfo (Debug target only) object to collect information */ #ifdef _DEBUG @@ -1772,7 +1772,7 @@ public: //hr=translate Hue Lab value (-Pi +Pi) in approximative hr (hsv values) (0 1) [red 1/6 yellow 1/6 green 1/6 cyan 1/6 blue 1/6 magenta 1/6 ] // with multi linear correspondances (I expect there is no error !!) double hr = 0.0; - //allways put h between 0 and 1 + //always put h between 0 and 1 if (HH >= 0.f && HH < 0.6f ) { hr = 0.11666 * double(HH) + 0.93; //hr 0.93 1.00 full red diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc index ab318aa73..21f1641cc 100644 --- a/rtengine/colortemp.cc +++ b/rtengine/colortemp.cc @@ -967,12 +967,12 @@ void ColorTemp::cieCAT02(double Xw, double Yw, double Zw, double &CAM02BB00, dou double D = adap; //white destination Wd : RT use always D50 - cam_dest[0] = CAT02[0][0] * whiteD50p[0] + CAT02[0][1] * whiteD50p[1] + CAT02[0][2] * whiteD50p[2]; //Cone reponse RoD + cam_dest[0] = CAT02[0][0] * whiteD50p[0] + CAT02[0][1] * whiteD50p[1] + CAT02[0][2] * whiteD50p[2]; //Cone response RoD cam_dest[1] = CAT02[1][0] * whiteD50p[0] + CAT02[1][1] * whiteD50p[1] + CAT02[1][2] * whiteD50p[2]; //GaD cam_dest[2] = CAT02[2][0] * whiteD50p[0] + CAT02[2][1] * whiteD50p[1] + CAT02[2][2] * whiteD50p[2]; //BeD //origin white Ws : A, D65, custom, etc. - cam_orig[0] = CAT02[0][0] * Xw + CAT02[0][1] * Yw + CAT02[0][2] * Zw; //Cone reponse RoS + cam_orig[0] = CAT02[0][0] * Xw + CAT02[0][1] * Yw + CAT02[0][2] * Zw; //Cone response RoS cam_orig[1] = CAT02[1][0] * Xw + CAT02[1][1] * Yw + CAT02[1][2] * Zw; cam_orig[2] = CAT02[2][0] * Xw + CAT02[2][1] * Yw + CAT02[2][2] * Zw; @@ -1373,7 +1373,7 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, bbb[i] = 200.*(fy[i] - fz[i]); } - //display value to verify calculs + //display value to verify calculus if(settings->CRI_color != 0) { printf("Color Number %i\n", numero_color); printf("L_refer=%2.2f a=%2.2f b=%2.2f\n", Lbb[numero_color], abb[numero_color], bbb[numero_color]); diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 508bd1640..e856ee1cc 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -118,7 +118,7 @@ void Curve::fillHash() hash.at(hashSize + 1).higherValue = poly_x.size(); /* - * Uncoment the code below to dump the polygon points and the hash table in files + * Uncomment the code below to dump the polygon points and the hash table in files if (poly_x.size() > 500) { printf("Files generated (%d points)\n", poly_x.size()); FILE* f = fopen ("hash.txt", "wt"); @@ -1905,7 +1905,7 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float // depending on color, the chroma scaling factor can be fine-tuned below { - // decrease chroma scaling sligthly of extremely saturated colors + // decrease chroma scaling slightly of extremely saturated colors float saturated_scale_factor = 0.95f; constexpr float lolim = 35.f; // lower limit, below this chroma all colors will keep original chroma scaling factor constexpr float hilim = 60.f; // high limit, above this chroma the chroma scaling factor is multiplied with the saturated scale factor value above diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 4786000bb..dfde78785 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -1951,7 +1951,7 @@ void CLASS parse_hasselblad_gain() Data block format. Seems to differ depending on sensor type. For tested H4D-50 and H3D-31: 10 16 bit signed values per row value 0: a correction factor (k) used on even columns, where the new pixel value is - calulated as follows: + calculated as follows: new_value = old_value + (2 * ((k * (old_value_on_row_above-256)) / 32767) - 2) note the connection to the value on the row above, seems to be some sort of signal leakage correction. @@ -2023,7 +2023,7 @@ void CLASS hasselblad_correct() TODO: - Support all gain tag formats - The 0x19 tag varies a bit between models. We don't have parsers for all models. - - The reference model used was during inital reverse-engineering was a H4D-50, + - The reference model used was during initial reverse-engineering was a H4D-50, we probably support the Hasselblads with Kodak 31, 39, 40 and 50 megapixels well, but more work is needed for Kodak 16 and 22, Dalsa 60 and Sony 50. - Apply bad column(?) data (hbd.unknown1) @@ -4378,7 +4378,7 @@ mask_set: //} /* - Seach from the current directory up to the root looking for + Search from the current directory up to the root looking for a ".badpixels" file, and fix those pixels now. */ //void CLASS bad_pixels (const char *cfname) diff --git a/rtengine/dcraw.patch b/rtengine/dcraw.patch deleted file mode 100644 index 43f9e12eb..000000000 --- a/rtengine/dcraw.patch +++ /dev/null @@ -1,4218 +0,0 @@ ---- dcraw.c 2016-11-01 01:07:55 +0000 -+++ dcraw.cc 2016-11-01 14:54:02 +0000 -@@ -1,3 +1,16 @@ -+/*RT*/#include -+/*RT*/#include -+/*RT*/#undef MAX -+/*RT*/#undef MIN -+/*RT*/#undef ABS -+/*RT*/#include "rt_math.h" -+/*RT*/#define NO_LCMS -+/*RT*/#define NO_JPEG -+/*RT*/#define NO_JASPER -+/*RT*/#define LOCALTIME -+/*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 -@@ -29,17 +42,17 @@ - #define _GNU_SOURCE - #endif - #define _USE_MATH_DEFINES --#include --#include -+#include -+#include - #include --#include --#include --#include --#include --#include --#include --#include --#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include - #include - - #if defined(DJGPP) || defined(__MINGW32__) -@@ -54,7 +67,6 @@ - #ifdef WIN32 - #include - #include --#pragma comment(lib, "ws2_32.lib") - #define snprintf _snprintf - #define strcasecmp stricmp - #define strncasecmp strnicmp -@@ -89,89 +101,38 @@ - #define _(String) (String) - #endif - --#if !defined(uchar) --#define uchar unsigned char --#endif --#if !defined(ushort) --#define ushort unsigned short --#endif -+#define ushort UshORt -+typedef unsigned char uchar; -+typedef unsigned short ushort; - -+#include "dcraw.h" - /* -- All global variables are defined here, and all functions that -+ RT All global variables are defined here, and all functions that - access them are prefixed with "CLASS". Note that a thread-safe - C++ class cannot have non-const static local variables. - */ --FILE *ifp, *ofp; --short order; --const char *ifname; --char *meta_data, xtrans[6][6], xtrans_abs[6][6]; --char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64]; --float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; --time_t timestamp; --off_t strip_offset, data_offset; --off_t thumb_offset, meta_offset, profile_offset; --unsigned shot_order, kodak_cbpp, exif_cfa, unique_id; --unsigned thumb_length, meta_length, profile_length; --unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0; --unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; --unsigned black, 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; --unsigned flip, tiff_flip, filters, colors; --ushort raw_height, raw_width, height, width, top_margin, left_margin; --ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; --ushort *raw_image, (*image)[4], cblack[4102]; --ushort white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; --double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; --float bright=1, user_mul[4]={0,0,0,0}, threshold=0; --int mask[8][4]; --int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; --int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=1; --int output_color=1, output_bps=8, output_tiff=0, med_passes=0; --int no_auto_bright=0; --unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; --float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; --const double xyz_rgb[3][3] = { /* XYZ from RGB */ -+ -+const double xyz_rgb[3][3] = { // XYZ from RGB - { 0.412453, 0.357580, 0.180423 }, - { 0.212671, 0.715160, 0.072169 }, - { 0.019334, 0.119193, 0.950227 } }; - const float d65_white[3] = { 0.950456, 1, 1.088754 }; --int histogram[4][0x2000]; --void (*write_thumb)(), (*write_fun)(); --void (*load_raw)(), (*thumb_load_raw)(); --jmp_buf failure; -- --struct decode { -- struct decode *branch[2]; -- int leaf; --} first_decode[2048], *second_decode, *free_decode; -- --struct tiff_ifd { -- int width, height, bps, comp, phint, offset, flip, samples, bytes; -- int tile_width, tile_length; -- float shutter; --} tiff_ifd[10]; -- --struct ph1 { -- int format, key_off, tag_21a; -- int black, split_col, black_col, split_row, black_row; -- float tag_210; --} ph1; - --#define CLASS -+/* RT: Removed unused structs */ -+#define CLASS DCraw:: - - #define FORC(cnt) for (c=0; c < cnt; c++) - #define FORC3 FORC(3) - #define FORC4 FORC(4) - #define FORCC FORC(colors) - --#define SQR(x) ((x)*(x)) -+#define SQR(x) rtengine::SQR(x) - #define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) --#define MIN(a,b) ((a) < (b) ? (a) : (b)) --#define MAX(a,b) ((a) > (b) ? (a) : (b)) --#define LIM(x,min,max) MAX(min,MIN(x,max)) --#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) --#define CLIP(x) LIM((int)(x),0,65535) -+#define MIN(a,b) rtengine::min(a,static_cast<__typeof__(a)>(b)) -+#define MAX(a,b) rtengine::max(a,static_cast<__typeof__(a)>(b)) -+#define LIM(x,min,max) rtengine::LIM(x,static_cast<__typeof__(x)>(min),static_cast<__typeof__(x)>(max)) -+#define ULIM(x,y,z) rtengine::median(x,static_cast<__typeof__(x)>(y),static_cast<__typeof__(x)>(z)) -+#define CLIP(x) rtengine::CLIP(x) - #define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } - - /* -@@ -247,6 +208,7 @@ - - if (filters == 1) return filter[(row+top_margin)&15][(col+left_margin)&15]; - if (filters == 9) return xtrans[(row+6) % 6][(col+6) % 6]; -+ - return FC(row,col); - } - -@@ -289,6 +251,7 @@ - fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp)); - } - data_error++; -+/*RT Issue 2467 longjmp (failure, 1);*/ - } - - ushort CLASS sget2 (uchar *s) -@@ -362,7 +325,7 @@ - { - if (fread (pixel, 2, count, ifp) < count) derror(); - if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) -- swab (pixel, pixel, count*2); -+ swab ((char*)pixel, (char*)pixel, count*2); - } - - void CLASS cubic_spline (const int *x_, const int *y_, const int len) -@@ -589,13 +552,13 @@ - return 0; - } - --unsigned CLASS getbithuff (int nbits, ushort *huff) -+inline unsigned CLASS getbithuff_t::operator() (int nbits, ushort *huff) - { -- static unsigned bitbuf=0; -- static int vbits=0, reset=0; -+/*RT static unsigned bitbuf=0; */ -+/*RT static int vbits=0, reset=0; */ - unsigned c; - -- if (nbits > 25) return 0; -+ if (UNLIKELY(nbits > 25)) return 0; - if (nbits < 0) - return bitbuf = vbits = reset = 0; - if (nbits == 0 || vbits < 0) return 0; -@@ -805,9 +768,13 @@ - FORC(2) free (huff[c]); - } - -+/* -+ Not a full implementation of Lossless JPEG, just -+ enough to decode Canon, Kodak and Adobe DNG images. -+ */ - struct jhead { -- int algo, bits, high, wide, clrs, sraw, psv, restart, vpred[6]; -- ushort quant[64], idct[64], *huff[20], *free[20], *row; -+ int bits, high, wide, clrs, sraw, psv, restart, vpred[6]; -+ ushort *huff[6], *free[4], *row; - }; - - int CLASS ljpeg_start (struct jhead *jh, int info_only) -@@ -828,9 +795,9 @@ - switch (tag) { - case 0xffc3: - jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3; -- case 0xffc1: -+ case 0xffc1: - case 0xffc0: -- jh->algo = tag & 0xff; -+ jh->algo = tag & 0xff; - jh->bits = data[0]; - jh->high = data[1] << 8 | data[2]; - jh->wide = data[3] << 8 | data[4]; -@@ -862,7 +829,7 @@ - FORC(4) jh->huff[2+c] = jh->huff[1]; - FORC(jh->sraw) jh->huff[1+c] = jh->huff[0]; - } -- jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4); -+ jh->row = (ushort *) calloc (2 * jh->wide*jh->clrs, 4); - merror (jh->row, "ljpeg_start()"); - return zero_after_ff = 1; - } -@@ -874,7 +841,7 @@ - free (jh->row); - } - --int CLASS ljpeg_diff (ushort *huff) -+inline int CLASS ljpeg_diff (ushort *huff) - { - int len, diff; - -@@ -901,7 +868,7 @@ - } - getbits(-1); - } -- FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1); -+ FORC3 row[c] = (jh->row + ((jrow & 1) + 1) * (jh->wide*jh->clrs*((jrow+c) & 1))); - for (col=0; col < jh->wide; col++) - FORC(jh->clrs) { - diff = ljpeg_diff (jh->huff[c]); -@@ -909,8 +876,7 @@ - pred = spred; - else if (col) pred = row[0][-jh->clrs]; - else pred = (jh->vpred[c] += diff) - diff; -- if (jrow && col) switch (jh->psv) { -- case 1: break; -+ if (jh->psv != 1 && jrow && col) switch (jh->psv) { - case 2: pred = row[1][0]; break; - case 3: pred = row[1][-jh->clrs]; break; - case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break; -@@ -919,7 +885,7 @@ - case 7: pred = (pred + row[1][0]) >> 1; break; - default: pred = 0; - } -- if ((**row = pred + diff) >> jh->bits) derror(); -+ if (UNLIKELY((**row = pred + diff) >> jh->bits)) derror(); - if (c <= jh->sraw) spred = **row; - row[0]++; row[1]++; - } -@@ -928,22 +894,38 @@ - - void CLASS lossless_jpeg_load_raw() - { -- int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0; - struct jhead jh; -- ushort *rp; -+ int row=0, col=0; - - if (!ljpeg_start (&jh, 0)) return; -- jwide = jh.wide * jh.clrs; -- -- for (jrow=0; jrow < jh.high; jrow++) { -- rp = ljpeg_row (jrow, &jh); -+ int jwide = jh.wide * jh.clrs; -+ ushort *rp[2]; -+ rp[0] = ljpeg_row (0, &jh); -+ -+ for (int jrow=0; jrow < jh.high; jrow++) { -+#ifdef _OPENMP -+#pragma omp parallel sections -+#endif -+{ -+#ifdef _OPENMP -+ #pragma omp section -+#endif -+ { -+ if(jrow < jh.high - 1) -+ rp[(jrow + 1)&1] = ljpeg_row (jrow + 1, &jh); -+ } -+#ifdef _OPENMP -+ #pragma omp section -+#endif -+ { - if (load_flags & 1) - row = jrow & 1 ? height-1-jrow/2 : jrow/2; -- for (jcol=0; jcol < jwide; jcol++) { -- val = curve[*rp++]; -+ for (int jcol=0; jcol < jwide; jcol++) { -+ int val = curve[*rp[jrow&1]++]; - if (cr2_slice[0]) { -- jidx = jrow*jwide + jcol; -- i = jidx / (cr2_slice[1]*raw_height); -+ int jidx = jrow*jwide + jcol; -+ int i = jidx / (cr2_slice[1]*raw_height); -+ int j; - if ((j = i >= cr2_slice[0])) - i = cr2_slice[0]; - jidx -= i * (cr2_slice[1]*raw_height); -@@ -956,6 +938,8 @@ - if (++col >= raw_width) - col = (row++,0); - } -+ } -+} - } - ljpeg_end (&jh); - } -@@ -1124,8 +1108,7 @@ - if (++col >= tile_width || col >= raw_width) - row += 1 + (col = 0); - } -- } -- } -+ } } - fseek (ifp, save+4, SEEK_SET); - if ((tcol += tile_width) >= raw_width) - trow += tile_length + (tcol = 0); -@@ -1332,14 +1315,14 @@ - int i, nz; - char tail[424]; - -- fseek (ifp, -sizeof tail, SEEK_END); -+ fseek (ifp, -(int)sizeof tail, SEEK_END); - fread (tail, 1, sizeof tail, ifp); - for (nz=i=0; i < sizeof tail; i++) - if (tail[i]) nz++; - return nz > 20; - } - --void CLASS jpeg_thumb(); -+/*RT void CLASS jpeg_thumb(); */ - - void CLASS ppm_thumb() - { -@@ -1701,10 +1684,10 @@ - } - } - --unsigned CLASS ph1_bithuff (int nbits, ushort *huff) -+unsigned CLASS ph1_bithuff_t::operator() (int nbits, ushort *huff) - { -- static UINT64 bitbuf=0; -- static int vbits=0; -+/*RT static UINT64 bitbuf=0; */ -+/*RT static int vbits=0; */ - unsigned c; - - if (nbits == -1) -@@ -1779,6 +1762,338 @@ - maximum = 0xfffc - ph1.black; - } - -+void CLASS parse_hasselblad_gain() -+{ -+ /* -+ Reverse-engineer's notes: -+ -+ The Hasselblad gain tag (0x19 in makernotes) is only available in the 3FR format and -+ is applied and removed when Hasselblad Phocus converts it to the FFF format. It's -+ always 0x300000 bytes large regardless of (tested) model, not all space in it is -+ used though. -+ -+ It contains individual calibration information from the factory to tune the sensor -+ performance. -+ -+ There is more calibration data in the tag than what is applied in conversion to FFF, -+ I've only cared to figure out the data which is actually used, but have some leads on -+ remaining info. -+ -+ The format is not equal between all models. Due to lack of 3FR files (harder to get -+ than FFF) only a subset of the models have been reverse-engineered. -+ -+ The header space is 512 bytes and is a mix of 16 and 32 bit values. Offset to blocks -+ are 32 bit values, but all information seems to be encoded in 16 bit values. Many -+ values in the header can be zeroed with no effect on FFF conversion, and their -+ meaning, if any, have not been further investigated. -+ -+ Formats: -+ hdr16[22] = raw width -+ hdr16[23] = raw height -+ hdr32[24] = offset to level corr block -+ Data block format. Seems to differ depending on sensor type. For tested H4D-50 -+ and H3D-31: 10 16 bit signed values per row -+ value 0: a correction factor (k) used on even columns, where the new pixel value is -+ calulated as follows: -+ new_value = old_value + (2 * ((k * (old_value_on_row_above-256)) / 32767) - 2) -+ note the connection to the value on the row above, seems to be some sort of signal -+ leakage correction. -+ value 1: same as value 0 but using old value on row below instead of above -+ value 2-3: same as value 0-1 but for odd columns -+ value 4-9: has some effect if non-zero (probably similar to the others) but not -+ investigated which, as it's seems to be always zero for the tested cameras. -+ -+ hdr32[25] = probably offset to "bad/unreliable pixels" info, always 512 as it starts -+ directly after the header. Not applied in FFF conversion (at least -+ typically). -+ Data block format guess: raw_height packets of -+ -+ -+ hdr32[27] = offset to unknown data (bad colulmns?), of the form: -+ <0> -+ packet: . -+ -+ hdr32[34] = curves offset, seems to be A/D curves (one per channel) on newer models -+ and some sort of a film curve on older. Not applied in FFF conversion. -+ -+ hdr32[36] = flatfield correction, not available in older models. Data format: -+ <1><11 * 2 pad> -+ packet: -+ -+ The header pad is not zeroed and might seem to contain some sort of -+ information, but it makes no difference if set to zero. See -+ hasselblad_correct() how the flatfield is applied. -+ -+ Applied in FFF conversion is levels, flatfield correction, and the bad columns(?) -+ data. A/D curves are surprisingly not applied, maybe pre-applied in hardware and -+ only available as information? Levels are applied before flatfield, further -+ ordering has not been investigated. -+ -+ Not all combinations/models have been tested so there may be gaps. -+ -+ Most clipped pixels in a 3FR is at 65535, but there's also some at 65534. Both -+ are set to 65535 when calibrated, while 65533 is treated as a normal value. In -+ the calibration process smaller values can be scaled to 65534 (which should -+ not be seen as clipped). -+ */ -+ -+ ushort raw_h, count, ch_count, u16; -+ int i, offset; -+ off_t base; -+ -+ base = ftell(ifp); -+ fseek(ifp, 2 * 23, SEEK_CUR); -+ raw_h = get2(); -+ fseek(ifp, 48, SEEK_CUR); -+ offset = get4(); -+ hbd.levels = offset ? base + offset : 0; -+ fseek(ifp, 8, SEEK_CUR); -+ offset = get4(); -+ hbd.unknown1 = offset ? base + offset : 0; -+ fseek(ifp, 32, SEEK_CUR); -+ offset = get4(); -+ hbd.flatfield = offset ? base + offset : 0; -+} -+ -+void CLASS hasselblad_correct() -+{ -+ unsigned col, row; -+ -+ /* -+ -+ This function applies 3FR calibration data. At the time of writing it supports a -+ subset, so here's a todo list: -+ -+ TODO: -+ - Support all gain tag formats -+ - The 0x19 tag varies a bit between models. We don't have parsers for all models. -+ - The reference model used was during inital reverse-engineering was a H4D-50, -+ we probably support the Hasselblads with Kodak 31, 39, 40 and 50 megapixels -+ well, but more work is needed for Kodak 16 and 22, Dalsa 60 and Sony 50. -+ - Apply bad column(?) data (hbd.unknown1) -+ - It was left out in this initial release since the effect is very small. -+ - Apply black(?) data, tag 0x1a and 0x1b is not parsed, it has however marginal -+ effect (at least for shorter exposures) so it's not too important. -+ -+ While there are things to do, the current implementation supports the most -+ important aspects, the faltfield and levels calibrations applied can have strong -+ visible effects. -+ -+ */ -+ -+ if (hbd.levels) { -+ int i; -+ fseek(ifp, hbd.levels, SEEK_SET); -+ /* skip the first set (not used as we don't apply on first/last row), we look at it though to see if -+ the levels format is one that we support (there are other formats on some models which is not -+ supported here) */ -+ short test[10]; -+ for (i = 0; i < 10; i++) test[i] = (short)get2(); -+ if (test[5] == 0 && test[6] == 0 && test[7] == 0 && test[8] == 0 && test[9] == 0) { -+ int corr[4]; -+ ushort *row_above = (ushort *)malloc(sizeof(ushort) * raw_width); // we need to cache row above as we write new values as we go -+ for (col = 0; col < raw_width; col++) row_above[col] = RAW(0,col); -+ for (row = 1; row < raw_height-1; row++) { -+ for (i = 0; i < 4; i++) corr[i] = (short)get2(); -+ fseek(ifp, 6 * 2, SEEK_CUR); -+ for (col = 0; col < raw_width; col++) { -+ unsigned v = RAW(row,col); -+ if (v >= 65534) { -+ v = 65535; -+ } else { -+ if (corr[((col & 1)<<1)+0] && row_above[col] > black) v += 2 * ((corr[((col & 1)<<1)+0] * (row_above[col]-(int)black)) / 32767) - 2; -+ if (corr[((col & 1)<<1)+1] && RAW(row+1,col) > black) v += 2 * ((corr[((col & 1)<<1)+1] * (RAW(row+1,col)-(int)black)) / 32767) - 2; -+ } -+ row_above[col] = RAW(row,col); -+ RAW(row,col) = CLIP(v); -+ } -+ } -+ free(row_above); -+ } -+ } -+ -+ if (hbd.flatfield) { -+ int bw, bh, ffrows, ffcols, i, c; -+ ushort ref[4], ref_max; -+ fseek(ifp, hbd.flatfield, SEEK_SET); -+ get2(); -+ bw = get2(); -+ bh = get2(); -+ ffcols = get2(); -+ ffrows = get2(); -+ fseek(ifp, hbd.flatfield + 16 * 2, SEEK_SET); -+ -+ ushort *ffmap = (ushort *)malloc(sizeof(*ffmap) * 4 * ffcols * ffrows); -+ for (i = 0; i < 4 * ffcols * ffrows; i++) ffmap[i] = get2(); -+ -+ /* Get reference values from center of field. This seems to be what Phocus does too, -+ but haven't cared to figure out exactly at which coordinate */ -+ i = 4 * (ffcols * ffrows / 2 + ffcols / 2); -+ ref[0] = ffmap[i+0]; -+ ref[1] = ffmap[i+1]; -+ ref[3] = ffmap[i+2]; // G2 = index 3 in dcraw, 2 in 3FR -+ ref[2] = ffmap[i+3]; -+ ref_max = 0; -+ FORC4 if (ref[c] > ref_max) ref_max = ref[c]; -+ if (ref_max == 0) ref[0] = ref[1] = ref[2] = ref[3] = ref_max = 10000; -+ -+ /* Convert measured flatfield values to actual multipliers. The measured flatfield -+ can have vignetting which should be normalized, only color cast should be corrected. */ -+ for (i = 0; i < 4 * ffcols * ffrows; i += 4) { -+ double base, min = 65535.0, max = 0; -+ double cur[4]; -+ cur[0] = (double)ffmap[i+0] / ref[0]; -+ cur[1] = (double)ffmap[i+1] / ref[1]; -+ cur[3] = (double)ffmap[i+2] / ref[3]; // G2 index differs in dcraw and 3FR -+ cur[2] = (double)ffmap[i+3] / ref[2]; -+ FORC4 { -+ if (cur[c] < min) min = cur[c]; -+ if (cur[c] > max) max = cur[c]; -+ } -+ if (max == 0) max = 1.0; -+ base = (cur[0]+cur[1]+cur[2]+cur[3])/(max*4); -+ FORC4 cur[c] = cur[c] == 0 ? 1.0 : (base * max) / cur[c]; -+ /* convert to integer multiplier and store back to ffmap, we limit -+ range to 4 (16384*4) which should be fine for flatfield */ -+ FORC4 { -+ cur[c] *= 16384.0; -+ if (cur[c] > 65535.0) cur[c] = 65535.0; -+ ffmap[i+c] = (ushort)cur[c]; -+ } -+ } -+ -+ // of the cameras we've tested we know the exact placement of the flatfield map -+ int row_offset, col_offset; -+ switch (raw_width) { -+ case 8282: // 50 megapixel Kodak -+ row_offset = 21; -+ col_offset = 71; -+ break; -+ default: -+ /* Default case for camera models we've not tested. We center the map, which may -+ not be exactly where it should be but close enough for the smooth flatfield */ -+ row_offset = (raw_height - bh * ffrows) / 2; -+ col_offset = (raw_width - bw * ffcols) / 2; -+ break; -+ } -+ -+ /* -+ Concerning smoothing between blocks in the map Phocus makes it only vertically, -+ probably because it's simpler and faster. Looking at actual flatfield data it seems -+ like it's better to smooth in both directions. Possibly flatfield could be used for -+ correcting tiling on Dalsa sensors (H4D-60) like partly done in Phase One IIQ format, -+ and then sharp edges may be beneficial at least at the tiling seams, but at the time -+ of writing I've had no H4D-60 3FR files to test with to verify that. -+ -+ Meanwhile we do both vertical and horizontal smoothing/blurring. -+ */ -+ -+ /* pre-calculate constants for blurring. We probably should make a more efficient -+ blur than this, but this does not need any buffer and makes nice-looking -+ radial gradients */ -+ ushort *corners_weight = (ushort *)malloc(bw*bh*9*sizeof(*corners_weight)); -+ const int corners_mix[9][4][2] = { { {0,0}, {0,1}, {1,0}, {1,1} }, -+ { {0,1}, {1,1}, {-1,-1}, {-1,-1} }, -+ { {0,1}, {0,2}, {1,1}, {1,2} }, -+ { {1,0}, {1,1}, {-1,-1}, {-1,-1} }, -+ { {1,1}, {-1,-1}, {-1,-1}, {-1,-1} }, -+ { {1,1}, {1,2}, {-1,-1}, {-1,-1} }, -+ { {1,0}, {1,1}, {2,0}, {2,1} }, -+ { {1,1}, {2,1}, {-1,-1}, {-1,-1} }, -+ { {1,1}, {1,2}, {2,1}, {2,2} } }; -+ const ushort corners_shift[9] = { 2, 1, 2, 1, 0, 1, 2, 1, 2 }; -+ for (row = 0; row < bh; row++) { -+ const ushort maxdist = bw < bh ? bw/2-1 : bh/2-1; -+ const unsigned bwu = (unsigned)bw; -+ const unsigned bhu = (unsigned)bh; -+ const unsigned corners[9][2] = {{0,0}, {0,bwu/2}, {0,bwu-1}, -+ {bhu/2,0},{bhu/2,bwu/2},{bhu/2,bwu-1}, -+ {bhu-1,0},{bhu-1,bwu/2},{bhu-1,bwu-1}}; -+ for (col = 0; col < bw; col++) { -+ for (i = 0; i < 9; i++) { -+ ushort dist = (ushort)sqrt(abs(corners[i][0] - row) * abs(corners[i][0] - row) + abs(corners[i][1] - col) * abs(corners[i][1] - col)); -+ ushort weight = dist > maxdist ? 0 : maxdist - dist; -+ corners_weight[9*(row*bw+col)+i] = weight; -+ } -+ } -+ } -+ -+ // apply flatfield -+#pragma omp parallel for -+ for (int row = 0; row < raw_height; row++) { -+ int ffs, cur_ffr, i, c; -+ if (row < row_offset) { -+ cur_ffr = row_offset; -+ ffs = 0; -+ } else if (row >= row_offset + ffrows * bh) { -+ cur_ffr = row_offset + (ffrows-1) * bh; -+ ffs = 4 * ffcols * (ffrows-1); -+ } else { -+ cur_ffr = row_offset + bh * ((row - row_offset) / bh); -+ ffs = 4 * ffcols * ((row - row_offset) / bh); -+ } -+ int next_ffc = 0, cur_ffc = col_offset; -+ int ffc = ffs; -+ ushort *cur[3][3]; // points to local ffmap entries with center at cur[1][1] -+ for (int col = 0; col < raw_width; col++) { -+ if (col == next_ffc) { -+ int rowsub = ffs == 0 ? 0 : ffcols*4; -+ int rowadd = ffs == 4 * ffcols * (ffrows-1) ? 0 : ffcols * 4; -+ int colsub = ffc == ffs ? 0 : 4; -+ int coladd = ffc == ffs + 4 * (ffcols-1) ? 0 : 4; -+ if (col != 0) cur_ffc = next_ffc; -+ else next_ffc += col_offset; -+ next_ffc += bw; -+ -+ cur[0][0] = &ffmap[ffc-rowsub-colsub]; -+ cur[0][1] = &ffmap[ffc-rowsub]; -+ cur[0][2] = &ffmap[ffc-rowsub+coladd]; -+ -+ cur[1][0] = &ffmap[ffc-colsub]; -+ cur[1][1] = &ffmap[ffc]; -+ cur[1][2] = &ffmap[ffc+coladd]; -+ -+ cur[2][0] = &ffmap[ffc+rowadd-colsub]; -+ cur[2][1] = &ffmap[ffc+rowadd]; -+ cur[2][2] = &ffmap[ffc+rowadd+coladd]; -+ -+ ffc += 4; -+ if (ffc == ffs + 4 * ffcols) next_ffc += raw_width; // last col in map, avoid stepping further -+ } -+ unsigned v = RAW(row,col); -+ if (v > black && v < 65535) { -+ c = FC(row,col); -+ unsigned x = col < cur_ffc ? 0 : col - cur_ffc; -+ unsigned y = row < cur_ffr ? 0 : row - cur_ffr; -+ if (x >= bw) x = bw-1; -+ if (y >= bh) y = bh-1; -+ unsigned wsum = 0; -+ unsigned mul = 0; -+ for (i = 0; i < 9; i++) { -+ ushort cw = corners_weight[9*(y*bw+x)+i]; -+ if (cw) { -+ unsigned m = 0; -+ int j; -+ for (j = 0; j < 1 << corners_shift[i]; j++) { -+ int cr = corners_mix[i][j][0], cc = corners_mix[i][j][1]; -+ m += cur[cr][cc][c]; -+ } -+ m >>= corners_shift[i]; -+ mul += m * cw; -+ wsum += cw; -+ } -+ } -+ mul /= wsum; -+ v = black + ((v-black) * mul) / 16384; -+ RAW(row,col) = v > 65535 ? 65535 : v; -+ } -+ } -+ } -+ free(ffmap); -+ free(corners_weight); -+ } -+} -+ - void CLASS hasselblad_load_raw() - { - struct jhead jh; -@@ -2002,10 +2317,10 @@ - maximum = curve[0x3ff]; - } - --unsigned CLASS pana_bits (int nbits) -+unsigned CLASS pana_bits_t::operator() (int nbits) - { -- static uchar buf[0x4000]; -- static int vbits; -+/*RT static uchar buf[0x4000]; */ -+/*RT static int vbits;*/ - int byte; - - if (!nbits) return vbits=0; -@@ -2188,7 +2503,7 @@ - - void CLASS kodak_radc_load_raw() - { -- static const char src[] = { -+ static const signed char src[] = { - 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8, - 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8, - 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8, -@@ -2294,11 +2609,11 @@ - METHODDEF(boolean) - fill_input_buffer (j_decompress_ptr cinfo) - { -- static uchar jpeg_buffer[4096]; -+/*RT static uchar jpeg_buffer[4096]; */ - size_t nbytes; - - nbytes = fread (jpeg_buffer, 1, 4096, ifp); -- swab (jpeg_buffer, jpeg_buffer, nbytes); -+ swab ((char*)jpeg_buffer, (char*)jpeg_buffer, nbytes); - cinfo->src->next_input_byte = jpeg_buffer; - cinfo->src->bytes_in_buffer = nbytes; - return TRUE; -@@ -2648,10 +2963,9 @@ - maximum = (1 << (thumb_misc & 31)) - 1; - } - --void CLASS sony_decrypt (unsigned *data, int len, int start, int key) -+void CLASS sony_decrypt_t::operator()(unsigned *data, int len, int start, int key) - { -- static unsigned pad[128], p; -- -+/*RT static unsigned pad[128], p;*/ - if (start) { - for (p=0; p < 4; p++) - pad[p] = key = key * 48828125 + 1; -@@ -2736,11 +3050,13 @@ - bit += 7; - } - for (i=0; i < 16; i++, col+=2) -- RAW(row,col) = curve[pix[i] << 1] >> 2; -+ RAW(row,col) = curve[pix[i] << 1]; // >> 2; RT: disabled shifting to avoid precision loss - col -= col & 1 ? 1:31; - } - } - free (data); -+ maximum = curve[0x7ff << 1]; // RT: fix maximum. -+ maximum = 16300; // RT: conservative white level tested on various ARW2 cameras. This constant was set in 2013-12-17, may need re-evaluation in the future. - } - - void CLASS samsung_load_raw() -@@ -2905,7 +3221,10 @@ - diff = diff ? -diff : 0x80; - if (ftell(ifp) + 12 >= seg[1][1]) - diff = 0; -- raw_image[pix] = pred[pix & 1] += diff; -+ if(pix>=raw_width*raw_height) -+ derror(); -+ else -+ raw_image[pix] = pred[pix & 1] += diff; - if (!(pix & 1) && HOLE(pix / raw_width)) pix += 2; - } - maximum = 0xff; -@@ -3038,7 +3357,7 @@ - - void CLASS foveon_decoder (unsigned size, unsigned code) - { -- static unsigned huff[1024]; -+/*RT static unsigned huff[1024];*/ - struct decode *cur; - int i, len; - -@@ -3135,7 +3454,7 @@ - pred[c] += diff[dindex->leaf]; - if (pred[c] >> 16 && ~pred[c] >> 16) derror(); - } -- FORC3 image[row*width+col][c] = pred[c]; -+ FORC3 image[row*width+col][c] = pred[c] < 0 ? 0 : pred[c]; - } - } - } -@@ -3746,6 +4065,8 @@ - if (load_raw == &CLASS phase_one_load_raw || - load_raw == &CLASS phase_one_load_raw_c) - phase_one_correct(); -+ if (load_raw == &CLASS hasselblad_load_raw) // RT -+ hasselblad_correct(); // RT - if (fuji_width) { - for (row=0; row < raw_height-top_margin*2; row++) { - for (col=0; col < fuji_width << !fuji_layout; col++) { -@@ -3761,10 +4082,13 @@ - } - } - } else { -- for (row=0; row < height; row++) -- for (col=0; col < width; col++) -+ -+#pragma omp parallel for -+ for (int row=0; row < height; row++) -+ for (int col=0; col < width; col++) - BAYER2(row,col) = RAW(row+top_margin,col+left_margin); - } -+ - if (mask[0][3] > 0) goto mask_set; - if (load_raw == &CLASS canon_load_raw || - load_raw == &CLASS lossless_jpeg_load_raw) { -@@ -3808,127 +4132,127 @@ - } - } - --void CLASS remove_zeroes() --{ -- unsigned row, col, tot, n, r, c; -- -- for (row=0; row < height; row++) -- for (col=0; col < width; col++) -- if (BAYER(row,col) == 0) { -- tot = n = 0; -- for (r = row-2; r <= row+2; r++) -- for (c = col-2; c <= col+2; c++) -- if (r < height && c < width && -- FC(r,c) == FC(row,col) && BAYER(r,c)) -- tot += (n++,BAYER(r,c)); -- if (n) BAYER(row,col) = tot/n; -- } --} -+//void CLASS remove_zeroes() -+//{ -+// unsigned row, col, tot, n, r, c; -+// -+// for (row=0; row < height; row++) -+// for (col=0; col < width; col++) -+// if (BAYER(row,col) == 0) { -+// tot = n = 0; -+// for (r = row-2; r <= row+2; r++) -+// for (c = col-2; c <= col+2; c++) -+// if (r < height && c < width && -+// FC(r,c) == FC(row,col) && BAYER(r,c)) -+// tot += (n++,BAYER(r,c)); -+// if (n) BAYER(row,col) = tot/n; -+// } -+//} - - /* - Seach from the current directory up to the root looking for - a ".badpixels" file, and fix those pixels now. - */ --void CLASS bad_pixels (const char *cfname) --{ -- FILE *fp=0; -- char *fname, *cp, line[128]; -- int len, time, row, col, r, c, rad, tot, n, fixed=0; -- -- if (!filters) return; -- if (cfname) -- fp = fopen (cfname, "r"); -- else { -- for (len=32 ; ; len *= 2) { -- fname = (char *) malloc (len); -- if (!fname) return; -- if (getcwd (fname, len-16)) break; -- free (fname); -- if (errno != ERANGE) return; -- } --#if defined(WIN32) || defined(DJGPP) -- if (fname[1] == ':') -- memmove (fname, fname+2, len-2); -- for (cp=fname; *cp; cp++) -- if (*cp == '\\') *cp = '/'; --#endif -- cp = fname + strlen(fname); -- if (cp[-1] == '/') cp--; -- while (*fname == '/') { -- strcpy (cp, "/.badpixels"); -- if ((fp = fopen (fname, "r"))) break; -- if (cp == fname) break; -- while (*--cp != '/'); -- } -- free (fname); -- } -- if (!fp) return; -- while (fgets (line, 128, fp)) { -- cp = strchr (line, '#'); -- if (cp) *cp = 0; -- if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue; -- if ((unsigned) col >= width || (unsigned) row >= height) continue; -- if (time > timestamp) continue; -- for (tot=n=0, rad=1; rad < 3 && n==0; rad++) -- for (r = row-rad; r <= row+rad; r++) -- for (c = col-rad; c <= col+rad; c++) -- if ((unsigned) r < height && (unsigned) c < width && -- (r != row || c != col) && fcol(r,c) == fcol(row,col)) { -- tot += BAYER2(r,c); -- n++; -- } -- BAYER2(row,col) = tot/n; -- if (verbose) { -- if (!fixed++) -- fprintf (stderr,_("Fixed dead pixels at:")); -- fprintf (stderr, " %d,%d", col, row); -- } -- } -- if (fixed) fputc ('\n', stderr); -- fclose (fp); --} -- --void CLASS subtract (const char *fname) --{ -- FILE *fp; -- int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col; -- ushort *pixel; -- -- if (!(fp = fopen (fname, "rb"))) { -- perror (fname); return; -- } -- if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1; -- while (!error && nd < 3 && (c = fgetc(fp)) != EOF) { -- if (c == '#') comment = 1; -- if (c == '\n') comment = 0; -- if (comment) continue; -- if (isdigit(c)) number = 1; -- if (number) { -- if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0'; -- else if (isspace(c)) { -- number = 0; nd++; -- } else error = 1; -- } -- } -- if (error || nd < 3) { -- fprintf (stderr,_("%s is not a valid PGM file!\n"), fname); -- fclose (fp); return; -- } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) { -- fprintf (stderr,_("%s has the wrong dimensions!\n"), fname); -- fclose (fp); return; -- } -- pixel = (ushort *) calloc (width, sizeof *pixel); -- merror (pixel, "subtract()"); -- for (row=0; row < height; row++) { -- fread (pixel, 2, width, fp); -- for (col=0; col < width; col++) -- BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0); -- } -- free (pixel); -- fclose (fp); -- memset (cblack, 0, sizeof cblack); -- black = 0; --} -+//void CLASS bad_pixels (const char *cfname) -+//{ -+// FILE *fp=0; -+// char *fname, *cp, line[128]; -+// int len, time, row, col, r, c, rad, tot, n, fixed=0; -+// -+// if (!filters) return; -+// if (cfname) -+// fp = fopen (cfname, "r"); -+// else { -+// for (len=32 ; ; len *= 2) { -+// fname = (char *) malloc (len); -+// if (!fname) return; -+// if (getcwd (fname, len-16)) break; -+// free (fname); -+// if (errno != ERANGE) return; -+// } -+//#if defined(WIN32) || defined(DJGPP) -+// if (fname[1] == ':') -+// memmove (fname, fname+2, len-2); -+// for (cp=fname; *cp; cp++) -+// if (*cp == '\\') *cp = '/'; -+//#endif -+// cp = fname + strlen(fname); -+// if (cp[-1] == '/') cp--; -+// while (*fname == '/') { -+// strcpy (cp, "/.badpixels"); -+// if ((fp = fopen (fname, "r"))) break; -+// if (cp == fname) break; -+// while (*--cp != '/'); -+// } -+// free (fname); -+// } -+// if (!fp) return; -+// while (fgets (line, 128, fp)) { -+// cp = strchr (line, '#'); -+// if (cp) *cp = 0; -+// if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue; -+// if ((unsigned) col >= width || (unsigned) row >= height) continue; -+// if (time > timestamp) continue; -+// for (tot=n=0, rad=1; rad < 3 && n==0; rad++) -+// for (r = row-rad; r <= row+rad; r++) -+// for (c = col-rad; c <= col+rad; c++) -+// if ((unsigned) r < height && (unsigned) c < width && -+// (r != row || c != col) && fcol(r,c) == fcol(row,col)) { -+// tot += BAYER2(r,c); -+// n++; -+// } -+// BAYER2(row,col) = tot/n; -+// if (verbose) { -+// if (!fixed++) -+// fprintf (stderr,_("Fixed dead pixels at:")); -+// fprintf (stderr, " %d,%d", col, row); -+// } -+// } -+// if (fixed) fputc ('\n', stderr); -+// fclose (fp); -+//} -+ -+//void CLASS subtract (const char *fname) -+//{ -+// FILE *fp; -+// int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col; -+// ushort *pixel; -+// -+// if (!(fp = fopen (fname, "rb"))) { -+// perror (fname); return; -+// } -+// if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1; -+// while (!error && nd < 3 && (c = fgetc(fp)) != EOF) { -+// if (c == '#') comment = 1; -+// if (c == '\n') comment = 0; -+// if (comment) continue; -+// if (isdigit(c)) number = 1; -+// if (number) { -+// if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0'; -+// else if (isspace(c)) { -+// number = 0; nd++; -+// } else error = 1; -+// } -+// } -+// if (error || nd < 3) { -+// fprintf (stderr,_("%s is not a valid PGM file!\n"), fname); -+// fclose (fp); return; -+// } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) { -+// fprintf (stderr,_("%s has the wrong dimensions!\n"), fname); -+// fclose (fp); return; -+// } -+// pixel = (ushort *) calloc (width, sizeof *pixel); -+// merror (pixel, "subtract()"); -+// for (row=0; row < height; row++) { -+// fread (pixel, 2, width, fp); -+// for (col=0; col < width; col++) -+// BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0); -+// } -+// free (pixel); -+// fclose (fp); -+// memset (cblack, 0, sizeof cblack); -+// black = 0; -+//} - - void CLASS gamma_curve (double pwr, double ts, int mode, int imax) - { -@@ -4093,94 +4417,94 @@ - } - #endif - --void CLASS hat_transform (float *temp, float *base, int st, int size, int sc) --{ -- int i; -- for (i=0; i < sc; i++) -- temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)]; -- for (; i+sc < size; i++) -- temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)]; -- for (; i < size; i++) -- temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))]; --} -- --void CLASS wavelet_denoise() --{ -- float *fimg=0, *temp, thold, mul[2], avg, diff; -- int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast, blk[2]; -- ushort *window[4]; -- static const float noise[] = -- { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 }; -- -- if (verbose) fprintf (stderr,_("Wavelet denoising...\n")); -- -- while (maximum << scale < 0x10000) scale++; -- maximum <<= --scale; -- black <<= scale; -- FORC4 cblack[c] <<= scale; -- if ((size = iheight*iwidth) < 0x15550000) -- fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg); -- merror (fimg, "wavelet_denoise()"); -- temp = fimg + size*3; -- if ((nc = colors) == 3 && filters) nc++; -- FORC(nc) { /* denoise R,G1,B,G3 individually */ -- for (i=0; i < size; i++) -- fimg[i] = 256 * sqrt(image[i][c] << scale); -- for (hpass=lev=0; lev < 5; lev++) { -- lpass = size*((lev & 1)+1); -- for (row=0; row < iheight; row++) { -- hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev); -- for (col=0; col < iwidth; col++) -- fimg[lpass + row*iwidth + col] = temp[col] * 0.25; -- } -- for (col=0; col < iwidth; col++) { -- hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev); -- for (row=0; row < iheight; row++) -- fimg[lpass + row*iwidth + col] = temp[row] * 0.25; -- } -- thold = threshold * noise[lev]; -- for (i=0; i < size; i++) { -- fimg[hpass+i] -= fimg[lpass+i]; -- if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold; -- else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold; -- else fimg[hpass+i] = 0; -- if (hpass) fimg[i] += fimg[hpass+i]; -- } -- hpass = lpass; -- } -- for (i=0; i < size; i++) -- image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000); -- } -- if (filters && colors == 3) { /* pull G1 and G3 closer together */ -- for (row=0; row < 2; row++) { -- mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1]; -- blk[row] = cblack[FC(row,0) | 1]; -- } -- for (i=0; i < 4; i++) -- window[i] = (ushort *) fimg + width*i; -- for (wlast=-1, row=1; row < height-1; row++) { -- while (wlast < row+1) { -- for (wlast++, i=0; i < 4; i++) -- window[(i+3) & 3] = window[i]; -- for (col = FC(wlast,1) & 1; col < width; col+=2) -- window[2][col] = BAYER(wlast,col); -- } -- thold = threshold/512; -- for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) { -- avg = ( window[0][col-1] + window[0][col+1] + -- window[2][col-1] + window[2][col+1] - blk[~row & 1]*4 ) -- * mul[row & 1] + (window[1][col] + blk[row & 1]) * 0.5; -- avg = avg < 0 ? 0 : sqrt(avg); -- diff = sqrt(BAYER(row,col)) - avg; -- if (diff < -thold) diff += thold; -- else if (diff > thold) diff -= thold; -- else diff = 0; -- BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5); -- } -- } -- } -- free (fimg); --} -+//void CLASS hat_transform (float *temp, float *base, int st, int size, int sc) -+//{ -+// int i; -+// for (i=0; i < sc; i++) -+// temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)]; -+// for (; i+sc < size; i++) -+// temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)]; -+// for (; i < size; i++) -+// temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))]; -+//} -+ -+//void CLASS wavelet_denoise() -+//{ -+// float *fimg=0, *temp, thold, mul[2], avg, diff; -+// int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast, blk[2]; -+// ushort *window[4]; -+// static const float noise[] = -+// { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 }; -+// -+// if (verbose) fprintf (stderr,_("Wavelet denoising...\n")); -+// -+// while (maximum << scale < 0x10000) scale++; -+// maximum <<= --scale; -+// black <<= scale; -+// FORC4 cblack[c] <<= scale; -+// if ((size = iheight*iwidth) < 0x15550000) -+// fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg); -+// merror (fimg, "wavelet_denoise()"); -+// temp = fimg + size*3; -+// if ((nc = colors) == 3 && filters) nc++; -+// FORC(nc) { /* denoise R,G1,B,G3 individually */ -+// for (i=0; i < size; i++) -+// fimg[i] = 256 * sqrt(image[i][c] << scale); -+// for (hpass=lev=0; lev < 5; lev++) { -+// lpass = size*((lev & 1)+1); -+// for (row=0; row < iheight; row++) { -+// hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev); -+// for (col=0; col < iwidth; col++) -+// fimg[lpass + row*iwidth + col] = temp[col] * 0.25; -+// } -+// for (col=0; col < iwidth; col++) { -+// hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev); -+// for (row=0; row < iheight; row++) -+// fimg[lpass + row*iwidth + col] = temp[row] * 0.25; -+// } -+// thold = threshold * noise[lev]; -+// for (i=0; i < size; i++) { -+// fimg[hpass+i] -= fimg[lpass+i]; -+// if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold; -+// else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold; -+// else fimg[hpass+i] = 0; -+// if (hpass) fimg[i] += fimg[hpass+i]; -+// } -+// hpass = lpass; -+// } -+// for (i=0; i < size; i++) -+// image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000); -+// } -+// if (filters && colors == 3) { /* pull G1 and G3 closer together */ -+// for (row=0; row < 2; row++) { -+// mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1]; -+// blk[row] = cblack[FC(row,0) | 1]; -+// } -+// for (i=0; i < 4; i++) -+// window[i] = (ushort *) fimg + width*i; -+// for (wlast=-1, row=1; row < height-1; row++) { -+// while (wlast < row+1) { -+// for (wlast++, i=0; i < 4; i++) -+// window[(i+3) & 3] = window[i]; -+// for (col = FC(wlast,1) & 1; col < width; col+=2) -+// window[2][col] = BAYER(wlast,col); -+// } -+// thold = threshold/512; -+// for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) { -+// avg = ( window[0][col-1] + window[0][col+1] + -+// window[2][col-1] + window[2][col+1] - blk[~row & 1]*4 ) -+// * mul[row & 1] + (window[1][col] + blk[row & 1]) * 0.5; -+// avg = avg < 0 ? 0 : sqrt(avg); -+// diff = sqrt(BAYER(row,col)) - avg; -+// if (diff < -thold) diff += thold; -+// else if (diff > thold) diff -= thold; -+// else diff = 0; -+// BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5); -+// } -+// } -+// } -+// free (fimg); -+//} - - void CLASS scale_colors() - { -@@ -4238,7 +4562,7 @@ - if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1; - dark = black; - sat = maximum; -- if (threshold) wavelet_denoise(); -+// if (threshold) wavelet_denoise(); - maximum -= black; - for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) { - if (dmin > pre_mul[c]) -@@ -4344,776 +4668,440 @@ - if (half_size) filters = 0; - } - --void CLASS border_interpolate (int border) --{ -- unsigned row, col, y, x, f, c, sum[8]; -- -- for (row=0; row < height; row++) -- for (col=0; col < width; col++) { -- if (col==border && row >= border && row < height-border) -- col = width-border; -- memset (sum, 0, sizeof sum); -- for (y=row-1; y != row+2; y++) -- for (x=col-1; x != col+2; x++) -- if (y < height && x < width) { -- f = fcol(y,x); -- sum[f] += image[y*width+x][f]; -- sum[f+4]++; -- } -- f = fcol(row,col); -- FORCC if (c != f && sum[c+4]) -- image[row*width+col][c] = sum[c] / sum[c+4]; -- } --} -- --void CLASS lin_interpolate() --{ -- int code[16][16][32], size=16, *ip, sum[4]; -- int f, c, i, x, y, row, col, shift, color; -- ushort *pix; -- -- if (verbose) fprintf (stderr,_("Bilinear interpolation...\n")); -- if (filters == 9) size = 6; -- border_interpolate(1); -- for (row=0; row < size; row++) -- for (col=0; col < size; col++) { -- ip = code[row][col]+1; -- f = fcol(row,col); -- memset (sum, 0, sizeof sum); -- for (y=-1; y <= 1; y++) -- for (x=-1; x <= 1; x++) { -- shift = (y==0) + (x==0); -- color = fcol(row+y,col+x); -- if (color == f) continue; -- *ip++ = (width*y + x)*4 + color; -- *ip++ = shift; -- *ip++ = color; -- sum[color] += 1 << shift; -- } -- code[row][col][0] = (ip - code[row][col]) / 3; -- FORCC -- if (c != f) { -- *ip++ = c; -- *ip++ = 256 / sum[c]; -- } -- } -- for (row=1; row < height-1; row++) -- for (col=1; col < width-1; col++) { -- pix = image[row*width+col]; -- ip = code[row % size][col % size]; -- memset (sum, 0, sizeof sum); -- for (i=*ip++; i--; ip+=3) -- sum[ip[2]] += pix[ip[0]] << ip[1]; -- for (i=colors; --i; ip+=2) -- pix[ip[0]] = sum[ip[0]] * ip[1] >> 8; -- } --} -- --/* -- This algorithm is officially called: -- -- "Interpolation using a Threshold-based variable number of gradients" -- -- described in http://scien.stanford.edu/pages/labsite/1999/psych221/projects/99/tingchen/algodep/vargra.html -- -- I've extended the basic idea to work with non-Bayer filter arrays. -- Gradients are numbered clockwise from NW=0 to W=7. -- */ --void CLASS vng_interpolate() --{ -- static const signed char *cp, terms[] = { -- -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01, -- -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01, -- -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03, -- -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06, -- -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04, -- -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01, -- -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40, -- -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11, -- -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11, -- -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22, -- -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44, -- -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10, -- -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04, -- +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40, -- +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20, -- +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08, -- +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20, -- +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44, -- +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60, -- +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80, -- +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40, -- +1,+0,+2,+1,0,0x10 -- }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 }; -- ushort (*brow[5])[4], *pix; -- int prow=8, pcol=2, *ip, *code[16][16], gval[8], gmin, gmax, sum[4]; -- int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag; -- int g, diff, thold, num, c; -- -- lin_interpolate(); -- if (verbose) fprintf (stderr,_("VNG interpolation...\n")); -- -- if (filters == 1) prow = pcol = 16; -- if (filters == 9) prow = pcol = 6; -- ip = (int *) calloc (prow*pcol, 1280); -- merror (ip, "vng_interpolate()"); -- for (row=0; row < prow; row++) /* Precalculate for VNG */ -- for (col=0; col < pcol; col++) { -- code[row][col] = ip; -- for (cp=terms, t=0; t < 64; t++) { -- y1 = *cp++; x1 = *cp++; -- y2 = *cp++; x2 = *cp++; -- weight = *cp++; -- grads = *cp++; -- color = fcol(row+y1,col+x1); -- if (fcol(row+y2,col+x2) != color) continue; -- diag = (fcol(row,col+1) == color && fcol(row+1,col) == color) ? 2:1; -- if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue; -- *ip++ = (y1*width + x1)*4 + color; -- *ip++ = (y2*width + x2)*4 + color; -- *ip++ = weight; -- for (g=0; g < 8; g++) -- if (grads & 1< gval[g]) gmin = gval[g]; -- if (gmax < gval[g]) gmax = gval[g]; -- } -- if (gmax == 0) { -- memcpy (brow[2][col], pix, sizeof *image); -- continue; -- } -- thold = gmin + (gmax >> 1); -- memset (sum, 0, sizeof sum); -- color = fcol(row,col); -- for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */ -- if (gval[g] <= thold) { -- FORCC -- if (c == color && ip[1]) -- sum[c] += (pix[c] + pix[ip[1]]) >> 1; -- else -- sum[c] += pix[ip[0] + c]; -- num++; -- } -- } -- FORCC { /* Save to buffer */ -- t = pix[color]; -- if (c != color) -- t += (sum[c] - sum[color]) / num; -- brow[2][col][c] = CLIP(t); -- } -- } -- if (row > 3) /* Write buffer to image */ -- memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); -- for (g=0; g < 4; g++) -- brow[(g-1) & 3] = brow[g]; -- } -- memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image); -- memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image); -- free (brow[4]); -- free (code[0][0]); --} -- --/* -- Patterned Pixel Grouping Interpolation by Alain Desbiolles --*/ --void CLASS ppg_interpolate() --{ -- int dir[5] = { 1, width, -1, -width, 1 }; -- int row, col, diff[2], guess[2], c, d, i; -- ushort (*pix)[4]; -- -- border_interpolate(3); -- if (verbose) fprintf (stderr,_("PPG interpolation...\n")); -- --/* Fill in the green layer with gradients and pattern recognition: */ -- for (row=3; row < height-3; row++) -- for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) { -- pix = image + row*width+col; -- for (i=0; (d=dir[i]) > 0; i++) { -- guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 -- - pix[-2*d][c] - pix[2*d][c]; -- diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) + -- ABS(pix[ 2*d][c] - pix[ 0][c]) + -- ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + -- ( ABS(pix[ 3*d][1] - pix[ d][1]) + -- ABS(pix[-3*d][1] - pix[-d][1]) ) * 2; -- } -- d = dir[i = diff[0] > diff[1]]; -- pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]); -- } --/* Calculate red and blue for each green pixel: */ -- for (row=1; row < height-1; row++) -- for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { -- pix = image + row*width+col; -- for (i=0; (d=dir[i]) > 0; c=2-c, i++) -- pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1] -- - pix[-d][1] - pix[d][1]) >> 1); -- } --/* Calculate blue for red pixels and vice versa: */ -- for (row=1; row < height-1; row++) -- for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) { -- pix = image + row*width+col; -- for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) { -- diff[i] = ABS(pix[-d][c] - pix[d][c]) + -- ABS(pix[-d][1] - pix[0][1]) + -- ABS(pix[ d][1] - pix[0][1]); -- guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1] -- - pix[-d][1] - pix[d][1]; -- } -- if (diff[0] != diff[1]) -- pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1); -- else -- pix[0][c] = CLIP((guess[0]+guess[1]) >> 2); -- } --} -- --void CLASS cielab (ushort rgb[3], short lab[3]) --{ -- int c, i, j, k; -- float r, xyz[3]; -- static float cbrt[0x10000], xyz_cam[3][4]; -- -- if (!rgb) { -- for (i=0; i < 0x10000; i++) { -- r = i / 65535.0; -- cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0; -- } -- for (i=0; i < 3; i++) -- for (j=0; j < colors; j++) -- for (xyz_cam[i][j] = k=0; k < 3; k++) -- xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; -- return; -- } -- xyz[0] = xyz[1] = xyz[2] = 0.5; -- FORCC { -- xyz[0] += xyz_cam[0][c] * rgb[c]; -- xyz[1] += xyz_cam[1][c] * rgb[c]; -- xyz[2] += xyz_cam[2][c] * rgb[c]; -- } -- xyz[0] = cbrt[CLIP((int) xyz[0])]; -- xyz[1] = cbrt[CLIP((int) xyz[1])]; -- xyz[2] = cbrt[CLIP((int) xyz[2])]; -- lab[0] = 64 * (116 * xyz[1] - 16); -- lab[1] = 64 * 500 * (xyz[0] - xyz[1]); -- lab[2] = 64 * 200 * (xyz[1] - xyz[2]); --} -- --#define TS 512 /* Tile Size */ --#define fcol(row,col) xtrans[(row+6) % 6][(col+6) % 6] -- --/* -- Frank Markesteijn's algorithm for Fuji X-Trans sensors -- */ --void CLASS xtrans_interpolate (int passes) --{ -- int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol; -- int val, ndir, pass, hm[8], avg[4], color[3][8]; -- static const short orth[12] = { 1,0,0,1,-1,0,0,-1,1,0,0,1 }, -- patt[2][16] = { { 0,1,0,-1,2,0,-1,0,1,1,1,-1,0,0,0,0 }, -- { 0,1,0,-2,1,0,-2,0,1,1,-2,-2,1,-1,-1,1 } }, -- dir[4] = { 1,TS,TS+1,TS-1 }; -- short allhex[3][3][2][8], *hex; -- ushort min, max, sgrow, sgcol; -- ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; -- short (*lab) [TS][3], (*lix)[3]; -- float (*drv)[TS][TS], diff[6], tr; -- char (*homo)[TS][TS], *buffer; -- -- if (verbose) -- fprintf (stderr,_("%d-pass X-Trans interpolation...\n"), passes); -- -- cielab (0,0); -- ndir = 4 << (passes > 1); -- buffer = (char *) malloc (TS*TS*(ndir*11+6)); -- merror (buffer, "xtrans_interpolate()"); -- rgb = (ushort(*)[TS][TS][3]) buffer; -- lab = (short (*) [TS][3])(buffer + TS*TS*(ndir*6)); -- drv = (float (*)[TS][TS]) (buffer + TS*TS*(ndir*6+6)); -- homo = (char (*)[TS][TS]) (buffer + TS*TS*(ndir*10+6)); -- --/* Map a green hexagon around each non-green pixel and vice versa: */ -- for (row=0; row < 3; row++) -- for (col=0; col < 3; col++) -- for (ng=d=0; d < 10; d+=2) { -- g = fcol(row,col) == 1; -- if (fcol(row+orth[d],col+orth[d+2]) == 1) ng=0; else ng++; -- if (ng == 4) { sgrow = row; sgcol = col; } -- if (ng == g+1) FORC(8) { -- v = orth[d ]*patt[g][c*2] + orth[d+1]*patt[g][c*2+1]; -- h = orth[d+2]*patt[g][c*2] + orth[d+3]*patt[g][c*2+1]; -- allhex[row][col][0][c^(g*2 & d)] = h + v*width; -- allhex[row][col][1][c^(g*2 & d)] = h + v*TS; -- } -- } -- --/* Set green1 and green3 to the minimum and maximum allowed values: */ -- for (row=2; row < height-2; row++) -- for (min=~(max=0), col=2; col < width-2; col++) { -- if (fcol(row,col) == 1 && (min=~(max=0))) continue; -- pix = image + row*width + col; -- hex = allhex[row % 3][col % 3][0]; -- if (!max) FORC(6) { -- val = pix[hex[c]][1]; -- if (min > val) min = val; -- if (max < val) max = val; -- } -- pix[0][1] = min; -- pix[0][3] = max; -- switch ((row-sgrow) % 3) { -- case 1: if (row < height-3) { row++; col--; } break; -- case 2: if ((min=~(max=0)) && (col+=2) < width-3 && row > 2) row--; -- } -- } -- -- for (top=3; top < height-19; top += TS-16) -- for (left=3; left < width-19; left += TS-16) { -- mrow = MIN (top+TS, height-3); -- mcol = MIN (left+TS, width-3); -- for (row=top; row < mrow; row++) -- for (col=left; col < mcol; col++) -- memcpy (rgb[0][row-top][col-left], image[row*width+col], 6); -- FORC3 memcpy (rgb[c+1], rgb[0], sizeof *rgb); -- --/* Interpolate green horizontally, vertically, and along both diagonals: */ -- for (row=top; row < mrow; row++) -- for (col=left; col < mcol; col++) { -- if ((f = fcol(row,col)) == 1) continue; -- pix = image + row*width + col; -- hex = allhex[row % 3][col % 3][0]; -- color[1][0] = 174 * (pix[ hex[1]][1] + pix[ hex[0]][1]) - -- 46 * (pix[2*hex[1]][1] + pix[2*hex[0]][1]); -- color[1][1] = 223 * pix[ hex[3]][1] + pix[ hex[2]][1] * 33 + -- 92 * (pix[ 0 ][f] - pix[ -hex[2]][f]); -- FORC(2) color[1][2+c] = -- 164 * pix[hex[4+c]][1] + 92 * pix[-2*hex[4+c]][1] + 33 * -- (2*pix[0][f] - pix[3*hex[4+c]][f] - pix[-3*hex[4+c]][f]); -- FORC4 rgb[c^!((row-sgrow) % 3)][row-top][col-left][1] = -- LIM(color[1][c] >> 8,pix[0][1],pix[0][3]); -- } -- -- for (pass=0; pass < passes; pass++) { -- if (pass == 1) -- memcpy (rgb+=4, buffer, 4*sizeof *rgb); -- --/* Recalculate green from interpolated values of closer pixels: */ -- if (pass) { -- for (row=top+2; row < mrow-2; row++) -- for (col=left+2; col < mcol-2; col++) { -- if ((f = fcol(row,col)) == 1) continue; -- pix = image + row*width + col; -- hex = allhex[row % 3][col % 3][1]; -- for (d=3; d < 6; d++) { -- rix = &rgb[(d-2)^!((row-sgrow) % 3)][row-top][col-left]; -- val = rix[-2*hex[d]][1] + 2*rix[hex[d]][1] -- - rix[-2*hex[d]][f] - 2*rix[hex[d]][f] + 3*rix[0][f]; -- rix[0][1] = LIM(val/3,pix[0][1],pix[0][3]); -- } -- } -- } -- --/* Interpolate red and blue values for solitary green pixels: */ -- for (row=(top-sgrow+4)/3*3+sgrow; row < mrow-2; row+=3) -- for (col=(left-sgcol+4)/3*3+sgcol; col < mcol-2; col+=3) { -- rix = &rgb[0][row-top][col-left]; -- h = fcol(row,col+1); -- memset (diff, 0, sizeof diff); -- for (i=1, d=0; d < 6; d++, i^=TS^1, h^=2) { -- for (c=0; c < 2; c++, h^=2) { -- g = 2*rix[0][1] - rix[i< 1) -- diff[d] += SQR (rix[i< 1 && (d & 1)) -- if (diff[d-1] < diff[d]) -- FORC(2) color[c*2][d] = color[c*2][d-1]; -- if (d < 2 || (d & 1)) { -- FORC(2) rix[0][c*2] = CLIP(color[c*2][d]/2); -- rix += TS*TS; -- } -- } -- } -- --/* Interpolate red for blue pixels and vice versa: */ -- for (row=top+3; row < mrow-3; row++) -- for (col=left+3; col < mcol-3; col++) { -- if ((f = 2-fcol(row,col)) == 1) continue; -- rix = &rgb[0][row-top][col-left]; -- c = (row-sgrow) % 3 ? TS:1; -- h = 3 * (c ^ TS ^ 1); -- for (d=0; d < 4; d++, rix += TS*TS) { -- i = d > 1 || ((d ^ c) & 1) || -- ((ABS(rix[0][1]-rix[c][1])+ABS(rix[0][1]-rix[-c][1])) < -- 2*(ABS(rix[0][1]-rix[h][1])+ABS(rix[0][1]-rix[-h][1]))) ? c:h; -- rix[0][f] = CLIP((rix[i][f] + rix[-i][f] + -- 2*rix[0][1] - rix[i][1] - rix[-i][1])/2); -- } -- } -- --/* Fill in red and blue for 2x2 blocks of green: */ -- for (row=top+2; row < mrow-2; row++) if ((row-sgrow) % 3) -- for (col=left+2; col < mcol-2; col++) if ((col-sgcol) % 3) { -- rix = &rgb[0][row-top][col-left]; -- hex = allhex[row % 3][col % 3][1]; -- for (d=0; d < ndir; d+=2, rix += TS*TS) -- if (hex[d] + hex[d+1]) { -- g = 3*rix[0][1] - 2*rix[hex[d]][1] - rix[hex[d+1]][1]; -- for (c=0; c < 4; c+=2) rix[0][c] = -- CLIP((g + 2*rix[hex[d]][c] + rix[hex[d+1]][c])/3); -- } else { -- g = 2*rix[0][1] - rix[hex[d]][1] - rix[hex[d+1]][1]; -- for (c=0; c < 4; c+=2) rix[0][c] = -- CLIP((g + rix[hex[d]][c] + rix[hex[d+1]][c])/2); -- } -- } -- } -- rgb = (ushort(*)[TS][TS][3]) buffer; -- mrow -= top; -- mcol -= left; -- --/* Convert to CIELab and differentiate in all directions: */ -- for (d=0; d < ndir; d++) { -- for (row=2; row < mrow-2; row++) -- for (col=2; col < mcol-2; col++) -- cielab (rgb[d][row][col], lab[row][col]); -- for (f=dir[d & 3],row=3; row < mrow-3; row++) -- for (col=3; col < mcol-3; col++) { -- lix = &lab[row][col]; -- g = 2*lix[0][0] - lix[f][0] - lix[-f][0]; -- drv[d][row][col] = SQR(g) -- + SQR((2*lix[0][1] - lix[f][1] - lix[-f][1] + g*500/232)) -- + SQR((2*lix[0][2] - lix[f][2] - lix[-f][2] - g*500/580)); -- } -- } -- --/* Build homogeneity maps from the derivatives: */ -- memset(homo, 0, ndir*TS*TS); -- for (row=4; row < mrow-4; row++) -- for (col=4; col < mcol-4; col++) { -- for (tr=FLT_MAX, d=0; d < ndir; d++) -- if (tr > drv[d][row][col]) -- tr = drv[d][row][col]; -- tr *= 8; -- for (d=0; d < ndir; d++) -- for (v=-1; v <= 1; v++) -- for (h=-1; h <= 1; h++) -- if (drv[d][row+v][col+h] <= tr) -- homo[d][row][col]++; -- } -- --/* Average the most homogenous pixels for the final result: */ -- if (height-top < TS+4) mrow = height-top+2; -- if (width-left < TS+4) mcol = width-left+2; -- for (row = MIN(top,8); row < mrow-8; row++) -- for (col = MIN(left,8); col < mcol-8; col++) { -- for (d=0; d < ndir; d++) -- for (hm[d]=0, v=-2; v <= 2; v++) -- for (h=-2; h <= 2; h++) -- hm[d] += homo[d][row+v][col+h]; -- for (d=0; d < ndir-4; d++) -- if (hm[d] < hm[d+4]) hm[d ] = 0; else -- if (hm[d] > hm[d+4]) hm[d+4] = 0; -- for (max=hm[0],d=1; d < ndir; d++) -- if (max < hm[d]) max = hm[d]; -- max -= max >> 3; -- memset (avg, 0, sizeof avg); -- for (d=0; d < ndir; d++) -- if (hm[d] >= max) { -- FORC3 avg[c] += rgb[d][row][col][c]; -- avg[3]++; -- } -- FORC3 image[(row+top)*width+col+left][c] = avg[c]/avg[3]; -- } -- } -- free(buffer); -- border_interpolate(8); --} --#undef fcol -- --/* -- Adaptive Homogeneity-Directed interpolation is based on -- the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. -- */ --void CLASS ahd_interpolate() --{ -- int i, j, top, left, row, col, tr, tc, c, d, val, hm[2]; -- static const int dir[4] = { -1, 1, -TS, TS }; -- unsigned ldiff[2][4], abdiff[2][4], leps, abeps; -- ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; -- short (*lab)[TS][TS][3], (*lix)[3]; -- char (*homo)[TS][TS], *buffer; -- -- if (verbose) fprintf (stderr,_("AHD interpolation...\n")); -- -- cielab (0,0); -- border_interpolate(5); -- buffer = (char *) malloc (26*TS*TS); -- merror (buffer, "ahd_interpolate()"); -- rgb = (ushort(*)[TS][TS][3]) buffer; -- lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS); -- homo = (char (*)[TS][TS]) (buffer + 24*TS*TS); -- -- for (top=2; top < height-5; top += TS-6) -- for (left=2; left < width-5; left += TS-6) { -- --/* Interpolate green horizontally and vertically: */ -- for (row=top; row < top+TS && row < height-2; row++) { -- col = left + (FC(row,left) & 1); -- for (c = FC(row,col); col < left+TS && col < width-2; col+=2) { -- pix = image + row*width+col; -- val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 -- - pix[-2][c] - pix[2][c]) >> 2; -- rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]); -- val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 -- - pix[-2*width][c] - pix[2*width][c]) >> 2; -- rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]); -- } -- } --/* Interpolate red and blue, and convert to CIELab: */ -- for (d=0; d < 2; d++) -- for (row=top+1; row < top+TS-1 && row < height-3; row++) -- for (col=left+1; col < left+TS-1 && col < width-3; col++) { -- pix = image + row*width+col; -- rix = &rgb[d][row-top][col-left]; -- lix = &lab[d][row-top][col-left]; -- if ((c = 2 - FC(row,col)) == 1) { -- c = FC(row+1,col); -- val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c] -- - rix[-1][1] - rix[1][1] ) >> 1); -- rix[0][2-c] = CLIP(val); -- val = pix[0][1] + (( pix[-width][c] + pix[width][c] -- - rix[-TS][1] - rix[TS][1] ) >> 1); -- } else -- val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c] -- + pix[+width-1][c] + pix[+width+1][c] -- - rix[-TS-1][1] - rix[-TS+1][1] -- - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2); -- rix[0][c] = CLIP(val); -- c = FC(row,col); -- rix[0][c] = pix[0][c]; -- cielab (rix[0],lix[0]); -- } --/* Build homogeneity maps from the CIELab images: */ -- memset (homo, 0, 2*TS*TS); -- for (row=top+2; row < top+TS-2 && row < height-4; row++) { -- tr = row-top; -- for (col=left+2; col < left+TS-2 && col < width-4; col++) { -- tc = col-left; -- for (d=0; d < 2; d++) { -- lix = &lab[d][tr][tc]; -- for (i=0; i < 4; i++) { -- ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]); -- abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1]) -- + SQR(lix[0][2]-lix[dir[i]][2]); -- } -- } -- leps = MIN(MAX(ldiff[0][0],ldiff[0][1]), -- MAX(ldiff[1][2],ldiff[1][3])); -- abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]), -- MAX(abdiff[1][2],abdiff[1][3])); -- for (d=0; d < 2; d++) -- for (i=0; i < 4; i++) -- if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) -- homo[d][tr][tc]++; -- } -- } --/* Combine the most homogenous pixels for the final result: */ -- for (row=top+3; row < top+TS-3 && row < height-5; row++) { -- tr = row-top; -- for (col=left+3; col < left+TS-3 && col < width-5; col++) { -- tc = col-left; -- for (d=0; d < 2; d++) -- for (hm[d]=0, i=tr-1; i <= tr+1; i++) -- for (j=tc-1; j <= tc+1; j++) -- hm[d] += homo[d][i][j]; -- if (hm[0] != hm[1]) -- FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; -- else -- FORC3 image[row*width+col][c] = -- (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1; -- } -- } -- } -- free (buffer); --} --#undef TS -- --void CLASS median_filter() --{ -- ushort (*pix)[4]; -- int pass, c, i, j, k, med[9]; -- static const uchar opt[] = /* Optimal 9-element median search */ -- { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8, -- 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 }; -- -- for (pass=1; pass <= med_passes; pass++) { -- if (verbose) -- fprintf (stderr,_("Median filter pass %d...\n"), pass); -- for (c=0; c < 3; c+=2) { -- for (pix = image; pix < image+width*height; pix++) -- pix[0][3] = pix[0][c]; -- for (pix = image+width; pix < image+width*(height-1); pix++) { -- if ((pix-image+1) % width < 2) continue; -- for (k=0, i = -width; i <= width; i += width) -- for (j = i-1; j <= i+1; j++) -- med[k++] = pix[j][3] - pix[j][1]; -- for (i=0; i < sizeof opt; i+=2) -- if (med[opt[i]] > med[opt[i+1]]) -- SWAP (med[opt[i]] , med[opt[i+1]]); -- pix[0][c] = CLIP(med[4] + pix[0][1]); -- } -- } -- } --} -- --void CLASS blend_highlights() --{ -- int clip=INT_MAX, row, col, c, i, j; -- static const float trans[2][4][4] = -- { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } }, -- { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } }; -- static const float itrans[2][4][4] = -- { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } }, -- { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } }; -- float cam[2][4], lab[2][4], sum[2], chratio; -- -- if ((unsigned) (colors-3) > 1) return; -- if (verbose) fprintf (stderr,_("Blending highlights...\n")); -- FORCC if (clip > (i = 65535*pre_mul[c])) clip = i; -- for (row=0; row < height; row++) -- for (col=0; col < width; col++) { -- FORCC if (image[row*width+col][c] > clip) break; -- if (c == colors) continue; -- FORCC { -- cam[0][c] = image[row*width+col][c]; -- cam[1][c] = MIN(cam[0][c],clip); -- } -- for (i=0; i < 2; i++) { -- FORCC for (lab[i][c]=j=0; j < colors; j++) -- lab[i][c] += trans[colors-3][c][j] * cam[i][j]; -- for (sum[i]=0,c=1; c < colors; c++) -- sum[i] += SQR(lab[i][c]); -- } -- chratio = sqrt(sum[1]/sum[0]); -- for (c=1; c < colors; c++) -- lab[0][c] *= chratio; -- FORCC for (cam[0][c]=j=0; j < colors; j++) -- cam[0][c] += itrans[colors-3][c][j] * lab[0][j]; -- FORCC image[row*width+col][c] = cam[0][c] / colors; -- } --} -- --#define SCALE (4 >> shrink) --void CLASS recover_highlights() --{ -- float *map, sum, wgt, grow; -- int hsat[4], count, spread, change, val, i; -- unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x; -- ushort *pixel; -- static const signed char dir[8][2] = -- { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} }; -- -- if (verbose) fprintf (stderr,_("Rebuilding highlights...\n")); -- -- grow = pow (2, 4-highlight); -- FORCC hsat[c] = 32000 * pre_mul[c]; -- for (kc=0, c=1; c < colors; c++) -- if (pre_mul[kc] < pre_mul[c]) kc = c; -- high = height / SCALE; -- wide = width / SCALE; -- map = (float *) calloc (high, wide*sizeof *map); -- merror (map, "recover_highlights()"); -- FORCC if (c != kc) { -- memset (map, 0, high*wide*sizeof *map); -- for (mrow=0; mrow < high; mrow++) -- for (mcol=0; mcol < wide; mcol++) { -- sum = wgt = count = 0; -- for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) -- for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { -- pixel = image[row*width+col]; -- if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) { -- sum += pixel[c]; -- wgt += pixel[kc]; -- count++; -- } -- } -- if (count == SCALE*SCALE) -- map[mrow*wide+mcol] = sum / wgt; -- } -- for (spread = 32/grow; spread--; ) { -- for (mrow=0; mrow < high; mrow++) -- for (mcol=0; mcol < wide; mcol++) { -- if (map[mrow*wide+mcol]) continue; -- sum = count = 0; -- for (d=0; d < 8; d++) { -- y = mrow + dir[d][0]; -- x = mcol + dir[d][1]; -- if (y < high && x < wide && map[y*wide+x] > 0) { -- sum += (1 + (d & 1)) * map[y*wide+x]; -- count += 1 + (d & 1); -- } -- } -- if (count > 3) -- map[mrow*wide+mcol] = - (sum+grow) / (count+grow); -- } -- for (change=i=0; i < high*wide; i++) -- if (map[i] < 0) { -- map[i] = -map[i]; -- change = 1; -- } -- if (!change) break; -- } -- for (i=0; i < high*wide; i++) -- if (map[i] == 0) map[i] = 1; -- for (mrow=0; mrow < high; mrow++) -- for (mcol=0; mcol < wide; mcol++) { -- for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) -- for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { -- pixel = image[row*width+col]; -- if (pixel[c] / hsat[c] > 1) { -- val = pixel[kc] * map[mrow*wide+mcol]; -- if (pixel[c] < val) pixel[c] = CLIP(val); -- } -- } -- } -- } -- free (map); --} --#undef SCALE -+//void CLASS border_interpolate (int border) -+//{ -+// unsigned row, col, y, x, f, c, sum[8]; -+// -+// for (row=0; row < height; row++) -+// for (col=0; col < width; col++) { -+// if (col==border && row >= border && row < height-border) -+// col = width-border; -+// memset (sum, 0, sizeof sum); -+// for (y=row-1; y != row+2; y++) -+// for (x=col-1; x != col+2; x++) -+// if (y < height && x < width) { -+// f = fcol(y,x); -+// sum[f] += image[y*width+x][f]; -+// sum[f+4]++; -+// } -+// f = fcol(row,col); -+// FORCC if (c != f && sum[c+4]) -+// image[row*width+col][c] = sum[c] / sum[c+4]; -+// } -+//} -+ -+/* RT: delete interpolation functions */ -+ -+ -+//void CLASS cielab (ushort rgb[3], short lab[3]) -+//{ -+// int c, i, j, k; -+// float r, xyz[3]; -+// static float cbrt[0x10000], xyz_cam[3][4]; -+// -+// if (!rgb) { -+// for (i=0; i < 0x10000; i++) { -+// r = i / 65535.0; -+// cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0; -+// } -+// for (i=0; i < 3; i++) -+// for (j=0; j < colors; j++) -+// for (xyz_cam[i][j] = k=0; k < 3; k++) -+// xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; -+// return; -+// } -+// xyz[0] = xyz[1] = xyz[2] = 0.5; -+// FORCC { -+// xyz[0] += xyz_cam[0][c] * rgb[c]; -+// xyz[1] += xyz_cam[1][c] * rgb[c]; -+// xyz[2] += xyz_cam[2][c] * rgb[c]; -+// } -+// xyz[0] = cbrt[CLIP((int) xyz[0])]; -+// xyz[1] = cbrt[CLIP((int) xyz[1])]; -+// xyz[2] = cbrt[CLIP((int) xyz[2])]; -+// lab[0] = 64 * (116 * xyz[1] - 16); -+// lab[1] = 64 * 500 * (xyz[0] - xyz[1]); -+// lab[2] = 64 * 200 * (xyz[1] - xyz[2]); -+//} -+// -+//#define TS 512 /* Tile Size */ -+//#define fcol(row,col) xtrans[(row+6) % 6][(col+6) % 6] -+// -+///* -+// Frank Markesteijn's algorithm for Fuji X-Trans sensors -+// */ -+//void CLASS xtrans_interpolate (int passes) -+//{ -+// int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol; -+// int val, ndir, pass, hm[8], avg[4], color[3][8]; -+// static const short orth[12] = { 1,0,0,1,-1,0,0,-1,1,0,0,1 }, -+// patt[2][16] = { { 0,1,0,-1,2,0,-1,0,1,1,1,-1,0,0,0,0 }, -+// { 0,1,0,-2,1,0,-2,0,1,1,-2,-2,1,-1,-1,1 } }, -+// dir[4] = { 1,TS,TS+1,TS-1 }; -+// short allhex[3][3][2][8], *hex; -+// ushort min, max, sgrow, sgcol; -+// ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; -+// short (*lab) [TS][3], (*lix)[3]; -+// float (*drv)[TS][TS], diff[6], tr; -+// char (*homo)[TS][TS], *buffer; -+// -+// if (verbose) -+// fprintf (stderr,_("%d-pass X-Trans interpolation...\n"), passes); -+// -+// cielab (0,0); -+// ndir = 4 << (passes > 1); -+// buffer = (char *) malloc (TS*TS*(ndir*11+6)); -+// merror (buffer, "xtrans_interpolate()"); -+// rgb = (ushort(*)[TS][TS][3]) buffer; -+// lab = (short (*) [TS][3])(buffer + TS*TS*(ndir*6)); -+// drv = (float (*)[TS][TS]) (buffer + TS*TS*(ndir*6+6)); -+// homo = (char (*)[TS][TS]) (buffer + TS*TS*(ndir*10+6)); -+// -+///* Map a green hexagon around each non-green pixel and vice versa: */ -+// for (row=0; row < 3; row++) -+// for (col=0; col < 3; col++) -+// for (ng=d=0; d < 10; d+=2) { -+// g = fcol(row,col) == 1; -+// if (fcol(row+orth[d],col+orth[d+2]) == 1) ng=0; else ng++; -+// if (ng == 4) { sgrow = row; sgcol = col; } -+// if (ng == g+1) FORC(8) { -+// v = orth[d ]*patt[g][c*2] + orth[d+1]*patt[g][c*2+1]; -+// h = orth[d+2]*patt[g][c*2] + orth[d+3]*patt[g][c*2+1]; -+// allhex[row][col][0][c^(g*2 & d)] = h + v*width; -+// allhex[row][col][1][c^(g*2 & d)] = h + v*TS; -+// } -+// } -+// -+///* Set green1 and green3 to the minimum and maximum allowed values: */ -+// for (row=2; row < height-2; row++) -+// for (min=~(max=0), col=2; col < width-2; col++) { -+// if (fcol(row,col) == 1 && (min=~(max=0))) continue; -+// pix = image + row*width + col; -+// hex = allhex[row % 3][col % 3][0]; -+// if (!max) FORC(6) { -+// val = pix[hex[c]][1]; -+// if (min > val) min = val; -+// if (max < val) max = val; -+// } -+// pix[0][1] = min; -+// pix[0][3] = max; -+// switch ((row-sgrow) % 3) { -+// case 1: if (row < height-3) { row++; col--; } break; -+// case 2: if ((min=~(max=0)) && (col+=2) < width-3 && row > 2) row--; -+// } -+// } -+// -+// for (top=3; top < height-19; top += TS-16) -+// for (left=3; left < width-19; left += TS-16) { -+// mrow = MIN (top+TS, height-3); -+// mcol = MIN (left+TS, width-3); -+// for (row=top; row < mrow; row++) -+// for (col=left; col < mcol; col++) -+// memcpy (rgb[0][row-top][col-left], image[row*width+col], 6); -+// FORC3 memcpy (rgb[c+1], rgb[0], sizeof *rgb); -+// -+///* Interpolate green horizontally, vertically, and along both diagonals: */ -+// for (row=top; row < mrow; row++) -+// for (col=left; col < mcol; col++) { -+// if ((f = fcol(row,col)) == 1) continue; -+// pix = image + row*width + col; -+// hex = allhex[row % 3][col % 3][0]; -+// color[1][0] = 174 * (pix[ hex[1]][1] + pix[ hex[0]][1]) - -+// 46 * (pix[2*hex[1]][1] + pix[2*hex[0]][1]); -+// color[1][1] = 223 * pix[ hex[3]][1] + pix[ hex[2]][1] * 33 + -+// 92 * (pix[ 0 ][f] - pix[ -hex[2]][f]); -+// FORC(2) color[1][2+c] = -+// 164 * pix[hex[4+c]][1] + 92 * pix[-2*hex[4+c]][1] + 33 * -+// (2*pix[0][f] - pix[3*hex[4+c]][f] - pix[-3*hex[4+c]][f]); -+// FORC4 rgb[c^!((row-sgrow) % 3)][row-top][col-left][1] = -+// LIM(color[1][c] >> 8,pix[0][1],pix[0][3]); -+// } -+// -+// for (pass=0; pass < passes; pass++) { -+// if (pass == 1) -+// memcpy (rgb+=4, buffer, 4*sizeof *rgb); -+// -+///* Recalculate green from interpolated values of closer pixels: */ -+// if (pass) { -+// for (row=top+2; row < mrow-2; row++) -+// for (col=left+2; col < mcol-2; col++) { -+// if ((f = fcol(row,col)) == 1) continue; -+// pix = image + row*width + col; -+// hex = allhex[row % 3][col % 3][1]; -+// for (d=3; d < 6; d++) { -+// rix = &rgb[(d-2)^!((row-sgrow) % 3)][row-top][col-left]; -+// val = rix[-2*hex[d]][1] + 2*rix[hex[d]][1] -+// - rix[-2*hex[d]][f] - 2*rix[hex[d]][f] + 3*rix[0][f]; -+// rix[0][1] = LIM(val/3,pix[0][1],pix[0][3]); -+// } -+// } -+// } -+// -+///* Interpolate red and blue values for solitary green pixels: */ -+// for (row=(top-sgrow+4)/3*3+sgrow; row < mrow-2; row+=3) -+// for (col=(left-sgcol+4)/3*3+sgcol; col < mcol-2; col+=3) { -+// rix = &rgb[0][row-top][col-left]; -+// h = fcol(row,col+1); -+// memset (diff, 0, sizeof diff); -+// for (i=1, d=0; d < 6; d++, i^=TS^1, h^=2) { -+// for (c=0; c < 2; c++, h^=2) { -+// g = 2*rix[0][1] - rix[i< 1) -+// diff[d] += SQR (rix[i< 1 && (d & 1)) -+// if (diff[d-1] < diff[d]) -+// FORC(2) color[c*2][d] = color[c*2][d-1]; -+// if (d < 2 || (d & 1)) { -+// FORC(2) rix[0][c*2] = CLIP(color[c*2][d]/2); -+// rix += TS*TS; -+// } -+// } -+// } -+// -+///* Interpolate red for blue pixels and vice versa: */ -+// for (row=top+3; row < mrow-3; row++) -+// for (col=left+3; col < mcol-3; col++) { -+// if ((f = 2-fcol(row,col)) == 1) continue; -+// rix = &rgb[0][row-top][col-left]; -+// c = (row-sgrow) % 3 ? TS:1; -+// h = 3 * (c ^ TS ^ 1); -+// for (d=0; d < 4; d++, rix += TS*TS) { -+// i = d > 1 || ((d ^ c) & 1) || -+// ((ABS(rix[0][1]-rix[c][1])+ABS(rix[0][1]-rix[-c][1])) < -+// 2*(ABS(rix[0][1]-rix[h][1])+ABS(rix[0][1]-rix[-h][1]))) ? c:h; -+// rix[0][f] = CLIP((rix[i][f] + rix[-i][f] + -+// 2*rix[0][1] - rix[i][1] - rix[-i][1])/2); -+// } -+// } -+// -+///* Fill in red and blue for 2x2 blocks of green: */ -+// for (row=top+2; row < mrow-2; row++) if ((row-sgrow) % 3) -+// for (col=left+2; col < mcol-2; col++) if ((col-sgcol) % 3) { -+// rix = &rgb[0][row-top][col-left]; -+// hex = allhex[row % 3][col % 3][1]; -+// for (d=0; d < ndir; d+=2, rix += TS*TS) -+// if (hex[d] + hex[d+1]) { -+// g = 3*rix[0][1] - 2*rix[hex[d]][1] - rix[hex[d+1]][1]; -+// for (c=0; c < 4; c+=2) rix[0][c] = -+// CLIP((g + 2*rix[hex[d]][c] + rix[hex[d+1]][c])/3); -+// } else { -+// g = 2*rix[0][1] - rix[hex[d]][1] - rix[hex[d+1]][1]; -+// for (c=0; c < 4; c+=2) rix[0][c] = -+// CLIP((g + rix[hex[d]][c] + rix[hex[d+1]][c])/2); -+// } -+// } -+// } -+// rgb = (ushort(*)[TS][TS][3]) buffer; -+// mrow -= top; -+// mcol -= left; -+// -+///* Convert to CIELab and differentiate in all directions: */ -+// for (d=0; d < ndir; d++) { -+// for (row=2; row < mrow-2; row++) -+// for (col=2; col < mcol-2; col++) -+// cielab (rgb[d][row][col], lab[row][col]); -+// for (f=dir[d & 3],row=3; row < mrow-3; row++) -+// for (col=3; col < mcol-3; col++) { -+// lix = &lab[row][col]; -+// g = 2*lix[0][0] - lix[f][0] - lix[-f][0]; -+// drv[d][row][col] = SQR(g) -+// + SQR((2*lix[0][1] - lix[f][1] - lix[-f][1] + g*500/232)) -+// + SQR((2*lix[0][2] - lix[f][2] - lix[-f][2] - g*500/580)); -+// } -+// } -+// -+///* Build homogeneity maps from the derivatives: */ -+// memset(homo, 0, ndir*TS*TS); -+// for (row=4; row < mrow-4; row++) -+// for (col=4; col < mcol-4; col++) { -+// for (tr=FLT_MAX, d=0; d < ndir; d++) -+// if (tr > drv[d][row][col]) -+// tr = drv[d][row][col]; -+// tr *= 8; -+// for (d=0; d < ndir; d++) -+// for (v=-1; v <= 1; v++) -+// for (h=-1; h <= 1; h++) -+// if (drv[d][row+v][col+h] <= tr) -+// homo[d][row][col]++; -+// } -+// -+///* Average the most homogenous pixels for the final result: */ -+// if (height-top < TS+4) mrow = height-top+2; -+// if (width-left < TS+4) mcol = width-left+2; -+// for (row = MIN(top,8); row < mrow-8; row++) -+// for (col = MIN(left,8); col < mcol-8; col++) { -+// for (d=0; d < ndir; d++) -+// for (hm[d]=0, v=-2; v <= 2; v++) -+// for (h=-2; h <= 2; h++) -+// hm[d] += homo[d][row+v][col+h]; -+// for (d=0; d < ndir-4; d++) -+// if (hm[d] < hm[d+4]) hm[d ] = 0; else -+// if (hm[d] > hm[d+4]) hm[d+4] = 0; -+// for (max=hm[0],d=1; d < ndir; d++) -+// if (max < hm[d]) max = hm[d]; -+// max -= max >> 3; -+// memset (avg, 0, sizeof avg); -+// for (d=0; d < ndir; d++) -+// if (hm[d] >= max) { -+// FORC3 avg[c] += rgb[d][row][col][c]; -+// avg[3]++; -+// } -+// FORC3 image[(row+top)*width+col+left][c] = avg[c]/avg[3]; -+// } -+// } -+// free(buffer); -+// border_interpolate(8); -+//} -+//#undef fcol -+// -+// -+//#undef TS -+ -+//void CLASS median_filter() -+//{ -+// ushort (*pix)[4]; -+// int pass, c, i, j, k, med[9]; -+// static const uchar opt[] = /* Optimal 9-element median search */ -+// { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8, -+// 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 }; -+// -+// for (pass=1; pass <= med_passes; pass++) { -+// if (verbose) -+// fprintf (stderr,_("Median filter pass %d...\n"), pass); -+// for (c=0; c < 3; c+=2) { -+// for (pix = image; pix < image+width*height; pix++) -+// pix[0][3] = pix[0][c]; -+// for (pix = image+width; pix < image+width*(height-1); pix++) { -+// if ((pix-image+1) % width < 2) continue; -+// for (k=0, i = -width; i <= width; i += width) -+// for (j = i-1; j <= i+1; j++) -+// med[k++] = pix[j][3] - pix[j][1]; -+// for (i=0; i < sizeof opt; i+=2) -+// if (med[opt[i]] > med[opt[i+1]]) -+// SWAP (med[opt[i]] , med[opt[i+1]]); -+// pix[0][c] = CLIP(med[4] + pix[0][1]); -+// } -+// } -+// } -+//} -+// -+//void CLASS blend_highlights() -+//{ -+// int clip=INT_MAX, row, col, c, i, j; -+// static const float trans[2][4][4] = -+// { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } }, -+// { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } }; -+// static const float itrans[2][4][4] = -+// { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } }, -+// { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } }; -+// float cam[2][4], lab[2][4], sum[2], chratio; -+// -+// if ((unsigned) (colors-3) > 1) return; -+// if (verbose) fprintf (stderr,_("Blending highlights...\n")); -+// FORCC if (clip > (i = 65535*pre_mul[c])) clip = i; -+// for (row=0; row < height; row++) -+// for (col=0; col < width; col++) { -+// FORCC if (image[row*width+col][c] > clip) break; -+// if (c == colors) continue; -+// FORCC { -+// cam[0][c] = image[row*width+col][c]; -+// cam[1][c] = MIN(cam[0][c],clip); -+// } -+// for (i=0; i < 2; i++) { -+// FORCC for (lab[i][c]=j=0; j < colors; j++) -+// lab[i][c] += trans[colors-3][c][j] * cam[i][j]; -+// for (sum[i]=0,c=1; c < colors; c++) -+// sum[i] += SQR(lab[i][c]); -+// } -+// chratio = sqrt(sum[1]/sum[0]); -+// for (c=1; c < colors; c++) -+// lab[0][c] *= chratio; -+// FORCC for (cam[0][c]=j=0; j < colors; j++) -+// cam[0][c] += itrans[colors-3][c][j] * lab[0][j]; -+// FORCC image[row*width+col][c] = cam[0][c] / colors; -+// } -+//} -+// -+//#define SCALE (4 >> shrink) -+//void CLASS recover_highlights() -+//{ -+// float *map, sum, wgt, grow; -+// int hsat[4], count, spread, change, val, i; -+// unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x; -+// ushort *pixel; -+// static const signed char dir[8][2] = -+// { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} }; -+// -+// if (verbose) fprintf (stderr,_("Rebuilding highlights...\n")); -+// -+// grow = pow (2, 4-highlight); -+// FORCC hsat[c] = 32000 * pre_mul[c]; -+// for (kc=0, c=1; c < colors; c++) -+// if (pre_mul[kc] < pre_mul[c]) kc = c; -+// high = height / SCALE; -+// wide = width / SCALE; -+// map = (float *) calloc (high, wide*sizeof *map); -+// merror (map, "recover_highlights()"); -+// FORCC if (c != kc) { -+// memset (map, 0, high*wide*sizeof *map); -+// for (mrow=0; mrow < high; mrow++) -+// for (mcol=0; mcol < wide; mcol++) { -+// sum = wgt = count = 0; -+// for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) -+// for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { -+// pixel = image[row*width+col]; -+// if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) { -+// sum += pixel[c]; -+// wgt += pixel[kc]; -+// count++; -+// } -+// } -+// if (count == SCALE*SCALE) -+// map[mrow*wide+mcol] = sum / wgt; -+// } -+// for (spread = 32/grow; spread--; ) { -+// for (mrow=0; mrow < high; mrow++) -+// for (mcol=0; mcol < wide; mcol++) { -+// if (map[mrow*wide+mcol]) continue; -+// sum = count = 0; -+// for (d=0; d < 8; d++) { -+// y = mrow + dir[d][0]; -+// x = mcol + dir[d][1]; -+// if (y < high && x < wide && map[y*wide+x] > 0) { -+// sum += (1 + (d & 1)) * map[y*wide+x]; -+// count += 1 + (d & 1); -+// } -+// } -+// if (count > 3) -+// map[mrow*wide+mcol] = - (sum+grow) / (count+grow); -+// } -+// for (change=i=0; i < high*wide; i++) -+// if (map[i] < 0) { -+// map[i] = -map[i]; -+// change = 1; -+// } -+// if (!change) break; -+// } -+// for (i=0; i < high*wide; i++) -+// if (map[i] == 0) map[i] = 1; -+// for (mrow=0; mrow < high; mrow++) -+// for (mcol=0; mcol < wide; mcol++) { -+// for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) -+// for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { -+// pixel = image[row*width+col]; -+// if (pixel[c] / hsat[c] > 1) { -+// val = pixel[kc] * map[mrow*wide+mcol]; -+// if (pixel[c] < val) pixel[c] = CLIP(val); -+// } -+// } -+// } -+// } -+// free (map); -+//} -+//#undef SCALE - - void CLASS tiff_get (unsigned base, - unsigned *tag, unsigned *type, unsigned *len, unsigned *save) -@@ -5139,7 +5127,7 @@ - } - } - --int CLASS parse_tiff_ifd (int base); -+/*RT int CLASS parse_tiff_ifd (int base);*/ - - void CLASS parse_makernote (int base, int uptag) - { -@@ -5244,6 +5232,11 @@ - tag |= uptag << 16; - if (tag == 2 && strstr(make,"NIKON") && !iso_speed) - iso_speed = (get2(),get2()); -+ if ((tag == 0x25 || tag == 0x28) && strstr(make,"NIKON") && !iso_speed) { // Nikon ISOInfo Tags/ISO & ISO2 -+ uchar iso[1]; -+ fread (iso, 1, 1, ifp); -+ iso_speed = 100 * pow(2,(float)iso[0]/12.0-5); -+ } - if (tag == 4 && len > 26 && len < 35) { - if ((i=(get4(),get2())) != 0x7fff && !iso_speed) - iso_speed = 50 * pow (2, i/32.0 - 4); -@@ -5296,12 +5289,16 @@ - cam_mul[2] = get4() << 2; - } - } -- if (tag == 0x15 && type == 2 && is_raw) -+ //if (tag == 0x15 && type == 2 && is_raw) -+ if (tag == 0x15 && type == 2 && is_raw && strstr(model, "Hasselblad ") != model) // RT: don't overwrite already parsed Hasselblad model - fread (model, 64, 1, ifp); - if (strstr(make,"PENTAX")) { - if (tag == 0x1b) tag = 0x1018; - if (tag == 0x1c) tag = 0x1017; - } -+ if (tag == 0x19 && !strcmp(make,"Hasselblad") && len == 0x300000) { // RT -+ parse_hasselblad_gain(); // RT -+ } // RT - if (tag == 0x1d) - while ((c = fgetc(ifp)) && c != EOF) - serial = serial*10 + (isdigit(c) ? c - '0' : c % 10); -@@ -5491,14 +5488,14 @@ - while (entries--) { - tiff_get (base, &tag, &type, &len, &save); - switch (tag) { -- case 33434: tiff_ifd[tiff_nifds-1].shutter = -- shutter = getreal(type); break; -+ case 33434: tiff_ifd[tiff_nifds-1].shutter = shutter = getreal(type); break; - case 33437: aperture = getreal(type); break; - case 34855: iso_speed = get2(); break; -+ case 34866: if((!iso_speed) || iso_speed == 65535) iso_speed = get4();break; - case 36867: - case 36868: get_timestamp(0); break; - case 37377: if ((expo = -getreal(type)) < 128) -- tiff_ifd[tiff_nifds-1].shutter = -+ tiff_ifd[tiff_nifds-1].shutter = - shutter = pow (2, expo); break; - case 37378: aperture = pow (2, getreal(type)/2); break; - case 37386: focal_len = getreal(type); break; -@@ -5667,28 +5664,33 @@ - } - } - --void CLASS parse_minolta (int base); --int CLASS parse_tiff (int base); -+/*RT void CLASS parse_minolta (int base); */ -+/*RT int CLASS parse_tiff (int base);*/ - - int CLASS parse_tiff_ifd (int base) - { - unsigned entries, tag, type, len, plen=16, save; -- int ifd, use_cm=0, cfa, i, j, c, ima_len=0; -+ int ifd, use_cm=0, cfa, i, j, c, ima_len=0,cm_D65=0; - char software[64], *cbuf, *cp; - uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256]; -- double cc[4][4], cm[4][3], cam_xyz[4][3], num; -+ double cc[2][4][4]; -+ double cm[2][4][3] = {NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN}; -+ double cam_xyz[4][3], num; - double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 }; - unsigned sony_curve[] = { 0,0,0,0,0,4095 }; - unsigned *buf, sony_offset=0, sony_length=0, sony_key=0; - struct jhead jh; -- FILE *sfp; -+/*RT*/ IMFILE *sfp; - - if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0]) - return 1; - ifd = tiff_nifds++; - for (j=0; j < 4; j++) - for (i=0; i < 4; i++) -- cc[j][i] = i == j; -+ { -+ cc[0][j][i] = i == j; -+ cc[1][j][i] = i == j; -+ } - entries = get2(); - if (entries > 512) return 1; - while (entries--) { -@@ -5758,7 +5760,8 @@ - fgets (make, 64, ifp); - break; - case 272: /* Model */ -- fgets (model, 64, ifp); -+ if (strstr(model, "Hasselblad ") != model) // RT: if Hasselblad, only parse the first model name (otherwise it can change from say Hasselblad CFV-50 to Hasselblad CW (ie the camera body model, not the back model which we are interested in) -+ fgets (model, 64, ifp); - break; - case 280: /* Panasonic RW2 offset */ - if (type != 4) break; -@@ -5818,6 +5821,9 @@ - case 315: /* Artist */ - fread (artist, 64, 1, ifp); - break; -+ case 317: /* Predictor */ -+ tiff_ifd[ifd].predictor = getint(type); -+ break; - case 322: /* TileWidth */ - tiff_ifd[ifd].tile_width = getint(type); - break; -@@ -5833,6 +5839,9 @@ - is_raw = 5; - } - break; -+ case 325: /* TileByteCounts */ -+ tiff_ifd[ifd].bytes = len > 1 ? ftell(ifp) : get4(); -+ break; - case 330: /* SubIFDs */ - if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) { - load_raw = &CLASS sony_arw_load_raw; -@@ -5846,6 +5855,9 @@ - fseek (ifp, i+4, SEEK_SET); - } - break; -+ case 339: -+ tiff_ifd[ifd].sample_format = getint(type); -+ break; - case 400: - strcpy (make, "Sarnoff"); - maximum = 0xfff; -@@ -6063,12 +6075,21 @@ - case 61450: - cblack[4] = cblack[5] = MIN(sqrt(len),64); - case 50714: /* BlackLevel */ -- if (!(cblack[4] * cblack[5])) -- cblack[4] = cblack[5] = 1; -- FORC (cblack[4] * cblack[5]) -- cblack[6+c] = getreal(type); -- black = 0; -- break; -+ if(cblack[4] * cblack[5] == 0) { -+ int dblack[] = { 0,0,0,0 }; -+ black = getreal(type); -+ if ((unsigned)(filters+1) < 1000) break; -+ dblack[0] = dblack[1] = dblack[2] = dblack[3] = black; -+ if (colors == 3) -+ filters |= ((filters >> 2 & 0x22222222) | -+ (filters << 2 & 0x88888888)) & filters << 1; -+ FORC4 cblack[filters >> (c << 1) & 3] = dblack[c]; -+ } else { -+ FORC (cblack[4] * cblack[5]) -+ cblack[6+c] = getreal(type); -+ } -+ black = 0; -+ break; - case 50715: /* BlackLevelDeltaH */ - case 50716: /* BlackLevelDeltaV */ - for (num=i=0; i < (len & 0xffff); i++) -@@ -6085,13 +6106,13 @@ - case 50721: /* ColorMatrix1 */ - case 50722: /* ColorMatrix2 */ - FORCC for (j=0; j < 3; j++) -- cm[c][j] = getreal(type); -+ cm[tag-50721][c][j] = getreal(type); - use_cm = 1; - break; - case 50723: /* CameraCalibration1 */ - case 50724: /* CameraCalibration2 */ - for (i=0; i < colors; i++) -- FORCC cc[i][c] = getreal(type); -+ FORCC cc[tag-50723][i][c] = getreal(type); - break; - case 50727: /* AnalogBalance */ - FORCC ab[c] = getreal(type); -@@ -6114,6 +6135,11 @@ - case 50752: - read_shorts (cr2_slice, 3); - break; -+ case 50778: -+ case 50779: -+ if( get2() == 21 ) -+ cm_D65 = (tag-50778); -+ break; - case 50829: /* ActiveArea */ - top_margin = getint(type); - left_margin = getint(type); -@@ -6146,21 +6172,27 @@ - fread (buf, sony_length, 1, ifp); - sony_decrypt (buf, sony_length/4, 1, sony_key); - sfp = ifp; -- if ((ifp = tmpfile())) { -- fwrite (buf, sony_length, 1, ifp); -- fseek (ifp, 0, SEEK_SET); -- parse_tiff_ifd (-sony_offset); -- fclose (ifp); -- } -+/*RT*/ ifp = fopen (buf, sony_length); -+// if ((ifp = tmpfile())) { -+// fwrite (buf, sony_length, 1, ifp); -+// fseek (ifp, 0, SEEK_SET); -+ parse_tiff_ifd (-sony_offset); -+// fclose (ifp); -+// } -+ if(ifp) -+ fclose(ifp); - ifp = sfp; - free (buf); - } -+ - for (i=0; i < colors; i++) -- FORCC cc[i][c] *= ab[i]; -+ FORCC cc[cm_D65][i][c] *= ab[i]; - if (use_cm) { -+ if(cm_D65 == 1 && std::isnan(cm[1][0][0])) -+ cm_D65 = 0; - FORCC for (i=0; i < 3; i++) - for (cam_xyz[c][i]=j=0; j < colors; j++) -- cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i]; -+ cam_xyz[c][i] += cc[cm_D65][c][j] * cm[cm_D65][j][i] * xyz[i]; - cam_xyz_coeff (cmatrix, cam_xyz); - } - if (asn[0]) { -@@ -6168,13 +6200,14 @@ - FORCC cam_mul[c] = 1 / asn[c]; - } - if (!use_cm) -- FORCC pre_mul[c] /= cc[c][c]; -+ FORCC pre_mul[c] /= cc[cm_D65][c][c]; - return 0; - } - - int CLASS parse_tiff (int base) - { - int doff; -+ /*RT*/ if (exif_base == -1) exif_base = base; - - fseek (ifp, base, SEEK_SET); - order = get2(); -@@ -6206,6 +6239,7 @@ - shutter = tiff_ifd[i].shutter; - tiff_ifd[i].shutter = shutter; - } -+ - for (i=0; i < tiff_nifds; i++) { - if (max_samp < tiff_ifd[i].samples) - max_samp = tiff_ifd[i].samples; -@@ -6266,7 +6300,12 @@ - case 8: load_raw = &CLASS eight_bit_load_raw; break; - case 12: if (tiff_ifd[raw].phint == 2) - load_flags = 6; -- load_raw = &CLASS packed_load_raw; break; -+ if(!strncmp(make,"SONY",4) && tiff_ifd[raw].comp == 1) { // hack for some sony cameras which report as 12 bit uncompressed but in fact are 14 bit uncompressed -+ tiff_bps = 14; -+ } else { -+ load_raw = &CLASS packed_load_raw; -+ break; -+ } - case 14: load_flags = 0; - case 16: load_raw = &CLASS unpacked_load_raw; - if (!strncmp(make,"OLYMPUS",7) && -@@ -6305,6 +6344,7 @@ - case 32803: load_raw = &CLASS kodak_65000_load_raw; - } - case 32867: case 34892: break; -+ case 8: break; - default: is_raw = 0; - } - if (!dng_version) -@@ -6390,7 +6430,7 @@ - { - const char *file, *ext; - char *jname, *jfile, *jext; -- FILE *save=ifp; -+/*RT*/ IMFILE *save=ifp; - - ext = strrchr (ifname, '.'); - file = strrchr (ifname, '/'); -@@ -6412,13 +6452,14 @@ - } else - while (isdigit(*--jext)) { - if (*jext != '9') { -- (*jext)++; -+ (*jext)++; - break; - } - *jext = '0'; - } - if (strcmp (jname, ifname)) { -- if ((ifp = fopen (jname, "rb"))) { -+/*RT*/ if ((ifp = fopen (jname))) { -+// if ((ifp = fopen (jname, "rb"))) { - if (verbose) - fprintf (stderr,_("Reading metadata from %s ...\n"), jname); - parse_tiff (12); -@@ -6693,6 +6734,7 @@ - load_raw = ph1.format < 3 ? - &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c; - maximum = 0xffff; -+ tiff_bps = 16; - strcpy (make, "Phase One"); - if (model[0]) return; - switch (raw_height) { -@@ -6761,7 +6803,11 @@ - order = get2(); - hlen = get4(); - if (get4() == 0x48454150) /* "HEAP" */ -+/*RT*/ { -+/*RT*/ ciff_base = save+hlen; -+/*RT*/ ciff_len = len-hlen; - parse_ciff (save+hlen, len-hlen, 0); -+/*RT*/ } - if (parse_tiff (save+6)) apply_tiff(); - fseek (ifp, save+len, SEEK_SET); - } -@@ -7033,7 +7079,8 @@ - { - static const struct { - const char *prefix; -- short black, maximum, trans[12]; -+ unsigned short black, maximum; // RT: Change to UShort -+ short trans[12]; - } table[] = { - { "AgfaPhoto DC-833m", 0, 0, /* DJC */ - { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, -@@ -7977,12 +8024,12 @@ - { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, - { "Sony DSC-RX100", 0, 0, - { 8651,-2754,-1057,-3464,12207,1373,-568,1398,4434 } }, -- { "Sony DSC-RX10", 0, 0, /* also RX10M2 */ -+ { "Sony DSC-RX10", 0, 0, - { 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 } }, - { "Sony DSC-RX1RM2", 0, 0, - { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, - { "Sony DSC-RX1", 0, 0, -- { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, -+ { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, - { "Sony DSLR-A100", 0, 0xfeb, - { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }, - { "Sony DSLR-A290", 0, 0, -@@ -8088,6 +8135,33 @@ - } - break; - } -+ if (load_raw == &CLASS sony_arw2_load_raw) { // RT: arw2 scale fix -+ black <<= 2; -+ tiff_bps += 2; -+ } -+ { /* Check for RawTherapee table overrides and extensions */ -+ int black_level, white_level; -+ short trans[12]; -+ if (dcraw_coeff_overrides(make, model, iso_speed, trans, &black_level, &white_level)) { -+ if (black_level > -1) { -+ black = (ushort)black_level; -+ } -+ if (white_level > -1) { -+ maximum = (ushort)white_level; -+ if(tiff_bps > 0) { -+ unsigned compare = ((uint64_t)1 << tiff_bps) - 1; // use uint64_t to avoid overflow if tiff_bps == 32 -+ while(maximum > compare) -+ maximum >>= 1; -+ } -+ } -+ if (trans[0]) { -+ for (j=0; j < 12; j++) { -+ ((double *)cam_xyz)[j] = trans[j] / 10000.0; -+ } -+ cam_xyz_coeff (rgb_cam,cam_xyz); -+ } -+ } -+ } - } - - void CLASS simple_coeff (int index) -@@ -8410,7 +8484,7 @@ - tiff_flip = flip = filters = UINT_MAX; /* unknown */ - raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0; - maximum = height = width = top_margin = left_margin = 0; -- cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0; -+ cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = model3[0] = 0; - iso_speed = shutter = aperture = focal_len = unique_id = 0; - tiff_nifds = 0; - memset (tiff_ifd, 0, sizeof tiff_ifd); -@@ -8442,13 +8516,20 @@ - fread (head, 1, 32, ifp); - fseek (ifp, 0, SEEK_END); - flen = fsize = ftell(ifp); -- if ((cp = (char *) memmem (head, 32, "MMMM", 4)) || -- (cp = (char *) memmem (head, 32, "IIII", 4))) { -+ /*RT*/ if (fsize<100000) { -+ is_raw = 0; -+ return; -+ } -+ /* RT: changed string constant */ -+ if ((cp = (char *) memmem (head, 32, (char*)"MMMM", 4)) || -+ (cp = (char *) memmem (head, 32, (char*)"IIII", 4))) { - parse_phase_one (cp-head); - if (cp-head && parse_tiff(0)) apply_tiff(); - } else if (order == 0x4949 || order == 0x4d4d) { - if (!memcmp (head+6,"HEAPCCDR",8)) { - data_offset = hlen; -+/*RT*/ ciff_base = hlen; -+/*RT*/ ciff_len = fsize - hlen; - parse_ciff (hlen, flen-hlen, 0); - load_raw = &CLASS canon_load_raw; - } else if (parse_tiff(0)) apply_tiff(); -@@ -8491,9 +8572,10 @@ - parse_fuji (i); - } - load_raw = &CLASS unpacked_load_raw; -- fseek (ifp, 100+28*(shot_select > 0), SEEK_SET); -+ fseek (ifp, 100+28*(shot_select > 0 && shot_select < is_raw), SEEK_SET); - parse_tiff (data_offset = get4()); - parse_tiff (thumb_offset+12); -+/*RT*/ exif_base = thumb_offset+12; - apply_tiff(); - } else if (!memcmp (head,"RIFF",4)) { - fseek (ifp, 0, SEEK_SET); -@@ -8607,9 +8689,10 @@ - if (make[0] == 0) parse_smal (0, flen); - if (make[0] == 0) { - parse_jpeg(0); -- if (!(strncmp(model,"ov",2) && strncmp(model,"RP_OV",5)) && -- !fseek (ifp, -6404096, SEEK_END) && -- fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) { -+ //RT fix for the use of fseek below -+ if (!(strncmp(model,"ov",2) && strncmp(model,"RP_OV",5))) { -+ fseek (ifp, -6404096, SEEK_END); -+ if (fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) { - strcpy (make, "OmniVision"); - data_offset = ftell(ifp) + 0x8000-32; - width = raw_width; -@@ -8618,6 +8701,7 @@ - filters = 0x16161616; - } else is_raw = 0; - } -+ } - - for (i=0; i < sizeof corp / sizeof *corp; i++) - if (strcasestr (make, corp[i])) /* Simplify company names */ -@@ -8649,7 +8733,7 @@ - if (height == 3136 && width == 4864) /* Pentax K20D and Samsung GX20 */ - { height = 3124; width = 4688; filters = 0x16161616; } - if (width == 4352 && (!strcmp(model,"K-r") || !strcmp(model,"K-x"))) -- { width = 4309; filters = 0x16161616; } -+/*RT*/ { width = 4308; filters = 0x16161616; } - if (width >= 4960 && !strncmp(model,"K-5",3)) - { left_margin = 10; width = 4950; filters = 0x16161616; } - if (width == 4736 && !strcmp(model,"K-7")) -@@ -8669,6 +8753,7 @@ - case 0: - case 1: load_raw = &CLASS packed_dng_load_raw; break; - case 7: load_raw = &CLASS lossless_dng_load_raw; break; -+ case 8: load_raw = &CLASS deflate_dng_load_raw; break; - case 34892: load_raw = &CLASS lossy_dng_load_raw; break; - default: load_raw = 0; - } -@@ -8725,6 +8810,7 @@ - if (height > width) pixel_aspect = 2; - filters = 0; - simple_coeff(0); -+ adobe_coeff (make, model); - } else if (!strcmp(make,"Canon") && tiff_bps == 15) { - switch (width) { - case 3344: width -= 66; -@@ -9034,24 +9120,53 @@ - if (load_raw == &CLASS lossless_jpeg_load_raw) - load_raw = &CLASS hasselblad_load_raw; - if (raw_width == 7262) { -+ if (!strcmp(model, "H3D")) strcpy(model, "H3D-39"); // RT - height = 5444; - width = 7248; - top_margin = 4; - left_margin = 7; - filters = 0x61616161; -- } else if (raw_width == 7410 || raw_width == 8282) { -- height -= 84; -- width -= 82; -+ } else if (raw_width == 7410) { -+ if (!strcmp(model, "H4D")) strcpy(model, "H4D-40"); // RT -+ height = 5502; -+ width = 7328; - top_margin = 4; - left_margin = 41; - filters = 0x61616161; -+ } else if (raw_width == 6542) { // RT, H3D-31, H3DII-31, H4D-31 -+ if (!strcmp(model, "H3D")) strcpy(model, "H3D-31"); -+ if (!strcmp(model, "H4D")) strcpy(model, "H4D-31"); -+ height = 4904; -+ width = 6524; -+ top_margin = 4; -+ left_margin = 8; -+ } else if (raw_width == 8282) { // RT, H3DII-50, H3DII-50MS, CFV-50, H4D-50 -+ if (!strcmp(model, "H3D")) strcpy(model, "H3DII-50"); -+ if (!strcmp(model, "H4D")) strcpy(model, "H4D-50"); -+ height = 6152; -+ width = 8196; -+ top_margin = 4; -+ left_margin = 44; -+ } else if (raw_width == 8374) { // RT, CFV-50c, H5D-50c, "H5D-50c MS", "H5D-200c MS" -+ if (!strcmp(model, "H5D")) strcpy(model, "H5D-50c"); -+ if (!strcmp(model, "CFV-2")) strcpy(model, "CFV-50c"); -+ height = 6208; -+ width = 8280; -+ top_margin = 96; -+ left_margin = 48; - } else if (raw_width == 9044) { - height = 6716; - width = 8964; - top_margin = 8; - left_margin = 40; -- black += load_flags = 256; -- maximum = 0x8101; -+ // RT: removed black level / maximum adjustment, as it does not seem to be correct when there are clipped highlights. Tested with Hasselblad H4D-60. -+ //black += load_flags = 256; -+ //maximum = 0x8101; -+ } else if (raw_width == 4096) { // RT: CF-22 etc -+ if (!strcmp(model, "H3D")) strcpy(model, "H3D-22"); -+ else if (strstr(model3, "Hasselblad ") == model3) strcpy(model, &model3[11]); -+ if (strstr(model3, "ixpressCF132")) strcpy(model, "CF-22"); // ixpressCF132 / CF132 is same as CF-22, we use the simpler name -+ else if (strstr(model3, "Hasselblad96")) strcpy(model, "CFV"); // popularly called CFV-16 - } else if (raw_width == 4090) { - strcpy (model, "V96C"); - height -= (top_margin = 6); -@@ -9109,6 +9224,7 @@ - filters = 0x16161616; - } - } else if (!strcmp(make,"Leica") || !strcmp(make,"Panasonic")) { -+ if(raw_width > 0) { // avoid divide by zero - if ((flen - data_offset) / (raw_width*8/7) == raw_height) - load_raw = &CLASS panasonic_load_raw; - if (!load_raw) { -@@ -9126,6 +9242,7 @@ - } - filters = 0x01010101 * (uchar) "\x94\x61\x49\x16" - [((filters-1) ^ (left_margin & 1) ^ (top_margin << 1)) & 3]; -+ } - } else if (!strcmp(model,"C770UZ")) { - height = 1718; - width = 2304; -@@ -9201,13 +9318,15 @@ - width -= 6; - } else if (!strcmp(make,"Sony") && raw_width == 7392) { - width -= 30; -- } else if (!strcmp(make,"Sony") && raw_width == 8000) { -- width -= 32; -- if (!strncmp(model,"DSC",3)) { -- tiff_bps = 14; -- load_raw = &CLASS unpacked_load_raw; -- black = 512; -- } -+// this was introduced with update to dcraw 9.27 -+// but led to broken decode for compressed files from Sony DSC-RX1RM2 -+// } else if (!strcmp(make,"Sony") && raw_width == 8000) { -+// width -= 32; -+// if (!strncmp(model,"DSC",3)) { -+// tiff_bps = 14; -+// load_raw = &CLASS unpacked_load_raw; -+// black = 512; -+// } - } else if (!strcmp(model,"DSLR-A100")) { - if (width == 3880) { - height--; -@@ -9357,6 +9476,20 @@ - memcpy (rgb_cam, cmatrix, sizeof cmatrix); - raw_color = 0; - } -+ if(!strncmp(make, "Panasonic", 9) && !strncmp(model, "DMC-LX100",9)) -+ adobe_coeff (make, model); -+ if(!strncmp(make, "Samsung", 7) && !strncmp(model, "GX20",4)) -+ adobe_coeff (make, model); -+ if(!strncmp(make, "Samsung", 7) && !strncmp(model, "NX1",3)) -+ adobe_coeff (make, model); -+ if(!strncmp(make, "Pentax", 6) && (!strncmp(model, "K10D",4) || !strncmp(model, "K-70",4))) -+ adobe_coeff (make, model); -+ if(!strncmp(make, "Leica", 5) && !strncmp(model, "Q",1)) -+ adobe_coeff (make, model); -+ if(!strncmp(make, "Leica", 5) && !strncmp(model, "SL",2)) -+ adobe_coeff (make, model); -+ if(!strncmp(make, "XIAOYI", 6) && !strncmp(model, "M1",2)) -+ adobe_coeff (make, model); - if (raw_color) adobe_coeff (make, model); - if (load_raw == &CLASS kodak_radc_load_raw) - if (raw_color) adobe_coeff ("Apple","Quicktake"); -@@ -9371,9 +9504,9 @@ - if (raw_width < width ) raw_width = width; - } - if (!tiff_bps) tiff_bps = 12; -- if (!maximum) maximum = (1 << tiff_bps) - 1; -+ if (!maximum) maximum = ((uint64_t)1 << tiff_bps) - 1; // use uint64_t to avoid overflow if tiff_bps == 32 - if (!load_raw || height < 22 || width < 22 || -- tiff_bps > 16 || tiff_samples > 6 || colors > 4) -+ tiff_samples > 6 || colors > 4) - is_raw = 0; - #ifdef NO_JASPER - if (load_raw == &CLASS redcine_load_raw) { -@@ -9402,249 +9535,300 @@ - if (flip == UINT_MAX) flip = 0; - } - --#ifndef NO_LCMS --void CLASS apply_profile (const char *input, const char *output) --{ -- char *prof; -- cmsHPROFILE hInProfile=0, hOutProfile=0; -- cmsHTRANSFORM hTransform; -- FILE *fp; -- unsigned size; -- -- if (strcmp (input, "embed")) -- hInProfile = cmsOpenProfileFromFile (input, "r"); -- else if (profile_length) { -- prof = (char *) malloc (profile_length); -- merror (prof, "apply_profile()"); -- fseek (ifp, profile_offset, SEEK_SET); -- fread (prof, 1, profile_length, ifp); -- hInProfile = cmsOpenProfileFromMem (prof, profile_length); -- free (prof); -- } else -- fprintf (stderr,_("%s has no embedded profile.\n"), ifname); -- if (!hInProfile) return; -- if (!output) -- hOutProfile = cmsCreate_sRGBProfile(); -- else if ((fp = fopen (output, "rb"))) { -- fread (&size, 4, 1, fp); -- fseek (fp, 0, SEEK_SET); -- oprof = (unsigned *) malloc (size = ntohl(size)); -- merror (oprof, "apply_profile()"); -- fread (oprof, 1, size, fp); -- fclose (fp); -- if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) { -- free (oprof); -- oprof = 0; -+//#ifndef NO_LCMS -+//void CLASS apply_profile (const char *input, const char *output) -+//{ -+// char *prof; -+// cmsHPROFILE hInProfile=0, hOutProfile=0; -+// cmsHTRANSFORM hTransform; -+// FILE *fp; -+// unsigned size; -+// -+// if (strcmp (input, "embed")) -+// hInProfile = cmsOpenProfileFromFile (input, "r"); -+// else if (profile_length) { -+// prof = (char *) malloc (profile_length); -+// merror (prof, "apply_profile()"); -+// fseek (ifp, profile_offset, SEEK_SET); -+// fread (prof, 1, profile_length, ifp); -+// hInProfile = cmsOpenProfileFromMem (prof, profile_length); -+// free (prof); -+// } else -+// fprintf (stderr,_("%s has no embedded profile.\n"), ifname); -+// if (!hInProfile) return; -+// if (!output) -+// hOutProfile = cmsCreate_sRGBProfile(); -+// else if ((fp = fopen (output, "rb"))) { -+// fread (&size, 4, 1, fp); -+// fseek (fp, 0, SEEK_SET); -+// oprof = (unsigned *) malloc (size = ntohl(size)); -+// merror (oprof, "apply_profile()"); -+// fread (oprof, 1, size, fp); -+// fclose (fp); -+// if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) { -+// free (oprof); -+// oprof = 0; -+// } -+// } else -+// fprintf (stderr,_("Cannot open file %s!\n"), output); -+// if (!hOutProfile) goto quit; -+// if (verbose) -+// fprintf (stderr,_("Applying color profile...\n")); -+// hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16, -+// hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0); -+// cmsDoTransform (hTransform, image, image, width*height); -+// raw_color = 1; /* Don't use rgb_cam with a profile */ -+// cmsDeleteTransform (hTransform); -+// cmsCloseProfile (hOutProfile); -+//quit: -+// cmsCloseProfile (hInProfile); -+//} -+//#endif -+ -+/* RT: DNG Float */ -+ -+#include -+#include -+ -+static void decodeFPDeltaRow(Bytef * src, Bytef * dst, size_t tileWidth, size_t realTileWidth, int bytesps, int factor) { -+ // DecodeDeltaBytes -+ for (size_t col = factor; col < realTileWidth*bytesps; ++col) { -+ src[col] += src[col - factor]; -+ } -+ // Reorder bytes into the image -+ // 16 and 32-bit versions depend on local architecture, 24-bit does not -+ if (bytesps == 3) { -+ for (size_t col = 0; col < tileWidth; ++col) { -+ dst[col*3] = src[col]; -+ dst[col*3 + 1] = src[col + realTileWidth]; -+ dst[col*3 + 2] = src[col + realTileWidth*2]; - } -- } else -- fprintf (stderr,_("Cannot open file %s!\n"), output); -- if (!hOutProfile) goto quit; -- if (verbose) -- fprintf (stderr,_("Applying color profile...\n")); -- hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16, -- hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0); -- cmsDoTransform (hTransform, image, image, width*height); -- raw_color = 1; /* Don't use rgb_cam with a profile */ -- cmsDeleteTransform (hTransform); -- cmsCloseProfile (hOutProfile); --quit: -- cmsCloseProfile (hInProfile); -+ } else { -+ union X { uint32_t x; uint8_t c; }; -+ if (((union X){1}).c) { -+ for (size_t col = 0; col < tileWidth; ++col) { -+ for (size_t byte = 0; byte < bytesps; ++byte) -+ dst[col*bytesps + byte] = src[col + realTileWidth*(bytesps-byte-1)]; // Little endian -+ } -+ } else { -+ for (size_t col = 0; col < tileWidth; ++col) { -+ for (size_t byte = 0; byte < bytesps; ++byte) -+ dst[col*bytesps + byte] = src[col + realTileWidth*byte]; -+ } -+ } -+ } -+ - } --#endif - --void CLASS convert_to_rgb() --{ -- int row, col, c, i, j, k; -- ushort *img; -- float out[3], out_cam[3][4]; -- double num, inverse[3][3]; -- static const double xyzd50_srgb[3][3] = -- { { 0.436083, 0.385083, 0.143055 }, -- { 0.222507, 0.716888, 0.060608 }, -- { 0.013930, 0.097097, 0.714022 } }; -- static const double rgb_rgb[3][3] = -- { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } }; -- static const double adobe_rgb[3][3] = -- { { 0.715146, 0.284856, 0.000000 }, -- { 0.000000, 1.000000, 0.000000 }, -- { 0.000000, 0.041166, 0.958839 } }; -- static const double wide_rgb[3][3] = -- { { 0.593087, 0.404710, 0.002206 }, -- { 0.095413, 0.843149, 0.061439 }, -- { 0.011621, 0.069091, 0.919288 } }; -- static const double prophoto_rgb[3][3] = -- { { 0.529317, 0.330092, 0.140588 }, -- { 0.098368, 0.873465, 0.028169 }, -- { 0.016879, 0.117663, 0.865457 } }; -- static const double aces_rgb[3][3] = -- { { 0.432996, 0.375380, 0.189317 }, -- { 0.089427, 0.816523, 0.102989 }, -- { 0.019165, 0.118150, 0.941914 } }; -- static const double (*out_rgb[])[3] = -- { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb, aces_rgb }; -- static const char *name[] = -- { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ", "ACES" }; -- static const unsigned phead[] = -- { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, -- 0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d }; -- unsigned pbody[] = -- { 10, 0x63707274, 0, 36, /* cprt */ -- 0x64657363, 0, 40, /* desc */ -- 0x77747074, 0, 20, /* wtpt */ -- 0x626b7074, 0, 20, /* bkpt */ -- 0x72545243, 0, 14, /* rTRC */ -- 0x67545243, 0, 14, /* gTRC */ -- 0x62545243, 0, 14, /* bTRC */ -- 0x7258595a, 0, 20, /* rXYZ */ -- 0x6758595a, 0, 20, /* gXYZ */ -- 0x6258595a, 0, 20 }; /* bXYZ */ -- static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc }; -- unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 }; -- -- gamma_curve (gamm[0], gamm[1], 0, 0); -- memcpy (out_cam, rgb_cam, sizeof out_cam); -- raw_color |= colors == 1 || document_mode || -- output_color < 1 || output_color > 6; -- if (!raw_color) { -- oprof = (unsigned *) calloc (phead[0], 1); -- merror (oprof, "convert_to_rgb()"); -- memcpy (oprof, phead, sizeof phead); -- if (output_color == 5) oprof[4] = oprof[5]; -- oprof[0] = 132 + 12*pbody[0]; -- for (i=0; i < pbody[0]; i++) { -- oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; -- pbody[i*3+2] = oprof[0]; -- oprof[0] += (pbody[i*3+3] + 3) & -4; -- } -- memcpy (oprof+32, pbody, sizeof pbody); -- oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1; -- memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite); -- pcurve[3] = (short)(256/gamm[5]+0.5) << 16; -- for (i=4; i < 7; i++) -- memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve); -- pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3); -- for (i=0; i < 3; i++) -- for (j=0; j < 3; j++) { -- for (num = k=0; k < 3; k++) -- num += xyzd50_srgb[i][k] * inverse[j][k]; -- oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5; -- } -- for (i=0; i < phead[0]/4; i++) -- oprof[i] = htonl(oprof[i]); -- strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw"); -- strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]); -- for (i=0; i < 3; i++) -- for (j=0; j < colors; j++) -- for (out_cam[i][j] = k=0; k < 3; k++) -- out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j]; -+// From DNG SDK dng_utils.h -+static inline uint32_t DNG_HalfToFloat(uint16_t halfValue) { -+ int32_t sign = (halfValue >> 15) & 0x00000001; -+ int32_t exponent = (halfValue >> 10) & 0x0000001f; -+ int32_t mantissa = halfValue & 0x000003ff; -+ if (exponent == 0) { -+ if (mantissa == 0) { -+ // Plus or minus zero -+ return (uint32_t) (sign << 31); -+ } else { -+ // Denormalized number -- renormalize it -+ while (!(mantissa & 0x00000400)) { -+ mantissa <<= 1; -+ exponent -= 1; -+ } -+ exponent += 1; -+ mantissa &= ~0x00000400; -+ } -+ } else if (exponent == 31) { -+ if (mantissa == 0) { -+ // Positive or negative infinity, convert to maximum (16 bit) values. -+ return (uint32_t) ((sign << 31) | ((0x1eL + 127 - 15) << 23) | (0x3ffL << 13)); -+ } else { -+ // Nan -- Just set to zero. -+ return 0; -+ } - } -- if (verbose) -- fprintf (stderr, raw_color ? _("Building histograms...\n") : -- _("Converting to %s colorspace...\n"), name[output_color-1]); -+ // Normalized number -+ exponent += (127 - 15); -+ mantissa <<= 13; -+ // Assemble sign, exponent and mantissa. -+ return (uint32_t) ((sign << 31) | (exponent << 23) | mantissa); -+} - -- memset (histogram, 0, sizeof histogram); -- for (img=image[0], row=0; row < height; row++) -- for (col=0; col < width; col++, img+=4) { -- if (!raw_color) { -- out[0] = out[1] = out[2] = 0; -- FORCC { -- out[0] += out_cam[0][c] * img[c]; -- out[1] += out_cam[1][c] * img[c]; -- out[2] += out_cam[2][c] * img[c]; -- } -- FORC3 img[c] = CLIP((int) out[c]); -- } -- else if (document_mode) -- img[0] = img[fcol(row,col)]; -- FORCC histogram[c][img[c] >> 3]++; -- } -- if (colors == 4 && output_color) colors = 3; -- if (document_mode && filters) colors = 1; --} -- --void CLASS fuji_rotate() --{ -- int i, row, col; -- double step; -- float r, c, fr, fc; -- unsigned ur, uc; -- ushort wide, high, (*img)[4], (*pix)[4]; -+static inline uint32_t DNG_FP24ToFloat(const uint8_t * input) { -+ int32_t sign = (input [0] >> 7) & 0x01; -+ int32_t exponent = (input [0] ) & 0x7F; -+ int32_t mantissa = (((int32_t) input [1]) << 8) | input[2]; -+ if (exponent == 0) { -+ if (mantissa == 0) { -+ // Plus or minus zero -+ return (uint32_t) (sign << 31); -+ } else { -+ // Denormalized number -- renormalize it -+ while (!(mantissa & 0x00010000)) { -+ mantissa <<= 1; -+ exponent -= 1; -+ } -+ exponent += 1; -+ mantissa &= ~0x00010000; -+ } -+ } else if (exponent == 127) { -+ if (mantissa == 0) { -+ // Positive or negative infinity, convert to maximum (24 bit) values. -+ return (uint32_t) ((sign << 31) | ((0x7eL + 128 - 64) << 23) | (0xffffL << 7)); -+ } else { -+ // Nan -- Just set to zero. -+ return 0; -+ } -+ } -+ // Normalized number -+ exponent += (128 - 64); -+ mantissa <<= 7; -+ // Assemble sign, exponent and mantissa. -+ return (uint32_t) ((sign << 31) | (exponent << 23) | mantissa); -+} - -- if (!fuji_width) return; -- if (verbose) -- fprintf (stderr,_("Rotating image 45 degrees...\n")); -- fuji_width = (fuji_width - 1 + shrink) >> shrink; -- step = sqrt(0.5); -- wide = fuji_width / step; -- high = (height - fuji_width) / step; -- img = (ushort (*)[4]) calloc (high, wide*sizeof *img); -- merror (img, "fuji_rotate()"); -- -- for (row=0; row < high; row++) -- for (col=0; col < wide; col++) { -- ur = r = fuji_width + (row-col)*step; -- uc = c = (row+col)*step; -- if (ur > height-2 || uc > width-2) continue; -- fr = r - ur; -- fc = c - uc; -- pix = image + ur*width + uc; -- for (i=0; i < colors; i++) -- img[row*wide+col][i] = -- (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) + -- (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr; -- } -- free (image); -- width = wide; -- height = high; -- image = img; -- fuji_width = 0; -+static void expandFloats(Bytef * dst, int tileWidth, int bytesps) { -+ if (bytesps == 2) { -+ uint16_t * dst16 = (uint16_t *) dst; -+ uint32_t * dst32 = (uint32_t *) dst; -+ for (int index = tileWidth - 1; index >= 0; --index) { -+ dst32[index] = DNG_HalfToFloat(dst16[index]); -+ } -+ } else if (bytesps == 3) { -+ uint8_t * dst8 = ((uint8_t *) dst) + (tileWidth - 1) * 3; -+ uint32_t * dst32 = (uint32_t *) dst; -+ for (int index = tileWidth - 1; index >= 0; --index, dst8 -= 3) { -+ dst32[index] = DNG_FP24ToFloat(dst8); -+ } -+ } - } - --void CLASS stretch() -+static void copyFloatDataToInt(float * src, ushort * dst, size_t size, float max) { -+ bool negative = false, nan = false; -+ -+#ifdef _OPENMP -+#pragma omp parallel for -+#endif -+ for (size_t i = 0; i < size; ++i) { -+ if (src[i] < 0.0f) { -+ negative = true; -+ src[i] = 0.0f; -+ } else if (std::isnan(src[i])) { -+ nan = true; -+ src[i] = max; -+ } -+ // Copy the data to the integer buffer to build the thumbnail -+ dst[i] = (ushort)src[i]; -+ } -+ if (negative) -+ fprintf(stderr, "DNG Float: Negative data found in input file\n"); -+ if (nan) -+ fprintf(stderr, "DNG Float: NaN data found in input file\n"); -+} -+ -+void CLASS deflate_dng_load_raw() { -+ struct tiff_ifd * ifd = &tiff_ifd[0]; -+ while (ifd < &tiff_ifd[tiff_nifds] && ifd->offset != data_offset) ++ifd; -+ if (ifd == &tiff_ifd[tiff_nifds]) { -+ fprintf(stderr, "DNG Deflate: Raw image not found???\n"); -+ return; -+ } -+ -+ int predFactor; -+ switch(ifd->predictor) { -+ case 3: predFactor = 1; break; -+ case 34894: predFactor = 2; break; -+ case 34895: predFactor = 4; break; -+ default: predFactor = 0; break; -+ } -+ -+ if (ifd->sample_format == 3) { // Floating point data -+ float_raw_image = new float[raw_width * raw_height]; -+ -+#ifdef _OPENMP -+#pragma omp parallel for -+#endif -+ for (size_t i = 0; i < raw_width * raw_height; ++i) -+ float_raw_image[i] = 0.0f; -+ } -+ -+ // NOTE: This reader is based on the official DNG SDK from Adobe. -+ // It assumes tiles without subtiles, but the standard does not say that -+ // subtiles or strips couldn't be used. -+ if (tile_length < INT_MAX) { -+ size_t tilesWide = (raw_width + tile_width - 1) / tile_width; -+ size_t tilesHigh = (raw_height + tile_length - 1) / tile_length; -+ size_t tileCount = tilesWide * tilesHigh; -+ //fprintf(stderr, "%dx%d tiles, %d total\n", tilesWide, tilesHigh, tileCount); -+ size_t tileOffsets[tileCount]; -+ for (size_t t = 0; t < tileCount; ++t) { -+ tileOffsets[t] = get4(); -+ } -+ size_t tileBytes[tileCount]; -+ uLongf maxCompressed = 0; -+ if (tileCount == 1) { -+ tileBytes[0] = maxCompressed = ifd->bytes; -+ } else { -+ fseek(ifp, ifd->bytes, SEEK_SET); -+ for (size_t t = 0; t < tileCount; ++t) { -+ tileBytes[t] = get4(); -+ //fprintf(stderr, "Tile %d at %d, size %d\n", t, tileOffsets[t], tileBytes[t]); -+ if (maxCompressed < tileBytes[t]) -+ maxCompressed = tileBytes[t]; -+ } -+ } -+ uLongf dstLen = tile_width * tile_length * 4; -+ -+#ifdef _OPENMP -+#pragma omp parallel -+#endif - { -- ushort newdim, (*img)[4], *pix0, *pix1; -- int row, col, c; -- double rc, frac; -+ Bytef * cBuffer = new Bytef[maxCompressed]; -+ Bytef * uBuffer = new Bytef[dstLen]; - -- if (pixel_aspect == 1) return; -- if (verbose) fprintf (stderr,_("Stretching the image...\n")); -- if (pixel_aspect < 1) { -- newdim = height / pixel_aspect + 0.5; -- img = (ushort (*)[4]) calloc (width, newdim*sizeof *img); -- merror (img, "stretch()"); -- for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) { -- frac = rc - (c = rc); -- pix0 = pix1 = image[c*width]; -- if (c+1 < height) pix1 += width*4; -- for (col=0; col < width; col++, pix0+=4, pix1+=4) -- FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5; -+#ifdef _OPENMP -+#pragma omp for collapse(2) nowait -+#endif -+ for (size_t y = 0; y < raw_height; y += tile_length) { -+ for (size_t x = 0; x < raw_width; x += tile_width) { -+ size_t t = (y / tile_length) * tilesWide + (x / tile_width); -+#pragma omp critical -+{ -+ fseek(ifp, tileOffsets[t], SEEK_SET); -+ fread(cBuffer, 1, tileBytes[t], ifp); -+} -+ int err = uncompress(uBuffer, &dstLen, cBuffer, tileBytes[t]); -+ if (err != Z_OK) { -+ fprintf(stderr, "DNG Deflate: Failed uncompressing tile %d, with error %d\n", (int)t, err); -+ } else if (ifd->sample_format == 3) { // Floating point data -+ int bytesps = ifd->bps >> 3; -+ size_t thisTileLength = y + tile_length > raw_height ? raw_height - y : tile_length; -+ size_t thisTileWidth = x + tile_width > raw_width ? raw_width - x : tile_width; -+ for (size_t row = 0; row < thisTileLength; ++row) { -+ Bytef * src = uBuffer + row*tile_width*bytesps; -+ Bytef * dst = (Bytef *)&float_raw_image[(y+row)*raw_width + x]; -+ if (predFactor) -+ decodeFPDeltaRow(src, dst, thisTileWidth, tile_width, bytesps, predFactor); -+ expandFloats(dst, thisTileWidth, bytesps); -+ } -+ } else { // 32-bit Integer data -+ // TODO -+ } -+ } - } -- height = newdim; -- } else { -- newdim = width * pixel_aspect + 0.5; -- img = (ushort (*)[4]) calloc (height, newdim*sizeof *img); -- merror (img, "stretch()"); -- for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) { -- frac = rc - (c = rc); -- pix0 = pix1 = image[c]; -- if (c+1 < width) pix1 += 4; -- for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4) -- FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5; -- } -- width = newdim; -- } -- free (image); -- image = img; --} -- --int CLASS flip_index (int row, int col) --{ -- if (flip & 4) SWAP(row,col); -- if (flip & 2) row = iheight - 1 - row; -- if (flip & 1) col = iwidth - 1 - col; -- return row * iwidth + col; -+ -+ delete [] cBuffer; -+ delete [] uBuffer; -+} -+ } -+ -+ if (ifd->sample_format == 3) { // Floating point data -+ copyFloatDataToInt(float_raw_image, raw_image, raw_width*raw_height, maximum); -+ } - } - -+/* RT: removed unused functions */ -+ - struct tiff_tag { - ushort tag, type; - int count; -@@ -9667,594 +9851,11 @@ - char desc[512], make[64], model[64], soft[32], date[20], artist[64]; - }; - --void CLASS tiff_set (struct tiff_hdr *th, ushort *ntag, -- ushort tag, ushort type, int count, int val) --{ -- struct tiff_tag *tt; -- int c; -- -- tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; -- tt->val.i = val; -- if (type == 1 && count <= 4) -- FORC(4) tt->val.c[c] = val >> (c << 3); -- else if (type == 2) { -- count = strnlen((char *)th + val, count-1) + 1; -- if (count <= 4) -- FORC(4) tt->val.c[c] = ((char *)th)[val+c]; -- } else if (type == 3 && count <= 2) -- FORC(2) tt->val.s[c] = val >> (c << 4); -- tt->count = count; -- tt->type = type; -- tt->tag = tag; --} -- --#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th) -- --void CLASS tiff_head (struct tiff_hdr *th, int full) --{ -- int c, psize=0; -- struct tm *t; -- -- memset (th, 0, sizeof *th); -- th->order = htonl(0x4d4d4949) >> 16; -- th->magic = 42; -- th->ifd = 10; -- th->rat[0] = th->rat[2] = 300; -- th->rat[1] = th->rat[3] = 1; -- FORC(6) th->rat[4+c] = 1000000; -- th->rat[4] *= shutter; -- th->rat[6] *= aperture; -- th->rat[8] *= focal_len; -- strncpy (th->desc, desc, 512); -- strncpy (th->make, make, 64); -- strncpy (th->model, model, 64); -- strcpy (th->soft, "dcraw v"DCRAW_VERSION); -- t = localtime (×tamp); -- sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d", -- t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); -- strncpy (th->artist, artist, 64); -- if (full) { -- tiff_set (th, &th->ntag, 254, 4, 1, 0); -- tiff_set (th, &th->ntag, 256, 4, 1, width); -- tiff_set (th, &th->ntag, 257, 4, 1, height); -- tiff_set (th, &th->ntag, 258, 3, colors, output_bps); -- if (colors > 2) -- th->tag[th->ntag-1].val.i = TOFF(th->bps); -- FORC4 th->bps[c] = output_bps; -- tiff_set (th, &th->ntag, 259, 3, 1, 1); -- tiff_set (th, &th->ntag, 262, 3, 1, 1 + (colors > 1)); -- } -- tiff_set (th, &th->ntag, 270, 2, 512, TOFF(th->desc)); -- tiff_set (th, &th->ntag, 271, 2, 64, TOFF(th->make)); -- tiff_set (th, &th->ntag, 272, 2, 64, TOFF(th->model)); -- if (full) { -- if (oprof) psize = ntohl(oprof[0]); -- tiff_set (th, &th->ntag, 273, 4, 1, sizeof *th + psize); -- tiff_set (th, &th->ntag, 277, 3, 1, colors); -- tiff_set (th, &th->ntag, 278, 4, 1, height); -- tiff_set (th, &th->ntag, 279, 4, 1, height*width*colors*output_bps/8); -- } else -- tiff_set (th, &th->ntag, 274, 3, 1, "12435867"[flip]-'0'); -- tiff_set (th, &th->ntag, 282, 5, 1, TOFF(th->rat[0])); -- tiff_set (th, &th->ntag, 283, 5, 1, TOFF(th->rat[2])); -- tiff_set (th, &th->ntag, 284, 3, 1, 1); -- tiff_set (th, &th->ntag, 296, 3, 1, 2); -- tiff_set (th, &th->ntag, 305, 2, 32, TOFF(th->soft)); -- tiff_set (th, &th->ntag, 306, 2, 20, TOFF(th->date)); -- tiff_set (th, &th->ntag, 315, 2, 64, TOFF(th->artist)); -- tiff_set (th, &th->ntag, 34665, 4, 1, TOFF(th->nexif)); -- if (psize) tiff_set (th, &th->ntag, 34675, 7, psize, sizeof *th); -- tiff_set (th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4])); -- tiff_set (th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6])); -- tiff_set (th, &th->nexif, 34855, 3, 1, iso_speed); -- tiff_set (th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8])); -- if (gpsdata[1]) { -- tiff_set (th, &th->ntag, 34853, 4, 1, TOFF(th->ngps)); -- tiff_set (th, &th->ngps, 0, 1, 4, 0x202); -- tiff_set (th, &th->ngps, 1, 2, 2, gpsdata[29]); -- tiff_set (th, &th->ngps, 2, 5, 3, TOFF(th->gps[0])); -- tiff_set (th, &th->ngps, 3, 2, 2, gpsdata[30]); -- tiff_set (th, &th->ngps, 4, 5, 3, TOFF(th->gps[6])); -- tiff_set (th, &th->ngps, 5, 1, 1, gpsdata[31]); -- tiff_set (th, &th->ngps, 6, 5, 1, TOFF(th->gps[18])); -- tiff_set (th, &th->ngps, 7, 5, 3, TOFF(th->gps[12])); -- tiff_set (th, &th->ngps, 18, 2, 12, TOFF(th->gps[20])); -- tiff_set (th, &th->ngps, 29, 2, 12, TOFF(th->gps[23])); -- memcpy (th->gps, gpsdata, sizeof th->gps); -- } --} -- --void CLASS jpeg_thumb() --{ -- char *thumb; -- ushort exif[5]; -- struct tiff_hdr th; -- -- thumb = (char *) malloc (thumb_length); -- merror (thumb, "jpeg_thumb()"); -- fread (thumb, 1, thumb_length, ifp); -- fputc (0xff, ofp); -- fputc (0xd8, ofp); -- if (strcmp (thumb+6, "Exif")) { -- memcpy (exif, "\xff\xe1 Exif\0\0", 10); -- exif[1] = htons (8 + sizeof th); -- fwrite (exif, 1, sizeof exif, ofp); -- tiff_head (&th, 0); -- fwrite (&th, 1, sizeof th, ofp); -- } -- fwrite (thumb+2, 1, thumb_length-2, ofp); -- free (thumb); --} -- --void CLASS write_ppm_tiff() --{ -- struct tiff_hdr th; -- uchar *ppm; -- ushort *ppm2; -- int c, row, col, soff, rstep, cstep; -- int perc, val, total, white=0x2000; -- -- perc = width * height * 0.01; /* 99th percentile white level */ -- if (fuji_width) perc /= 2; -- if (!((highlight & ~2) || no_auto_bright)) -- for (white=c=0; c < colors; c++) { -- for (val=0x2000, total=0; --val > 32; ) -- if ((total += histogram[c][val]) > perc) break; -- if (white < val) white = val; -- } -- gamma_curve (gamm[0], gamm[1], 2, (white << 3)/bright); -- iheight = height; -- iwidth = width; -- if (flip & 4) SWAP(height,width); -- ppm = (uchar *) calloc (width, colors*output_bps/8); -- ppm2 = (ushort *) ppm; -- merror (ppm, "write_ppm_tiff()"); -- if (output_tiff) { -- tiff_head (&th, 1); -- fwrite (&th, sizeof th, 1, ofp); -- if (oprof) -- fwrite (oprof, ntohl(oprof[0]), 1, ofp); -- } else if (colors > 3) -- fprintf (ofp, -- "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n", -- width, height, colors, (1 << output_bps)-1, cdesc); -- else -- fprintf (ofp, "P%d\n%d %d\n%d\n", -- colors/2+5, width, height, (1 << output_bps)-1); -- soff = flip_index (0, 0); -- cstep = flip_index (0, 1) - soff; -- rstep = flip_index (1, 0) - flip_index (0, width); -- for (row=0; row < height; row++, soff += rstep) { -- for (col=0; col < width; col++, soff += cstep) -- if (output_bps == 8) -- FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8; -- else FORCC ppm2[col*colors+c] = curve[image[soff][c]]; -- if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa) -- swab (ppm2, ppm2, width*colors*2); -- fwrite (ppm, colors*output_bps/8, width, ofp); -- } -- free (ppm); --} -- --int CLASS main (int argc, const char **argv) --{ -- int arg, status=0, quality, i, c; -- int timestamp_only=0, thumbnail_only=0, identify_only=0; -- int user_qual=-1, user_black=-1, user_sat=-1, user_flip=-1; -- int use_fuji_rotate=1, write_to_stdout=0, read_from_stdin=0; -- const char *sp, *bpfile=0, *dark_frame=0, *write_ext; -- char opm, opt, *ofname, *cp; -- struct utimbuf ut; --#ifndef NO_LCMS -- const char *cam_profile=0, *out_profile=0; --#endif -- --#ifndef LOCALTIME -- putenv ((char *) "TZ=UTC"); --#endif --#ifdef LOCALEDIR -- setlocale (LC_CTYPE, ""); -- setlocale (LC_MESSAGES, ""); -- bindtextdomain ("dcraw", LOCALEDIR); -- textdomain ("dcraw"); --#endif -- -- if (argc == 1) { -- printf(_("\nRaw photo decoder \"dcraw\" v%s"), DCRAW_VERSION); -- printf(_("\nby Dave Coffin, dcoffin a cybercom o net\n")); -- printf(_("\nUsage: %s [OPTION]... [FILE]...\n\n"), argv[0]); -- puts(_("-v Print verbose messages")); -- puts(_("-c Write image data to standard output")); -- puts(_("-e Extract embedded thumbnail image")); -- puts(_("-i Identify files without decoding them")); -- puts(_("-i -v Identify files and show metadata")); -- puts(_("-z Change file dates to camera timestamp")); -- puts(_("-w Use camera white balance, if possible")); -- puts(_("-a Average the whole image for white balance")); -- puts(_("-A Average a grey box for white balance")); -- puts(_("-r Set custom white balance")); -- puts(_("+M/-M Use/don't use an embedded color matrix")); -- puts(_("-C Correct chromatic aberration")); -- puts(_("-P Fix the dead pixels listed in this file")); -- puts(_("-K Subtract dark frame (16-bit raw PGM)")); -- puts(_("-k Set the darkness level")); -- puts(_("-S Set the saturation level")); -- puts(_("-n Set threshold for wavelet denoising")); -- puts(_("-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)")); -- puts(_("-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)")); -- puts(_("-o [0-6] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES)")); --#ifndef NO_LCMS -- puts(_("-o Apply output ICC profile from file")); -- puts(_("-p Apply camera ICC profile from file or \"embed\"")); --#endif -- puts(_("-d Document mode (no color, no interpolation)")); -- puts(_("-D Document mode without scaling (totally raw)")); -- puts(_("-j Don't stretch or rotate raw pixels")); -- puts(_("-W Don't automatically brighten the image")); -- puts(_("-b Adjust brightness (default = 1.0)")); -- puts(_("-g

Set custom gamma curve (default = 2.222 4.5)")); -- puts(_("-q [0-3] Set the interpolation quality")); -- puts(_("-h Half-size color image (twice as fast as \"-q 0\")")); -- puts(_("-f Interpolate RGGB as four colors")); -- puts(_("-m Apply a 3x3 median filter to R-G and B-G")); -- puts(_("-s [0..N-1] Select one raw image or \"all\" from each file")); -- puts(_("-6 Write 16-bit instead of 8-bit")); -- puts(_("-4 Linear 16-bit, same as \"-6 -W -g 1 1\"")); -- puts(_("-T Write TIFF instead of PPM")); -- puts(""); -- return 1; -- } -- argv[argc] = ""; -- for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) { -- opt = argv[arg++][1]; -- if ((cp = (char *) strchr (sp="nbrkStqmHACg", opt))) -- for (i=0; i < "114111111422"[cp-sp]-'0'; i++) -- if (!isdigit(argv[arg+i][0])) { -- fprintf (stderr,_("Non-numeric argument to \"-%c\"\n"), opt); -- return 1; -- } -- switch (opt) { -- case 'n': threshold = atof(argv[arg++]); break; -- case 'b': bright = atof(argv[arg++]); break; -- case 'r': -- FORC4 user_mul[c] = atof(argv[arg++]); break; -- case 'C': aber[0] = 1 / atof(argv[arg++]); -- aber[2] = 1 / atof(argv[arg++]); break; -- case 'g': gamm[0] = atof(argv[arg++]); -- gamm[1] = atof(argv[arg++]); -- if (gamm[0]) gamm[0] = 1/gamm[0]; break; -- case 'k': user_black = atoi(argv[arg++]); break; -- case 'S': user_sat = atoi(argv[arg++]); break; -- case 't': user_flip = atoi(argv[arg++]); break; -- case 'q': user_qual = atoi(argv[arg++]); break; -- case 'm': med_passes = atoi(argv[arg++]); break; -- case 'H': highlight = atoi(argv[arg++]); break; -- case 's': -- shot_select = abs(atoi(argv[arg])); -- multi_out = !strcmp(argv[arg++],"all"); -- break; -- case 'o': -- if (isdigit(argv[arg][0]) && !argv[arg][1]) -- output_color = atoi(argv[arg++]); --#ifndef NO_LCMS -- else out_profile = argv[arg++]; -- break; -- case 'p': cam_profile = argv[arg++]; --#endif -- break; -- case 'P': bpfile = argv[arg++]; break; -- case 'K': dark_frame = argv[arg++]; break; -- case 'z': timestamp_only = 1; break; -- case 'e': thumbnail_only = 1; break; -- case 'i': identify_only = 1; break; -- case 'c': write_to_stdout = 1; break; -- case 'v': verbose = 1; break; -- case 'h': half_size = 1; break; -- case 'f': four_color_rgb = 1; break; -- case 'A': FORC4 greybox[c] = atoi(argv[arg++]); -- case 'a': use_auto_wb = 1; break; -- case 'w': use_camera_wb = 1; break; -- case 'M': use_camera_matrix = 3 * (opm == '+'); break; -- case 'I': read_from_stdin = 1; break; -- case 'E': document_mode++; -- case 'D': document_mode++; -- case 'd': document_mode++; -- case 'j': use_fuji_rotate = 0; break; -- case 'W': no_auto_bright = 1; break; -- case 'T': output_tiff = 1; break; -- case '4': gamm[0] = gamm[1] = -- no_auto_bright = 1; -- case '6': output_bps = 16; break; -- default: -- fprintf (stderr,_("Unknown option \"-%c\".\n"), opt); -- return 1; -- } -- } -- if (arg == argc) { -- fprintf (stderr,_("No files to process.\n")); -- return 1; -- } -- if (write_to_stdout) { -- if (isatty(1)) { -- fprintf (stderr,_("Will not write an image to the terminal!\n")); -- return 1; -- } --#if defined(WIN32) || defined(DJGPP) || defined(__CYGWIN__) -- if (setmode(1,O_BINARY) < 0) { -- perror ("setmode()"); -- return 1; -- } --#endif -- } -- for ( ; arg < argc; arg++) { -- status = 1; -- raw_image = 0; -- image = 0; -- oprof = 0; -- meta_data = ofname = 0; -- ofp = stdout; -- if (setjmp (failure)) { -- if (fileno(ifp) > 2) fclose(ifp); -- if (fileno(ofp) > 2) fclose(ofp); -- status = 1; -- goto cleanup; -- } -- ifname = argv[arg]; -- if (!(ifp = fopen (ifname, "rb"))) { -- perror (ifname); -- continue; -- } -- status = (identify(),!is_raw); -- if (user_flip >= 0) -- flip = user_flip; -- switch ((flip+3600) % 360) { -- case 270: flip = 5; break; -- case 180: flip = 3; break; -- case 90: flip = 6; -- } -- if (timestamp_only) { -- if ((status = !timestamp)) -- fprintf (stderr,_("%s has no timestamp.\n"), ifname); -- else if (identify_only) -- printf ("%10ld%10d %s\n", (long) timestamp, shot_order, ifname); -- else { -- if (verbose) -- fprintf (stderr,_("%s time set to %d.\n"), ifname, (int) timestamp); -- ut.actime = ut.modtime = timestamp; -- utime (ifname, &ut); -- } -- goto next; -- } -- write_fun = &CLASS write_ppm_tiff; -- if (thumbnail_only) { -- if ((status = !thumb_offset)) { -- fprintf (stderr,_("%s has no thumbnail.\n"), ifname); -- goto next; -- } else if (thumb_load_raw) { -- load_raw = thumb_load_raw; -- data_offset = thumb_offset; -- height = thumb_height; -- width = thumb_width; -- filters = 0; -- colors = 3; -- } else { -- fseek (ifp, thumb_offset, SEEK_SET); -- write_fun = write_thumb; -- goto thumbnail; -- } -- } -- if (load_raw == &CLASS kodak_ycbcr_load_raw) { -- height += height & 1; -- width += width & 1; -- } -- if (identify_only && verbose && make[0]) { -- printf (_("\nFilename: %s\n"), ifname); -- printf (_("Timestamp: %s"), ctime(×tamp)); -- printf (_("Camera: %s %s\n"), make, model); -- if (artist[0]) -- printf (_("Owner: %s\n"), artist); -- if (dng_version) { -- printf (_("DNG Version: ")); -- for (i=24; i >= 0; i -= 8) -- printf ("%d%c", dng_version >> i & 255, i ? '.':'\n'); -- } -- printf (_("ISO speed: %d\n"), (int) iso_speed); -- printf (_("Shutter: ")); -- if (shutter > 0 && shutter < 1) -- shutter = (printf ("1/"), 1 / shutter); -- printf (_("%0.1f sec\n"), shutter); -- printf (_("Aperture: f/%0.1f\n"), aperture); -- printf (_("Focal length: %0.1f mm\n"), focal_len); -- printf (_("Embedded ICC profile: %s\n"), profile_length ? _("yes"):_("no")); -- printf (_("Number of raw images: %d\n"), is_raw); -- if (pixel_aspect != 1) -- printf (_("Pixel Aspect Ratio: %0.6f\n"), pixel_aspect); -- if (thumb_offset) -- printf (_("Thumb size: %4d x %d\n"), thumb_width, thumb_height); -- printf (_("Full size: %4d x %d\n"), raw_width, raw_height); -- } else if (!is_raw) -- fprintf (stderr,_("Cannot decode file %s\n"), ifname); -- if (!is_raw) goto next; -- shrink = filters && (half_size || (!identify_only && -- (threshold || aber[0] != 1 || aber[2] != 1))); -- iheight = (height + shrink) >> shrink; -- iwidth = (width + shrink) >> shrink; -- if (identify_only) { -- if (verbose) { -- if (document_mode == 3) { -- top_margin = left_margin = fuji_width = 0; -- height = raw_height; -- width = raw_width; -- } -- iheight = (height + shrink) >> shrink; -- iwidth = (width + shrink) >> shrink; -- if (use_fuji_rotate) { -- if (fuji_width) { -- fuji_width = (fuji_width - 1 + shrink) >> shrink; -- iwidth = fuji_width / sqrt(0.5); -- iheight = (iheight - fuji_width) / sqrt(0.5); -- } else { -- if (pixel_aspect < 1) iheight = iheight / pixel_aspect + 0.5; -- if (pixel_aspect > 1) iwidth = iwidth * pixel_aspect + 0.5; -- } -- } -- if (flip & 4) -- SWAP(iheight,iwidth); -- printf (_("Image size: %4d x %d\n"), width, height); -- printf (_("Output size: %4d x %d\n"), iwidth, iheight); -- printf (_("Raw colors: %d"), colors); -- if (filters) { -- int fhigh = 2, fwide = 2; -- if ((filters ^ (filters >> 8)) & 0xff) fhigh = 4; -- if ((filters ^ (filters >> 16)) & 0xffff) fhigh = 8; -- if (filters == 1) fhigh = fwide = 16; -- if (filters == 9) fhigh = fwide = 6; -- printf (_("\nFilter pattern: ")); -- for (i=0; i < fhigh; i++) -- for (c = i && putchar('/') && 0; c < fwide; c++) -- putchar (cdesc[fcol(i,c)]); -- } -- printf (_("\nDaylight multipliers:")); -- FORCC printf (" %f", pre_mul[c]); -- if (cam_mul[0] > 0) { -- printf (_("\nCamera multipliers:")); -- FORC4 printf (" %f", cam_mul[c]); -- } -- putchar ('\n'); -- } else -- printf (_("%s is a %s %s image.\n"), ifname, make, model); --next: -- fclose(ifp); -- continue; -- } -- if (meta_length) { -- meta_data = (char *) malloc (meta_length); -- merror (meta_data, "main()"); -- } -- if (filters || colors == 1) { -- raw_image = (ushort *) calloc ((raw_height+7), raw_width*2); -- merror (raw_image, "main()"); -- } else { -- image = (ushort (*)[4]) calloc (iheight, iwidth*sizeof *image); -- merror (image, "main()"); -- } -- if (verbose) -- fprintf (stderr,_("Loading %s %s image from %s ...\n"), -- make, model, ifname); -- if (shot_select >= is_raw) -- fprintf (stderr,_("%s: \"-s %d\" requests a nonexistent image!\n"), -- ifname, shot_select); -- fseeko (ifp, data_offset, SEEK_SET); -- if (raw_image && read_from_stdin) -- fread (raw_image, 2, raw_height*raw_width, stdin); -- else (*load_raw)(); -- if (document_mode == 3) { -- top_margin = left_margin = fuji_width = 0; -- height = raw_height; -- width = raw_width; -- } -- iheight = (height + shrink) >> shrink; -- iwidth = (width + shrink) >> shrink; -- if (raw_image) { -- image = (ushort (*)[4]) calloc (iheight, iwidth*sizeof *image); -- merror (image, "main()"); -- crop_masked_pixels(); -- free (raw_image); -- } -- if (zero_is_bad) remove_zeroes(); -- bad_pixels (bpfile); -- if (dark_frame) subtract (dark_frame); -- quality = 2 + !fuji_width; -- if (user_qual >= 0) quality = user_qual; -- i = cblack[3]; -- FORC3 if (i > cblack[c]) i = cblack[c]; -- FORC4 cblack[c] -= i; -- black += i; -- i = cblack[6]; -- FORC (cblack[4] * cblack[5]) -- if (i > cblack[6+c]) i = cblack[6+c]; -- FORC (cblack[4] * cblack[5]) -- cblack[6+c] -= i; -- black += i; -- if (user_black >= 0) black = user_black; -- FORC4 cblack[c] += black; -- if (user_sat > 0) maximum = user_sat; --#ifdef COLORCHECK -- colorcheck(); --#endif -- if (is_foveon) { -- if (document_mode || load_raw == &CLASS foveon_dp_load_raw) { -- for (i=0; i < height*width*4; i++) -- if ((short) image[0][i] < 0) image[0][i] = 0; -- } else foveon_interpolate(); -- } else if (document_mode < 2) -- scale_colors(); -- pre_interpolate(); -- if (filters && !document_mode) { -- if (quality == 0) -- lin_interpolate(); -- else if (quality == 1 || colors > 3) -- vng_interpolate(); -- else if (quality == 2 && filters > 1000) -- ppg_interpolate(); -- else if (filters == 9) -- xtrans_interpolate (quality*2-3); -- else -- ahd_interpolate(); -- } -- if (mix_green) -- for (colors=3, i=0; i < height*width; i++) -- image[i][1] = (image[i][1] + image[i][3]) >> 1; -- if (!is_foveon && colors == 3) median_filter(); -- if (!is_foveon && highlight == 2) blend_highlights(); -- if (!is_foveon && highlight > 2) recover_highlights(); -- if (use_fuji_rotate) fuji_rotate(); --#ifndef NO_LCMS -- if (cam_profile) apply_profile (cam_profile, out_profile); --#endif -- convert_to_rgb(); -- if (use_fuji_rotate) stretch(); --thumbnail: -- if (write_fun == &CLASS jpeg_thumb) -- write_ext = ".jpg"; -- else if (output_tiff && write_fun == &CLASS write_ppm_tiff) -- write_ext = ".tiff"; -- else -- write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5; -- ofname = (char *) malloc (strlen(ifname) + 64); -- merror (ofname, "main()"); -- if (write_to_stdout) -- strcpy (ofname,_("standard output")); -- else { -- strcpy (ofname, ifname); -- if ((cp = strrchr (ofname, '.'))) *cp = 0; -- if (multi_out) -- sprintf (ofname+strlen(ofname), "_%0*d", -- snprintf(0,0,"%d",is_raw-1), shot_select); -- if (thumbnail_only) -- strcat (ofname, ".thumb"); -- strcat (ofname, write_ext); -- ofp = fopen (ofname, "wb"); -- if (!ofp) { -- status = 1; -- perror (ofname); -- goto cleanup; -- } -- } -- if (verbose) -- fprintf (stderr,_("Writing data to %s ...\n"), ofname); -- (*write_fun)(); -- fclose(ifp); -- if (ofp != stdout) fclose(ofp); --cleanup: -- if (meta_data) free (meta_data); -- if (ofname) free (ofname); -- if (oprof) free (oprof); -- if (image) free (image); -- if (multi_out) { -- if (++shot_select < is_raw) arg--; -- else shot_select = 0; -- } -- } -- return status; --} -+/* RT: Delete from here */ -+/*RT*/#undef SQR -+/*RT*/#undef MAX -+/*RT*/#undef MIN -+/*RT*/#undef ABS -+/*RT*/#undef LIM -+/*RT*/#undef ULIM -+/*RT*/#undef CLIP diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 88397d6ee..482b64a55 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -434,7 +434,7 @@ void Crop::update (int todo) Imagefloat *origCropPart = new Imagefloat (crW, crH);//allocate memory Imagefloat *provicalc = new Imagefloat ((crW + 1) / 2, (crH + 1) / 2); //for denoise curves - int coordW[3];//coordonate of part of image to mesure noise + int coordW[3];//coordinate of part of image to measure noise int coordH[3]; int begW = 50; int begH = 50; @@ -507,7 +507,7 @@ void Crop::update (int todo) float multip = 1.f; if (!parent->imgsrc->isRAW()) { - multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good for gamma=1 } float adjustr = 1.f; @@ -1037,7 +1037,7 @@ void Crop::update (int todo) dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, skip, execsharp, dd, dj, 1); } } else { - // CIECAM is disbaled, we free up its image buffer to save some space + // CIECAM is disabled, we free up its image buffer to save some space if (cieCrop) { delete cieCrop; } diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index a8d31f0ac..96b8ddc59 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -136,7 +136,7 @@ void dfInfo::updateRawImage() if( !pathNames.empty() ) { std::list::iterator iName = pathNames.begin(); - ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. ) + ri = new RawImage(*iName); // First file used also for extra pixels information (width,height, shutter, filters etc.. ) if( ri->loadRaw(true)) { delete ri; @@ -363,7 +363,7 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool) } RawImage ri(filename); - int res = ri.loadRaw(false); // Read informations about shot + int res = ri.loadRaw(false); // Read information about shot if (res != 0) { return nullptr; diff --git a/rtengine/diagonalcurves.cc b/rtengine/diagonalcurves.cc index 3f885782c..a3b00b165 100644 --- a/rtengine/diagonalcurves.cc +++ b/rtengine/diagonalcurves.cc @@ -35,11 +35,11 @@ DiagonalCurve::DiagonalCurve (const std::vector& p, int poly_pn) ppn = poly_pn > 65500 ? 65500 : poly_pn; if (ppn < 500) { - hashSize = 100; // Arbitrary cut-off value, but mutliple of 10 + hashSize = 100; // Arbitrary cut-off value, but multiple of 10 } if (ppn < 50) { - hashSize = 10; // Arbitrary cut-off value, but mutliple of 10 + hashSize = 10; // Arbitrary cut-off value, but multiple of 10 } if (p.size() < 3) { diff --git a/rtengine/ex1simple.cc b/rtengine/ex1simple.cc index 0768a97e7..921ee6e44 100644 --- a/rtengine/ex1simple.cc +++ b/rtengine/ex1simple.cc @@ -77,7 +77,7 @@ int main (int argc, char* argv[]) rtengine::procparams::ProcParams params; params.load (argv[2]); - /* First, simplest scenario. Develope image and save it in a file */ + /* First, simplest scenario. Develop image and save it in a file */ // create a processing job with the loaded image and the current processing parameters rtengine::ProcessingJob* job = ProcessingJob::create (i, params); // process image. The error is given back in errorcode. diff --git a/rtengine/fast_demo.cc b/rtengine/fast_demo.cc index 900ff2119..cab38b1f2 100644 --- a/rtengine/fast_demo.cc +++ b/rtengine/fast_demo.cc @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////// // -// Fast demosaicing algorythm +// Fast demosaicing algorithm // // copyright (c) 2008-2010 Emil Martinec // diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index 028b8a79a..82aa709b7 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -130,7 +130,7 @@ void ffInfo::updateRawImage() // this may not be necessary, as flatfield is further blurred before being applied to the processed image. if( !pathNames.empty() ) { std::list::iterator iName = pathNames.begin(); - ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. ) + ri = new RawImage(*iName); // First file used also for extra pixels information (width, height, shutter, filters etc.. ) if( ri->loadRaw(true)) { delete ri; ri = nullptr; @@ -318,7 +318,7 @@ ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool) } RawImage ri(filename); - int res = ri.loadRaw(false); // Read informations about shot + int res = ri.loadRaw(false); // Read information about shot if (res != 0) { return nullptr; diff --git a/rtengine/image16.cc b/rtengine/image16.cc index 1c023d181..997d7d992 100644 --- a/rtengine/image16.cc +++ b/rtengine/image16.cc @@ -330,7 +330,7 @@ Image16::tofloat() return imgfloat; } -// // Parallized transformation; create transform with cmsFLAGS_NOCACHE! +// // Parallelized transformation; create transform with cmsFLAGS_NOCACHE! // void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy) // { // // LittleCMS cannot parallelize planar Lab float images diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 5fb1e98f6..eb213a8ea 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -207,7 +207,7 @@ FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* // Focus distance from EXIF or XMP. MakerNote ones are scattered and partly encrypted int num = -3, denom = -3; - // First try, offical EXIF. Set by Adobe on some DNGs + // First try, official EXIF. Set by Adobe on some DNGs tag = exif->getTag("SubjectDistance"); if (tag) { diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index 0352c0b10..3b211d15e 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -534,7 +534,7 @@ void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform) } } -// Parallized transformation; create transform with cmsFLAGS_NOCACHE! +// Parallelized transformation; create transform with cmsFLAGS_NOCACHE! void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy) { // LittleCMS cannot parallelize planar Lab float images diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index 4ea09aaf2..bebebbd2d 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -789,7 +789,7 @@ int ImageIO::loadTIFF (Glib::ustring fname) * effective minimum and maximum values */ if (options.rtSettings.verbose) { - printf("Informations of \"%s\":\n", fname.c_str()); + printf("Information of \"%s\":\n", fname.c_str()); uint16 tiffDefaultScale, tiffBaselineExposure, tiffLinearResponseLimit; if (TIFFGetField(in, TIFFTAG_DEFAULTSCALE, &tiffDefaultScale)) { printf(" DefaultScale: %d\n", tiffDefaultScale); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index b35b9f661..ff1bd7b3a 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -359,7 +359,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) calclum->b(ii>>1,jj>>1) = orig_prev->b(ii,jj); } } - imgsrc->convertColorSpace(calclum, params.icm, currWB);//claculate values after colorspace conversion + imgsrc->convertColorSpace(calclum, params.icm, currWB);//calculate values after colorspace conversion } int kall=1; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index e7ff01f46..74d73f382 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -723,7 +723,7 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int pW, int pwb, L hist16Q[CLIP ((int) (32768.f * sqrt ((koef * (lab->L[i][j])) / 32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L } - sum += koef * lab->L[i][j]; //evaluate mean J to calcualte Yb + sum += koef * lab->L[i][j]; //evaluate mean J to calculate Yb } //mean=(sum/((endh-begh)*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone @@ -885,7 +885,7 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int pW, int pwb, L c_ = c; f_l = fl; - // we cannot have all algoritms with all chroma curves + // we cannot have all algorithms with all chroma curves if (alg == 1) { // Lightness saturation if (Jpro > 99.9f) { @@ -1063,7 +1063,7 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int pW, int pwb, L t1L = true; } else if (curveMode == ColorAppearanceParams::TcMode::BRIGHT) { - //attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algoritms will be different + //attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algorithms will be different float coef = ((aw + 4.f) * (4.f / c)) / 100.f; float Qanc = Qpro; float Qq = (float) Qpro * 327.68f * (1.f / coef); @@ -2467,7 +2467,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int pW, int pw Jpro = 1.f; } } else if (curveMode == ColorAppearanceParams::TcMode::BRIGHT) { - //attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algoritms will be different + //attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algorithms will be different float coef = ((aw + 4.f) * (4.f / c)) / 100.f; float Qanc = Qpro; float Qq = (float) Qpro * 327.68f * (1.f / coef); @@ -2905,7 +2905,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int pW, int pw -//all this treatments reduce artefacts, but can leed to slighty different results +//all this treatments reduce artifacts, but can lead to slighty different results if (params->defringe.enabled) if (execsharp) { @@ -3996,7 +3996,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer valparam *= (1.f - SQR (SQR (1.f - min (s, 1.0f)))); if (valparam > 0.00001f) { - v = (1.f - valparam) * v + valparam * (1.f - SQR (1.f - min (v, 1.0f))); // SQR (SQR to increase action and avoid artefacts + v = (1.f - valparam) * v + valparam * (1.f - SQR (1.f - min (v, 1.0f))); // SQR (SQR to increase action and avoid artifacts if (v < 0) { v = 0; @@ -4137,7 +4137,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float b = btemp[ti * TS + tj]; float ro, go, bo; labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip); - rtemp[ti * TS + tj] = CLIP (ro); //I used CLIP because there is a little bug in gamutLchonly that return 65536.ii intead of 65535 ==> crash + rtemp[ti * TS + tj] = CLIP (ro); //I used CLIP because there is a little bug in gamutLchonly that return 65536.ii instead of 65535 ==> crash gtemp[ti * TS + tj] = CLIP (go); btemp[ti * TS + tj] = CLIP (bo); } @@ -4286,7 +4286,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer #endif } - } else if (algm == 1) { //Luminance mixer in Lab mode to avoid artefacts + } else if (algm == 1) { //Luminance mixer in Lab mode to avoid artifacts for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { //rgb => xyz @@ -4682,7 +4682,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer const float lumbefore = 0.299f * r + 0.587f * g + 0.114f * b; - if (lumbefore < 65000.f && lumbefore > 500.f) { //reduce artefacts for highlights and extreme shadows + if (lumbefore < 65000.f && lumbefore > 500.f) { //reduce artifacts for highlights and extreme shadows float ro, go, bo; toningsmh(r, g, b, ro, go, bo, RedLow, GreenLow, BlueLow, RedMed, GreenMed, BlueMed, RedHigh, GreenHigh, BlueHigh, reducac, mode, strProtect); @@ -5230,7 +5230,7 @@ void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &g const float lumbefore = 0.299f * r + 0.587f * g + 0.114f * b; const float v = max(r, g, b) / 65535.f; - const float rlo = strProtect; //0.5 ==> 0.75 transfered value for more action + const float rlo = strProtect; //0.5 ==> 0.75 transferred value for more action const float rlh = 2.2f * strProtect; //low tones @@ -5785,7 +5785,7 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW Lprov1 = l_r * 100.f; float Chprov2 = sqrt (SQR (atmp) + SQR (btmp)) / 327.68f; - //Gamut control especialy fot negative values slightly different of gamutlchonly + //Gamut control especially for negative values slightly different from gamutlchonly bool inRGB; do { @@ -6412,7 +6412,7 @@ void ImProcFunctions::EPDToneMapCIE (CieImage *ncie, float a_w, float c_, int Wi for (int i=heir; iQ_p[i][j];} - if(minQ>0.0) minQ=0.0;//normaly minQ always > 0... + if(minQ>0.0) minQ=0.0;//normally minQ always > 0... // EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei); //EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei/2); for(i = N2; i != N; i++) @@ -6787,7 +6787,7 @@ void ImProcFunctions::getAutoExp (const LUTu &histogram, int histcompr, double gavg /= sum; if (black < gavg) { - int maxwhiteclip = (gavg - black) * 4 / 3 + black; // dont let whiteclip be such large that the histogram average goes above 3/4 + int maxwhiteclip = (gavg - black) * 4 / 3 + black; // don't let whiteclip be such large that the histogram average goes above 3/4 if (whiteclipg < maxwhiteclip) { whiteclipg = maxwhiteclip; @@ -6833,7 +6833,7 @@ void ImProcFunctions::getAutoExp (const LUTu &histogram, int histcompr, double gavg += histogram[i] * CurveFactory::gamma2((int)(corr*(i<sharpenEdge.enabled) { return; @@ -574,7 +574,7 @@ void ImProcFunctions::MLmicrocontrast(float** luminance, int W, int H) const int width = W, height = H; const float uniform = params->sharpenMicro.uniformity; //between 0 to 100 const int unif = (int)(uniform / 10.0f); //put unif between 0 to 10 - float amount = params->sharpenMicro.amount / 1500.0f; //amount 2000.0 quasi no artefacts ==> 1500 = maximum, after artefacts + float amount = params->sharpenMicro.amount / 1500.0f; //amount 2000.0 quasi no artifacts ==> 1500 = maximum, after artifacts if (amount < 0.000001f) { return; diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 4ffe9c9af..ad4a169b6 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -1875,7 +1875,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * // I was inspired by the principle of Canny and Lipschitz (continuity and derivability) // I adapted the principle but have profoundly changed the algorithm // One can 1) change all parameters and found good parameters; - //one can also chnage in calckoe + //one can also change in calckoe float edd = 3.f; float eddlow = 15.f; float eddlipinfl = 0.005f * cp.edgsens + 0.4f; @@ -1920,7 +1920,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * float interm = 0.f; if(cp.lip3 && cp.lipp) { - // comparaison between pixel and neighbours + // comparison between pixel and neighbours const auto neigh = cp.neigh == 1; const auto kneigh = neigh ? 28.f : 38.f; const auto somm = neigh ? 40.f : 50.f; @@ -1987,7 +1987,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * kampli = AmpLip / aamp; } - // comparaison betwwen pixel and neighbours to do ==> I think 3 dir above is better + // comparison betwwen pixel and neighbours to do ==> I think 3 dir above is better /* if(cp.lip3){ koeLi[lvl*3][i*W_L + j] = (koeLi[lvl*3][i*W_L + j] + koeLi[lvl*3][(i-1)*W_L + j] + koeLi[lvl*3][(i+1)*W_L + j] + koeLi[lvl*3][i*W_L + j+1] + koeLi[lvl*3][i*W_L + j-1] + koeLi[lvl*3][(i-1)*W_L + j-1] diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 64b7fea15..c69592991 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -3491,7 +3491,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group ("Exposure")) { if (ppVersion < PPVERSION_AEXP) { - toneCurve.autoexp = false; // prevent execution of autoexp when opening file created with earlier verions of autoexp algorithm + toneCurve.autoexp = false; // prevent execution of autoexp when opening file created with earlier versions of autoexp algorithm } else { assignFromKeyfile(keyFile, "Exposure", "Auto", pedited, toneCurve.autoexp, pedited->toneCurve.autoexp); } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 14cf00581..b885629bc 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1487,7 +1487,7 @@ private: * saving too) * * PartialProfile is not responsible of ProcParams and ParamsEdited object creation - * and hence is not responsible of their destructions. The function that instanciate + * and hence is not responsible of their destructions. The function that instantiate * PartialProfile object has to handle all this itself. */ class PartialProfile : diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 04066d49f..8a86a7a1e 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1698,7 +1698,7 @@ int RawImageSource::load (const Glib::ustring &fname) } - // Load complete Exif informations + // Load complete Exif information std::unique_ptr rml(new RawMetaDataLocation (ri->get_exifBase(), ri->get_ciffBase(), ri->get_ciffLen())); idata = new FramesData (fname, std::move(rml)); idata->setDCRawFrameCount (numFrames); diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 22b05d91f..846366cee 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -399,8 +399,8 @@ class StagedImageProcessor { public: - /** Returns the inital image corresponding to the image processor. - * @return the inital image corresponding to the image processor */ + /** Returns the initial image corresponding to the image processor. + * @return the initial image corresponding to the image processor */ virtual InitialImage* getInitialImage () = 0; /** Returns the current processing parameters. * @param dst is the location where the image processing parameters are copied (it is assumed that the memory is allocated by the caller) */ @@ -501,7 +501,7 @@ int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDi /** Cleanup the RT engine (static variables) */ void cleanup (); -/** This class holds all the necessary informations to accomplish the full processing of the image */ +/** This class holds all the necessary information to accomplish the full processing of the image */ class ProcessingJob { @@ -526,7 +526,7 @@ public: static ProcessingJob* create (InitialImage* initialImage, const procparams::ProcParams& pparams, bool fast = false); /** Cancels and destroys a processing job. The reference count of the corresponding initialImage (if any) is decreased. After the call of this function the ProcessingJob instance - * gets invalid, you must not use it any more. Dont call this function while the job is being processed. + * gets invalid, you must not use it any more. Don't call this function while the job is being processed. * @param job is the job to destroy */ static void destroy (ProcessingJob* job); @@ -536,7 +536,7 @@ public: /** This function performs all the image processinf steps corresponding to the given ProcessingJob. It returns when it is ready, so it can be slow. * The ProcessingJob passed becomes invalid, you can not use it any more. * @param job the ProcessingJob to cancel. - * @param errorCode is the error code if an error occured (e.g. the input image could not be loaded etc.) + * @param errorCode is the error code if an error occurred (e.g. the input image could not be loaded etc.) * @param pl is an optional ProgressListener if you want to keep track of the progress * @return the resulting image, with the output profile applied, exif and iptc data set. You have to save it or you can access the pixel data directly. */ IImagefloat* processImage (ProcessingJob* job, int& errorCode, ProgressListener* pl = nullptr, bool flush = false); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 06e811420..9b6b4596f 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -386,7 +386,7 @@ private: } if (!imgsrc->isRAW()) { - multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good for gamma=1 } float maxmax = max (maxredaut, maxblueaut); @@ -537,7 +537,7 @@ private: float gam, gamthresh, gamslope; ipf.RGB_denoise_infoGamCurve (params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); int Nb[9]; - int coordW[3];//coordonate of part of image to mesure noise + int coordW[3];//coordinate of part of image to measure noise int coordH[3]; int begW = 50; int begH = 50; @@ -629,7 +629,7 @@ private: } if (!imgsrc->isRAW()) { - multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good for gamma=1 } float delta[9]; diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index b2721b2b7..dfdeb56b5 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -153,7 +153,7 @@ void downSample (const Array2Df& A, Array2Df& B) const int height = B.getRows(); // Note, I've uncommented all omp directives. They are all ok but are - // applied to too small problems and in total don't lead to noticable + // applied to too small problems and in total don't lead to noticeable // speed improvements. The main issue is the pde solver and in case of the // fft solver uses optimised threaded fftw routines. //#pragma omp parallel for @@ -293,7 +293,7 @@ float calculateGradients (Array2Df* H, Array2Df* G, int k, bool multithread) gx = ((*H) (w, y) - (*H) (e, y)); gy = ((*H) (x, s) - (*H) (x, n)); - // note this implicitely assumes that H(-1)=H(0) + // note this implicitly assumes that H(-1)=H(0) // for the fft-pde slover this would need adjustment as H(-1)=H(1) // is assumed, which means gx=0.0, gy=0.0 at the boundaries // however, the impact is not visible so we ignore this here diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 453f9b78f..b7ba5ff1d 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -78,7 +78,7 @@ struct TIFFHeader { class Tag; class Interpreter; -/// Structure of informations describing an Exif tag +/// Structure of information describing an Exif tag struct TagAttrib { int ignore; // =0: never ignore, =1: always ignore, =2: ignore if the subdir type is reduced image, =-1: end of table ActionCode action; diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index ba07f6f4d..6dfa9ad9c 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -192,7 +192,7 @@ void BatchQueuePanel::init (RTWindow *parent) saveFormatPanel->init (options.saveFormatBatch); } -// it is expected to have a non null forceOrientation value on Preferences update only. In this case, qsize is ingored and computed automatically +// it is expected to have a non null forceOrientation value on Preferences update only. In this case, qsize is ignored and computed automatically void BatchQueuePanel::updateTab (int qsize, int forceOrientation) { Gtk::Notebook *nb = (Gtk::Notebook *)(this->get_parent()); diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 8f2663b0b..d3c3fb4c6 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -390,7 +390,7 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G } // If only a single item is selected, we emulate the behaviour of the editor tool panel coordinator, - // otherwise we adjust the inital parameters on a per-image basis. + // otherwise we adjust the initial parameters on a per-image basis. if (selected.size() == 1) { // Compensate rotation on flip if (event == rtengine::EvCTHFlip || event == rtengine::EvCTVFlip) { diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 52675d77b..71541cdb8 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -29,7 +29,7 @@ class CacheImageData: public rtengine::FramesMetaData public: - // basic informations + // basic information Glib::ustring md5; Glib::ustring version; bool supported; diff --git a/rtgui/edit.h b/rtgui/edit.h index eeeca694d..c6878c54a 100644 --- a/rtgui/edit.h +++ b/rtgui/edit.h @@ -148,7 +148,7 @@ class EditSubscriber; * * When the Edit process stops, the Subscriber is removed from the DataProvider, so buffers can be freed up. * A new ToolPanelListener::panelChanged event is also thrown to update the preview again, without the tool's - * graphical objects. The Edit button is also toggled off (by the user or programatically). + * graphical objects. The Edit button is also toggled off (by the user or programmatically). * * It means that each Edit buttons toggled on will start an update of the preview which might or might not create * a new History entry, depending on the ProcEvent used. diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index a2088b9e2..33411b6a7 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -674,7 +674,7 @@ void FileCatalog::_refreshProgressBar () // Also mention that this progress bar only measures the FIRST pass (quick thumbnails) // The second, usually longer pass is done multithreaded down in the single entries and is NOT measured by this if (!inTabMode) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected Gtk::Notebook *nb = (Gtk::Notebook *)(filepanel->get_parent()); Gtk::Grid* grid = Gtk::manage (new Gtk::Grid ()); @@ -790,7 +790,7 @@ void FileCatalog::previewsFinishedUI () { { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected redrawAll (); previewsToLoad = 0; @@ -872,7 +872,7 @@ void FileCatalog::refreshHeight () { int newHeight = fileBrowser->getEffectiveHeight(); - if (newHeight < 5) { // This may occure if there's no thumbnail. + if (newHeight < 5) { // This may occur if there's no thumbnail. int w, h; get_size_request(w, h); newHeight = h; diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index b3e3668c5..40e9440f6 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -411,7 +411,7 @@ bool FilePanel::handleShortcutKey (GdkEventKey* event) void FilePanel::loadingThumbs(Glib::ustring str, double rate) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected if( !str.empty()) { parent->setProgressStr(str); diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h index d54f5f75a..b8389d1c9 100644 --- a/rtgui/filepanel.h +++ b/rtgui/filepanel.h @@ -58,7 +58,7 @@ public: { parent = p; } - void init (); // dont call it directly, the constructor calls it as idle source + void init (); // don't call it directly, the constructor calls it as idle source void on_realize (); void setAspect(); void open (const Glib::ustring& d); // open a file or a directory diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index 49ce25b60..5160ccedd 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -336,7 +336,7 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int } } else if (cparams.guide == "ePassport") { /* Official measurements do not specify exact ratios, just min/max measurements within which the eyes and chin-crown distance must lie. I averaged those measurements to produce these guides. - * The first horizontal guide is for the crown, the second is rougly for the nostrils, the third is for the chin. + * The first horizontal guide is for the crown, the second is roughly for the nostrils, the third is for the chin. * http://www.homeoffice.gov.uk/agencies-public-bodies/ips/passports/information-photographers/ * "(...) the measurement of the face from the bottom of the chin to the crown (ie the top of the head, not the top of the hair) is between 29mm and 34mm." */ diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index c713b51a8..a41786d4e 100644 --- a/rtgui/histogrampanel.cc +++ b/rtgui/histogrampanel.cc @@ -483,7 +483,7 @@ void HistogramRGBArea::updateBackBuffer (int r, int g, int b, const Glib::ustrin } // Mostly not necessary, but should be in some case - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected Glib::RefPtr window = get_window(); int winx, winy, winw, winh; diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 052cb1455..df26678d9 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -272,7 +272,7 @@ void LensProfilePanel::setRawMeta(bool raw, const rtengine::FramesMetaData* pMet if (!raw || pMeta->getFocusDist() <= 0) { disableListener(); - // CA is very focus layer dependend, otherwise it might even worsen things + // CA is very focus layer dependent, otherwise it might even worsen things allowFocusDep = false; ckbUseCA->set_active(false); ckbUseCA->set_sensitive(false); diff --git a/rtgui/lwbutton.cc b/rtgui/lwbutton.cc index acc0cd734..4998a302e 100644 --- a/rtgui/lwbutton.cc +++ b/rtgui/lwbutton.cc @@ -178,7 +178,7 @@ bool LWButton::releaseNotify (int x, int y) void LWButton::redraw (Cairo::RefPtr context) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected context->set_line_width (1.0); context->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); context->rectangle (xpos + 0.5, ypos + 0.5, w - 1.0, h - 1.0); diff --git a/rtgui/mydiagonalcurve.cc b/rtgui/mydiagonalcurve.cc index d249d4439..e7874dad2 100644 --- a/rtgui/mydiagonalcurve.cc +++ b/rtgui/mydiagonalcurve.cc @@ -1280,7 +1280,7 @@ void MyDiagonalCurve::pipetteDrag(EditDataProvider *provider, int modifierKey) void MyDiagonalCurve::getCursorPositionFromCurve(float x) { - // the graph is refreshed only if a new point is created (snaped to a pixel) + // the graph is refreshed only if a new point is created (snapped to a pixel) clampedX = x; clampedY = point.getVal01(x); @@ -1292,7 +1292,7 @@ void MyDiagonalCurve::getCursorPositionFromCurve(float x) void MyDiagonalCurve::getCursorPositionFromCurve(int x) { - // the graph is refreshed only if a new point is created (snaped to a pixel) + // the graph is refreshed only if a new point is created (snapped to a pixel) cursorX = x - graphX; clampedX = (float(cursorX) - 1.5) / float(graphW - 3); clampedY = point.getVal01(clampedX); diff --git a/rtgui/options.cc b/rtgui/options.cc index 0d227b6eb..60ac9a74e 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -556,7 +556,7 @@ void Options::setDefaults () rtSettings.verbose = false; rtSettings.gamutICC = true; rtSettings.gamutLch = true; - rtSettings.amchroma = 40;//between 20 and 140 low values increase effect..and also artefacts, high values reduces + rtSettings.amchroma = 40;//between 20 and 140 low values increase effect..and also artifacts, high values reduces rtSettings.artifact_cbdl = 4.; rtSettings.level0_cbdl = 0; rtSettings.level123_cbdl = 30; diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index 1eb54d68b..a3fcef20a 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -25,7 +25,7 @@ 321 2014-08-17 [Film Simulation] new tool using HALDCLUT files 320 2014-07-02 (yes, same version number... this is an error due to a wrong version number set in comment of previous change) - New [RAW Bayer] and [RAW X-Trans] sections, with some parameters transfered from [RAW] to [RAW Bayer] + New [RAW Bayer] and [RAW X-Trans] sections, with some parameters transferred from [RAW] to [RAW Bayer] 320 2014-03-29 [ColorToning] new tool for color toning 319 2014-02-11 diff --git a/rtgui/soundman.cc b/rtgui/soundman.cc index ff562d030..62c7d59b6 100644 --- a/rtgui/soundman.cc +++ b/rtgui/soundman.cc @@ -40,7 +40,7 @@ void SoundManager::init() // Unfortunately MinGW does not support this yet. If audioclient.h is available, add an Init // called once on program start. // - // This mitigation plays an empty file on start, so RT is immidiately avaible in the Windows mixer at least + // This mitigation plays an empty file on start, so RT is immediately available in the Windows mixer at least playSoundAsync(Glib::ustring("sounds\\Empty.wav")); #endif } diff --git a/rtgui/splash.cc b/rtgui/splash.cc index 576692690..9e0cc2015 100644 --- a/rtgui/splash.cc +++ b/rtgui/splash.cc @@ -116,7 +116,7 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t nb->append_page (*splashImage, M("ABOUT_TAB_SPLASH")); splashImage->show (); - // Tab 2: the informations about the current version + // Tab 2: the information about the current version std::string buildFileName = Glib::build_filename (creditsPath, "AboutThisBuild.txt"); if ( Glib::file_test(buildFileName, (Glib::FILE_TEST_EXISTS)) ) { diff --git a/rtgui/thumbimageupdater.cc b/rtgui/thumbimageupdater.cc index 533967b72..696c68811 100644 --- a/rtgui/thumbimageupdater.cc +++ b/rtgui/thumbimageupdater.cc @@ -208,7 +208,7 @@ ThumbImageUpdater::add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, } // create a new job and append to queue - DEBUG("queing job %s", tbe->shortname.c_str()); + DEBUG("queueing job %s", tbe->shortname.c_str()); impl_->jobs_.push_back(Impl::Job(tbe, priority, upgrade, l)); DEBUG("adding run request %s", tbe->shortname.c_str()); diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index 07822f857..b0bd8334d 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -803,7 +803,7 @@ void ToneCurve::enableAll () bool ToneCurve::autoExpComputed_ () { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected disableListener (); enableAll (); expcomp->setValue (nextExpcomp); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 4b3a7fae1..a88feff7d 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -845,7 +845,7 @@ bool ToolPanelCoordinator::handleShortcutKey (GdkEventKey* event) void ToolPanelCoordinator::updateVScrollbars (bool hide) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected Gtk::PolicyType policy = hide ? Gtk::POLICY_NEVER : Gtk::POLICY_AUTOMATIC; exposurePanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); detailsPanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); @@ -861,7 +861,7 @@ void ToolPanelCoordinator::updateVScrollbars (bool hide) void ToolPanelCoordinator::updateTabsHeader (bool useIcons) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected TOITypes type = useIcons ? TOI_ICON : TOI_TEXT; toiE->switchTo (type); @@ -887,7 +887,7 @@ void ToolPanelCoordinator::updateTabsUsesIcons (bool useIcons) void ToolPanelCoordinator::toolSelected (ToolMode tool) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected switch (tool) { case TMCropSelect: diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 160abf07e..b24bfa207 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -890,7 +890,7 @@ void Wavelet::wavChanged (double nlevel) nextnlevel = nlevel; const auto func = [](gpointer data) -> gboolean { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected static_cast(data)->wavComputed_(); return FALSE; diff --git a/tools/RTProfileBuilderSample.cs b/tools/RTProfileBuilderSample.cs index 81b724ab2..4b1b2bff0 100644 --- a/tools/RTProfileBuilderSample.cs +++ b/tools/RTProfileBuilderSample.cs @@ -115,7 +115,7 @@ namespace RTProfilerBuilder { } // end if camera=xxx - // This is for camera independend settings + // This is for camera independent settings switch (sectionEntry) { // These are parsed from EXIFTOOL and XMP in DNG (see http://en.wikipedia.org/wiki/Extensible_Metadata_Platform) case "IPTC/City": @@ -262,7 +262,7 @@ namespace RTProfilerBuilder { /// Correction factors public DistortionCorrectProf(double[] focLen, double[] correct) { if (focLen == null || correct == null || focLen.Length != correct.Length || focLen.Length < 2) - throw new Exception("DistortionCorrectProf inputs must be valid and of the same lenghts, at least 2 points"); + throw new Exception("DistortionCorrectProf inputs must be valid and of the same lengths, at least 2 points"); adFocLen = focLen; adCorrect = correct; diff --git a/tools/benchmarkRT b/tools/benchmarkRT index fbe27ebc8..57d78a52b 100755 --- a/tools/benchmarkRT +++ b/tools/benchmarkRT @@ -31,7 +31,7 @@ download () { wget --progress=dot:binary --continue --trust-server-names --tries=1 --timestamping "$1" 2>&1 | sed "s/^/\t/" return=${PIPESTATUS[0]} ((retries--)) - if [[ $return -eq 0 ]]; then # I don't trust wget to only exit with 0 if it downloaded the file succesfully, so I check. + if [[ $return -eq 0 ]]; then # I don't trust wget to only exit with 0 if it downloaded the file successfully, so I check. if [[ -f "$(basename "$1")" ]]; then break fi @@ -145,7 +145,7 @@ if [[ ${inFile} = http* ]]; then # if inFile is a url and if we haven't download echo } else # otherwise if inFile is not a url, check if it exists - [[ ! -e "${inFile}" ]] && { # if it doesnt exist, choke + [[ ! -e "${inFile}" ]] && { # if it doesn't exist, choke printf "%s\n" "You specified" "-i ${inFile}" "but that file does not exist." exit 1 } @@ -242,7 +242,7 @@ for s in "${!sidecarFinal[@]}"; do ## t="$(( $RANDOM %20 )).$(( $RANDOM %999 ))" # benchmark stores time array of each run, gets reset after each PP3 benchmark+=("$t") - # total stores time array of each run, doesnt get reset, adds up total afterwards + # total stores time array of each run, doesn't get reset, adds up total afterwards total+=("$t") i="$(printf "%02d\n" "$i")" if [[ $testAllTools -eq 1 ]]; then diff --git a/tools/win/readme.txt b/tools/win/readme.txt index b20bf104a..d0633e348 100644 --- a/tools/win/readme.txt +++ b/tools/win/readme.txt @@ -8,7 +8,7 @@ As requested in issue 1904 ( http://code.google.com/p/rawtherapee/issues/detail? the preferred choice of setup mechanism is Wix widgets. However an InnoSetup script has been created before the definitive choice and has been added to the source tree, for convenience. -Once the Wix setup mechanism will be operational, the InnoSetup can be supressed from the source +Once the Wix setup mechanism will be operational, the InnoSetup can be suppressed from the source tree. All discussion about the present document and the setup scripts has to be done in issue 1904. \ No newline at end of file