diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 537c4890a..3b023ca61 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -9197,15 +9197,21 @@ rtengine::Thumbnail* rtengine::Thumbnail::loadQuickFromRaw (const Glib::ustring& rml.ciffBase = ciff_base; rml.ciffLength = ciff_len; - char thumb_buffer[thumb_length]; + char *thumb_buffer malloc(thumb_length+64); // malloc instead of on the stack. + if ( thumb_buffer == NULL ) + { + printf("DCRAW: failed3\n"); + return NULL; + } fseek(ifp,thumb_offset,SEEK_SET); fread(thumb_buffer,1,thumb_length,ifp); fclose(ifp); rtengine::Thumbnail* tpp = rtengine::Thumbnail::loadFromMemory(thumb_buffer,thumb_length,w,h,fixwh); + free(thumb_buffer); if ( tpp == 0 ) { - printf("DCRAW: failed3\n"); + printf("DCRAW: failed4\n"); return NULL; } diff --git a/rtengine/dcraw.patch b/rtengine/dcraw.patch index fec902bbc..7d059f919 100644 --- a/rtengine/dcraw.patch +++ b/rtengine/dcraw.patch @@ -1,887 +1,857 @@ ---- dcraw.c 2010-10-25 09:45:14.000000000 -0400 -+++ dcraw.cc 2010-10-27 11:30:33.000000000 -0400 -@@ -1,3 +1,15 @@ -+/*RT*/#include -+/*RT*/#include -+/*RT*/#undef MAX -+/*RT*/#undef MIN -+/*RT*/#define NO_LCMS -+/*RT*/#define NO_JPEG -+/*RT*/#define LOCALTIME -+/*RT*/#define DJGPP -+/*RT*/#include -+ -+#include "myfile.h" -+ - /* - dcraw.c -- Dave Coffin's raw photo decoder - Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net -@@ -46,7 +58,9 @@ - NO_LCMS disables the "-p" option. - */ - #ifndef NO_JPEG --#include -+/*RT*/extern "C" { -+/*RT*/#include -+/*RT*/} - #endif - #ifndef NO_LCMS - #include -@@ -96,59 +110,70 @@ - typedef unsigned char uchar; - typedef unsigned short ushort; - -+// RT specify thread local storage -+#ifdef __GNUC__ -+#define THREAD_LOCAL static __thread -+#define THREAD_LOCK -+#else -+#define THREAD_LOCAL -+#define THREAD_LOCK Glib::Mutex::Lock locker(*dcrMutex); -+#endif -+ - /* - 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; --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; --unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; --off_t strip_offset, data_offset; --off_t thumb_offset, meta_offset, profile_offset; --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[8], 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; --ushort raw_height, raw_width, height, width, top_margin, left_margin; --ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; --int flip, tiff_flip, colors; --double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; --ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; --float bright=1, user_mul[4]={0,0,0,0}, threshold=0; --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 */ -+/*RT*/THREAD_LOCAL int ciff_base, ciff_len, exif_base, pre_filters; -+/*RT*/THREAD_LOCAL IMFILE *ifp; -+THREAD_LOCAL FILE * ofp; -+THREAD_LOCAL short order; -+THREAD_LOCAL const char *ifname; -+THREAD_LOCAL char *meta_data; -+THREAD_LOCAL char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64]; -+THREAD_LOCAL float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; -+THREAD_LOCAL time_t timestamp; -+THREAD_LOCAL unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; -+THREAD_LOCAL off_t strip_offset, data_offset; -+THREAD_LOCAL off_t thumb_offset, meta_offset, profile_offset; -+THREAD_LOCAL unsigned thumb_length, meta_length, profile_length; -+THREAD_LOCAL unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0; -+THREAD_LOCAL unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; -+THREAD_LOCAL unsigned black, cblack[8], maximum, mix_green, raw_color, zero_is_bad; -+THREAD_LOCAL unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; -+THREAD_LOCAL unsigned tile_width, tile_length, gpsdata[32], load_flags; -+THREAD_LOCAL ushort raw_height, raw_width, height, width, top_margin, left_margin; -+THREAD_LOCAL ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; -+THREAD_LOCAL int flip, tiff_flip, colors; -+THREAD_LOCAL double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; -+THREAD_LOCAL ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; -+THREAD_LOCAL float bright=1, user_mul[4]={0,0,0,0}, threshold=0; -+THREAD_LOCAL int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; -+THREAD_LOCAL int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1; -+THREAD_LOCAL int output_color=1, output_bps=8, output_tiff=0, med_passes=0; -+THREAD_LOCAL int no_auto_bright=0; -+THREAD_LOCAL unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; -+THREAD_LOCAL float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; -+static 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; -+static const float d65_white[3] = { 0.950456, 1, 1.088754 }; -+THREAD_LOCAL int histogram[4][0x2000]; -+THREAD_LOCAL void (*write_thumb)(), (*write_fun)(); -+THREAD_LOCAL void (*load_raw)(), (*thumb_load_raw)(); -+THREAD_LOCAL jmp_buf failure; - --struct decode { -+THREAD_LOCAL struct decode { - struct decode *branch[2]; - int leaf; - } first_decode[2048], *second_decode, *free_decode; - --struct tiff_ifd { -+THREAD_LOCAL struct tiff_ifd { - int width, height, bps, comp, phint, offset, flip, samples, bytes; - } tiff_ifd[10]; - --struct ph1 { -+THREAD_LOCAL struct ph1 { - int format, key_off, black, black_off, split_col, tag_21a; - float tag_210; - } ph1; -@@ -271,6 +296,7 @@ - fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp)); - } - data_error++; -+ /*RT*/ longjmp (failure, 1); - } - - ushort CLASS sget2 (uchar *s) -@@ -344,7 +370,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) -@@ -538,8 +564,8 @@ - */ - unsigned CLASS getbithuff (int nbits, ushort *huff) - { -- static unsigned bitbuf=0; -- static int vbits=0, reset=0; -+ THREAD_LOCAL unsigned bitbuf=0; -+ THREAD_LOCAL int vbits=0, reset=0; - unsigned c; - - if (nbits == -1) -@@ -1560,8 +1586,8 @@ - - unsigned CLASS ph1_bithuff (int nbits, ushort *huff) - { -- static UINT64 bitbuf=0; -- static int vbits=0; -+ THREAD_LOCAL UINT64 bitbuf=0; -+ THREAD_LOCAL int vbits=0; - unsigned c; - - if (nbits == -1) -@@ -1823,8 +1849,8 @@ - - unsigned CLASS pana_bits (int nbits) - { -- static uchar buf[0x4000]; -- static int vbits; -+ THREAD_LOCAL uchar buf[0x4000]; -+ THREAD_LOCAL int vbits; - int byte; - - if (!nbits) return vbits=0; -@@ -2113,11 +2139,11 @@ - METHODDEF(boolean) - fill_input_buffer (j_decompress_ptr cinfo) - { -- static uchar jpeg_buffer[4096]; -+ THREAD_LOCAL 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; -@@ -2391,7 +2417,7 @@ - - void CLASS sony_decrypt (unsigned *data, int len, int start, int key) - { -- static unsigned pad[128], p; -+ THREAD_LOCAL unsigned pad[128], p; - - if (start) { - for (p=0; p < 4; p++) -@@ -2638,7 +2664,7 @@ - - void CLASS foveon_decoder (unsigned size, unsigned code) - { -- static unsigned huff[1024]; -+ THREAD_LOCAL unsigned huff[1024]; - struct decode *cur; - int i, len; - -@@ -3765,6 +3791,7 @@ - for (row = FC(1,0) >> 1; row < height; row+=2) - for (col = FC(row,1) & 1; col < width; col+=2) - image[row*width+col][1] = image[row*width+col][3]; -+/*RT*/ pre_filters = filters; - filters &= ~((filters & 0x55555555) << 1); - } - } -@@ -4817,7 +4844,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; -@@ -5225,12 +5252,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); -+/*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); -- } -+// fclose (ifp); -+// } - ifp = sfp; - free (buf); - } -@@ -5256,6 +5284,8 @@ - int doff, max_samp=0, raw=-1, thm=-1, i; - struct jhead jh; - -+ /*RT*/ exif_base = base; -+ - fseek (ifp, base, SEEK_SET); - order = get2(); - if (order != 0x4949 && order != 0x4d4d) return; -@@ -5424,7 +5454,7 @@ - { - const char *file, *ext; - char *jname, *jfile, *jext; -- FILE *save=ifp; -+/*RT*/ IMFILE *save=ifp; - - ext = strrchr (ifname, '.'); - file = strrchr (ifname, '/'); -@@ -5452,7 +5482,8 @@ - *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); -@@ -5790,7 +5821,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); -+/*RT*/ } - parse_tiff (save+6); - fseek (ifp, save+len, SEEK_SET); - } -@@ -6738,6 +6773,12 @@ - fread (head, 1, 32, ifp); - fseek (ifp, 0, SEEK_END); - flen = fsize = ftell(ifp); -+ -+ /*RT*/ if (fsize<100000) { -+ is_raw = 0; -+ return; -+ } -+ - if ((cp = (char *) memmem (head, 32, "MMMM", 4)) || - (cp = (char *) memmem (head, 32, "IIII", 4))) { - parse_phase_one (cp-head); -@@ -6745,6 +6786,8 @@ - } 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); - } else { - parse_tiff(0); -@@ -6858,6 +6901,8 @@ - if (height == 3136 && width == 4736) /* Pentax K-7 */ - { height = 3122; width = 4684; - top_margin = 2; filters = 0x16161616; } -+ if (height == 2868 && width == 4352) /* Pentax K-x */ -+ width = 4308; - if (height == 3014 && width == 4096) /* Ricoh GX200 */ - width = 4014; - if (dng_version) { -@@ -7405,7 +7450,7 @@ - } else if (!strcmp(model,"K20D")) { - filters = 0x16161616; - } else if (!strcmp(model,"K-x")) { -- width = 4309; -+ width = 4308; - filters = 0x16161616; - } else if (!strcmp(model,"Optio S")) { - if (fsize == 3178560) { -@@ -8494,13 +8539,13 @@ - 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); -+ swab ((char*)ppm2, (char*)ppm2, width*colors*2); - fwrite (ppm, colors*output_bps/8, width, ofp); - } - free (ppm); - } - --int CLASS main (int argc, const char **argv) -+/*int CLASS main (int argc, const char **argv) - { - int arg, status=0; - int timestamp_only=0, thumbnail_only=0, identify_only=0; -@@ -8613,7 +8658,7 @@ - case 'i': identify_only = 1; break; - case 'c': write_to_stdout = 1; break; - case 'v': verbose = 1; break; -- case 'h': half_size = 1; /* "-h" implies "-f" */ -+ case 'h': half_size = 1; /* "-h" implies "-f" *//* - case 'f': four_color_rgb = 1; break; - case 'A': FORC4 greybox[c] = atoi(argv[arg++]); - case 'a': use_auto_wb = 1; break; -@@ -8877,3 +8922,526 @@ - } - return status; - } -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+namespace rtengine { -+ -+extern Settings* settings; -+ -+Glib::Mutex* dcrMutex=NULL; -+ -+int loadRaw (const char* fname, struct RawImage *ri) { -+ -+ 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 } }; -+ -+ THREAD_LOCK -+ -+ ifname = fname;//strdup (fname); -+ image = NULL; -+ -+ exif_base = -1; -+ ciff_base = -1; -+ ciff_len = -1; -+ verbose = settings->verbose; -+ oprof = NULL; -+ ri->data = NULL; -+ ri->allocation = NULL; -+ ri->profile_data = NULL; -+ ifp = gfopen (fname); -+ if (!ifp) { -+ return 3; -+ } -+ -+ use_camera_wb = 0; -+ highlight = 1; -+ half_size = 0; -+ -+ identify (); -+ use_camera_wb = 1; -+ if (!is_raw) { -+ fclose(ifp); -+ return 2; -+ } -+ -+ shrink = 0; -+ -+ if (settings->verbose) printf ("Loading %s %s image from %s...\n", make, model, fname); -+ iheight = height; -+ iwidth = width; -+ -+ image = (UshORt (*)[4])calloc (height*width*sizeof *image + meta_length, 1); -+ meta_data = (char *) (image + height*width); -+ -+ if (setjmp (failure)) { -+ if (image) -+ free (image); -+ if (ri->data) -+ free(ri->data); -+ fclose (ifp); -+ return 100; -+ } -+ -+ fseek (ifp, data_offset, SEEK_SET); -+ (*load_raw)(); -+ -+ ri->profile_len = 0; -+ ri->profile_data = NULL; -+ if (profile_length) { -+ ri->profile_len = profile_length; -+ ri->profile_data = (char *) malloc (profile_length); -+ fseek (ifp, profile_offset, SEEK_SET); -+ fread (ri->profile_data, 1, profile_length, ifp); -+ } -+ -+ fclose(ifp); -+ if (zero_is_bad) remove_zeroes(); -+ -+ ri->red_multiplier = pre_mul[0]; -+ ri->green_multiplier = pre_mul[1]; -+ ri->blue_multiplier = pre_mul[2]; -+ -+ scale_colors(); -+ pre_interpolate (); -+ -+ ri->width = width; -+ ri->height = height; -+ ri->filters = filters; -+ -+ if (filters) { -+ ri->allocation = (short unsigned int*)calloc(height*width, sizeof(unsigned short)); -+ ri->data = (unsigned short**)calloc(height, sizeof(unsigned short*)); -+ for (int i=0; idata[i] = ri->allocation + i*width; -+ for (int row = 0; row < height; row++) -+ for (int col = 0; col < width; col++) -+ if (ISGREEN(ri,row,col)) -+ ri->data[row][col] = image[row*width+col][1]; -+ else if (ISRED(ri,row,col)) -+ ri->data[row][col] = image[row*width+col][0]; -+ else -+ ri->data[row][col] = image[row*width+col][2]; -+ } -+ else { -+ ri->allocation = (short unsigned int*)calloc(3*height*width, sizeof(unsigned short)); -+ ri->data = (unsigned short**)calloc(height, sizeof(unsigned short*)); -+ for (int i=0; idata[i] = ri->allocation + 3*i*width; -+ for (int row = 0; row < height; row++) -+ for (int col = 0; col < width; col++) { -+ ri->data[row][3*col+0] = image[row*width+col][0]; -+ ri->data[row][3*col+1] = image[row*width+col][1]; -+ ri->data[row][3*col+2] = image[row*width+col][2]; -+ } -+ } -+ -+ if (flip==5) -+ ri->rotate_deg = 270; -+ else if (flip==3) -+ ri->rotate_deg = 180; -+ else if (flip==6) -+ ri->rotate_deg = 90; -+ else -+ ri->rotate_deg = 0; -+ -+ ri->make = strdup (make); -+ ri->model = strdup (model); -+ -+ ri->exifbase = exif_base; -+ ri->prefilters = pre_filters; -+ ri->ciff_base = ciff_base; -+ ri->ciff_len = ciff_len; -+ -+ ri->camwb_red = ri->red_multiplier / pre_mul[0]; -+ ri->camwb_green = ri->green_multiplier / pre_mul[1]; -+ ri->camwb_blue = ri->blue_multiplier / pre_mul[2]; -+ -+ ri->defgain = 1.0 / MIN(MIN(pre_mul[0],pre_mul[1]),pre_mul[2]); -+ -+ ri->fuji_width = fuji_width; -+ -+ for (int a=0; a < 3; a++) -+ for (int b=0; b < 3; b++) -+ ri->coeff[a][b] = rgb_cam[a][b]; -+ -+ free (image); -+ return 0; -+} -+ -+int getRawFileBasicInfo (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int& rotation, int& thumbWidth, int& thumbHeight, int& thumbOffset, int& thumbType) { -+ -+ THREAD_LOCK -+ -+ int status=0; -+ -+ exif_base = -1; -+ ciff_base = -1; -+ ciff_len = -1; -+ -+ half_size = 1; -+ bright = 1.0; -+ verbose = settings->verbose; -+ use_camera_wb = 1; -+ -+ thumb_length = 0; -+ thumb_offset = 0; -+ thumb_load_raw = 0; -+ status = 1; -+ -+ ifname = fname.c_str(); -+ if (!(ifp = gfopen (ifname))) { -+ status = 2; -+ return status; -+ } -+ identify (); -+ if (!is_raw || colors>3) { -+ status = 3; -+ fclose (ifp); -+ return status; -+ } -+ -+ thumbOffset = thumb_offset; -+ -+ if (flip==5) -+ rotation = 270; -+ else if (flip==3) -+ rotation = 180; -+ else if (flip==6) -+ rotation = 90; -+ else -+ rotation = 0; -+ -+ thumbWidth = thumb_width; -+ thumbHeight = thumb_height; -+ if (!thumb_load_raw && thumb_offset && write_thumb == jpeg_thumb) -+ thumbType = 1; -+ else if (!thumb_load_raw && thumb_offset && write_thumb == ppm_thumb) -+ thumbType = 2; -+ else { -+ thumbType = 0; -+ thumbWidth = width; -+ thumbHeight = height; -+ } -+ -+ rml.exifBase = exif_base; -+ rml.ciffBase = ciff_base; -+ rml.ciffLength = ciff_len; -+ -+ fclose (ifp); -+ return !is_raw; -+} -+ -+#include -+ -+rtengine::Thumbnail* rtengine::Thumbnail::loadFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh) { -+ -+ THREAD_LOCK -+ -+MyTime t0, t1, t2, t3, t4, t5, t6; -+t0.set (); -+ -+ image = NULL; -+ ifname = fname.c_str(); -+ exif_base = -1; -+ ciff_base = -1; -+ ciff_len = -1; -+ verbose = settings->verbose; -+ oprof = NULL; -+ ifp = gfopen (fname.c_str()); -+ if (!ifp) { -+ return NULL; -+ } -+ -+t1.set (); -+ -+ if (setjmp (failure)) { -+ if (image) -+ free (image); -+ fclose (ifp); -+ return NULL; -+ } -+ -+ use_camera_wb = 0; -+ highlight = 1; -+ half_size = 0; -+ shrink = 0; -+ identify (); -+ use_camera_wb = 1; -+ if (!is_raw || colors>3) { -+ fclose(ifp); -+ return NULL; -+ } -+ -+t2.set(); -+ -+ iheight = ::height; -+ iwidth = ::width; -+ -+ image = (UshORt (*)[4])calloc (::height*::width*sizeof *image + meta_length, 1); -+ meta_data = (char *) (image + ::height*::width); -+ -+ if (settings->verbose) printf ("Loading %s %s image from %s...\n", make, model, fname.c_str()); -+ fseek (ifp, data_offset, SEEK_SET); -+ (*load_raw)(); -+ if (zero_is_bad) remove_zeroes(); -+ -+ rtengine::Thumbnail* tpp = new rtengine::Thumbnail; -+ -+ tpp->isRaw = true; -+ tpp->embProfileLength = 0; -+ if (profile_length) { -+ tpp->embProfileLength = profile_length; -+ tpp->embProfileData = new unsigned char[profile_length]; -+ fseek (ifp, profile_offset, SEEK_SET); -+ fread (tpp->embProfileData, 1, profile_length, ifp); -+ tpp->embProfile = cmsOpenProfileFromMem (tpp->embProfileData, tpp->embProfileLength); -+ } -+ else { -+ tpp->embProfile = NULL; -+ tpp->embProfileData = NULL; -+ } -+ -+ fclose(ifp); -+ tpp->redMultiplier = pre_mul[0]; -+ tpp->greenMultiplier = pre_mul[1]; -+ tpp->blueMultiplier = pre_mul[2]; -+ -+t3.set (); -+ -+ scale_colors(); -+ pre_interpolate (); -+ -+ unsigned filter = filters; -+ int firstgreen = 1; -+ // locate first green location in the first row -+ while (!FISGREEN(filter,1,firstgreen)) -+ firstgreen++; -+ -+ int skip = 1; -+ if (fixwh==1) // fix height, scale width -+ skip = (::height-firstgreen-1) / h; -+ else -+ skip = (::width-firstgreen-1) / w; -+ if (skip%2) -+ skip--; -+ if (skip<1) -+ skip = 1; -+ -+ int hskip = skip, vskip = skip; -+ if (!strcmp (model, "D1X")) -+ hskip *=2; -+ -+ rml.exifBase = exif_base; -+ rml.ciffBase = ciff_base; -+ rml.ciffLength = ciff_len; -+ tpp->camwbRed = tpp->redMultiplier / pre_mul[0]; -+ tpp->camwbGreen = tpp->greenMultiplier / pre_mul[1]; -+ tpp->camwbBlue = tpp->blueMultiplier / pre_mul[2]; -+ -+ tpp->defGain = 1.0 / MIN(MIN(pre_mul[0],pre_mul[1]),pre_mul[2]); -+ tpp->gammaCorrected = true; -+ -+ int ix = 0; -+ int rofs = 0; -+ int tmpw = (::width-2)/hskip; -+ int tmph = (::height-2)/vskip; -+ Image16* tmpImg = new Image16 (tmpw, tmph); -+ if (filter) { -+ for (int row=1, y=0; row< ::height-1 && y> 1; -+ b = (image[ofs+::width][2] + image[ofs-::width][2]) >> 1; -+ } -+ else { -+ b = (image[ofs+1][2] + image[ofs-1][2]) >> 1; -+ r = (image[ofs+::width][0] + image[ofs-::width][0]) >> 1; -+ } -+ tmpImg->r[y][x] = r; -+ tmpImg->g[y][x] = g; -+ tmpImg->b[y][x] = b; -+ } -+ } -+ } -+ else { -+ for (int row=1, y=0; row< ::height-1 && yr[y][x] = image[ofs][0]; -+ tmpImg->g[y][x] = image[ofs][1]; -+ tmpImg->b[y][x] = image[ofs][2]; -+ } -+ } -+ } -+ -+ if (fuji_width) { -+ int fw = fuji_width / hskip; -+ double step = sqrt(0.5); -+ int wide = fw / step; -+ int high = (tmph - fw) / step; -+ Image16* fImg = new Image16 (wide, high); -+ float r, c; -+ -+ for (int row=0; row < high; row++) -+ for (int col=0; col < wide; col++) { -+ unsigned ur = r = fw + (row-col)*step; -+ unsigned uc = c = (row+col)*step; -+ if (ur > tmph-2 || uc > tmpw-2) -+ continue; -+ double fr = r - ur; -+ double fc = c - uc; -+ int oofs = (ur*tmpw + uc)*3; -+ int fofs = (row*wide+col)*3; -+ fImg->r[row][col] = (tmpImg->r[ur][uc] * (1-fc) + tmpImg->r[ur][uc+1] * fc) * (1-fr) + (tmpImg->r[ur+1][uc] * (1-fc) + tmpImg->r[ur+1][uc+1] * fc) * fr; -+ fImg->g[row][col] = (tmpImg->g[ur][uc] * (1-fc) + tmpImg->g[ur][uc+1] * fc) * (1-fr) + (tmpImg->g[ur+1][uc] * (1-fc) + tmpImg->g[ur+1][uc+1] * fc) * fr; -+ fImg->b[row][col] = (tmpImg->b[ur][uc] * (1-fc) + tmpImg->b[ur][uc+1] * fc) * (1-fr) + (tmpImg->b[ur+1][uc] * (1-fc) + tmpImg->b[ur+1][uc+1] * fc) * fr; -+ } -+ delete tmpImg; -+ tmpImg = fImg; -+ } -+ -+ -+ if (fixwh==1) // fix height, scale width -+ w = tmpw * h / tmph; -+ else -+ h = tmph * w / tmpw; -+ -+ tpp->thumbImg = tmpImg->resize (w, h, TI_Bilinear); -+ delete tmpImg; -+ -+ if (fuji_width) -+ tpp->scale = (double)(::height - fuji_width) / sqrt(0.5) / h; -+ else -+ tpp->scale = (double)::height / h; -+ -+t4.set (); -+ -+ // generate histogram for auto exposure -+ tpp->aeHistCompression = 3; -+ tpp->aeHistogram = new unsigned int[65536>>tpp->aeHistCompression]; -+ memset (tpp->aeHistogram, 0, (65536>>tpp->aeHistCompression)*sizeof(int)); -+ int radd = 4; -+ int gadd = 2; -+ int badd = 4; -+ if (!filter) -+ radd = gadd = badd = 1; -+ for (int i=8; i< ::height-8; i++) { -+ int start, end; -+ if (fuji_width) { -+ int fw = fuji_width; -+ start = ABS(fw-i) + 8; -+ end = MIN( ::height+ ::width-fw-i, fw+i) - 8; -+ } -+ else { -+ start = 8; -+ end = ::width-8; -+ } -+ for (int j=start; jaeHistogram[image[i* ::width+j][1]>>tpp->aeHistCompression]+=gadd; -+ else if (FISRED(filter,i,j)) -+ tpp->aeHistogram[image[i* ::width+j][0]>>tpp->aeHistCompression]+=radd; -+ else if (FISBLUE(filter,i,j)) -+ tpp->aeHistogram[image[i* ::width+j][2]>>tpp->aeHistCompression]+=badd; -+ } -+ -+t5.set (); -+ -+ // generate autoWB -+ double avg_r = 0; -+ double avg_g = 0; -+ double avg_b = 0; -+ int rn = 0, gn = 0, bn = 0; -+ -+ for (int i=32; i< ::height-32; i++) { -+ int start, end; -+ if (fuji_width) { -+ int fw = fuji_width; -+ start = ABS(fw-i) + 32; -+ end = MIN( ::height+ ::width-fw-i, fw+i) - 32; -+ } -+ else { -+ start = 32; -+ end = ::width-32; -+ } -+ for (int j=start; jdefGain * image[i* ::width+j][1]; -+ if (d>64000) -+ continue; -+ avg_g += d; -+ gn++; -+ } -+ if (FISRED(filter,i,j)) { -+ double d = tpp->defGain * image[i* ::width+j][0]; -+ if (d>64000) -+ continue; -+ avg_r += d; -+ rn++; -+ } -+ if (FISBLUE(filter,i,j)) { -+ double d = tpp->defGain * image[i* ::width+j][2]; -+ if (d>64000) -+ continue; -+ avg_b += d; -+ bn++; -+ } -+ } -+ } -+ -+ double reds = avg_r/rn * tpp->camwbRed; -+ double greens = avg_g/gn * tpp->camwbGreen; -+ double blues = avg_b/bn * tpp->camwbBlue; -+ -+ double rm = rgb_cam[0][0]*reds + rgb_cam[0][1]*greens + rgb_cam[0][2]*blues; -+ double gm = rgb_cam[1][0]*reds + rgb_cam[1][1]*greens + rgb_cam[1][2]*blues; -+ double bm = rgb_cam[2][0]*reds + rgb_cam[2][1]*greens + rgb_cam[2][2]*blues; -+ -+ ColorTemp::mul2temp (rm, gm, bm, tpp->autowbTemp, tpp->autowbGreen); -+ -+t6.set (); -+ -+if (settings->verbose) printf ("0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d All: %d\n", t1.etime(t0), t2.etime(t1), t3.etime(t2), t4.etime(t3), t5.etime(t4), t6.etime(t5), t6.etime(t0)); -+ -+ int deg = 0; -+ if (flip==5) -+ deg = 270; -+ else if (flip==3) -+ deg = 180; -+ else if (flip==6) -+ deg = 90; -+ -+ if (deg>0) { -+ Image16* rot = tpp->thumbImg->rotate (deg); -+ delete tpp->thumbImg; -+ tpp->thumbImg = rot; -+ } -+ -+ for (int a=0; a < 3; a++) -+ for (int b=0; b < 3; b++) -+ tpp->colorMatrix[a][b] = rgb_cam[a][b]; -+ -+ tpp->init (); -+ -+ free (image); -+ -+ return tpp; -+} -+ -+ -+} -+ +0a1,12 +> /*RT*/#include +> /*RT*/#include +> /*RT*/#undef MAX +> /*RT*/#undef MIN +> /*RT*/#define NO_LCMS +> /*RT*/#define NO_JPEG +> /*RT*/#define LOCALTIME +> /*RT*/#define DJGPP +> /*RT*/#include +> +> #include "myfile.h" +> +49c61,63 +< #include +--- +> /*RT*/extern "C" { +> /*RT*/#include +> /*RT*/} +98a113,135 +> // RT specify thread local storage +> #ifdef __GNUC__ +> #define THREAD_LOCAL static __thread +> #define THREAD_LOCK +> #else +> #define THREAD_LOCAL static +> #define THREAD_LOCK Glib::Mutex::Lock locker(*dcrMutex); +> #endif +> +> // patch for gcc<=4.2 on OSX +> #ifdef __APPLE__ +> #define GCC_VERSION (__GNUC__ * 10000 \ +> + __GNUC_MINOR__ * 100 \ +> + __GNUC_PATCHLEVEL__) +> #if GCC_VERSION < 40300 +> #undef THREAD_LOCAL +> #undef THREAD_LOCK +> #define THREAD_LOCAL static +> #define THREAD_LOCK Glib::Mutex::Lock locker(*dcrMutex); +> #endif +> #endif +> +> +104,132c141,171 +< FILE *ifp, *ofp; +< short order; +< const char *ifname; +< char *meta_data; +< 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; +< unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; +< off_t strip_offset, data_offset; +< off_t thumb_offset, meta_offset, profile_offset; +< 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[8], 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; +< ushort raw_height, raw_width, height, width, top_margin, left_margin; +< ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; +< int flip, tiff_flip, colors; +< double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; +< ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; +< float bright=1, user_mul[4]={0,0,0,0}, threshold=0; +< 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 */ +--- +> /*RT*/THREAD_LOCAL int ciff_base, ciff_len, exif_base, pre_filters; +> /*RT*/THREAD_LOCAL IMFILE *ifp; +> THREAD_LOCAL FILE * ofp; +> THREAD_LOCAL short order; +> THREAD_LOCAL const char *ifname; +> THREAD_LOCAL char *meta_data; +> THREAD_LOCAL char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64]; +> THREAD_LOCAL float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len; +> THREAD_LOCAL time_t timestamp; +> THREAD_LOCAL unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id; +> THREAD_LOCAL off_t strip_offset, data_offset; +> THREAD_LOCAL off_t thumb_offset, meta_offset, profile_offset; +> THREAD_LOCAL unsigned thumb_length, meta_length, profile_length; +> THREAD_LOCAL unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0; +> THREAD_LOCAL unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress; +> THREAD_LOCAL unsigned black, cblack[8], maximum, mix_green, raw_color, zero_is_bad; +> THREAD_LOCAL unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error; +> THREAD_LOCAL unsigned tile_width, tile_length, gpsdata[32], load_flags; +> THREAD_LOCAL ushort raw_height, raw_width, height, width, top_margin, left_margin; +> THREAD_LOCAL ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height; +> THREAD_LOCAL int flip, tiff_flip, colors; +> THREAD_LOCAL double pixel_aspect, aber[4]={1,1,1,1}, gamm[6]={ 0.45,4.5,0,0,0,0 }; +> THREAD_LOCAL ushort (*image)[4], white[8][8], curve[0x10000], cr2_slice[3], sraw_mul[4]; +> THREAD_LOCAL float bright=1, user_mul[4]={0,0,0,0}, threshold=0; +> THREAD_LOCAL int half_size=0, four_color_rgb=0, document_mode=0, highlight=0; +> THREAD_LOCAL int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1; +> THREAD_LOCAL int output_color=1, output_bps=8, output_tiff=0, med_passes=0; +> THREAD_LOCAL int no_auto_bright=0; +> THREAD_LOCAL unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; +> THREAD_LOCAL float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; +> static const double xyz_rgb[3][3] = { /* XYZ from RGB */ +136,140c175,179 +< 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; +--- +> static const float d65_white[3] = { 0.950456, 1, 1.088754 }; +> THREAD_LOCAL int histogram[4][0x2000]; +> THREAD_LOCAL void (*write_thumb)(), (*write_fun)(); +> THREAD_LOCAL void (*load_raw)(), (*thumb_load_raw)(); +> THREAD_LOCAL jmp_buf failure; +142c181 +< struct decode { +--- +> THREAD_LOCAL struct decode { +147c186 +< struct tiff_ifd { +--- +> THREAD_LOCAL struct tiff_ifd { +151c190 +< struct ph1 { +--- +> THREAD_LOCAL struct ph1 { +273a313 +> /*RT*/ longjmp (failure, 1); +347c387 +< swab (pixel, pixel, count*2); +--- +> swab ((char*)pixel, (char*)pixel, count*2); +541,542c581,582 +< static unsigned bitbuf=0; +< static int vbits=0, reset=0; +--- +> THREAD_LOCAL unsigned bitbuf=0; +> THREAD_LOCAL int vbits=0, reset=0; +1563,1564c1603,1604 +< static UINT64 bitbuf=0; +< static int vbits=0; +--- +> THREAD_LOCAL UINT64 bitbuf=0; +> THREAD_LOCAL int vbits=0; +1826,1827c1866,1867 +< static uchar buf[0x4000]; +< static int vbits; +--- +> THREAD_LOCAL uchar buf[0x4000]; +> THREAD_LOCAL int vbits; +2116c2156 +< static uchar jpeg_buffer[4096]; +--- +> THREAD_LOCAL uchar jpeg_buffer[4096]; +2120c2160 +< swab (jpeg_buffer, jpeg_buffer, nbytes); +--- +> swab ((char*)jpeg_buffer, (char*)jpeg_buffer, nbytes); +2394c2434 +< static unsigned pad[128], p; +--- +> THREAD_LOCAL unsigned pad[128], p; +2641c2681 +< static unsigned huff[1024]; +--- +> THREAD_LOCAL unsigned huff[1024]; +3763,3771c3803,3814 +< if ((mix_green = four_color_rgb)) colors++; +< else { +< for (row = FC(1,0) >> 1; row < height; row+=2) +< for (col = FC(row,1) & 1; col < width; col+=2) +< image[row*width+col][1] = image[row*width+col][3]; +< filters &= ~((filters & 0x55555555) << 1); +< } +< } +< if (half_size) filters = 0; +--- +> if ((mix_green = four_color_rgb)) +> colors++; +> else { +> for (row = FC(1,0) >> 1; row < height; row += 2) +> for (col = FC(row,1) & 1; col < width; col += 2) +> image[row * width + col][1] = image[row * width + col][3]; +> /*RT*/ pre_filters = filters; +> filters &= ~((filters & 0x55555555) << 1); +> } +> } +> if (half_size) +> filters = 0; +4820c4863 +< FILE *sfp; +--- +> /*RT*/ IMFILE *sfp; +5228,5230c5271,5274 +< if ((ifp = tmpfile())) { +< fwrite (buf, sony_length, 1, ifp); +< fseek (ifp, 0, SEEK_SET); +--- +> /*RT*/ ifp = fopen (buf, sony_length); +> // if ((ifp = tmpfile())) { +> // fwrite (buf, sony_length, 1, ifp); +> // fseek (ifp, 0, SEEK_SET); +5232,5233c5276,5277 +< fclose (ifp); +< } +--- +> // fclose (ifp); +> // } +5258a5303,5304 +> /*RT*/ exif_base = base; +> +5427c5473 +< FILE *save=ifp; +--- +> /*RT*/ IMFILE *save=ifp; +5455c5501,5502 +< if ((ifp = fopen (jname, "rb"))) { +--- +> /*RT*/ if ((ifp = fopen (jname))) { +> // if ((ifp = fopen (jname, "rb"))) { +5792a5840,5842 +> /*RT*/ { +> /*RT*/ ciff_base = save+hlen; +> /*RT*/ ciff_len = len-hlen; +5793a5844 +> /*RT*/ } +6740a6792,6797 +> +> /*RT*/ if (fsize<100000) { +> is_raw = 0; +> return; +> } +> +6747a6805,6806 +> /*RT*/ ciff_base = hlen; +> /*RT*/ ciff_len = fsize - hlen; +6860a6920,6921 +> if (height == 2868 && width == 4352) /* Pentax K-x */ +> width = 4308; +7193a7255,7256 +> } else if (!strcmp(model,"D7000")) { +> width -= 40; +7408c7471 +< width = 4309; +--- +> width = 4308; +8497c8560 +< swab (ppm2, ppm2, width*colors*2); +--- +> swab ((char*)ppm2, (char*)ppm2, width*colors*2); +8503c8566 +< int CLASS main (int argc, const char **argv) +--- +> /*int CLASS main (int argc, const char **argv) +8616c8679 +< case 'h': half_size = 1; /* "-h" implies "-f" */ +--- +> case 'h': half_size = 1; /* "-h" implies "-f" *//* +8879a8943,9537 +> */ +> +> #include +> #include +> #include +> #include +> #include +> +> namespace rtengine { +> +> extern Settings* settings; +> +> Glib::Mutex* dcrMutex=NULL; +> +> int RawImage::loadRaw (bool loadData) { +> +> THREAD_LOCK +> +> ifname = fname.c_str(); +> image = NULL; +> exif_base = -1; +> ciff_base = -1; +> ciff_len = -1; +> verbose = settings->verbose; +> oprof = NULL; +> +> ifp = gfopen (fname.c_str()); +> if (!ifp) +> return 3; +> +> thumb_length = 0; +> thumb_offset = 0; +> thumb_load_raw = 0; +> use_camera_wb = 0; +> highlight = 1; +> half_size = 0; +> +> //***************** Read ALL raw file info +> identify (); +> if (!is_raw) { +> fclose(ifp); +> return 2; +> } +> this->filters = ::filters; +> this->height = ::height; +> this->width = ::width; +> this->colors = ::colors; +> this->profile_len = ::profile_length; +> +> this->maximum = ::maximum; +> this->fuji_width = ::fuji_width; +> +> for(int i=0; i<8;i++) +> for(int j=0;j<8;j++) +> this->white[i][j] = ::white[i][j]; +> +> if (flip==5) +> this->rotate_deg = 270; +> else if (flip==3) +> this->rotate_deg = 180; +> else if (flip==6) +> this->rotate_deg = 90; +> else +> this->rotate_deg = 0; +> +> this->make = strdup (::make); +> this->model = strdup (::model); +> this->iso_speed = ::iso_speed; +> this->shutter = ::shutter; +> this->aperture = ::aperture; +> this->focal_len = ::focal_len; +> this->timestamp = ::timestamp; +> this->exifbase = ::exif_base; +> this->ciff_base = ::ciff_base; +> this->ciff_len = ::ciff_len; +> this->thumbOffset = ::thumb_offset; +> this->thumbLength = ::thumb_length; +> this->thumbHeight = ::thumb_height; +> this->thumbWidth = ::thumb_width; +> if (!thumb_load_raw && thumb_offset && write_thumb == jpeg_thumb) +> this->thumbType = 1; +> else if (!thumb_load_raw && thumb_offset && write_thumb == ppm_thumb) +> this->thumbType = 2; +> else { +> this->thumbType = 0; +> this->thumbWidth = ::width; +> this->thumbHeight = ::height; +> } +> +> if( loadData ){ +> allocData(); +> use_camera_wb = 1; +> shrink = 0; +> if (settings->verbose) printf ("Loading %s %s image from %s...\n", make, model, fname.c_str()); +> iheight = height; +> iwidth = width; +> +> // dcraw needs this global variable to hold pixel data +> image = (UshORt (*)[4])calloc (height*width*sizeof *image + meta_length, 1); +> meta_data = (char *) (image + height*width); +> if(!image) +> return 200; +> +> if (setjmp (failure)) { +> if (image) +> free (image); +> fclose (ifp); +> return 100; +> } +> +> // Load raw pixels data +> fseek (ifp, data_offset, SEEK_SET); +> (*load_raw)(); +> +> // Load embedded profile +> if (profile_length) { +> fseek (ifp, profile_offset, SEEK_SET); +> fread ( this->profile_data, 1, this->profile_len, ifp); +> } +> fclose(ifp); +> +> // Setting the black_point and cblack +> int i = ::cblack[3]; +> for (int c=0; c <3; c++) +> if (i > ::cblack[c]) +> i = ::cblack[c]; +> for (int c=0; c < 4; c++) +> ::cblack[c] -= i; +> ::black += i; +> for (int c=0; c < 4; c++) this->cblack[c] = ::cblack[c]; +> for (int c=0; c < 4; c++) this->cam_mul[c] = ::cam_mul[c]; +> for (int c=0; c < 4; c++) this->pre_mul[c] = ::pre_mul[c]; +> for (int a = 0; a < 3; a++) +> for (int b = 0; b < 3; b++) +> this->coeff[a][b] = ::rgb_cam[a][b]; +> +> this->black_point = ::black; +> +> // copy pixel raw data: the compressed format earns space +> if (this->filters) { +> for (int row = 0; row < height; row++) +> for (int col = 0; col < width; col++) +> this->data[row][col] = image[row * width + col][FC(row,col)]; +> } else { +> for (int row = 0; row < height; row++) +> for (int col = 0; col < width; col++) { +> this->data[row][3 * col + 0] = image[row * width + col][0]; +> this->data[row][3 * col + 1] = image[row * width + col][1]; +> this->data[row][3 * col + 2] = image[row * width + col][2]; +> } +> } +> free(image); // we don't need this anymore +> } +> return 0; +> } +> +> +> +> int getRawFileBasicInfo (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int& rotation, int& thumbWidth, int& thumbHeight, int& thumbOffset, int& thumbType) { +> +> THREAD_LOCK +> +> int status=0; +> +> exif_base = -1; +> ciff_base = -1; +> ciff_len = -1; +> +> half_size = 1; +> bright = 1.0; +> verbose = settings->verbose; +> use_camera_wb = 1; +> +> thumb_length = 0; +> thumb_offset = 0; +> thumb_load_raw = 0; +> status = 1; +> +> ifname = fname.c_str(); +> if (!(ifp = gfopen (ifname))) { +> status = 2; +> return status; +> } +> identify (); +> if (!is_raw || colors>3) { +> status = 3; +> fclose (ifp); +> return status; +> } +> +> thumbOffset = thumb_offset; +> +> if (flip==5) +> rotation = 270; +> else if (flip==3) +> rotation = 180; +> else if (flip==6) +> rotation = 90; +> else +> rotation = 0; +> +> thumbWidth = thumb_width; +> thumbHeight = thumb_height; +> if (!thumb_load_raw && thumb_offset && write_thumb == jpeg_thumb) +> thumbType = 1; +> else if (!thumb_load_raw && thumb_offset && write_thumb == ppm_thumb) +> thumbType = 2; +> else { +> thumbType = 0; +> thumbWidth = width; +> thumbHeight = height; +> } +> +> rml.exifBase = exif_base; +> rml.ciffBase = ciff_base; +> rml.ciffLength = ciff_len; +> +> fclose (ifp); +> return !is_raw; +> } +> +> #include +> +> rtengine::Thumbnail* rtengine::Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh) { +> +> THREAD_LOCK +> +> image = NULL; +> ifname = fname.c_str(); +> exif_base = -1; +> ciff_base = -1; +> ciff_len = -1; +> verbose = settings->verbose; +> oprof = NULL; +> ifp = gfopen (fname.c_str()); +> if (!ifp) { +> printf("DCRAW: failed0\n"); +> return NULL; +> } +> +> if (setjmp (failure)) { +> printf("DCRAW: failed1\n"); +> fclose (ifp); +> return NULL; +> } +> +> identify (); +> if (!is_raw || colors>3) { +> printf("DCRAW: failed2\n"); +> fclose(ifp); +> return NULL; +> } +> +> rml.exifBase = exif_base; +> rml.ciffBase = ciff_base; +> rml.ciffLength = ciff_len; +> +> char *thumb_buffer malloc(thumb_length+64); // malloc instead of on the stack. +> if ( thumb_buffer == NULL ) +> { +> printf("DCRAW: failed3\n"); +> return NULL; +> } +> fseek(ifp,thumb_offset,SEEK_SET); +> fread(thumb_buffer,1,thumb_length,ifp); +> fclose(ifp); +> +> rtengine::Thumbnail* tpp = rtengine::Thumbnail::loadFromMemory(thumb_buffer,thumb_length,w,h,fixwh); +> free(thumb_buffer); +> if ( tpp == 0 ) +> { +> printf("DCRAW: failed4\n"); +> return NULL; +> } +> +> int deg = 0; +> if (flip==5) +> deg = 270; +> else if (flip==3) +> deg = 180; +> else if (flip==6) +> deg = 90; +> +> if (deg>0) { +> Image16* rot = tpp->thumbImg->rotate (deg); +> delete tpp->thumbImg; +> tpp->thumbImg = rot; +> } +> +> return tpp; +> } +> +> rtengine::Thumbnail* rtengine::Thumbnail::loadFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh) { +> +> THREAD_LOCK +> +> MyTime t0, t1, t2, t3, t4, t5, t6; +> t0.set (); +> +> image = NULL; +> ifname = fname.c_str(); +> exif_base = -1; +> ciff_base = -1; +> ciff_len = -1; +> verbose = settings->verbose; +> oprof = NULL; +> ifp = gfopen (fname.c_str()); +> if (!ifp) { +> return NULL; +> } +> +> t1.set (); +> +> if (setjmp (failure)) { +> if (image) +> free (image); +> fclose (ifp); +> return NULL; +> } +> +> use_camera_wb = 0; +> highlight = 1; +> half_size = 0; +> shrink = 0; +> identify (); +> use_camera_wb = 1; +> if (!is_raw || colors>3) { +> fclose(ifp); +> return NULL; +> } +> +> t2.set(); +> +> iheight = ::height; +> iwidth = ::width; +> +> image = (UshORt (*)[4])calloc (::height*::width*sizeof *image + meta_length, 1); +> meta_data = (char *) (image + ::height*::width); +> +> if (settings->verbose) printf ("Loading %s %s image from %s...\n", make, model, fname.c_str()); +> fseek (ifp, data_offset, SEEK_SET); +> (*load_raw)(); +> if (zero_is_bad) remove_zeroes(); +> +> rtengine::Thumbnail* tpp = new rtengine::Thumbnail; +> +> tpp->isRaw = true; +> tpp->embProfileLength = 0; +> if (profile_length) { +> tpp->embProfileLength = profile_length; +> tpp->embProfileData = new unsigned char[profile_length]; +> fseek (ifp, profile_offset, SEEK_SET); +> fread (tpp->embProfileData, 1, profile_length, ifp); +> tpp->embProfile = cmsOpenProfileFromMem (tpp->embProfileData, tpp->embProfileLength); +> } +> else { +> tpp->embProfile = NULL; +> tpp->embProfileData = NULL; +> } +> +> fclose(ifp); +> tpp->redMultiplier = pre_mul[0]; +> tpp->greenMultiplier = pre_mul[1]; +> tpp->blueMultiplier = pre_mul[2]; +> +> t3.set (); +> +> scale_colors(); +> pre_interpolate (); +> +> unsigned filter = filters; +> int firstgreen = 1; +> // locate first green location in the first row +> while (!FISGREEN(filter,1,firstgreen)) +> firstgreen++; +> +> int skip = 1; +> if (fixwh==1) // fix height, scale width +> skip = (::height-firstgreen-1) / h; +> else +> skip = (::width-firstgreen-1) / w; +> if (skip%2) +> skip--; +> if (skip<1) +> skip = 1; +> +> int hskip = skip, vskip = skip; +> if (!strcmp (model, "D1X")) +> hskip *=2; +> +> rml.exifBase = exif_base; +> rml.ciffBase = ciff_base; +> rml.ciffLength = ciff_len; +> tpp->camwbRed = tpp->redMultiplier / pre_mul[0]; +> tpp->camwbGreen = tpp->greenMultiplier / pre_mul[1]; +> tpp->camwbBlue = tpp->blueMultiplier / pre_mul[2]; +> +> tpp->defGain = 1.0 / MIN(MIN(pre_mul[0],pre_mul[1]),pre_mul[2]); +> tpp->gammaCorrected = true; +> +> int ix = 0; +> int rofs = 0; +> int tmpw = (::width-2)/hskip; +> int tmph = (::height-2)/vskip; +> Image16* tmpImg = new Image16 (tmpw, tmph); +> if (filter) { +> for (int row=1, y=0; row< ::height-1 && y rofs = row*::width; +> for (int col=firstgreen,x=0; col< ::width-1 && x int ofs = rofs+col; +> int g = image[ofs][1]; +> int r, b; +> if (FISRED(filter,row,col+1)) { +> r = (image[ofs+1][0] + image[ofs-1][0]) >> 1; +> b = (image[ofs+::width][2] + image[ofs-::width][2]) >> 1; +> } +> else { +> b = (image[ofs+1][2] + image[ofs-1][2]) >> 1; +> r = (image[ofs+::width][0] + image[ofs-::width][0]) >> 1; +> } +> tmpImg->r[y][x] = r; +> tmpImg->g[y][x] = g; +> tmpImg->b[y][x] = b; +> } +> } +> } +> else { +> for (int row=1, y=0; row< ::height-1 && y rofs = row*::width; +> for (int col=firstgreen,x=0; col< ::width-1 && x int ofs = rofs+col; +> tmpImg->r[y][x] = image[ofs][0]; +> tmpImg->g[y][x] = image[ofs][1]; +> tmpImg->b[y][x] = image[ofs][2]; +> } +> } +> } +> +> if (fuji_width) { +> int fw = fuji_width / hskip; +> double step = sqrt(0.5); +> int wide = fw / step; +> int high = (tmph - fw) / step; +> Image16* fImg = new Image16 (wide, high); +> float r, c; +> +> for (int row=0; row < high; row++) +> for (int col=0; col < wide; col++) { +> unsigned ur = r = fw + (row-col)*step; +> unsigned uc = c = (row+col)*step; +> if (ur > tmph-2 || uc > tmpw-2) +> continue; +> double fr = r - ur; +> double fc = c - uc; +> int oofs = (ur*tmpw + uc)*3; +> int fofs = (row*wide+col)*3; +> fImg->r[row][col] = (tmpImg->r[ur][uc] * (1-fc) + tmpImg->r[ur][uc+1] * fc) * (1-fr) + (tmpImg->r[ur+1][uc] * (1-fc) + tmpImg->r[ur+1][uc+1] * fc) * fr; +> fImg->g[row][col] = (tmpImg->g[ur][uc] * (1-fc) + tmpImg->g[ur][uc+1] * fc) * (1-fr) + (tmpImg->g[ur+1][uc] * (1-fc) + tmpImg->g[ur+1][uc+1] * fc) * fr; +> fImg->b[row][col] = (tmpImg->b[ur][uc] * (1-fc) + tmpImg->b[ur][uc+1] * fc) * (1-fr) + (tmpImg->b[ur+1][uc] * (1-fc) + tmpImg->b[ur+1][uc+1] * fc) * fr; +> } +> delete tmpImg; +> tmpImg = fImg; +> } +> +> +> if (fixwh==1) // fix height, scale width +> w = tmpw * h / tmph; +> else +> h = tmph * w / tmpw; +> +> tpp->thumbImg = tmpImg->resize (w, h, TI_Bilinear); +> delete tmpImg; +> +> if (fuji_width) +> tpp->scale = (double)(::height - fuji_width) / sqrt(0.5) / h; +> else +> tpp->scale = (double)::height / h; +> +> t4.set (); +> +> // generate histogram for auto exposure +> tpp->aeHistCompression = 3; +> tpp->aeHistogram = new unsigned int[65536>>tpp->aeHistCompression]; +> memset (tpp->aeHistogram, 0, (65536>>tpp->aeHistCompression)*sizeof(int)); +> int radd = 4; +> int gadd = 2; +> int badd = 4; +> if (!filter) +> radd = gadd = badd = 1; +> for (int i=8; i< ::height-8; i++) { +> int start, end; +> if (fuji_width) { +> int fw = fuji_width; +> start = ABS(fw-i) + 8; +> end = MIN( ::height+ ::width-fw-i, fw+i) - 8; +> } +> else { +> start = 8; +> end = ::width-8; +> } +> for (int j=start; j if (FISGREEN(filter,i,j)) +> tpp->aeHistogram[image[i* ::width+j][1]>>tpp->aeHistCompression]+=gadd; +> else if (FISRED(filter,i,j)) +> tpp->aeHistogram[image[i* ::width+j][0]>>tpp->aeHistCompression]+=radd; +> else if (FISBLUE(filter,i,j)) +> tpp->aeHistogram[image[i* ::width+j][2]>>tpp->aeHistCompression]+=badd; +> } +> +> t5.set (); +> +> // generate autoWB +> double avg_r = 0; +> double avg_g = 0; +> double avg_b = 0; +> int rn = 0, gn = 0, bn = 0; +> +> for (int i=32; i< ::height-32; i++) { +> int start, end; +> if (fuji_width) { +> int fw = fuji_width; +> start = ABS(fw-i) + 32; +> end = MIN( ::height+ ::width-fw-i, fw+i) - 32; +> } +> else { +> start = 32; +> end = ::width-32; +> } +> for (int j=start; j if (FISGREEN(filter,i,j)) { +> double d = tpp->defGain * image[i* ::width+j][1]; +> if (d>64000) +> continue; +> avg_g += d; +> gn++; +> } +> if (FISRED(filter,i,j)) { +> double d = tpp->defGain * image[i* ::width+j][0]; +> if (d>64000) +> continue; +> avg_r += d; +> rn++; +> } +> if (FISBLUE(filter,i,j)) { +> double d = tpp->defGain * image[i* ::width+j][2]; +> if (d>64000) +> continue; +> avg_b += d; +> bn++; +> } +> } +> } +> +> double reds = avg_r/rn * tpp->camwbRed; +> double greens = avg_g/gn * tpp->camwbGreen; +> double blues = avg_b/bn * tpp->camwbBlue; +> +> double rm = rgb_cam[0][0]*reds + rgb_cam[0][1]*greens + rgb_cam[0][2]*blues; +> double gm = rgb_cam[1][0]*reds + rgb_cam[1][1]*greens + rgb_cam[1][2]*blues; +> double bm = rgb_cam[2][0]*reds + rgb_cam[2][1]*greens + rgb_cam[2][2]*blues; +> +> ColorTemp::mul2temp (rm, gm, bm, tpp->autowbTemp, tpp->autowbGreen); +> +> t6.set (); +> +> if (settings->verbose) printf ("0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d All: %d\n", t1.etime(t0), t2.etime(t1), t3.etime(t2), t4.etime(t3), t5.etime(t4), t6.etime(t5), t6.etime(t0)); +> +> int deg = 0; +> if (flip==5) +> deg = 270; +> else if (flip==3) +> deg = 180; +> else if (flip==6) +> deg = 90; +> +> if (deg>0) { +> Image16* rot = tpp->thumbImg->rotate (deg); +> delete tpp->thumbImg; +> tpp->thumbImg = rot; +> } +> +> for (int a=0; a < 3; a++) +> for (int b=0; b < 3; b++) +> tpp->colorMatrix[a][b] = rgb_cam[a][b]; +> +> tpp->init (); +> +> free (image); +> +> return tpp; +> } +> +> +> } +>