diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 5f3adf267..a2683041c 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -138,19 +138,14 @@ CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_) } CameraConst * -CameraConst::parseEntry(void *cJSON_) +CameraConst::parseEntry(void *cJSON_, const char *make_model) { CameraConst *cc = 0; cJSON *js, *ji, *jranges; js = (cJSON *)cJSON_; - ji = cJSON_GetObjectItem(js, "make_model"); - if (!ji || ji->type != cJSON_String) { - fprintf(stderr, "missing \"make_model\" object item\n"); - goto parse_error; - } cc = new CameraConst; - cc->make_model = Glib::ustring(ji->valuestring); + cc->make_model = Glib::ustring(make_model); ji = cJSON_GetObjectItem(js, "dcraw_matrix"); if (ji) { @@ -285,7 +280,7 @@ CameraConst::get_Levels(struct camera_const_levels & lvl, int bw, int iso, float } lvl = it->second; - if (fnumber > 0 && mApertureScaling.size() > 0) { + if (bw == 1 && fnumber > 0 && mApertureScaling.size() > 0) { std::map::iterator it; it = mApertureScaling.find(fnumber); if (it == mApertureScaling.end()) { @@ -343,11 +338,11 @@ CameraConst::get_Levels(struct camera_const_levels & lvl, int bw, int iso, float } int -CameraConst::get_BlackLevel(const int idx, const int iso_speed, const float fnumber) +CameraConst::get_BlackLevel(const int idx, const int iso_speed) { assert(idx >= 0 && idx <= 3); struct camera_const_levels lvl; - if (!get_Levels(lvl, 0, iso_speed, fnumber)) { + if (!get_Levels(lvl, 0, iso_speed, 0.0)) { return -1; } return lvl.levels[idx]; @@ -424,29 +419,44 @@ CameraConstantsStore::parse_camera_constants_file(Glib::ustring filename_) } for (js = js->child; js != NULL; js = js->next) { cJSON *ji = cJSON_GetObjectItem(js, "make_model"); - if (!ji || ji->type != cJSON_String) { + if (!ji) { fprintf(stderr, "missing \"make_model\" object item\n"); goto parse_error; } - CameraConst *cc = CameraConst::parseEntry((void *)js); - if (!cc) { - goto parse_error; + bool is_array = false; + if (ji->type == cJSON_Array) { + ji = ji->child; + is_array = true; } + while (ji != NULL) { + if (ji->type != cJSON_String) { + fprintf(stderr, "\"make_model\" must be a string or an array of strings\n"); + goto parse_error; + } + CameraConst *cc = CameraConst::parseEntry((void *)js, ji->valuestring); + if (!cc) { + goto parse_error; + } + Glib::ustring make_model(ji->valuestring); + std::map::iterator existingccIter = mCameraConstants.find(make_model); - Glib::ustring make_model(ji->valuestring); - std::map::iterator existingccIter = mCameraConstants.find(make_model); + if (existingccIter == mCameraConstants.end()) + // add the new CamConst to the map + mCameraConstants.insert(std::pair(make_model, cc)); + else { + // The CameraConst already exist for this camera make/model -> we merge the values + CameraConst *existingcc = existingccIter->second; - if (existingccIter == mCameraConstants.end()) - // add the new CamConst to the map - mCameraConstants.insert(std::pair(make_model, cc)); - else { - // The CameraConst already exist for this camera make/model -> we merge the values - CameraConst *existingcc = existingccIter->second; - - // updating the dcraw matrix - existingcc->update_dcrawMatrix(cc->get_dcrawMatrix()); - // deleting all the existing levels, replaced by the new ones - existingcc->update_Levels(cc); + // updating the dcraw matrix + existingcc->update_dcrawMatrix(cc->get_dcrawMatrix()); + // deleting all the existing levels, replaced by the new ones + existingcc->update_Levels(cc); + } + if (is_array) { + ji = ji->next; + } else { + ji = NULL; + } } } cJSON_Delete(jsroot); diff --git a/rtengine/camconst.h b/rtengine/camconst.h index e98dbdac7..c26ff99f8 100644 --- a/rtengine/camconst.h +++ b/rtengine/camconst.h @@ -28,11 +28,11 @@ class CameraConst { bool get_Levels(struct camera_const_levels & lvl, int bw, int iso, float fnumber); public: - static CameraConst *parseEntry(void *cJSON); + static CameraConst *parseEntry(void *cJSON, const char *make_model); bool has_dcrawMatrix(void); void update_dcrawMatrix(const short *other); const short *get_dcrawMatrix(void); - int get_BlackLevel(int idx, int iso_speed, float fnumber); + int get_BlackLevel(int idx, int iso_speed); int get_WhiteLevel(int idx, int iso_speed, float fnumber); void update_Levels(const CameraConst *other); }; diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 9c0d538f1..aa2e3c370 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -95,25 +95,43 @@ white level constant is too high. You can fix this by adjusting the measuring and providing a more exact white level in camconst.json so RawTherapee gets to know from start where the camera actually clips. -Here's a guide how to do it. +Providing a complete and detailed white-level profile can be a quite large +and complicated effort. As an alternative you can provide a simpler profile. +We suggest one of the following alternatives in rising difficulty (and +generally diminishing return): + +A) Provide a single white-level value measured on the native ISO (base ISO). + For many cameras this will actually be complete information, those that + don't vary on channel, ISO or aperture. +B) Check through all ISOs and if there are differences in white level provide + an array with white level per ISO. +C) In addition to ISO, check for aperture scaling and add that. +D) In addition to ISO and aperture scaling check for color channel + differences and add that. + +Doing A) is often better than nothing, as dcraw's default is often too high. +B) can also be worthwhile for some cameras (or else you'll get pink highlights +for some ISOs), while C) and D) can generally be seen as fine-tuning. + +Here follows a guide how to measure white levels (clipping levels): Shoot with your camera into a bright light source, such as a lamp, and make sure the shutter speed is long enough to get overexposure (we want -clipping!). Some cameras have fuzzy white levels and may look less fuzzy with -strong over-exposure (most samples are then pushed to some hard raw limit), if -you measure such a camera you'd want to over-expose softly (ie one-two stops or -so) so you can more correctly see where the camera stops providing sane -information. +clipping!). Preferably overexpose lightly, say 1 or 2 stops if you can. The +reason for this is that some cameras with fuzzy white levels may look less +fuzzy than they actually are if over-exposure is heavy. Use f/5.6 or smaller aperture (=larger f-number) to avoid any raw scaling -the camera might have for large apertures. Open the file in a raw analyzer -such as Rawdigger and check the pixel values for the clipped areas (if you -are using Rawdigger, make sure you have disabled "subtract black" in -preferences or else sample values can be wrong). In this stage we always look -at white level before black level subtraction! White levels can be different on -color channel (R, G1, B, G2, note the two greens, most often both green -channels have the same white level though) and vary depending on ISO setting, -so make one shoot for each ISO (even 1/3 steps, so yes it can be quite a lot of +the camera might have for large apertures. + +Open the file in a raw analyzer such as Rawdigger and check the pixel values +for the clipped areas (if you are using Rawdigger, make sure you have disabled +"subtract black" in preferences or else sample values can be wrong). In this +stage we always look at white level before black level subtraction! White +levels can be different on color channel (R, G1, B, G2, note the two greens, +most often both green channels have the same white level though) and vary +depending on ISO setting, so if you want to provide a complete profile make +one shoot for each ISO (even 1/3 steps, so yes it can be quite a lot of pictures to shoot and check). In addition, many cameras scale the raw values for large apertures. It's @@ -126,14 +144,15 @@ have ISO scaling you need to shoot at these different ISOs to detect any differences in scaling, there can be a bit of variation. If you don't have access to the widest lens available for the system (say only an f/1.8 lens instead of an f/1.2) it can still be valuable to have the values down to -what you can provide. +what you can provide. Brands known to have models that have aperture scaling +include Canon, Nikon and Sony. PROVIDE CONSERVATIVE VALUES. Most cameras have a little noise at the white level, and some can have a lot. In your raw analyzer, move around and look at the values in the clipped areas to get a sense of the variation, and/or look -at the histogram. White it's common to have very little variation, say only -+/-2 units, some can have +/-500 or more. There can also be camera-to-camera -variation. +at the histogram. While it's common to with very little variation, say only ++/-2 units, some can have +/-500 or more (some may have different variation +depending on ISO). There can also be camera-to-camera variation. If the white level is set too high RawTherapee will not think the pixels are clipped and you can get discoloured highlights (usually pink), this is what @@ -142,8 +161,8 @@ you lose a little highlight detail, but the color is rendered correctly and highlight reconstruction can work properly, so this is not as bad. This is why we want conservative values. -By conservative values we mean that if you see a clipping level of most often -15760 and occassionally 15759 (ie very small variation of clipping level which +By conservative values we mean that if you see a white level of most often +15760 and occassionally 15759 (ie very small variation of white level which is a common case), you set the white level 10 - 20 units below, say at 15750 in this example, this way we get a little margin from noise and camera variation. Since sensor raw values are linear you lose in this example log2(1-10/15760) = @@ -154,18 +173,18 @@ properly. If you have a fuzzy white level look at the linear histogram; you will probably see a normal/gaussian distribution (bell shape) noise peak at clipping and -probably also a peak at a hard raw data clip level usually at a power of -two - 1, such as 4095 or 16383. Then you pick a value just before the bell -shape rises, ie to the left of the bell meaning that you cut away the whole -fuzzy noise peak. If a little of the starting edge of the noise will be +probably also a peak at a hard raw data clip level usually at or close to a +power of two - 1, such as 4095 or 16383. Then you pick a value just before the +bell shape rises, ie to the left of the bell meaning that you cut away the +whole fuzzy noise peak. If a little of the starting edge of the noise will be included it's not harmful, but 99% of it should be above. If you have used Adobe's DNG Converter and analyzed it's output you may have noticed that it's very conservative regarding white levels, ie it cuts away quite a lot from the top. While we also recommend to be conservative, you can -generally be a little bit less conservative than Adobe's DNG Converter. -RawTherapee is meant to max out what you can get from your camera, and the -white levels should (within reason) mirror that. +generally be a little bit less so than Adobe's DNG Converter. RawTherapee is +meant to max out what you can get from your camera, and the white levels should +mirror that, within reason. The aperture scaling feature is meant to raise the white level to not miss out on highlight detail when the camera has scaled the raw values (and thus @@ -179,35 +198,41 @@ for example the Canon 5D mark II maxes out at 16383 which happens at f/1.8 for ISOs with the white level at 15750, but for ISO160 when the white level is 12800 it does not max out. If there is such a raw limit it must also be provided ("ranges":"white_max"). Usually you will not need a margin on -white_max as it clipping is a result of an in-camera math operation. +white_max as it clips there as a result of an in-camera math operation. Note that aperture scaling can be quite small, for the 5D mark II it's only 0.1 stop down to f/1.4 and then it can be discussed if it's worthwhile to care. The "worst" cameras scale about 0.6 stops though, and then it's more -valuable to compensate. If you skip aperture scaling you will clip too early -and miss that highlight detail, but you get no processing problems. Setting -unconservative scale factors can on the other hand cause a too high -whitelevel and break highlight processing, so be careful. Scaling can vary -sligthly depending on ISO (if white levels vary) so make sure to provide -conservative scalings so regardless of ISO you don't get a too high white -level. We recommend to keep a wider margin here than on the white levels, -ie 0.5-1% lower or so. For example if base (conservative!) white level is -15750 and the scaled is 16221 we have a scaling factor of 16221/15750=1.0299 -ie +2.9% we set the factor to 1.02 or +2% to keep a margin. +valuable to compensate. If you skip aperture scaling RawTherapee will clip the +files a little bit too early and you miss that last fraction of highlight +detail, but you get no processing problems. Setting unconservative scale +factors can on the other hand cause a too high whitelevel and break highlight +processing, so be careful. -Scaling takes place on the raw values before black level subtraction, and if -a black level constant is provided also that will be scaled. +Scaling can vary sligthly depending on ISO (if white levels vary) so make +sure to provide conservative scalings so regardless of ISO you don't get a +too high white level. We recommend to keep a wider margin here than on the +white levels, ie 0.5-1% lower or so. For example if base (conservative!) +white level is 15750 and the scaled is 16221 we have a scaling factor of +16221/15750=1.0299 ie +2.9% we set the factor to 1.02 or +2% to keep a +margin. + +The scale factor you provide here is applied on the white level before black +level subtraction (if any), ie directly on the white level value you provide in +the camconst.json file. Black level (if provided) is not scaled. Please report +to us if you come across a camera which scales black levels, then we can add +that as an option. Usually the camera applies an offset to shift back the +black level to the standard level after scaling. If RawTherapee doesn't find an entry for the aperture used in the image, it will pick the closest above. Ie if the apertures 1.0 and 2.0 is in the table and the image has aperture 1.2, it will pick scaling for 2.0, even if 1.0 is the closer aperture. The reason for always checking the closest above is that -we rather get a bit low white level than too high, as discussed before. +we rather get a bit too low white level than too high, as discussed before. -Some cameras have different white levels on different color channels. Note -that some cameras with different white levels per color have so small -differences that you may just provide a single value instead, then pick -the lowest white level and make a conservative margin as always. +Some cameras have different white levels on different color channels. When +this is the case the difference is often so small so you can just provide a +single value instead, ie a conservative value based on the lowest clipping. */ {"camera_constants": [ @@ -258,6 +283,52 @@ the lowest white level and make a conservative margin as always. ] } }, + { + "make_model": "Canon EOS 5D Mark III", + "dcraw_matrix": [ 6722,-635,-963,-4287,12460,2028,-908,2162,5668 ], + "ranges": { + // black levels are read from raw masked pixels + // white levels are same for all colors, but vary on ISO + "white": [ + { "iso": 50, "levels": 15270 }, // typical: 15282 + { "iso": 100, "levels": 15270 }, + { "iso": 125, "levels": 15270 }, + { "iso": 160, "levels": 13300 }, // typical: 13306 + { "iso": 200, "levels": 15270 }, + { "iso": 250, "levels": 15270 }, + { "iso": 320, "levels": 13300 }, + { "iso": 400, "levels": 15270 }, + { "iso": 500, "levels": 15270 }, + { "iso": 640, "levels": 13300 }, + { "iso": 800, "levels": 15270 }, + { "iso": 1000, "levels": 15270 }, + { "iso": 1250, "levels": 13300 }, + { "iso": 1600, "levels": 15270 }, + { "iso": 2000, "levels": 15270 }, + { "iso": 2500, "levels": 13300 }, + { "iso": 3200, "levels": 15270 }, + { "iso": 4000, "levels": 15270 }, + { "iso": 5000, "levels": 13300 }, + { "iso": 6400, "levels": 15270 }, + { "iso": 8000, "levels": 15270 }, + { "iso": 10000, "levels": 13300 }, // no data, guessed + { "iso": 12800, "levels": 15270 }, + { "iso": 16000, "levels": 15270 }, + { "iso": 20000, "levels": 15270 }, + { "iso": 25600, "levels": 16300 }, + { "iso": 32000, "levels": 16300 }, + { "iso": 40000, "levels": 16300 }, + { "iso": 51200, "levels": 16300 }, + { "iso": 102400, "levels": 16300 } + ], + "white_max": 16383, + "aperture_scaling": [ + // limited scaling info available, please provide more + { "aperture": 2.0, "scale_factor": 1.024 }, + { "aperture": 2.8, "scale_factor": 1.010 } + ] + } + }, { "make_model": "Nikon D7000", @@ -270,24 +341,21 @@ the lowest white level and make a conservative margin as always. "ranges": { "white": [ 16370, 15760, 16370 ] } }, + { + "make_model": "Sony SLT-A77", + "dcraw_matrix": [ 5126,-830,-261,-4788,12196,2934,-948,1602,7068 ], // matrix provided by Colin Walker + // note: Sony ARW2 file format gets 14 bit values, not 12 bit like in dcraw 9.19 + "ranges": { "black": 512, "white": 16350 } + }, + { + "make_model": [ "Sony SLT-A99", "Sony SLT-A99V" ], + "dcraw_matrix": [ 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 ], + "ranges": { "black": 512, "white": 16350 } + }, + // Phase One: color matrices borrowed from Adobe DNG Converter, black/white levels tested on actual raw files { - "make_model": "Phase One P40+", - "dcraw_matrix": [ 8035,435,-962,-6001,13872,2320,-1159,3065,5434 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One IQ140", - "dcraw_matrix": [ 8035,435,-962,-6001,13872,2320,-1159,3065,5434 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One P65+", - "dcraw_matrix": [ 8035,435,-962,-6001,13872,2320,-1159,3065,5434 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One IQ160", + "make_model": [ "Phase One P40+", "Phase One IQ140", "Phase One P65+", "Phase One IQ160" ], "dcraw_matrix": [ 8035,435,-962,-6001,13872,2320,-1159,3065,5434 ], "ranges": { "black": 0, "white": 64400 } }, @@ -297,52 +365,22 @@ the lowest white level and make a conservative margin as always. "ranges": { "black": 0, "white": 64400 } }, { - "make_model": "Phase One P20", + "make_model": [ "Phase One P20", "Phase One P20+", "Phase One P25", "Phase One P25+" ], "dcraw_matrix": [ 2905,732,-237,-8135,16626,1476,-3038,4253,7517 ], "ranges": { "black": 0, "white": 64400 } }, { - "make_model": "Phase One P20+", - "dcraw_matrix": [ 2905,732,-237,-8135,16626,1476,-3038,4253,7517 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One P21", + "make_model": [ "Phase One P21", "Phase One P21+" ], "dcraw_matrix": [ 6516,-2050,-507,-8217,16703,1479,-3492,4741,8489 ], "ranges": { "black": 0, "white": 64400 } }, { - "make_model": "Phase One P21+", - "dcraw_matrix": [ 6516,-2050,-507,-8217,16703,1479,-3492,4741,8489 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One P25", - "dcraw_matrix": [ 2905,732,-237,-8135,16626,1476,-3038,4253,7517 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One P25+", - "dcraw_matrix": [ 2905,732,-237,-8135,16626,1476,-3038,4253,7517 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One P30", + "make_model": [ "Phase One P30", "Phase One P30+"], "dcraw_matrix": [ 4516,-244,-36,-7020,14976,2174,-3206,4670,7087 ], "ranges": { "black": 0, "white": 64400 } }, { - "make_model": "Phase One P30+", - "dcraw_matrix": [ 4516,-244,-36,-7020,14976,2174,-3206,4670,7087 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One 45", - "dcraw_matrix": [ 5053,-24,-117,-5685,14077,1703,-2619,4491,5850 ], - "ranges": { "black": 0, "white": 64400 } - }, - { - "make_model": "Phase One 45+", + "make_model": [ "Phase One 45", "Phase One 45+" ], "dcraw_matrix": [ 5053,-24,-117,-5685,14077,1703,-2619,4491,5850 ], "ranges": { "black": 0, "white": 64400 } }, diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 281bc0cec..e60607264 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -2408,7 +2408,8 @@ void CLASS sony_arw2_load_raw() ushort pix[16]; int row, col, val, max, min, imax, imin, sh, bit, i; - data = (uchar *) malloc (raw_width); + //data = (uchar *) malloc (raw_width); + data = (uchar *) malloc (raw_width + 1); // RT: added +1 to avoid buffer overrun merror (data, "sony_arw2_load_raw()"); for (row=0; row < height; row++) { fread (data, 1, raw_width, ifp); @@ -2427,11 +2428,12 @@ void CLASS sony_arw2_load_raw() 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. } void CLASS samsung_load_raw() @@ -4804,7 +4806,7 @@ void CLASS parse_mos (int offset) { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22", "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65", "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7", - "","","","","","","","","","","","","","","","","","AFi-II 12" }; + "AFi-II 7","","","Aptus-II 6","","","Aptus-II 10","Aptus-II 5","","","","","Aptus-II 10R","Aptus-II 8","","Aptus-II 12","","AFi-II 12" }; // RT: added missing model names float romm_cam[3][3]; fseek (ifp, offset, SEEK_SET); @@ -7018,6 +7020,9 @@ void CLASS adobe_coeff (const char *make, const char *model) } break; } + if (strcmp(make, "Sony") == 0 && table[i].black > 0 && table[i].black < 400) { // RT: arw2 scale fix + black <<= 2; + } { /* Check for RawTherapee table overrides and extensions */ int black_level, white_level; short trans[12]; diff --git a/rtengine/dcraw.patch b/rtengine/dcraw.patch index 0df5f24c3..bb020bc8a 100644 --- a/rtengine/dcraw.patch +++ b/rtengine/dcraw.patch @@ -1,1638 +1,1674 @@ ---- dcraw.c 2013-08-12 09:32:14.000000000 +0200 -+++ dcraw.cc 2013-10-09 21:07:43.000000000 +0200 -@@ -1,3 +1,15 @@ -+/*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 -+ - /* - dcraw.c -- Dave Coffin's raw photo decoder - Copyright 1997-2013 by Dave Coffin, dcoffin a cybercom o net -@@ -29,17 +41,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__) -@@ -98,87 +110,37 @@ - #define LONG_BIT (8 * sizeof (long)) - #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]; --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, cblack[4], 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]; --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; --} tiff_ifd[10]; -- --struct ph1 { -- int format, key_off, black, black_off, split_col, tag_21a; -- 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(x,0,65535) -+#define MIN(a,b) rtengine::min(a,static_cast(b)) -+#define MAX(a,b) rtengine::max(a,static_cast(b)) -+#define LIM(x,min,max) rtengine::LIM(x,static_cast(min),static_cast(max)) -+#define ULIM(x,y,z) rtengine::ULIM(x,static_cast(y),static_cast(z)) -+#define CLIP(x) rtengine::CLIP(x) - #define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } - - /* -@@ -250,10 +212,11 @@ - { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 }, - { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 }, - { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 }, -- { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } }; +--- dcraw.c 2013-08-12 09:32:14.000000000 +0200 ++++ dcraw.cc 2013-10-22 08:42:39.000000000 +0200 +@@ -1,3 +1,15 @@ ++/*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 ++ + /* + dcraw.c -- Dave Coffin's raw photo decoder + Copyright 1997-2013 by Dave Coffin, dcoffin a cybercom o net +@@ -29,17 +41,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__) +@@ -98,87 +110,37 @@ + #define LONG_BIT (8 * sizeof (long)) + #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]; +-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, cblack[4], 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]; +-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; +-} tiff_ifd[10]; +- +-struct ph1 { +- int format, key_off, black, black_off, split_col, tag_21a; +- 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(x,0,65535) ++#define MIN(a,b) rtengine::min(a,static_cast(b)) ++#define MAX(a,b) rtengine::max(a,static_cast(b)) ++#define LIM(x,min,max) rtengine::LIM(x,static_cast(min),static_cast(max)) ++#define ULIM(x,y,z) rtengine::ULIM(x,static_cast(y),static_cast(z)) ++#define CLIP(x) rtengine::CLIP(x) + #define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } + + /* +@@ -250,10 +212,11 @@ + { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 }, + { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 }, + { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 }, +- { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } }; + { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } }; - -- if (filters == 1) return filter[(row+top_margin)&15][(col+left_margin)&15]; + +- if (filters == 1) return filter[(row+top_margin)&15][(col+left_margin)&15]; + if (filters == 1) return filter[(row+top_margin)&15][(col+left_margin)&15]; - if (filters == 9) return xtrans[(row+top_margin+6)%6][(col+left_margin+6)%6]; + if (filters == 9) return xtrans[(row+top_margin+6)%6][(col+left_margin+6)%6]; ++ + return FC(row,col); + } + +@@ -296,6 +259,7 @@ + fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp)); + } + data_error++; ++/*RT*/ longjmp (failure, 1); + } + + ushort CLASS sget2 (uchar *s) +@@ -369,7 +333,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 canon_600_fixed_wb (int temp) +@@ -541,10 +505,10 @@ + return 0; + } + +-unsigned CLASS getbithuff (int nbits, ushort *huff) ++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; +@@ -1209,14 +1173,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() + { +@@ -1494,10 +1458,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) +@@ -1757,10 +1721,10 @@ + maximum = 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; +@@ -2049,11 +2013,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; +@@ -2373,10 +2337,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; +@@ -2445,7 +2408,8 @@ + ushort pix[16]; + int row, col, val, max, min, imax, imin, sh, bit, i; + +- data = (uchar *) malloc (raw_width); ++ //data = (uchar *) malloc (raw_width); ++ data = (uchar *) malloc (raw_width + 1); // RT: added +1 to avoid buffer overrun + merror (data, "sony_arw2_load_raw()"); + for (row=0; row < height; row++) { + fread (data, 1, raw_width, ifp); +@@ -2464,11 +2428,12 @@ + 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. + } + + void CLASS samsung_load_raw() +@@ -2690,7 +2655,7 @@ + + void CLASS foveon_decoder (unsigned size, unsigned code) + { +- static unsigned huff[1024]; ++/*RT static unsigned huff[1024];*/ + struct decode *cur; + int i, len; + +@@ -4002,240 +3967,9 @@ + image[row*width+col][c] = sum[c] / sum[c+4]; + } + } + - return FC(row,col); - } - -@@ -296,6 +259,7 @@ - fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp)); - } - data_error++; -+/*RT*/ longjmp (failure, 1); - } - - ushort CLASS sget2 (uchar *s) -@@ -369,7 +333,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 canon_600_fixed_wb (int temp) -@@ -541,10 +505,10 @@ - return 0; - } - --unsigned CLASS getbithuff (int nbits, ushort *huff) -+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; -@@ -1209,14 +1173,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() - { -@@ -1494,10 +1458,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) -@@ -1757,10 +1721,10 @@ - maximum = 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; -@@ -2049,11 +2013,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; -@@ -2373,10 +2337,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; -@@ -2690,7 +2653,7 @@ - - void CLASS foveon_decoder (unsigned size, unsigned code) - { -- static unsigned huff[1024]; -+/*RT static unsigned huff[1024];*/ - struct decode *cur; - int i, len; - -@@ -4002,240 +3965,9 @@ - image[row*width+col][c] = sum[c] / sum[c+4]; - } - } ++/* RT: delete interpolation functions */ + +-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]) + { +@@ -4496,112 +4230,7 @@ + } + #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() +@@ -4771,7 +4400,7 @@ + } + } + +-int CLASS parse_tiff_ifd (int base); ++/*RT int CLASS parse_tiff_ifd (int base);*/ + + void CLASS parse_makernote (int base, int uptag) + { +@@ -5177,7 +4806,7 @@ + { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22", + "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65", + "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7", +- "","","","","","","","","","","","","","","","","","AFi-II 12" }; ++ "AFi-II 7","","","Aptus-II 6","","","Aptus-II 10","Aptus-II 5","","","","","Aptus-II 10R","Aptus-II 8","","Aptus-II 12","","AFi-II 12" }; // RT: added missing model names + float romm_cam[3][3]; + + fseek (ifp, offset, SEEK_SET); +@@ -5284,8 +4913,8 @@ + } + } + +-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) + { +@@ -5299,7 +4928,7 @@ + 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; +@@ -5737,12 +5366,13 @@ + 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); ++// } + ifp = sfp; + free (buf); + } +@@ -5766,6 +5396,7 @@ + int CLASS parse_tiff (int base) + { + int doff; ++ /*RT*/ if (exif_base == -1) exif_base = base; + + fseek (ifp, base, SEEK_SET); + order = get2(); +@@ -5843,7 +5474,7 @@ + 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; ++ 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) && +@@ -5959,7 +5590,7 @@ + { + const char *file, *ext; + char *jname, *jfile, *jext; +- FILE *save=ifp; ++/*RT*/ IMFILE *save=ifp; + + ext = strrchr (ifname, '.'); + file = strrchr (ifname, '/'); +@@ -5981,13 +5612,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); +@@ -6330,7 +5962,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); + } +@@ -6582,7 +6218,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 } }, +@@ -7383,6 +7020,27 @@ + } + break; + } ++ if (strcmp(make, "Sony") == 0 && table[i].black > 0 && table[i].black < 400) { // RT: arw2 scale fix ++ black <<= 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 (trans[0]) { ++ for (j=0; j < 12; j++) { ++ cam_xyz[0][j] = trans[j] / 10000.0; ++ } ++ cam_xyz_coeff (cam_xyz); ++ } ++ } ++ } + } + + void CLASS simple_coeff (int index) +@@ -7682,13 +7340,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(); +@@ -7734,6 +7399,7 @@ + fseek (ifp, 100+28*(shot_select > 0), 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); +@@ -7839,15 +7505,18 @@ + if (make[0] == 0) parse_smal (0, flen); + if (make[0] == 0) { + parse_jpeg(0); +- if (!strncmp(model,"ov",2) && !fseek (ifp, -6404096, SEEK_END) && +- fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) { +- strcpy (make, "OmniVision"); +- data_offset = ftell(ifp) + 0x8000-32; +- width = raw_width; +- raw_width = 2611; +- load_raw = &CLASS nokia_load_raw; +- filters = 0x16161616; +- } else is_raw = 0; ++ //RT fix for the use of fseek below ++ if (!strncmp(model,"ov",2)) { ++ 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; ++ raw_width = 2611; ++ load_raw = &CLASS nokia_load_raw; ++ filters = 0x16161616; ++ } else is_raw = 0; ++ } + } + + for (i=0; i < sizeof corp / sizeof *corp; i++) +@@ -7878,7 +7547,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")) +@@ -8026,7 +7695,7 @@ + width -= 44; + } else if (!strcmp(model,"D3200") || + !strcmp(model,"D600") || +- !strncmp(model,"D800",4)) { ++ !strcmp(model,"D800") || !strcmp(model,"D800E") ) { + width -= 46; + } else if (!strcmp(model,"D4")) { + width -= 52; +@@ -8630,195 +8299,8 @@ + cmsCloseProfile (hInProfile); + } + #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 (*out_rgb[])[3] = +- { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb }; +- static const char *name[] = +- { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" }; +- 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 > 5; +- 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]; +- } +- if (verbose) +- fprintf (stderr, raw_color ? _("Building histograms...\n") : +- _("Converting to %s colorspace...\n"), name[output_color-1]); +- +- 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]; +- +- 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; +-} +- +-void CLASS stretch() +-{ +- ushort newdim, (*img)[4], *pix0, *pix1; +- int row, col, c; +- double rc, frac; +- +- 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; +- } +- 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; +-} + -+/* RT: delete interpolation functions */ - --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]) - { -@@ -4496,112 +4228,7 @@ - } - #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() -@@ -4771,7 +4398,7 @@ - } - } - --int CLASS parse_tiff_ifd (int base); -+/*RT int CLASS parse_tiff_ifd (int base);*/ - - void CLASS parse_makernote (int base, int uptag) - { -@@ -5284,8 +4911,8 @@ - } - } - --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) - { -@@ -5299,7 +4926,7 @@ - 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; -@@ -5737,12 +5364,13 @@ - 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); -+// } - ifp = sfp; - free (buf); - } -@@ -5766,6 +5394,7 @@ - int CLASS parse_tiff (int base) - { - int doff; -+ /*RT*/ if (exif_base == -1) exif_base = base; - - fseek (ifp, base, SEEK_SET); - order = get2(); -@@ -5843,7 +5472,7 @@ - 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; -+ 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) && -@@ -5959,7 +5588,7 @@ - { - const char *file, *ext; - char *jname, *jfile, *jext; -- FILE *save=ifp; -+/*RT*/ IMFILE *save=ifp; - - ext = strrchr (ifname, '.'); - file = strrchr (ifname, '/'); -@@ -5981,13 +5610,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); -@@ -6330,7 +5960,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); - } -@@ -6582,7 +6216,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 } }, -@@ -7383,6 +7018,24 @@ - } - break; - } -+ { /* 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 (trans[0]) { -+ for (j=0; j < 12; j++) { -+ cam_xyz[0][j] = trans[j] / 10000.0; -+ } -+ cam_xyz_coeff (cam_xyz); -+ } -+ } -+ } - } - - void CLASS simple_coeff (int index) -@@ -7682,13 +7335,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(); -@@ -7734,6 +7394,7 @@ - fseek (ifp, 100+28*(shot_select > 0), 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); -@@ -7839,15 +7500,18 @@ - if (make[0] == 0) parse_smal (0, flen); - if (make[0] == 0) { - parse_jpeg(0); -- if (!strncmp(model,"ov",2) && !fseek (ifp, -6404096, SEEK_END) && -- fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) { -- strcpy (make, "OmniVision"); -- data_offset = ftell(ifp) + 0x8000-32; -- width = raw_width; -- raw_width = 2611; -- load_raw = &CLASS nokia_load_raw; -- filters = 0x16161616; -- } else is_raw = 0; -+ //RT fix for the use of fseek below -+ if (!strncmp(model,"ov",2)) { -+ 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; -+ raw_width = 2611; -+ load_raw = &CLASS nokia_load_raw; -+ filters = 0x16161616; -+ } else is_raw = 0; -+ } - } - - for (i=0; i < sizeof corp / sizeof *corp; i++) -@@ -7878,7 +7542,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")) -@@ -8026,7 +7690,7 @@ - width -= 44; - } else if (!strcmp(model,"D3200") || - !strcmp(model,"D600") || -- !strncmp(model,"D800",4)) { -+ !strcmp(model,"D800") || !strcmp(model,"D800E") ) { - width -= 46; - } else if (!strcmp(model,"D4")) { - width -= 52; -@@ -8630,195 +8294,8 @@ - cmsCloseProfile (hInProfile); - } - #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 (*out_rgb[])[3] = -- { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb }; -- static const char *name[] = -- { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" }; -- 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 > 5; -- 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]; -- } -- if (verbose) -- fprintf (stderr, raw_color ? _("Building histograms...\n") : -- _("Converting to %s colorspace...\n"), name[output_color-1]); -- -- 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]; -- -- 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; --} -- --void CLASS stretch() --{ -- ushort newdim, (*img)[4], *pix0, *pix1; -- int row, col, c; -- double rc, frac; -- -- 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; -- } -- 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; --} -+ -+/* RT: removed unused functions */ - - struct tiff_tag { - ushort tag, type; -@@ -8841,584 +8318,12 @@ - unsigned gps[26]; - char desc[512], make[64], model[64], soft[32], date[20], artist[64]; - }; -+/* 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 - --void CLASS tiff_set (ushort *ntag, -- ushort tag, ushort type, int count, int val) --{ -- struct tiff_tag *tt; -- int c; -- -- tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; -- tt->tag = tag; -- tt->type = type; -- tt->count = count; -- if (type < 3 && count <= 4) -- FORC(4) tt->val.c[c] = val >> (c << 3); -- else if (type == 3 && count <= 2) -- FORC(2) tt->val.s[c] = val >> (c << 4); -- else tt->val.i = val; --} -- --#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; -- if (full) { -- tiff_set (&th->ntag, 254, 4, 1, 0); -- tiff_set (&th->ntag, 256, 4, 1, width); -- tiff_set (&th->ntag, 257, 4, 1, height); -- tiff_set (&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->ntag, 259, 3, 1, 1); -- tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1)); -- } -- tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc)); -- tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make)); -- tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model)); -- if (full) { -- if (oprof) psize = ntohl(oprof[0]); -- tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize); -- tiff_set (&th->ntag, 277, 3, 1, colors); -- tiff_set (&th->ntag, 278, 4, 1, height); -- tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8); -- } else -- tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0'); -- tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0])); -- tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2])); -- tiff_set (&th->ntag, 284, 3, 1, 1); -- tiff_set (&th->ntag, 296, 3, 1, 2); -- tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft)); -- tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date)); -- tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist)); -- tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif)); -- if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th); -- tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4])); -- tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6])); -- tiff_set (&th->nexif, 34855, 3, 1, iso_speed); -- tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8])); -- if (gpsdata[1]) { -- tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps)); -- tiff_set (&th->ngps, 0, 1, 4, 0x202); -- tiff_set (&th->ngps, 1, 2, 2, gpsdata[29]); -- tiff_set (&th->ngps, 2, 5, 3, TOFF(th->gps[0])); -- tiff_set (&th->ngps, 3, 2, 2, gpsdata[30]); -- tiff_set (&th->ngps, 4, 5, 3, TOFF(th->gps[6])); -- tiff_set (&th->ngps, 5, 1, 1, gpsdata[31]); -- tiff_set (&th->ngps, 6, 5, 1, TOFF(th->gps[18])); -- tiff_set (&th->ngps, 7, 5, 3, TOFF(th->gps[12])); -- tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20])); -- tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23])); -- memcpy (th->gps, gpsdata, sizeof th->gps); -- } -- 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); --} -- --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-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)")); --#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 = (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 (use_camera_matrix < 0) -- use_camera_matrix = use_camera_wb; -- 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; -- } 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) { -- printf (_("\nFilter pattern: ")); -- for (i=0; i < 16; i++) -- putchar (cdesc[fcol(i >> 1,i & 1)]); -- } -- 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 (use_camera_matrix && cmatrix[0][0] > 0.25) { -- memcpy (rgb_cam, cmatrix, sizeof cmatrix); -- raw_color = 0; -- } -- 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; -- 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: removed unused functions */ + + struct tiff_tag { + ushort tag, type; +@@ -8841,584 +8323,12 @@ + unsigned gps[26]; + char desc[512], make[64], model[64], soft[32], date[20], artist[64]; + }; ++/* 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 + +-void CLASS tiff_set (ushort *ntag, +- ushort tag, ushort type, int count, int val) +-{ +- struct tiff_tag *tt; +- int c; +- +- tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; +- tt->tag = tag; +- tt->type = type; +- tt->count = count; +- if (type < 3 && count <= 4) +- FORC(4) tt->val.c[c] = val >> (c << 3); +- else if (type == 3 && count <= 2) +- FORC(2) tt->val.s[c] = val >> (c << 4); +- else tt->val.i = val; +-} +- +-#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; +- if (full) { +- tiff_set (&th->ntag, 254, 4, 1, 0); +- tiff_set (&th->ntag, 256, 4, 1, width); +- tiff_set (&th->ntag, 257, 4, 1, height); +- tiff_set (&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->ntag, 259, 3, 1, 1); +- tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1)); +- } +- tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc)); +- tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make)); +- tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model)); +- if (full) { +- if (oprof) psize = ntohl(oprof[0]); +- tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize); +- tiff_set (&th->ntag, 277, 3, 1, colors); +- tiff_set (&th->ntag, 278, 4, 1, height); +- tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8); +- } else +- tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0'); +- tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0])); +- tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2])); +- tiff_set (&th->ntag, 284, 3, 1, 1); +- tiff_set (&th->ntag, 296, 3, 1, 2); +- tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft)); +- tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date)); +- tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist)); +- tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif)); +- if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th); +- tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4])); +- tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6])); +- tiff_set (&th->nexif, 34855, 3, 1, iso_speed); +- tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8])); +- if (gpsdata[1]) { +- tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps)); +- tiff_set (&th->ngps, 0, 1, 4, 0x202); +- tiff_set (&th->ngps, 1, 2, 2, gpsdata[29]); +- tiff_set (&th->ngps, 2, 5, 3, TOFF(th->gps[0])); +- tiff_set (&th->ngps, 3, 2, 2, gpsdata[30]); +- tiff_set (&th->ngps, 4, 5, 3, TOFF(th->gps[6])); +- tiff_set (&th->ngps, 5, 1, 1, gpsdata[31]); +- tiff_set (&th->ngps, 6, 5, 1, TOFF(th->gps[18])); +- tiff_set (&th->ngps, 7, 5, 3, TOFF(th->gps[12])); +- tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20])); +- tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23])); +- memcpy (th->gps, gpsdata, sizeof th->gps); +- } +- 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); +-} +- +-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-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)")); +-#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 = (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 (use_camera_matrix < 0) +- use_camera_matrix = use_camera_wb; +- 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; +- } 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) { +- printf (_("\nFilter pattern: ")); +- for (i=0; i < 16; i++) +- putchar (cdesc[fcol(i >> 1,i & 1)]); +- } +- 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 (use_camera_matrix && cmatrix[0][0] > 0.25) { +- memcpy (rgb_cam, cmatrix, sizeof cmatrix); +- raw_color = 0; +- } +- 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; +- 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; +-} diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index db1f7e08b..e5602de1d 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -242,7 +242,7 @@ int RawImage::loadRaw (bool loadData, bool closeFile) if (cc) { for (int i = 0; i < 4; i++) { if (RT_blacklevel_from_constant) { - black_c4[i] = cc->get_BlackLevel(i, iso_speed, aperture); + black_c4[i] = cc->get_BlackLevel(i, iso_speed); } // load 4 channel white level here, will be used if available if (RT_whitelevel_from_constant) { @@ -328,7 +328,7 @@ RawImage::get_thumbSwap() const bool DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int iso_speed, short trans[12], int *black_level, int *white_level) { - static const int dcraw_arw2_scaling_bugfix_shift = 0; // not yet enabled, should be 2 when enabled + static const int dcraw_arw2_scaling_bugfix_shift = 2; static const struct { const char *prefix; int black_level, white_level; // set to -1 for no change @@ -475,7 +475,7 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is rtengine::CameraConstantsStore* ccs = rtengine::CameraConstantsStore::getInstance(); rtengine::CameraConst *cc = ccs->get(make, model); if (cc) { - *black_level = cc->get_BlackLevel(0, iso_speed, aperture); + *black_level = cc->get_BlackLevel(0, iso_speed); *white_level = cc->get_WhiteLevel(0, iso_speed, aperture); if (cc->has_dcrawMatrix()) { const short *mx = cc->get_dcrawMatrix();