#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */
#define _XOPEN_SOURCE 500
    /* Make sure putenv is in stdlib.h, strcaseeq is in nstring.h */

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>

#ifdef HAVE_JPEG
#include <jpeglib.h>
#endif

#include "pm_config.h"
#include "pm.h"
#include "mallocvar.h"
#include "pm_c_util.h"
#include "nstring.h"

#include "global_variables.h"
#include "cameratopam.h"
#include "util.h"
#include "decode.h"
#include "bayer.h"
#include "ljpeg.h"
#include "dng.h"
#include "stdio_nofail.h"

#include "camera.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-const-variable"
#if HAVE_INT64
     typedef int64_t INT64;
     static bool const have64BitArithmetic = true;
#else
     /* We define INT64 to something that lets the code compile, but we
        should not execute any INT64 code, because it will get the wrong
        result.
     */
     typedef int INT64;
     static bool const have64BitArithmetic = false;
#endif
#pragma GCC diagnostic pop

#ifndef LONG_BIT
#define LONG_BIT (8 * sizeof (long))
#endif

#define FORC3 for (c=0; c < 3; c++)
#define FORC4 for (c=0; c < colors; c++)

static void
merror (const void *ptr, const char *where) {

    if (ptr == NULL)
        pm_error ("Out of memory in %s", where);
}



static void
adobeCopyPixel(Image             const image,
               unsigned int      const row,
               unsigned int      const col,
               unsigned short ** const rp,
               bool              const useSecondary) {

    unsigned r=row, c=col;

    if (fuji_secondary && useSecondary)
        ++(*rp);
    if (filters) {
        if (fuji_width) {
            r = row + fuji_width - 1 - (col >> 1);
            c = row + ((col+1) >> 1);
        }
        if (r < height && c < width)
            BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
        *rp += 1 + fuji_secondary;
    } else {
        unsigned int c;
        for (c = 0; c < tiff_samples; ++c) {
            image[row*width+col][c] = **rp < 0x1000 ? curve[**rp] : **rp;
            ++(*rp);
        }
    }
    if (fuji_secondary && useSecondary)
        --(*rp);
}



void
adobe_dng_load_raw_lj(Image const image) {

    int save, twide, trow=0, tcol=0, jrow, jcol;
    struct jhead jh;
    unsigned short *rp;

    while (1) {
        save = ftell_nofail(ifp);
        fseek_nofail (ifp, get4(ifp), SEEK_SET);
        if (!ljpeg_start (ifp, &jh)) break;
        if (trow >= raw_height) break;
        if (jh.high > raw_height-trow)
            jh.high = raw_height-trow;
        twide = jh.wide;
        if (filters) twide *= jh.clrs;
        else         colors = jh.clrs;
        if (fuji_secondary) twide /= 2;
        if (twide > raw_width-tcol)
            twide = raw_width-tcol;

        for (jrow=0; jrow < jh.high; jrow++) {
            ljpeg_row(ifp, &jh);
            for (rp=jh.row, jcol=0; jcol < twide; jcol++)
                adobeCopyPixel(image,
                               trow+jrow, tcol+jcol, &rp, use_secondary);
        }
        fseek_nofail (ifp, save+4, SEEK_SET);
        if ((tcol += twide) >= raw_width) {
            tcol = 0;
            trow += jh.high;
        }
        free (jh.row);
    }
}



void
adobe_dng_load_raw_nc(Image const image) {

    unsigned short *pixel, *rp;
    int row, col;

    pixel = calloc (raw_width * tiff_samples, sizeof *pixel);
    merror (pixel, "adobe_dng_load_raw_nc()");
    for (row=0; row < raw_height; row++) {
        read_shorts (ifp, pixel, raw_width * tiff_samples);
        for (rp=pixel, col=0; col < raw_width; col++)
            adobeCopyPixel(image, row, col, &rp, use_secondary);
    }
    free (pixel);
}



static int nikon_curve_offset;

void
nikon_compressed_load_raw(Image const image) {

    static const unsigned char nikon_tree[] = {
        0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,
        5,4,3,6,2,7,1,0,8,9,11,10,12
    };
    int csize, row, col, i, diff;
    unsigned short vpred[4], hpred[2], *curve;

    init_decoder();
    make_decoder (nikon_tree, 0);

    fseek_nofail (ifp, nikon_curve_offset, SEEK_SET);
    read_shorts (ifp, vpred, 4);
    csize = get2(ifp);
    curve = calloc (csize, sizeof *curve);
    merror (curve, "nikon_compressed_load_raw()");
    read_shorts (ifp, curve, csize);

    fseek_nofail (ifp, data_offset, SEEK_SET);
    getbits(ifp, -1);

    for (row=0; row < height; row++)
        for (col=0; col < raw_width; col++)
        {
            diff = ljpeg_diff (ifp, first_decode);
            if (col < 2) {
                i = 2*(row & 1) + (col & 1);
                vpred[i] += diff;
                hpred[col] = vpred[i];
            } else
                hpred[col & 1] += diff;
            if ((unsigned) (col-left_margin) >= width) continue;
            diff = hpred[col & 1];
            if (diff >= csize) diff = csize-1;
            BAYER(row,col-left_margin) = curve[diff];
        }
    maximum = curve[csize-1];
    free (curve);
}



void
nikon_load_raw(Image const image) {

    int irow, row, col, i;

    getbits(ifp, -1);
    for (irow=0; irow < height; irow++) {
      row = irow;
      if (model[0] == 'E') {
        row = irow * 2 % height + irow / (height/2);
        if (row == 1 && atoi(model+1) < 5000) {
          fseek_nofail (ifp, 0, SEEK_END);
          fseek_nofail (ifp, ftell_nofail(ifp)/2, SEEK_SET);
          getbits(ifp, -1);
        }
      }
      for (col=0; col < raw_width; col++) {
        i = getbits(ifp, 12);
        if ((unsigned) (col-left_margin) < width)
          BAYER(row,col-left_margin) = i;
        if (tiff_data_compression == 34713 && (col % 10) == 9)
          getbits(ifp, 8);
      }
    }
}



/*
   Figure out if a NEF file is compressed.  These fancy heuristics
   are only needed for the D100, thanks to a bug in some cameras
   that tags all images as "compressed".
 */
int
nikon_is_compressed()
{
    unsigned char test[256];
    int i;

    if (tiff_data_compression != 34713)
        return 0;
    if (strcmp(model,"D100"))
        return 1;
    fseek_nofail (ifp, data_offset, SEEK_SET);
    fread_nofail (test, 1, 256, ifp);
    for (i=15; i < 256; i+=16)
        if (test[i]) return 1;
    return 0;
}



/*
   Returns 1 for a Coolpix 990, 0 for a Coolpix 995.
 */
int
nikon_e990()
{
    int i, histo[256];
    const unsigned char often[] = { 0x00, 0x55, 0xaa, 0xff };

    memset (histo, 0, sizeof histo);
    fseek_nofail (ifp, 2064*1540*3/4, SEEK_SET);
    for (i=0; i < 2000; i++)
        histo[fgetc_nofail(ifp)]++;
    for (i=0; i < 4; i++)
        if (histo[often[i]] > 400)
            return 1;
    return 0;
}



/*
  Returns 1 for a Coolpix 2100, 0 for anything else.
*/
int
nikon_e2100()
{
    unsigned char t[12];
    int i;

    fseek_nofail (ifp, 0, SEEK_SET);
    for (i=0; i < 1024; i++) {
        fread_nofail (t, 1, 12, ifp);
        if (((t[2] & t[4] & t[7] & t[9]) >> 4
             & t[1] & t[6] & t[8] & t[11] & 3) != 3)
            return 0;
    }
    return 1;
}



/*
  Separates a Pentax Optio 33WR from a Nikon E3700.
*/
int
pentax_optio33()
{
    int i, sum[] = { 0, 0 };
    unsigned char tail[952];

    fseek_nofail (ifp, -sizeof tail, SEEK_END);
    fread_nofail (tail, 1, sizeof tail, ifp);
    for (i=0; i < sizeof tail; i++)
        sum[(i>>2) & 1] += tail[i];
    return sum[0] < sum[1]*4;
}



/*
  Separates a Minolta DiMAGE Z2 from a Nikon E4300.
*/
int
minolta_z2()
{
    int i;
    char tail[424];

    fseek_nofail (ifp, -sizeof tail, SEEK_END);
    fread_nofail (tail, 1, sizeof tail, ifp);
    for (i=0; i < sizeof tail; i++)
        if (tail[i]) return 1;
    return 0;
}



void
nikon_e2100_load_raw(Image const image) {

    unsigned char   data[3432], *dp;
    unsigned short pixel[2288], *pix;
    int row, col;

    for (row=0; row <= height; row+=2) {
        if (row == height) {
            fseek_nofail (ifp, ((width==1616) << 13) - (-ftell_nofail(ifp) & -2048), SEEK_SET);
            row = 1;
        }
        fread_nofail (data, 1, width*3/2, ifp);
        for (dp=data, pix=pixel; pix < pixel+width; dp+=12, pix+=8) {
            pix[0] = (dp[2] >> 4) + (dp[ 3] << 4);
            pix[1] = (dp[2] << 8) +  dp[ 1];
            pix[2] = (dp[7] >> 4) + (dp[ 0] << 4);
            pix[3] = (dp[7] << 8) +  dp[ 6];
            pix[4] = (dp[4] >> 4) + (dp[ 5] << 4);
            pix[5] = (dp[4] << 8) +  dp[11];
            pix[6] = (dp[9] >> 4) + (dp[10] << 4);
            pix[7] = (dp[9] << 8) +  dp[ 8];
        }
        for (col=0; col < width; col++)
            BAYER(row,col) = (pixel[col] & 0xfff);
    }
}



void
nikon_e950_load_raw(Image const image) {

    int irow, row, col;

    getbits(ifp, -1);
    for (irow=0; irow < height; irow++) {
        row = irow * 2 % height;
        for (col=0; col < width; col++)
            BAYER(row,col) = getbits(ifp, 10);
        for (col=28; col--; )
            getbits(ifp, 8);
    }
    maximum = 0x3dd;
}



/*
  The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
*/
void
fuji_s2_load_raw(Image const image) {
    unsigned short pixel[2944];
    int row, col, r, c;

    fseek_nofail (ifp, (2944*24+32)*2, SEEK_CUR);
    for (row=0; row < 2144; row++) {
        read_shorts(ifp, pixel, 2944);
        for (col=0; col < 2880; col++) {
            r = row + ((col+1) >> 1);
            c = 2143 - row + (col >> 1);
            BAYER(r,c) = pixel[col];
        }
    }
}



void
fuji_s3_load_raw(Image const image) {
    unsigned short pixel[4352];
    int row, col, r, c;

    fseek_nofail (ifp, (4352*2+32)*2, SEEK_CUR);
    for (row=0; row < 1440; row++) {
        read_shorts(ifp, pixel, 4352);
        for (col=0; col < 4288; col++) {
            r = 2143 + row - (col >> 1);
            c = row + ((col+1) >> 1);
            BAYER(r,c) = pixel[col];
        }
    }
}



static void
fuji_common_load_raw(Image        const image,
                     unsigned int const ncol,
                     unsigned int const icol,
                     unsigned int const nrow) {

    unsigned short pixel[2048];
    unsigned int row;

    for (row = 0; row < nrow; ++row) {
        unsigned int col;
        read_shorts(ifp, pixel, ncol);
        for (col = 0; col <= icol; ++col) {
            int const r = icol - col + (row >> 1);
            int const c = col + ((row+1) >> 1);
            BAYER(r,c) = pixel[col];
        }
    }
}



void
fuji_s5000_load_raw(Image const image) {

    fseek_nofail (ifp, (1472*4+24)*2, SEEK_CUR);
    fuji_common_load_raw(image, 1472, 1423, 2152);
}



void
fuji_s7000_load_raw(Image const image) {

    fuji_common_load_raw(image, 2048, 2047, 3080);
}



/*
  The Fuji Super CCD SR has two photodiodes for each pixel.
  The secondary has about 1/16 the sensitivity of the primary,
  but this ratio may vary.
*/
void
fuji_f700_load_raw(Image const image) {
    unsigned short pixel[2944];
    int row, col, r, c, val;

    for (row=0; row < 2168; row++) {
        read_shorts(ifp, pixel, 2944);
        for (col=0; col < 1440; col++) {
            r = 1439 - col + (row >> 1);
            c = col + ((row+1) >> 1);
            val = pixel[col+16 + use_secondary*1472];
            BAYER(r,c) = val;
        }
    }
}



void
rollei_load_raw(Image const image) {
    unsigned char pixel[10];
    unsigned iten=0, isix, i, buffer=0, row, col, todo[16];

    isix = raw_width * raw_height * 5 / 8;
    while (fread_or_eof_nofail (pixel, 1, 10, ifp) == 10) {
        for (i=0; i < 10; i+=2) {
            todo[i]   = iten++;
            todo[i+1] = pixel[i] << 8 | pixel[i+1];
            buffer    = pixel[i] >> 2 | buffer << 6;
        }
        for (   ; i < 16; i+=2) {
            todo[i]   = isix++;
            todo[i+1] = buffer >> (14-i)*5;
        }
        for (i=0; i < 16; i+=2) {
            row = todo[i] / raw_width - top_margin;
            col = todo[i] % raw_width - left_margin;
            if (row < height && col < width)
                BAYER(row,col) = (todo[i+1] & 0x3ff);
        }
    }
    maximum = 0x3ff;
}



void
phase_one_load_raw(Image const image) {
    int row, col, a, b;
    unsigned short *pixel, akey, bkey;

    fseek_nofail (ifp, 8, SEEK_CUR);
    fseek_nofail (ifp, get4(ifp) + 296, SEEK_CUR);
    akey = get2(ifp);
    bkey = get2(ifp);
    fseek_nofail (ifp, data_offset + 12 + top_margin*raw_width*2, SEEK_SET);
    pixel = calloc (raw_width, sizeof *pixel);
    merror (pixel, "phase_one_load_raw()");
    for (row=0; row < height; row++) {
        read_shorts(ifp, pixel, raw_width);
        for (col=0; col < raw_width; col+=2) {
            a = pixel[col+0] ^ akey;
            b = pixel[col+1] ^ bkey;
            pixel[col+0] = (b & 0xaaaa) | (a & 0x5555);
            pixel[col+1] = (a & 0xaaaa) | (b & 0x5555);
        }
        for (col=0; col < width; col++)
            BAYER(row,col) = pixel[col+left_margin];
    }
    free (pixel);
}



void
ixpress_load_raw(Image const image) {
    unsigned short pixel[4090];
    int row, col;

    order = 0x4949;
    fseek_nofail (ifp, 304 + 6*2*4090, SEEK_SET);
    for (row=height; --row >= 0; ) {
        read_shorts(ifp, pixel, 4090);
        for (col=0; col < width; col++)
            BAYER(row,col) = pixel[width-1-col];
    }
}



void
leaf_load_raw(Image const image) {
    unsigned short *pixel;
    int r, c, row, col;

    pixel = calloc (raw_width, sizeof *pixel);
    merror (pixel, "leaf_load_raw()");
    for (r=0; r < height-32; r+=32)
        FORC3 for (row=r; row < r+32; row++) {
            read_shorts(ifp, pixel, raw_width);
            for (col=0; col < width; col++)
                image[row*width+col][c] = pixel[col];
        }
    free (pixel);
}



/*
  For this function only, raw_width is in bytes, not pixels!
*/
void
packed_12_load_raw(Image const image) {
    int row, col;

    getbits(ifp, -1);
    for (row=0; row < height; row++) {
        for (col=0; col < width; col++)
            BAYER(row,col) = getbits(ifp, 12);
        for (col = width*3/2; col < raw_width; col++)
            getbits(ifp, 8);
    }
}



void
unpacked_load_raw(Image const image) {
    unsigned short *pixel;
    int row, col;

    pixel = calloc (raw_width, sizeof *pixel);
    merror (pixel, "unpacked_load_raw()");
    for (row=0; row < height; row++) {
        read_shorts(ifp, pixel, raw_width);
        for (col=0; col < width; col++)
            BAYER(row,col) = pixel[col];
    }
    free (pixel);
}



void
olympus_e300_load_raw(Image const image) {
    unsigned char  *data,  *dp;
    unsigned short *pixel, *pix;
    int dwide, row, col;

    dwide = raw_width * 16 / 10;
    data = malloc (dwide + raw_width*2);
    merror (data, "olympus_e300_load_raw()");
    pixel = (unsigned short *) (data + dwide);
    for (row=0; row < height; row++) {
        fread_nofail (data, 1, dwide, ifp);
        for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) {
            if (((dp-data) & 15) == 15) dp++;
            pix[0] = dp[1] << 8 | dp[0];
            pix[1] = dp[2] << 4 | dp[1] >> 4;
        }
        for (col=0; col < width; col++)
            BAYER(row,col) = (pixel[col] & 0xfff);
    }
    free (data);
}



void
olympus_cseries_load_raw(Image const image) {
    int irow, row, col;

    for (irow=0; irow < height; irow++) {
        row = irow * 2 % height + irow / (height/2);
        if (row < 2) {
            fseek_nofail (ifp, data_offset - row*(-width*height*3/4 & -2048), SEEK_SET);
            getbits(ifp, -1);
        }
        for (col=0; col < width; col++)
            BAYER(row,col) = getbits(ifp, 12);
    }
}



void
eight_bit_load_raw(Image const image) {
    unsigned char *pixel;
    int row, col;

    pixel = calloc (raw_width, sizeof *pixel);
    merror (pixel, "eight_bit_load_raw()");
    for (row=0; row < height; row++) {
        fread_nofail (pixel, 1, raw_width, ifp);
        for (col=0; col < width; col++)
            BAYER(row,col) = pixel[col];
    }
    free (pixel);
    maximum = 0xff;
}



void
casio_qv5700_load_raw(Image const image) {
    unsigned char  data[3232],  *dp;
    unsigned short pixel[2576], *pix;
    int row, col;

    for (row=0; row < height; row++) {
        fread_nofail (data, 1, 3232, ifp);
        for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) {
            pix[0] = (dp[0] << 2) + (dp[1] >> 6);
            pix[1] = (dp[1] << 4) + (dp[2] >> 4);
            pix[2] = (dp[2] << 6) + (dp[3] >> 2);
            pix[3] = (dp[3] << 8) + (dp[4]     );
        }
        for (col=0; col < width; col++)
            BAYER(row,col) = (pixel[col] & 0x3ff);
    }
    maximum = 0x3fc;
}



void
nucore_load_raw(Image const image) {
    unsigned short *pixel;
    int irow, row, col;

    pixel = calloc (width, 2);
    merror (pixel, "nucore_load_raw()");
    for (irow=0; irow < height; irow++) {
        read_shorts(ifp, pixel, width);
        row = irow/2 + height/2 * (irow & 1);
        for (col=0; col < width; col++)
            BAYER(row,col) = pixel[col];
    }
    free (pixel);
}



static int  radc_token (int tree)
{
    int t;
    static struct decode *dstart[18], *dindex;
    static const int *s, source[] = {
        1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
        1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
        2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
        2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
        2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
        2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
        2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
        2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
        2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
        2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
        1,0, 2,2, 2,-2,
        1,-3, 1,3,
        2,-17, 2,-5, 2,5, 2,17,
        2,-7, 2,2, 2,9, 2,18,
        2,-18, 2,-9, 2,-2, 2,7,
        2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
        2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
        2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
    };

    if (free_decode == first_decode)
        for (s=source, t=0; t < 18; t++) {
            dstart[t] = free_decode;
            s = make_decoder_int (s, 0);
        }
    if (tree == 18) {
        if (model[2] == '4')
            return (getbits(ifp, 5) << 3) + 4; /* DC40 */
        else
            return (getbits(ifp, 6) << 2) + 2; /* DC50 */
    }
    for (dindex = dstart[tree]; dindex->branch[0]; )
        dindex = dindex->branch[getbits(ifp, 1)];
    return dindex->leaf;
}



#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)

#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2            \
                   : (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)

void
kodak_radc_load_raw(Image const image) {
    int row, col, tree, nreps, rep, step, c, s, r, x, y, val;
    unsigned int i;
    short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];

    init_decoder();
    getbits(ifp, -1);
    for (i = 0; i < ARRAY_SIZE(buf); ++i) {
        unsigned int j;
        for (j = 0; j < ARRAY_SIZE(buf[0]); ++j) {
            unsigned int k;
            for (k = 0; k < ARRAY_SIZE(buf[0][0]); ++k)
                buf[i][j][k] = 2048;
        }
    }
    for (row=0; row < height; row+=4) {
        unsigned int i;
        for (i = 0; i < 3; ++i)
            mul[i] = getbits(ifp, 6);
        FORC3 {
            val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
            s = val > 65564 ? 10:12;
            x = ~(-1 << (s-1));
            val <<= 12-s;
            for (i=0; i < ARRAY_SIZE(buf[c][0]); i++)
                buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
            last[c] = mul[c];
            for (r=0; r <= !c; r++) {
                buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
                for (tree=1, col=width/2; col > 0; ) {
                    if ((tree = radc_token(tree))) {
                        col -= 2;
                        if (tree == 8)
                            FORYX buf[c][y][x] =
                                radc_token(tree+10) * mul[c];
                        else
                            FORYX buf[c][y][x] =
                                radc_token(tree+10) * 16 + PREDICTOR;
                    } else
                        do {
                            nreps = (col > 2) ? radc_token(9) + 1 : 1;
                            for (rep=0;
                                 rep < 8 && rep < nreps && col > 0;
                                 rep++) {
                                col -= 2;
                                FORYX buf[c][y][x] = PREDICTOR;
                                if (rep & 1) {
                                    step = radc_token(10) << 4;
                                    FORYX buf[c][y][x] += step;
                                }
                            }
                        } while (nreps == 9);
                }
                for (y=0; y < 2; y++)
                    for (x=0; x < width/2; x++) {
                        val = (buf[c][y+1][x] << 4) / mul[c];
                        if (val < 0) val = 0;
                        if (c)
                            BAYER(row+y*2+c-1,x*2+2-c) = val;
                        else
                            BAYER(row+r*2+y,x*2+y) = val;
                    }
                memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
            }
        }
        for (y=row; y < row+4; y++)
            for (x=0; x < width; x++)
                if ((x+y) & 1) {
                    val = (BAYER(y,x)-2048)*2 + (BAYER(y,x-1)+BAYER(y,x+1))/2;
                    if (val < 0) val = 0;
                    BAYER(y,x) = val;
                }
    }
    maximum = 0x1fff;     /* wild guess */
}



#undef FORYX
#undef PREDICTOR

#ifndef HAVE_JPEG
void
kodak_jpeg_load_raw(Image const Image) {}
#else

static bool
fill_input_buffer (j_decompress_ptr cinfo)
{
    static char jpeg_buffer[4096];
    size_t nbytes;

    nbytes = fread_or_eof_nofail (jpeg_buffer, 1, 4096, ifp);
    swab (jpeg_buffer, jpeg_buffer, nbytes);
    cinfo->src->next_input_byte = jpeg_buffer;
    cinfo->src->bytes_in_buffer = nbytes;
    return TRUE;
}



void
kodak_jpeg_load_raw(Image const image)
{
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPARRAY buf;
    JSAMPLE (*pixel)[3];
    int row, col;

    cinfo.err = jpeg_std_error (&jerr);
    jpeg_create_decompress (&cinfo);
    jpeg_stdio_src (&cinfo, ifp);
    cinfo.src->fill_input_buffer = fill_input_buffer;
    jpeg_read_header (&cinfo, TRUE);
    jpeg_start_decompress (&cinfo);
    if ((cinfo.output_width      != width  ) ||
        (cinfo.output_height*2   != height ) ||
        (cinfo.output_components != 3      )) {
        pm_error ("incorrect JPEG dimensions");
    }
    buf = (*cinfo.mem->alloc_sarray)
        ((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);

    while (cinfo.output_scanline < cinfo.output_height) {
        row = cinfo.output_scanline * 2;
        jpeg_read_scanlines (&cinfo, buf, 1);
        pixel = (void *) buf[0];
        for (col=0; col < width; col+=2) {
            BAYER(row+0,col+0) = pixel[col+0][1] << 1;
            BAYER(row+1,col+1) = pixel[col+1][1] << 1;
            BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
            BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
        }
    }
    jpeg_finish_decompress (&cinfo);
    jpeg_destroy_decompress (&cinfo);
    maximum = 0xff << 1;
}



#endif

void
kodak_dc120_load_raw(Image const image)
{
    static const int mul[4] = { 162, 192, 187,  92 };
    static const int add[4] = {   0, 636, 424, 212 };
    unsigned char pixel[848];
    int row, shift, col;

    for (row=0; row < height; row++) {
        fread_nofail (pixel, 848, 1, ifp);
        shift = row * mul[row & 3] + add[row & 3];
        for (col=0; col < width; col++)
            BAYER(row,col) = (unsigned short) pixel[(col + shift) % 848];
    }
    maximum = 0xff;
}



void
kodak_dc20_coeff (float const juice)
{
    static const float my_coeff[3][4] =
        { {  2.25,  0.75, -1.75, -0.25 },
          { -0.25,  0.75,  0.75, -0.25 },
          { -0.25, -1.75,  0.75,  2.25 } };
    static const float flat[3][4] =
        { {  1, 0,   0,   0 },
          {  0, 0.5, 0.5, 0 },
          {  0, 0,   0,   1 } };
    int r, g;

    for (r=0; r < 3; r++)
        for (g=0; g < 4; g++)
            coeff[r][g] = my_coeff[r][g] * juice + flat[r][g] * (1-juice);
    use_coeff = 1;
}



void
kodak_easy_load_raw(Image const image)
{
    unsigned char *pixel;
    unsigned row, col, icol;

    if (raw_width > width)
        black = 0;
    pixel = calloc (raw_width, sizeof *pixel);
    merror (pixel, "kodak_easy_load_raw()");
    for (row=0; row < height; row++) {
        fread_nofail (pixel, 1, raw_width, ifp);
        for (col=0; col < raw_width; col++) {
            icol = col - left_margin;
            if (icol < width)
                BAYER(row,icol) = (unsigned short) curve[pixel[col]];
            else
                black += curve[pixel[col]];
        }
    }
    free (pixel);
    if (raw_width > width)
        black /= (raw_width - width) * height;
    if (!strncmp(model,"DC2",3))
        black = 0;
    maximum = curve[0xff];
}



void
kodak_compressed_load_raw(Image const image) {
/*----------------------------------------------------------------------------
   Caller must ensure that the system has 64 bit arithmetic (inasmuch as the
   compile environment has type 'int64_t').
-----------------------------------------------------------------------------*/
    unsigned char c, blen[256];
    unsigned short raw[6];
    unsigned row, col, len, save, i, israw=0, bits=0, pred[2];
    INT64 bitbuf=0;
    int diff;

    assert(have64BitArithmetic);

    for (row=0; row < height; row++)
        for (col=0; col < width; col++)
        {
            if ((col & 255) == 0) {       /* Get the bit-lengths of the */
                len = width - col;      /* next 256 pixel values      */
                if (len > 256) len = 256;
                save = ftell_nofail(ifp);
                for (israw=i=0; i < len; i+=2) {
                    c = fgetc_nofail(ifp);
                    if ((blen[i+0] = c & 15) > 12 ||
                        (blen[i+1] = c >> 4) > 12 )
                        israw = 1;
                }
                bitbuf = bits = pred[0] = pred[1] = 0;
                if (len % 8 == 4) {
                    bitbuf  = fgetc_nofail(ifp) << 8;
                    bitbuf += fgetc_nofail(ifp);
                    bits = 16;
                }
                if (israw)
                    fseek_nofail (ifp, save, SEEK_SET);
            }
            if (israw) {          /* If the data is not compressed */
                switch (col & 7) {
                case 0:
                    read_shorts(ifp, raw, 6);
                    diff = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
                    break;
                case 1:
                    diff = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
                    break;
                default:
                    diff = raw[(col & 7) - 2] & 0xfff;
                }
            } else {              /* If the data is compressed */
                len = blen[col & 255];      /* Number of bits for this pixel */
                if (bits < len) {       /* Got enough bits in the buffer? */
                    for (i=0; i < 32; i+=8)
                        bitbuf += (INT64) fgetc_nofail(ifp) << (bits+(i^8));
                    bits += 32;
                }
                diff = bitbuf & (0xffff >> (16-len));  /* Pull bits from buffer */
                bitbuf >>= len;
                bits -= len;
                if ((diff & (1 << (len-1))) == 0)
                    diff -= (1 << len) - 1;
                pred[col & 1] += diff;
                diff = pred[col & 1];
            }
            BAYER(row,col) = curve[diff];
        }
}



void
kodak_yuv_load_raw(Image const image) {
/*----------------------------------------------------------------------------
   Caller must ensure that the system has 64 bit arithmetic (inasmuch as the
   compile environment has type 'int64_t').
-----------------------------------------------------------------------------*/
    unsigned char c, blen[384];
    unsigned row, col, len, bits=0;
    INT64 bitbuf=0;
    int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3];
    unsigned short *ip;

    assert(have64BitArithmetic);

    for (row=0; row < height; row+=2)
        for (col=0; col < width; col+=2) {
            if ((col & 127) == 0) {
                len = (width - col + 1) * 3 & -4;
                if (len > 384) len = 384;
                for (i=0; i < len; ) {
                    c = fgetc_nofail(ifp);
                    blen[i++] = c & 15;
                    blen[i++] = c >> 4;
                }
                li = bitbuf = bits = y[1] = y[3] = cb = cr = 0;
                if (len % 8 == 4) {
                    bitbuf  = fgetc_nofail(ifp) << 8;
                    bitbuf += fgetc_nofail(ifp);
                    bits = 16;
                }
            }
            for (si=0; si < 6; si++) {
                len = blen[li++];
                if (bits < len) {
                    for (i=0; i < 32; i+=8)
                        bitbuf += (INT64) fgetc_nofail(ifp) << (bits+(i^8));
                    bits += 32;
                }
                diff = bitbuf & (0xffff >> (16-len));
                bitbuf >>= len;
                bits -= len;
                if ((diff & (1 << (len-1))) == 0)
                    diff -= (1 << len) - 1;
                six[si] = diff;
            }
            y[0] = six[0] + y[1];
            y[1] = six[1] + y[0];
            y[2] = six[2] + y[3];
            y[3] = six[3] + y[2];
            cb  += six[4];
            cr  += six[5];
            for (i=0; i < 4; i++) {
                ip = image[(row+(i >> 1))*width + col+(i & 1)];
                rgb[0] = y[i] + cr;
                rgb[1] = y[i];
                rgb[2] = y[i] + cb;
                FORC3 if (rgb[c] > 0) ip[c] = curve[rgb[c]];
            }
        }
    maximum = 0xe74;
}



static void  sony_decrypt (unsigned *data, int len, int start, int key)
{
    static uint32_t pad[128];
    unsigned int p;
    unsigned int i;

    if (start) {
        for (p=0; p < 4; p++)
            pad[p] = key = key * 48828125 + 1;
        pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
        for (p=4; p < 127; p++)
            pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;

        /* Convert to big-endian */

        for (p=0; p < 127; p++) {
            union {
                unsigned char bytes[4];
                uint32_t word;
            } u;

            u.bytes[0] = pad[p] >> 24;
            u.bytes[1] = pad[p] >> 16;
            u.bytes[2] = pad[p] >>  8;
            u.bytes[3] = pad[p] >>  0;

            pad[p] = u.word;
        }
    }
    for (i = 0, p = 0; i < len; ++i, ++p) {
        *data++ ^= pad[p & 0x7f] = pad[(p+1) & 0x7f] ^ pad[(p+65) & 0x7f];
    }
}



void
sony_load_raw(Image const image)
{
    unsigned char head[40];
    struct pixel {
        unsigned char bytes[2];
    };
    struct pixel * pixelrow;
    unsigned i, key, row, col;

    fseek_nofail (ifp, 200896, SEEK_SET);
    fseek_nofail (ifp, (unsigned) fgetc_nofail(ifp)*4 - 1, SEEK_CUR);
    order = 0x4d4d;
    key = get4(ifp);
    fseek_nofail (ifp, 164600, SEEK_SET);
    fread_nofail (head, 1, 40, ifp);
    sony_decrypt ((void *) head, 10, 1, key);
    for (i=26; i-- > 22; )
        key = key << 8 | head[i];
    fseek_nofail (ifp, data_offset, SEEK_SET);
    MALLOCARRAY(pixelrow, raw_width);
    merror (pixelrow, "sony_load_raw()");
    for (row=0; row < height; row++) {
        fread_nofail (pixelrow, 2, raw_width, ifp);
        sony_decrypt ((void *) pixelrow, raw_width/2, !row, key);
        for (col=9; col < left_margin; col++)
            black += pixelrow[col].bytes[0] * 256 + pixelrow[col].bytes[1];
        for (col=0; col < width; col++)
            BAYER(row,col) =
                pixelrow[col+left_margin].bytes[0] * 256 +
                pixelrow[col+left_margin].bytes[1];
    }
    free (pixelrow);
    if (left_margin > 9)
        black /= (left_margin-9) * height;
    maximum = 0x3ff0;
}



void
parse_minolta(FILE * const ifp)
{
    int save, tag, len, offset, high=0, wide=0;

    fseek_nofail (ifp, 4, SEEK_SET);
    offset = get4(ifp) + 8;
    while ((save=ftell_nofail(ifp)) < offset) {
        tag = get4(ifp);
        len = get4(ifp);
        switch (tag) {
        case 0x505244:                /* PRD */
            fseek_nofail (ifp, 8, SEEK_CUR);
            high = get2(ifp);
            wide = get2(ifp);
            break;
        case 0x574247:                /* WBG */
            get4(ifp);
            camera_red  = get2(ifp);
            camera_red /= get2(ifp);
            camera_blue = get2(ifp);
            camera_blue = get2(ifp) / camera_blue;
            break;
        case 0x545457:                /* TTW */
            parse_tiff(ifp, ftell_nofail(ifp));
        }
        fseek_nofail (ifp, save+len+8, SEEK_SET);
    }
    raw_height = high;
    raw_width  = wide;
    data_offset = offset;
}



/*
  CIFF block 0x1030 contains an 8x8 white sample.
  Load this into white[][] for use in scale_colors().
*/
static void  ciff_block_1030()
{
    static const unsigned short key[] = { 0x410, 0x45f3 };
    int i, bpp, row, col, vbits=0;
    unsigned long bitbuf=0;

    get2(ifp);
    if (get4(ifp) != 0x80008) return;
    if (get4(ifp) == 0) return;
    bpp = get2(ifp);
    if (bpp != 10 && bpp != 12) return;
    for (i=row=0; row < 8; row++)
        for (col=0; col < 8; col++) {
            if (vbits < bpp) {
                bitbuf = bitbuf << 16 | (get2(ifp) ^ key[i++ & 1]);
                vbits += 16;
            }
            white[row][col] =
                bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
            vbits -= bpp;
        }
}



/*
  Parse a CIFF file, better known as Canon CRW format.
*/
void
parse_ciff(FILE * const ifp,
           int    const offset,
           int    const length)
{
    int tboff, nrecs, i, type, len, roff, aoff, save, wbi=-1;
    static const int remap[] = { 1,2,3,4,5,1 };
    static const int remap_10d[] = { 0,1,3,4,5,6,0,0,2,8 };
    static const int remap_s70[] = { 0,1,2,9,4,3,6,7,8,9,10,0,0,0,7,0,0,8 };
    unsigned short key[] = { 0x410, 0x45f3 };

    if (strcmp(model,"Canon PowerShot G6") &&
        strcmp(model,"Canon PowerShot S70") &&
        strcmp(model,"Canon PowerShot Pro1"))
        key[0] = key[1] = 0;
    fseek_nofail (ifp, offset+length-4, SEEK_SET);
    tboff = get4(ifp) + offset;
    fseek_nofail (ifp, tboff, SEEK_SET);
    nrecs = get2(ifp);
    for (i = 0; i < nrecs; i++) {
        type = get2(ifp);
        len  = get4(ifp);
        roff = get4(ifp);
        aoff = offset + roff;
        save = ftell_nofail(ifp);
        if (type == 0x080a) {       /* Get the camera make and model */
            fseek_nofail (ifp, aoff, SEEK_SET);
            fread_nofail (make, 64, 1, ifp);
            fseek_nofail (ifp, aoff+strlen(make)+1, SEEK_SET);
            fread_nofail (model, 64, 1, ifp);
        }
        if (type == 0x102a) {       /* Find the White Balance index */
            fseek_nofail (ifp, aoff+14, SEEK_SET);   /* 0=auto, 1=daylight, 2=cloudy ... */
            wbi = get2(ifp);
            if (((!strcmp(model,"Canon EOS DIGITAL REBEL") ||
                  !strcmp(model,"Canon EOS 300D DIGITAL"))) && wbi == 6)
                wbi++;
        }
        if (type == 0x102c) {       /* Get white balance (G2) */
            if (!strcmp(model,"Canon PowerShot G1") ||
                !strcmp(model,"Canon PowerShot Pro90 IS")) {
                fseek_nofail (ifp, aoff+120, SEEK_SET);
                white[0][1] = get2(ifp);
                white[0][0] = get2(ifp);
                white[1][0] = get2(ifp);
                white[1][1] = get2(ifp);
            } else {
                fseek_nofail (ifp, aoff+100, SEEK_SET);
                goto common;
            }
        }
        if (type == 0x0032) {       /* Get white balance (D30 & G3) */
            if (!strcmp(model,"Canon EOS D30")) {
                fseek_nofail (ifp, aoff+72, SEEK_SET);
            common:
                camera_red   = get2(ifp) ^ key[0];
                camera_red   =(get2(ifp) ^ key[1]) / camera_red;
                camera_blue  = get2(ifp) ^ key[0];
                camera_blue /= get2(ifp) ^ key[1];
            } else if (!strcmp(model,"Canon PowerShot G6") ||
                       !strcmp(model,"Canon PowerShot S70")) {
                fseek_nofail (ifp, aoff+96 + remap_s70[wbi]*8, SEEK_SET);
                goto common;
            } else if (!strcmp(model,"Canon PowerShot Pro1")) {
                fseek_nofail (ifp, aoff+96 + wbi*8, SEEK_SET);
                goto common;
            } else {
                fseek_nofail (ifp, aoff+80 + (wbi < 6 ? remap[wbi]*8 : 0), SEEK_SET);
                if (!camera_red)
                    goto common;
            }
        }
        if (type == 0x10a9) {       /* Get white balance (D60) */
            if (!strcmp(model,"Canon EOS 10D"))
                wbi = remap_10d[wbi];
            fseek_nofail (ifp, aoff+2 + wbi*8, SEEK_SET);
            camera_red  = get2(ifp);
            camera_red /= get2(ifp);
            camera_blue = get2(ifp);
            camera_blue = get2(ifp) / camera_blue;
        }
        if (type == 0x1030 && (wbi == 6 || wbi == 15)) {
            fseek_nofail (ifp, aoff, SEEK_SET);  /* Get white sample */
            ciff_block_1030();
        }
        if (type == 0x1031) {       /* Get the raw width and height */
            fseek_nofail (ifp, aoff+2, SEEK_SET);
            raw_width  = get2(ifp);
            raw_height = get2(ifp);
        }
        if (type == 0x180e) {       /* Get the timestamp */
            fseek_nofail (ifp, aoff, SEEK_SET);
            timestamp = get4(ifp);
        }
        if (type == 0x580e)
            timestamp = len;
        if (type == 0x1810) {       /* Get the rotation */
            fseek_nofail (ifp, aoff+12, SEEK_SET);
            flip = get4(ifp);
        }
        if (type == 0x1835) {       /* Get the decoder table */
            fseek_nofail (ifp, aoff, SEEK_SET);
            crw_init_tables (get4(ifp));
        }
        if (type >> 8 == 0x28 || type >> 8 == 0x30) /* Get sub-tables */
            parse_ciff(ifp, aoff, len);
        fseek_nofail (ifp, save, SEEK_SET);
    }
    if (wbi == 0 && !strcmp(model,"Canon EOS D30"))
        camera_red = -1;            /* Use my auto WB for this photo */
}



void
parse_rollei(FILE * const ifp)
{
    char line[128], *val;
    int tx=0, ty=0;
    struct tm t;
    time_t ts;

    fseek_nofail (ifp, 0, SEEK_SET);
    do {
        fgets_nofail (line, 128, ifp);
        if ((val = strchr(line,'=')))
            *val++ = 0;
        else
            val = line + strlen(line);
        if (!strcmp(line,"DAT"))
            sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
        if (!strcmp(line,"TIM"))
            sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
        if (!strcmp(line,"HDR"))
            data_offset = atoi(val);
        if (!strcmp(line,"X  "))
            raw_width = atoi(val);
        if (!strcmp(line,"Y  "))
            raw_height = atoi(val);
        if (!strcmp(line,"TX "))
            tx = atoi(val);
        if (!strcmp(line,"TY "))
            ty = atoi(val);
    } while (strncmp(line,"EOHD",4));
    t.tm_year -= 1900;
    t.tm_mon -= 1;
    putenv((char*)"TZ=");
    if ((ts = mktime(&t)) > 0)
        timestamp = ts;
    data_offset += tx * ty * 2;
    strcpy (make, "Rollei");
    strcpy (model,"d530flex");
}



void
parse_mos(FILE * const ifp,
          int    const offset)
{
    char data[40];
    int skip, from, i, neut[4];

    fseek_nofail (ifp, offset, SEEK_SET);
    while (1) {
        fread_nofail (data, 1, 8, ifp);
        if (strcmp(data,"PKTS")) break;
        fread_nofail (data, 1, 40, ifp);
        skip = get4(ifp);
        from = ftell_nofail(ifp);
        if (!strcmp(data,"NeutObj_neutrals")) {
            for (i=0; i < 4; i++)
                fscanf (ifp, "%d", neut+i);
            camera_red  = (float) neut[2] / neut[1];
            camera_blue = (float) neut[2] / neut[3];
        }
        parse_mos(ifp, from);
        fseek_nofail (ifp, skip+from, SEEK_SET);
    }
}



void
nikon_e950_coeff()
{
    int r, g;
    static const float my_coeff[3][4] =
        { { -1.936280,  1.800443, -1.448486,  2.584324 },
          {  1.405365, -0.524955, -0.289090,  0.408680 },
          { -1.204965,  1.082304,  2.941367, -1.818705 } };

    for (r=0; r < 3; r++)
        for (g=0; g < 4; g++)
            coeff[r][g] = my_coeff[r][g];
    use_coeff = 1;
}



static double getrat()
{
    double num = get4(ifp);
    return num / get4(ifp);
}



static void
parse_makernote(FILE * const ifp)
{
    unsigned base=0, offset=0, entries, tag, type, len, save;
    static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 };
    short sorder;
    char buf[10];
/*
  The MakerNote might have its own TIFF header (possibly with
  its own byte-order!), or it might just be a table.
*/
    sorder = order;
    fread_nofail (buf, 1, 10, ifp);
    if (!strncmp (buf,"KC" ,2) ||     /* these aren't TIFF format */
        !strncmp (buf,"MLY",3)) return;
    if (!strcmp (buf,"Nikon")) {
        base = ftell_nofail(ifp);
        order = get2(ifp);
        if (get2(ifp) != 42) goto quit;
        offset = get4(ifp);
        fseek_nofail (ifp, offset-8, SEEK_CUR);
    } else if (!strncmp (buf,"FUJIFILM",8) ||
               !strcmp  (buf,"Panasonic")) {
        order = 0x4949;
        fseek_nofail (ifp,  2, SEEK_CUR);
    } else if (!strcmp (buf,"OLYMP") ||
               !strcmp (buf,"LEICA") ||
               !strcmp (buf,"EPSON"))
        fseek_nofail (ifp, -2, SEEK_CUR);
    else if (!strcmp (buf,"AOC") ||
             !strcmp (buf,"QVC"))
        fseek_nofail (ifp, -4, SEEK_CUR);
    else fseek_nofail (ifp, -10, SEEK_CUR);

    entries = get2(ifp);
    while (entries--) {
        tag  = get2(ifp);
        type = get2(ifp);
        len  = get4(ifp);
        save = ftell_nofail(ifp);
        if (len * size[type < 13 ? type:0] > 4)
            fseek_nofail (ifp, get4(ifp)+base, SEEK_SET);

        if (tag == 0xc && len == 4) {
            camera_red  = getrat();
            camera_blue = getrat();
        }
        if (tag == 0x14 && len == 2560 && type == 7) {
            fseek_nofail (ifp, 1248, SEEK_CUR);
            goto get2_256;
        }
        if (strstr(make,"PENTAX")) {
            if (tag == 0x1b) tag = 0x1018;
            if (tag == 0x1c) tag = 0x1017;
        }
        if (tag == 0x8c)
            nikon_curve_offset = ftell_nofail(ifp) + 2112;
        if (tag == 0x96)
            nikon_curve_offset = ftell_nofail(ifp) + 2;
        if (tag == 0x97) {
            if (!strcmp(model,"NIKON D100 ")) {
                fseek_nofail (ifp, 72, SEEK_CUR);
                camera_red  = get2(ifp) / 256.0;
                camera_blue = get2(ifp) / 256.0;
            } else if (!strcmp(model,"NIKON D2H")) {
                fseek_nofail (ifp, 10, SEEK_CUR);
                goto get2_rggb;
            } else if (!strcmp(model,"NIKON D70")) {
                fseek_nofail (ifp, 20, SEEK_CUR);
                camera_red  = get2(ifp);
                camera_red /= get2(ifp);
                camera_blue = get2(ifp);
                camera_blue/= get2(ifp);
            }
        }
        if (tag == 0xe0 && len == 17) {
            get2(ifp);
            raw_width  = get2(ifp);
            raw_height = get2(ifp);
        }
        if (tag == 0x200 && len == 4)
            black = (get2(ifp)+get2(ifp)+get2(ifp)+get2(ifp))/4;
        if (tag == 0x201 && len == 4) {
            camera_red  = get2(ifp);
            camera_red /= get2(ifp);
            camera_blue = get2(ifp);
            camera_blue = get2(ifp) / camera_blue;
        }
        if (tag == 0x401 && len == 4) {
            black = (get4(ifp)+get4(ifp)+get4(ifp)+get4(ifp))/4;
        }
        if (tag == 0xe80 && len == 256 && type == 7) {
            fseek_nofail (ifp, 48, SEEK_CUR);
            camera_red  = get2(ifp) * 508 * 1.078 / 0x10000;
            camera_blue = get2(ifp) * 382 * 1.173 / 0x10000;
        }
        if (tag == 0xf00 && len == 614 && type == 7) {
            fseek_nofail (ifp, 188, SEEK_CUR);
            goto get2_256;
        }
        if (tag == 0x1017)
            camera_red  = get2(ifp) / 256.0;
        if (tag == 0x1018)
            camera_blue = get2(ifp) / 256.0;
        if (tag == 0x2011 && len == 2) {
        get2_256:
            order = 0x4d4d;
            camera_red  = get2(ifp) / 256.0;
            camera_blue = get2(ifp) / 256.0;
        }
        if (tag == 0x4001) {
            fseek_nofail (ifp, strstr(model,"EOS-1D") ? 68:50, SEEK_CUR);
        get2_rggb:
            camera_red  = get2(ifp);
            camera_red /= get2(ifp);
            camera_blue = get2(ifp);
            camera_blue = get2(ifp) / camera_blue;
        }
        fseek_nofail (ifp, save+4, SEEK_SET);
    }
quit:
    order = sorder;
}



static void
get_timestamp(FILE * const ifp)
{
/*
  Since the TIFF DateTime string has no timezone information,
  assume that the camera's clock was set to Universal Time.
*/
    struct tm t;
    time_t ts;

    if (fscanf (ifp, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
                &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
        return;
    t.tm_year -= 1900;
    t.tm_mon -= 1;
    putenv((char*)"TZ=UTC");   /* Remove this to assume local time */
    if ((ts = mktime(&t)) > 0)
        timestamp = ts;
}



static void
parse_exif(FILE * const ifp, int base)
{
    int entries, tag, len, val, save;

    entries = get2(ifp);
    while (entries--) {
        tag  = get2(ifp);
        /* type = */ get2(ifp);
        len  = get4(ifp);
        val  = get4(ifp);
        save = ftell_nofail(ifp);
        fseek_nofail (ifp, base+val, SEEK_SET);
        if (tag == 0x9003 || tag == 0x9004)
            get_timestamp(ifp);
        if (tag == 0x927c) {
            if (!strncmp(make,"SONY",4))
                data_offset = base+val+len;
            else
                parse_makernote(ifp);
        }
        fseek_nofail (ifp, save, SEEK_SET);
    }
}



static int
parse_tiff_ifd(FILE * const ifp, int base, int level)
{
    unsigned entries, tag, type, len, plen=16, save;
    int done=0, use_cm=0, cfa, i, j, c;
    static const int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 };
    char software[64];
    static const int flip_map[] = { 0,1,3,2,4,6,7,5 };
    unsigned char cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
    unsigned short scale[4];
    double dblack, cc[4][4], cm[4][3];
    double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };

    for (j=0; j < 4; j++)
        for (i=0; i < 4; i++)
            cc[j][i] = i == j;
    entries = get2(ifp);
    if (entries > 512) return 1;
    while (entries--) {
        tag  = get2(ifp);
        type = get2(ifp);
        len  = get4(ifp);
        save = ftell_nofail(ifp);
        if (tag > 50700 && tag < 50800) done = 1;
        if (len * size[type < 13 ? type:0] > 4)
            fseek_nofail (ifp, get4(ifp)+base, SEEK_SET);
        switch (tag) {
        case 0x11:
            camera_red  = get4(ifp) / 256.0;
            break;
        case 0x12:
            camera_blue = get4(ifp) / 256.0;
            break;
        case 0x100:           /* ImageWidth */
            if (strcmp(make,"Canon") || level)
                raw_width = type==3 ? get2(ifp) : get4(ifp);
                    break;
        case 0x101:           /* ImageHeight */
            if (strcmp(make,"Canon") || level)
                raw_height = type==3 ? get2(ifp) : get4(ifp);
                    break;
        case 0x102:           /* Bits per sample */
            fuji_secondary = len == 2;
            if (level) maximum = (1 << get2(ifp)) - 1;
            break;
        case 0x103:           /* Compression */
            tiff_data_compression = get2(ifp);
            break;
        case 0x106:           /* Kodak color format */
            kodak_data_compression = get2(ifp);
            break;
        case 0x10f:           /* Make */
            fgets_nofail (make, 64, ifp);
            break;
        case 0x110:           /* Model */
            fgets_nofail (model, 64, ifp);
            break;
        case 0x111:           /* StripOffset */
            data_offset = get4(ifp);
            break;
        case 0x112:           /* Orientation */
            flip = flip_map[(get2(ifp)-1) & 7];
            break;
        case 0x115:           /* SamplesPerPixel */
            tiff_samples = get2(ifp);
            break;
        case 0x131:           /* Software tag */
            fgets_nofail (software, 64, ifp);
            if (!strncmp(software,"Adobe",5))
                make[0] = 0;
            break;
        case 0x132:           /* DateTime tag */
            get_timestamp(ifp);
            break;
        case 0x144:           /* TileOffsets */
            if (level) {
                data_offset = ftell_nofail(ifp);
            } else {
                strcpy (make, "Leaf");
                data_offset = get4(ifp);
            }
            break;
        case 0x14a:           /* SubIFD tag */
            if (len > 2 && !is_dng && !strcmp(make,"Kodak"))
                len = 2;
            while (len--) {
                i = ftell_nofail(ifp);
                fseek_nofail (ifp, get4(ifp)+base, SEEK_SET);
                if (parse_tiff_ifd(ifp, base, level+1)) break;
                fseek_nofail (ifp, i+4, SEEK_SET);
            }
            break;
        case 33405:           /* Model2 */
            fgets_nofail (model2, 64, ifp);
            break;
        case 33422:           /* CFAPattern */
            if ((plen=len) > 16) plen = 16;
            fread_nofail (cfa_pat, 1, plen, ifp);
            for (colors=cfa=i=0; i < plen; i++) {
                colors += !(cfa & (1 << cfa_pat[i]));
                cfa |= 1 << cfa_pat[i];
            }
            if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3);   /* CMY */
            if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4);   /* GMCY */
            goto guess_cfa_pc;
        case 34665:           /* EXIF tag */
            fseek_nofail (ifp, get4(ifp)+base, SEEK_SET);
            parse_exif(ifp, base);
            break;
        case 50706:           /* DNGVersion */
            is_dng = 1;
            if (flip == 7) flip = 4;    /* Adobe didn't read the TIFF spec. */
            break;
        case 50710:           /* CFAPlaneColor */
            if (len > 4) len = 4;
            colors = len;
            fread_nofail (cfa_pc, 1, colors, ifp);
        guess_cfa_pc:
            FORC4 tab[cfa_pc[c]] = c;
            for (i=16; i--; )
                filters = filters << 2 | tab[cfa_pat[i % plen]];
            break;
        case 50711:           /* CFALayout */
            if (get2(ifp) == 2) {
                fuji_width = (raw_width+1)/2;
                filters = 0x49494949;
            }
            break;
        case 0x123:
        case 0x90d:
        case 50712:           /* LinearizationTable */
            if (len > 0x1000)
                len = 0x1000;
            read_shorts(ifp, curve, len);
            for (i=len; i < 0x1000; i++)
                maximum = curve[i] = curve[i-1];
            break;
        case 50714:           /* BlackLevel */
        case 50715:           /* BlackLevelDeltaH */
        case 50716:           /* BlackLevelDeltaV */
            for (dblack=i=0; i < len; i++)
                dblack += getrat();
            black += dblack/len + 0.5;
            break;
        case 50717:           /* WhiteLevel */
            maximum = get2(ifp);
            break;
        case 50718:           /* DefaultScale */
            for (i=0; i < 4; i++)
                scale[i] = get4(ifp);
            if (scale[1]*scale[2] == 2*scale[0]*scale[3]) ymag = 2;
            break;
        case 50721:           /* ColorMatrix1 */
        case 50722:           /* ColorMatrix2 */
            FORC4 for (j=0; j < 3; j++)
                cm[c][j] = getrat();
            use_cm = 1;
            break;
        case 50723:           /* CameraCalibration1 */
        case 50724:           /* CameraCalibration2 */
            for (i=0; i < colors; i++)
                FORC4 cc[i][c] = getrat();
        case 50727:           /* AnalogBalance */
            FORC4 ab[c] = getrat();
            break;
        case 50728:           /* AsShotNeutral */
            FORC4 asn[c] = getrat();
            break;
        case 50729:           /* AsShotWhiteXY */
            xyz[0] = getrat();
            xyz[1] = getrat();
            xyz[2] = 1 - xyz[0] - xyz[1];
        }
        fseek_nofail (ifp, save+4, SEEK_SET);
    }
    for (i=0; i < colors; i++)
        FORC4 cc[i][c] *= ab[i];
    if (use_cm)
        dng_coeff (cc, cm, xyz);
    if (asn[0])
        FORC4 pre_mul[c] = 1 / asn[c];
    if (!use_cm)
        FORC4 pre_mul[c] /= cc[c][c];

    if (is_dng || level) return done;

    if ((raw_height & 1) && !strncmp (make,"OLYMPUS",7))
        raw_height++;

    if (make[0] == 0 && raw_width == 680 && raw_height == 680) {
        strcpy (make, "Imacon");
        strcpy (model,"Ixpress");
    }
    return done;
}



void
parse_tiff(FILE * const ifp, int base)
{
    int doff;

    fseek_nofail (ifp, base, SEEK_SET);
    order = get2(ifp);
    if (order != 0x4949 && order != 0x4d4d) return;
    get2(ifp);
    while ((doff = get4(ifp))) {
        fseek_nofail (ifp, doff+base, SEEK_SET);
        if (parse_tiff_ifd(ifp, base, 0)) break;
    }
    if (!is_dng && !strncmp(make,"Kodak",5)) {
        fseek_nofail (ifp, 12+base, SEEK_SET);
        parse_tiff_ifd(ifp, base, 2);
    }
}



/*
  Many cameras have a "debug mode" that writes JPEG and raw
  at the same time.  The raw file has no header, so try to
  to open the matching JPEG file and read its metadata.
*/
void
parse_external_jpeg(const char * const ifname)
{
    const char *file, *ext;
    char * jfile;
    char * jext;
    char * jname;

    ext  = strrchr (ifname, '.');
    file = strrchr (ifname, '/');
    if (!file) file = strrchr (ifname, '\\');
    if (!file) file = ifname-1;
    file++;
    if (strlen(ext) != 4 || ext-file != 8) return;
    jname = malloc (strlen(ifname) + 1);
    merror (jname, "parse_external()");
    strcpy (jname, ifname);
    jfile = jname + (file - ifname);
    jext  = jname + (ext  - ifname);
    if (!strcaseeq (ext, ".jpg")) {
        strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
        memcpy (jfile, file+4, 4);
        memcpy (jfile+4, file, 4);
    } else
        while (isdigit(*--jext)) {
            if (*jext != '9') {
                (*jext)++;
                break;
            }
            *jext = '0';
        }
    if (strcmp (jname, ifname)) {
        FILE * ifP;
        ifP = fopen (jname, "rb");
        if (ifP) {
            if (verbose)
                pm_message ("Reading metadata from %s...", jname);
            parse_tiff(ifP, 12);
            fclose (ifP);
        }
    }
    if (!timestamp)
        pm_message ( "Failed to read metadata from %s", jname);
    free (jname);
}



