Files
rawTherapee/rtengine/dcraw.patch
Hombre 8b2eac9a3d Pipette and "On Preview Widgets" branch. See issue 227
The pipette part is already working quite nice but need to be finished. The widgets part needs more work...
2014-01-21 23:37:36 +01:00

1696 lines
55 KiB
Diff
Executable File

--- dcraw.c 2014-01-01 15:42:38 +0000
+++ dcraw.cc 2014-01-01 18:32:58 +0000
@@ -1,3 +1,15 @@
+/*RT*/#include <glib.h>
+/*RT*/#include <glib/gstdio.h>
+/*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 <ctype.h>
-#include <errno.h>
+#include <cctype>
+#include <cerrno>
#include <fcntl.h>
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
+#include <cfloat>
+#include <climits>
+#include <cmath>
+#include <csetjmp>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
#include <sys/types.h>
#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<typeof(a)>(b))
+#define MAX(a,b) rtengine::max(a,static_cast<typeof(a)>(b))
+#define LIM(x,min,max) rtengine::LIM(x,static_cast<typeof(x)>(min),static_cast<typeof(x)>(max))
+#define ULIM(x,y,z) rtengine::ULIM(x,static_cast<typeof(x)>(y),static_cast<typeof(x)>(z))
+#define CLIP(x) rtengine::CLIP(x)
#define SWAP(a,b) { a=a+b; b=a-b; a=a-b; }
/*
@@ -254,6 +216,7 @@
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];
+
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;
@@ -2386,8 +2349,10 @@
for (p=0; p < 127; p++)
pad[p] = htonl(pad[p]);
}
- while (len--)
- *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+ while (len--){
+ *data++ ^= pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+ p++;
+ }
}
void CLASS sony_load_raw()
@@ -2445,7 +2410,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 +2430,13 @@
bit += 7;
}
for (i=0; i < 16; i++, col+=2)
- RAW(row,col) = curve[pix[i] << 1] >> 2;
+ RAW(row,col) = curve[pix[i] << 1]; // >> 2; RT: disabled shifting to avoid precision loss
col -= col & 1 ? 1:31;
}
}
free (data);
+ maximum = curve[0x7ff << 1]; // RT: fix maximum.
+ maximum = 16300; // RT: conservative white level tested on various ARW2 cameras. This constant was set in 2013-12-17, may need re-evaluation in the future.
}
void CLASS samsung_load_raw()
@@ -2690,7 +2658,7 @@
void CLASS foveon_decoder (unsigned size, unsigned code)
{
- static unsigned huff[1024];
+/*RT static unsigned huff[1024];*/
struct decode *cur;
int i, len;
@@ -4003,239 +3971,8 @@
}
}
-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<<g) *ip++ = g;
- *ip++ = -1;
- }
- *ip++ = INT_MAX;
- for (cp=chood, g=0; g < 8; g++) {
- y = *cp++; x = *cp++;
- *ip++ = (y*width + x) * 4;
- color = fcol(row,col);
- if (fcol(row+y,col+x) != color && fcol(row+y*2,col+x*2) == color)
- *ip++ = (y*width + x) * 8 + color;
- else
- *ip++ = 0;
- }
- }
- brow[4] = (ushort (*)[4]) calloc (width*3, sizeof **brow);
- merror (brow[4], "vng_interpolate()");
- for (row=0; row < 3; row++)
- brow[row] = brow[4] + row*width;
- for (row=2; row < height-2; row++) { /* Do VNG interpolation */
- for (col=2; col < width-2; col++) {
- pix = image[row*width+col];
- ip = code[row % prow][col % pcol];
- memset (gval, 0, sizeof gval);
- while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */
- diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
- gval[ip[3]] += diff;
- ip += 5;
- if ((g = ip[-1]) == -1) continue;
- gval[g] += diff;
- while ((g = *ip++) != -1)
- gval[g] += diff;
- }
- ip++;
- gmin = gmax = gval[0]; /* Choose a threshold */
- for (g=1; g < 8; g++) {
- if (gmin > 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];
+/* RT: delete interpolation functions */
- 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 +4233,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 +4403,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 +4809,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);
@@ -5265,6 +4897,8 @@
wbi = -2;
}
if (tag == 2118) wbtemp = getint(type);
+ if (tag == 2120 + wbi) /* RT: wb tag for DCS760 */
+ FORC3 cam_mul[c] = 2048.0 / getreal(type); /* RT: wb tag for DCS760 */
if (tag == 2130 + wbi)
FORC3 mul[c] = getreal(type);
if (tag == 2140 + wbi && wbi >= 0)
@@ -5284,8 +4918,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 +4933,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;
@@ -5647,6 +5281,7 @@
break;
case 61450:
blrr = blrc = 2;
+ if (filters == UINT_MAX) filters = 0x94949494; /* RT: Fuji X100 fix for dcraw 9.19 to get proper black level parsing, hopefully works for other Fuji cameras too! */
case 50714: /* BlackLevel */
black = getreal(type);
if ((unsigned)(filters+1) < 1000) break;
@@ -5737,12 +5372,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 +5402,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 +5480,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 +5596,7 @@
{
const char *file, *ext;
char *jname, *jfile, *jext;
- FILE *save=ifp;
+/*RT*/ IMFILE *save=ifp;
ext = strrchr (ifname, '.');
file = strrchr (ifname, '/');
@@ -5981,13 +5618,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 +5968,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 +6224,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 +7026,27 @@
}
break;
}
+ if (load_raw == &CLASS sony_arw2_load_raw) { // 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 +7346,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 +7405,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 +7511,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 +7553,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 +7701,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;
@@ -8631,194 +8306,7 @@
}
#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 +8329,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 (&timestamp);
- 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 <x y w h> Average a grey box for white balance"));
- puts(_("-r <r g b g> Set custom white balance"));
- puts(_("+M/-M Use/don't use an embedded color matrix"));
- puts(_("-C <r b> Correct chromatic aberration"));
- puts(_("-P <file> Fix the dead pixels listed in this file"));
- puts(_("-K <file> Subtract dark frame (16-bit raw PGM)"));
- puts(_("-k <num> Set the darkness level"));
- puts(_("-S <num> Set the saturation level"));
- puts(_("-n <num> 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 <file> Apply output ICC profile from file"));
- puts(_("-p <file> 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 <num> Adjust brightness (default = 1.0)"));
- puts(_("-g <p ts> 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 <num> 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(&timestamp));
- 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;
-}