File indexing completed on 2025-01-05 03:57:09

0001 /* -*- C++ -*-
0002  * Copyright 2019-2021 LibRaw LLC (info@libraw.org)
0003  *
0004  LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
0005  dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net.
0006  LibRaw do not use RESTRICTED code from dcraw.c
0007 
0008  LibRaw is free software; you can redistribute it and/or modify
0009  it under the terms of the one of two licenses as you choose:
0010 
0011 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
0012    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
0013 
0014 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
0015    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
0016 
0017  */
0018 
0019 #include "../../internal/dcraw_defs.h"
0020 #include <vector>
0021 
0022 int LibRaw::flip_index(int row, int col)
0023 {
0024   if (flip & 4)
0025     SWAP(row, col);
0026   if (flip & 2)
0027     row = iheight - 1 - row;
0028   if (flip & 1)
0029     col = iwidth - 1 - col;
0030   return row * iwidth + col;
0031 }
0032 
0033 void LibRaw::tiff_set(struct tiff_hdr *th, ushort *ntag, ushort tag,
0034                       ushort type, int count, int val)
0035 {
0036   struct libraw_tiff_tag *tt;
0037   int c;
0038 
0039   tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++;
0040   tt->val.i = val;
0041   if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_BYTE) && count <= 4)
0042     FORC(4) tt->val.c[c] = val >> (c << 3);
0043   else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII))
0044   {
0045     count = int(strnlen((char *)th + val, count - 1)) + 1;
0046     if (count <= 4)
0047       FORC(4) tt->val.c[c] = ((char *)th)[val + c];
0048   }
0049   else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && count <= 2)
0050     FORC(2) tt->val.s[c] = val >> (c << 4);
0051   tt->count = count;
0052   tt->type = type;
0053   tt->tag = tag;
0054 }
0055 
0056 #define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
0057 
0058 void LibRaw::tiff_head(struct tiff_hdr *th, int full)
0059 {
0060   int c, psize = 0;
0061   struct tm *t;
0062 
0063   memset(th, 0, sizeof *th);
0064   th->t_order = htonl(0x4d4d4949) >> 16;
0065   th->magic = 42;
0066   th->ifd = 10;
0067   th->rat[0] = th->rat[2] = 300;
0068   th->rat[1] = th->rat[3] = 1;
0069   FORC(6) th->rat[4 + c] = 1000000;
0070   th->rat[4] *= shutter;
0071   th->rat[6] *= aperture;
0072   th->rat[8] *= focal_len;
0073   strncpy(th->t_desc, desc, 512);
0074   strncpy(th->t_make, make, 64);
0075   strncpy(th->t_model, model, 64);
0076   strcpy(th->soft, "dcraw v" DCRAW_VERSION);
0077   t = localtime(&timestamp);
0078   sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900,
0079           t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
0080   strncpy(th->t_artist, artist, 64);
0081   if (full)
0082   {
0083     tiff_set(th, &th->ntag, 254, 4, 1, 0);
0084     tiff_set(th, &th->ntag, 256, 4, 1, width);
0085     tiff_set(th, &th->ntag, 257, 4, 1, height);
0086     tiff_set(th, &th->ntag, 258, 3, colors, output_bps);
0087     if (colors > 2)
0088       th->tag[th->ntag - 1].val.i = TOFF(th->bps);
0089     FORC4 th->bps[c] = output_bps;
0090     tiff_set(th, &th->ntag, 259, 3, 1, 1);
0091     tiff_set(th, &th->ntag, 262, 3, 1, 1 + (colors > 1));
0092   }
0093   tiff_set(th, &th->ntag, 270, 2, 512, TOFF(th->t_desc));
0094   tiff_set(th, &th->ntag, 271, 2, 64, TOFF(th->t_make));
0095   tiff_set(th, &th->ntag, 272, 2, 64, TOFF(th->t_model));
0096   if (full)
0097   {
0098     if (oprof)
0099       psize = ntohl(oprof[0]);
0100     tiff_set(th, &th->ntag, 273, 4, 1, sizeof *th + psize);
0101     tiff_set(th, &th->ntag, 277, 3, 1, colors);
0102     tiff_set(th, &th->ntag, 278, 4, 1, height);
0103     tiff_set(th, &th->ntag, 279, 4, 1,
0104              height * width * colors * output_bps / 8);
0105   }
0106   else
0107     tiff_set(th, &th->ntag, 274, 3, 1, "12435867"[flip] - '0');
0108   tiff_set(th, &th->ntag, 282, 5, 1, TOFF(th->rat[0]));
0109   tiff_set(th, &th->ntag, 283, 5, 1, TOFF(th->rat[2]));
0110   tiff_set(th, &th->ntag, 284, 3, 1, 1);
0111   tiff_set(th, &th->ntag, 296, 3, 1, 2);
0112   tiff_set(th, &th->ntag, 305, 2, 32, TOFF(th->soft));
0113   tiff_set(th, &th->ntag, 306, 2, 20, TOFF(th->date));
0114   tiff_set(th, &th->ntag, 315, 2, 64, TOFF(th->t_artist));
0115   tiff_set(th, &th->ntag, 34665, 4, 1, TOFF(th->nexif));
0116   if (psize)
0117     tiff_set(th, &th->ntag, 34675, 7, psize, sizeof *th);
0118   tiff_set(th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
0119   tiff_set(th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
0120   tiff_set(th, &th->nexif, 34855, 3, 1, iso_speed);
0121   tiff_set(th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
0122   if (gpsdata[1])
0123   {
0124     uchar latref[4] = { (uchar)(gpsdata[29]),0,0,0 },
0125           lonref[4] = { (uchar)(gpsdata[30]),0,0,0 };
0126     tiff_set(th, &th->ntag, 34853, 4, 1, TOFF(th->ngps));
0127     tiff_set(th, &th->ngps, 0, 1, 4, 0x202);
0128     tiff_set(th, &th->ngps, 1, 2, 2, TOFF(latref));
0129     tiff_set(th, &th->ngps, 2, 5, 3, TOFF(th->gps[0]));
0130     tiff_set(th, &th->ngps, 3, 2, 2, TOFF(lonref));
0131     tiff_set(th, &th->ngps, 4, 5, 3, TOFF(th->gps[6]));
0132     tiff_set(th, &th->ngps, 5, 1, 1, gpsdata[31]);
0133     tiff_set(th, &th->ngps, 6, 5, 1, TOFF(th->gps[18]));
0134     tiff_set(th, &th->ngps, 7, 5, 3, TOFF(th->gps[12]));
0135     tiff_set(th, &th->ngps, 18, 2, 12, TOFF(th->gps[20]));
0136     tiff_set(th, &th->ngps, 29, 2, 12, TOFF(th->gps[23]));
0137     memcpy(th->gps, gpsdata, sizeof th->gps);
0138   }
0139 }
0140 
0141 void LibRaw::jpeg_thumb_writer(FILE *tfp, char *t_humb, int t_humb_length)
0142 {
0143   ushort exif[5];
0144   struct tiff_hdr th;
0145   fputc(0xff, tfp);
0146   fputc(0xd8, tfp);
0147   if (strcmp(t_humb + 6, "Exif"))
0148   {
0149     memcpy(exif, "\xff\xe1  Exif\0\0", 10);
0150     exif[1] = htons(8 + sizeof th);
0151     fwrite(exif, 1, sizeof exif, tfp);
0152     tiff_head(&th, 0);
0153     fwrite(&th, 1, sizeof th, tfp);
0154   }
0155   fwrite(t_humb + 2, 1, t_humb_length - 2, tfp);
0156 }
0157 void LibRaw::write_ppm_tiff()
0158 {
0159     try
0160     {
0161         struct tiff_hdr th;
0162         ushort *ppm2;
0163         int c, row, col, soff, rstep, cstep;
0164         int perc, val, total, t_white = 0x2000;
0165 
0166         perc = width * height * auto_bright_thr;
0167 
0168         if (fuji_width)
0169             perc /= 2;
0170         if (!((highlight & ~2) || no_auto_bright))
0171             for (t_white = c = 0; c < colors; c++)
0172             {
0173                 for (val = 0x2000, total = 0; --val > 32;)
0174                     if ((total += histogram[c][val]) > perc)
0175                         break;
0176                 if (t_white < val)
0177                     t_white = val;
0178             }
0179         gamma_curve(gamm[0], gamm[1], 2, (t_white << 3) / bright);
0180         iheight = height;
0181         iwidth = width;
0182         if (flip & 4)
0183             SWAP(height, width);
0184 
0185         std::vector<uchar> ppm(width * colors * output_bps / 8);
0186         ppm2 = (ushort *)ppm.data();
0187         if (output_tiff)
0188         {
0189             tiff_head(&th, 1);
0190             fwrite(&th, sizeof th, 1, ofp);
0191             if (oprof)
0192                 fwrite(oprof, ntohl(oprof[0]), 1, ofp);
0193         }
0194         else if (colors > 3)
0195     {
0196         if(imgdata.params.output_flags & LIBRAW_OUTPUT_FLAGS_PPMMETA)
0197           fprintf(ofp,
0198               "P7\n# EXPTIME=%0.5f\n# TIMESTAMP=%d\n# ISOSPEED=%d\n"
0199               "# APERTURE=%0.1f\n# FOCALLEN=%0.1f\n# MAKE=%s\n# MODEL=%s\n"
0200               "WIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
0201               shutter, (int)timestamp, (int)iso_speed,aperture, 
0202           focal_len, make, model,
0203           width, height, colors, (1 << output_bps) - 1, cdesc);
0204         else
0205             fprintf(
0206                 ofp,
0207                 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
0208                 width, height, colors, (1 << output_bps) - 1, cdesc);
0209     }
0210         else
0211     {
0212         if(imgdata.params.output_flags & LIBRAW_OUTPUT_FLAGS_PPMMETA)
0213             fprintf(ofp, "P%d\n# EXPTIME=%0.5f\n# TIMESTAMP=%d\n"
0214         "# ISOSPEED=%d\n# APERTURE=%0.1f\n# FOCALLEN=%0.1f\n"
0215         "# MAKE=%s\n# MODEL=%s\n%d %d\n%d\n",
0216                 colors/2+5,
0217         shutter, (int)timestamp, (int)iso_speed,aperture,focal_len,
0218         make,model,
0219         width, height, (1 << output_bps)-1);
0220         else
0221              fprintf(ofp, "P%d\n%d %d\n%d\n", colors / 2 + 5, width, height,
0222             (1 << output_bps) - 1);
0223         }
0224         soff = flip_index(0, 0);
0225         cstep = flip_index(0, 1) - soff;
0226         rstep = flip_index(1, 0) - flip_index(0, width);
0227         for (row = 0; row < height; row++, soff += rstep)
0228         {
0229             for (col = 0; col < width; col++, soff += cstep)
0230                 if (output_bps == 8)
0231                     FORCC ppm[col * colors + c] = curve[image[soff][c]] >> 8;
0232                 else
0233                     FORCC ppm2[col * colors + c] = curve[image[soff][c]];
0234             if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
0235                 libraw_swab(ppm2, width * colors * 2);
0236             fwrite(ppm.data(), colors * output_bps / 8, width, ofp);
0237         }
0238     }
0239     catch (...)
0240     {
0241       throw LIBRAW_EXCEPTION_ALLOC; // rethrow
0242     }
0243 }
0244 #if 0
0245 void LibRaw::ppm_thumb()
0246 {
0247     try
0248     {
0249         thumb_length = thumb_width * thumb_height * 3;
0250         std::vector<char> thumb(thumb_length);
0251         fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
0252         fread(thumb.data(), 1, thumb_length, ifp);
0253         fwrite(thumb.data(), 1, thumb_length, ofp);
0254     }
0255     catch (...)
0256     {
0257       throw LIBRAW_EXCEPTION_ALLOC; // rethrow
0258     }
0259 }
0260 
0261 void LibRaw::ppm16_thumb()
0262 {
0263     try
0264     {
0265         unsigned i;
0266         thumb_length = thumb_width * thumb_height * 3;
0267         std::vector<char> thumb(thumb_length * 2, 0);
0268         read_shorts((ushort *)thumb.data(), thumb_length);
0269         for (i = 0; i < thumb_length; i++)
0270             thumb[i] = ((ushort *)thumb.data())[i] >> 8;
0271         fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
0272         fwrite(thumb.data(), 1, thumb_length, ofp);
0273     }
0274     catch (...)
0275     {
0276       throw LIBRAW_EXCEPTION_ALLOC; // rethrow
0277     }
0278 }
0279 
0280 void LibRaw::layer_thumb()
0281 {
0282     try
0283     {
0284         unsigned int i;
0285         int c;
0286         char map[][4] = { "012", "102" };
0287 
0288         colors = thumb_misc >> 5 & 7;
0289         thumb_length = thumb_width * thumb_height;
0290         std::vector<char> thumb(colors * thumb_length, 0);
0291         fprintf(ofp, "P%d\n%d %d\n255\n", 5 + (colors >> 1), thumb_width,
0292             thumb_height);
0293         fread(thumb.data(), thumb_length, colors, ifp);
0294         for (i = 0; i < thumb_length; i++)
0295             FORCC putc(thumb[i + thumb_length * (map[thumb_misc >> 8][c] - '0')], ofp);
0296     }
0297     catch (...)
0298     {
0299       throw LIBRAW_EXCEPTION_ALLOC; // rethrow
0300     }
0301 }
0302 
0303 void LibRaw::rollei_thumb()
0304 {
0305     try
0306     {
0307         unsigned i;
0308         thumb_length = thumb_width * thumb_height;
0309         std::vector<ushort> thumb(thumb_length, 0);
0310         fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
0311         read_shorts(thumb.data(), thumb_length);
0312         for (i = 0; i < thumb_length; i++)
0313         {
0314             putc(thumb[i] << 3, ofp);
0315             putc(thumb[i] >> 5 << 2, ofp);
0316             putc(thumb[i] >> 11 << 3, ofp);
0317         }
0318     }
0319     catch (...)
0320     {
0321       throw LIBRAW_EXCEPTION_ALLOC; // rethrow
0322     }
0323 }
0324 
0325 void LibRaw::jpeg_thumb()
0326 {
0327     try
0328     {
0329         std::vector<char> thumb(thumb_length);
0330         fread(thumb.data(), 1, thumb_length, ifp);
0331         jpeg_thumb_writer(ofp, thumb.data(), thumb_length);
0332     }
0333     catch (...)
0334     {
0335       throw LIBRAW_EXCEPTION_ALLOC; // rethrow
0336     }
0337 }
0338 #endif