#include "../../internal/dcraw_defs.h"
int LibRaw::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;
}
void LibRaw::tiff_set(struct tiff_hdr *th, ushort *ntag, ushort tag,
ushort type, int count, int val)
{
struct libraw_tiff_tag *tt;
int c;
tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++;
tt->val.i = val;
if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_BYTE) && count <= 4)
FORC(4) tt->val.c[c] = val >> (c << 3);
else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII))
{
count = strnlen((char *)th + val, count - 1) + 1;
if (count <= 4)
FORC(4) tt->val.c[c] = ((char *)th)[val + c];
}
else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && count <= 2)
FORC(2) tt->val.s[c] = val >> (c << 4);
tt->count = count;
tt->type = type;
tt->tag = tag;
}
#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
void LibRaw::tiff_head(struct tiff_hdr *th, int full)
{
int c, psize = 0;
struct tm *t;
memset(th, 0, sizeof *th);
th->t_order = htonl(0x4d4d4949) >> 16;
th->magic = 42;
th->ifd = 10;
th->rat[0] = th->rat[2] = 300;
th->rat[1] = th->rat[3] = 1;
FORC(6) th->rat[4 + c] = 1000000;
th->rat[4] *= shutter;
th->rat[6] *= aperture;
th->rat[8] *= focal_len;
strncpy(th->t_desc, desc, 512);
strncpy(th->t_make, make, 64);
strncpy(th->t_model, model, 64);
strcpy(th->soft, "dcraw v" DCRAW_VERSION);
t = localtime(×tamp);
sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900,
t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
strncpy(th->t_artist, artist, 64);
if (full)
{
tiff_set(th, &th->ntag, 254, 4, 1, 0);
tiff_set(th, &th->ntag, 256, 4, 1, width);
tiff_set(th, &th->ntag, 257, 4, 1, height);
tiff_set(th, &th->ntag, 258, 3, colors, output_bps);
if (colors > 2)
th->tag[th->ntag - 1].val.i = TOFF(th->bps);
FORC4 th->bps[c] = output_bps;
tiff_set(th, &th->ntag, 259, 3, 1, 1);
tiff_set(th, &th->ntag, 262, 3, 1, 1 + (colors > 1));
}
tiff_set(th, &th->ntag, 270, 2, 512, TOFF(th->t_desc));
tiff_set(th, &th->ntag, 271, 2, 64, TOFF(th->t_make));
tiff_set(th, &th->ntag, 272, 2, 64, TOFF(th->t_model));
if (full)
{
if (oprof)
psize = ntohl(oprof[0]);
tiff_set(th, &th->ntag, 273, 4, 1, sizeof *th + psize);
tiff_set(th, &th->ntag, 277, 3, 1, colors);
tiff_set(th, &th->ntag, 278, 4, 1, height);
tiff_set(th, &th->ntag, 279, 4, 1,
height * width * colors * output_bps / 8);
}
else
tiff_set(th, &th->ntag, 274, 3, 1, "12435867"[flip] - '0');
tiff_set(th, &th->ntag, 282, 5, 1, TOFF(th->rat[0]));
tiff_set(th, &th->ntag, 283, 5, 1, TOFF(th->rat[2]));
tiff_set(th, &th->ntag, 284, 3, 1, 1);
tiff_set(th, &th->ntag, 296, 3, 1, 2);
tiff_set(th, &th->ntag, 305, 2, 32, TOFF(th->soft));
tiff_set(th, &th->ntag, 306, 2, 20, TOFF(th->date));
tiff_set(th, &th->ntag, 315, 2, 64, TOFF(th->t_artist));
tiff_set(th, &th->ntag, 34665, 4, 1, TOFF(th->nexif));
if (psize)
tiff_set(th, &th->ntag, 34675, 7, psize, sizeof *th);
tiff_set(th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
tiff_set(th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
tiff_set(th, &th->nexif, 34855, 3, 1, iso_speed);
tiff_set(th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
if (gpsdata[1])
{
uchar latref[4] = { (uchar)(gpsdata[29]),0,0,0 },
lonref[4] = { (uchar)(gpsdata[30]),0,0,0 };
tiff_set(th, &th->ntag, 34853, 4, 1, TOFF(th->ngps));
tiff_set(th, &th->ngps, 0, 1, 4, 0x202);
tiff_set(th, &th->ngps, 1, 2, 2, TOFF(latref));
tiff_set(th, &th->ngps, 2, 5, 3, TOFF(th->gps[0]));
tiff_set(th, &th->ngps, 3, 2, 2, TOFF(lonref));
tiff_set(th, &th->ngps, 4, 5, 3, TOFF(th->gps[6]));
tiff_set(th, &th->ngps, 5, 1, 1, gpsdata[31]);
tiff_set(th, &th->ngps, 6, 5, 1, TOFF(th->gps[18]));
tiff_set(th, &th->ngps, 7, 5, 3, TOFF(th->gps[12]));
tiff_set(th, &th->ngps, 18, 2, 12, TOFF(th->gps[20]));
tiff_set(th, &th->ngps, 29, 2, 12, TOFF(th->gps[23]));
memcpy(th->gps, gpsdata, sizeof th->gps);
}
}
void LibRaw::jpeg_thumb_writer(FILE *tfp, char *t_humb, int t_humb_length)
{
ushort exif[5];
struct tiff_hdr th;
fputc(0xff, tfp);
fputc(0xd8, tfp);
if (strcmp(t_humb + 6, "Exif"))
{
memcpy(exif, "\xff\xe1 Exif\0\0", 10);
exif[1] = htons(8 + sizeof th);
fwrite(exif, 1, sizeof exif, tfp);
tiff_head(&th, 0);
fwrite(&th, 1, sizeof th, tfp);
}
fwrite(t_humb + 2, 1, t_humb_length - 2, tfp);
}
void LibRaw::write_ppm_tiff()
{
struct tiff_hdr th;
uchar *ppm;
ushort *ppm2;
int c, row, col, soff, rstep, cstep;
int perc, val, total, t_white = 0x2000;
perc = width * height * auto_bright_thr;
if (fuji_width)
perc /= 2;
if (!((highlight & ~2) || no_auto_bright))
for (t_white = c = 0; c < colors; c++)
{
for (val = 0x2000, total = 0; --val > 32;)
if ((total += histogram[c][val]) > perc)
break;
if (t_white < val)
t_white = val;
}
gamma_curve(gamm[0], gamm[1], 2, (t_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((char *)ppm2, (char *)ppm2, width * colors * 2);
fwrite(ppm, colors * output_bps / 8, width, ofp);
}
free(ppm);
}
void LibRaw::ppm_thumb()
{
char *thumb;
thumb_length = thumb_width * thumb_height * 3;
thumb = (char *)malloc(thumb_length);
merror(thumb, "ppm_thumb()");
fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
fread(thumb, 1, thumb_length, ifp);
fwrite(thumb, 1, thumb_length, ofp);
free(thumb);
}
void LibRaw::ppm16_thumb()
{
unsigned i;
char *thumb;
thumb_length = thumb_width * thumb_height * 3;
thumb = (char *)calloc(thumb_length, 2);
merror(thumb, "ppm16_thumb()");
read_shorts((ushort *)thumb, thumb_length);
for (i = 0; i < thumb_length; i++)
thumb[i] = ((ushort *)thumb)[i] >> 8;
fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
fwrite(thumb, 1, thumb_length, ofp);
free(thumb);
}
void LibRaw::layer_thumb()
{
unsigned int i;
int c;
char *thumb, map[][4] = {"012", "102"};
colors = thumb_misc >> 5 & 7;
thumb_length = thumb_width * thumb_height;
thumb = (char *)calloc(colors, thumb_length);
merror(thumb, "layer_thumb()");
fprintf(ofp, "P%d\n%d %d\n255\n", 5 + (colors >> 1), thumb_width,
thumb_height);
fread(thumb, thumb_length, colors, ifp);
for (i = 0; i < thumb_length; i++)
FORCC putc(thumb[i + thumb_length * (map[thumb_misc >> 8][c] - '0')], ofp);
free(thumb);
}
void LibRaw::rollei_thumb()
{
unsigned i;
ushort *thumb;
thumb_length = thumb_width * thumb_height;
thumb = (ushort *)calloc(thumb_length, 2);
merror(thumb, "rollei_thumb()");
fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
read_shorts(thumb, thumb_length);
for (i = 0; i < thumb_length; i++)
{
putc(thumb[i] << 3, ofp);
putc(thumb[i] >> 5 << 2, ofp);
putc(thumb[i] >> 11 << 3, ofp);
}
free(thumb);
}
void LibRaw::jpeg_thumb()
{
char *thumb;
thumb = (char *)malloc(thumb_length);
merror(thumb, "jpeg_thumb()");
fread(thumb, 1, thumb_length, ifp);
jpeg_thumb_writer(ofp, thumb, thumb_length);
free(thumb);
}