Coverage Report

Created: 2025-07-12 06:17

/src/libraw/src/write/file_write.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- C++ -*-
2
 * Copyright 2019-2024 LibRaw LLC (info@libraw.org)
3
 *
4
 LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
5
 dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net.
6
 LibRaw do not use RESTRICTED code from dcraw.c
7
8
 LibRaw is free software; you can redistribute it and/or modify
9
 it under the terms of the one of two licenses as you choose:
10
11
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
12
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
13
14
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
15
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
16
17
 */
18
19
#include "../../internal/dcraw_defs.h"
20
#include <vector>
21
22
int LibRaw::flip_index(int row, int col)
23
520
{
24
520
  if (flip & 4)
25
32
    SWAP(row, col);
26
520
  if (flip & 2)
27
36
    row = iheight - 1 - row;
28
520
  if (flip & 1)
29
12
    col = iwidth - 1 - col;
30
520
  return row * iwidth + col;
31
520
}
32
33
void LibRaw::tiff_set(struct tiff_hdr *th, ushort *ntag, ushort tag,
34
                      ushort type, int count, int val)
35
0
{
36
0
  struct libraw_tiff_tag *tt;
37
0
  int c;
38
39
0
  tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++;
40
0
  tt->val.i = val;
41
0
  if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_BYTE) && count <= 4)
42
0
    FORC(4) tt->val.c[c] = val >> (c << 3);
43
0
  else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII))
44
0
  {
45
0
    count = int(strnlen((char *)th + val, count - 1)) + 1;
46
0
    if (count <= 4)
47
0
      FORC(4) tt->val.c[c] = ((char *)th)[val + c];
48
0
  }
49
0
  else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && count <= 2)
50
0
    FORC(2) tt->val.s[c] = val >> (c << 4);
51
0
  tt->count = count;
52
0
  tt->type = type;
53
0
  tt->tag = tag;
54
0
}
55
56
0
#define TOFF(ptr) int((char *)(&(ptr)) - (char *)th)
57
58
void LibRaw::tiff_head(struct tiff_hdr *th, int full)
59
0
{
60
0
  int c, psize = 0;
61
0
  struct tm *t;
62
63
0
  memset(th, 0, sizeof *th);
64
0
  th->t_order = htonl(0x4d4d4949) >> 16;
65
0
  th->magic = 42;
66
0
  th->ifd = 10;
67
0
  th->rat[0] = th->rat[2] = 300;
68
0
  th->rat[1] = th->rat[3] = 1;
69
0
  FORC(6) th->rat[4 + c] = 1000000;
70
0
  th->rat[4] = int(shutter * 1000000.f);
71
0
  th->rat[6] = int(aperture * 1000000.f);
72
0
  th->rat[8] = int(focal_len * 1000000.f);
73
0
  strncpy(th->t_desc, desc, 512);
74
0
  strncpy(th->t_make, make, 64);
75
0
  strncpy(th->t_model, model, 64);
76
0
  strcpy(th->soft, "dcraw v" DCRAW_VERSION);
77
0
  t = localtime(&timestamp);
78
0
  sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900,
79
0
          t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
80
0
  strncpy(th->t_artist, artist, 64);
81
0
  if (full)
82
0
  {
83
0
    tiff_set(th, &th->ntag, 254, 4, 1, 0);
84
0
    tiff_set(th, &th->ntag, 256, 4, 1, width);
85
0
    tiff_set(th, &th->ntag, 257, 4, 1, height);
86
0
    tiff_set(th, &th->ntag, 258, 3, colors, output_bps);
87
0
    if (colors > 2)
88
0
      th->tag[th->ntag - 1].val.i = TOFF(th->bps);
89
0
    FORC4 th->bps[c] = output_bps;
90
0
    tiff_set(th, &th->ntag, 259, 3, 1, 1);
91
0
    tiff_set(th, &th->ntag, 262, 3, 1, 1 + (colors > 1));
92
0
  }
93
0
  tiff_set(th, &th->ntag, 270, 2, 512, TOFF(th->t_desc));
94
0
  tiff_set(th, &th->ntag, 271, 2, 64, TOFF(th->t_make));
95
0
  tiff_set(th, &th->ntag, 272, 2, 64, TOFF(th->t_model));
96
0
  if (full)
97
0
  {
98
0
    if (oprof)
99
0
      psize = ntohl(oprof[0]);
100
0
    tiff_set(th, &th->ntag, 273, 4, 1, sizeof *th + psize);
101
0
    tiff_set(th, &th->ntag, 277, 3, 1, colors);
102
0
    tiff_set(th, &th->ntag, 278, 4, 1, height);
103
0
    tiff_set(th, &th->ntag, 279, 4, 1,
104
0
             height * width * colors * output_bps / 8);
105
0
  }
106
0
  else
107
0
    tiff_set(th, &th->ntag, 274, 3, 1, "12435867"[flip] - '0');
108
0
  tiff_set(th, &th->ntag, 282, 5, 1, TOFF(th->rat[0]));
109
0
  tiff_set(th, &th->ntag, 283, 5, 1, TOFF(th->rat[2]));
110
0
  tiff_set(th, &th->ntag, 284, 3, 1, 1);
111
0
  tiff_set(th, &th->ntag, 296, 3, 1, 2);
112
0
  tiff_set(th, &th->ntag, 305, 2, 32, TOFF(th->soft));
113
0
  tiff_set(th, &th->ntag, 306, 2, 20, TOFF(th->date));
114
0
  tiff_set(th, &th->ntag, 315, 2, 64, TOFF(th->t_artist));
115
0
  tiff_set(th, &th->ntag, 34665, 4, 1, TOFF(th->nexif));
116
0
  if (psize)
117
0
    tiff_set(th, &th->ntag, 34675, 7, psize, sizeof *th);
118
0
  tiff_set(th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
119
0
  tiff_set(th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
120
0
  tiff_set(th, &th->nexif, 34855, 3, 1, int(iso_speed));
121
0
  tiff_set(th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
122
0
  if (gpsdata[1])
123
0
  {
124
0
    uchar latref[4] = { (uchar)(gpsdata[29]),0,0,0 },
125
0
          lonref[4] = { (uchar)(gpsdata[30]),0,0,0 };
126
0
    tiff_set(th, &th->ntag, 34853, 4, 1, TOFF(th->ngps));
127
0
    tiff_set(th, &th->ngps, 0, 1, 4, 0x202);
128
0
    tiff_set(th, &th->ngps, 1, 2, 2, TOFF(latref));
129
0
    tiff_set(th, &th->ngps, 2, 5, 3, TOFF(th->gps[0]));
130
0
    tiff_set(th, &th->ngps, 3, 2, 2, TOFF(lonref));
131
0
    tiff_set(th, &th->ngps, 4, 5, 3, TOFF(th->gps[6]));
132
0
    tiff_set(th, &th->ngps, 5, 1, 1, gpsdata[31]);
133
0
    tiff_set(th, &th->ngps, 6, 5, 1, TOFF(th->gps[18]));
134
0
    tiff_set(th, &th->ngps, 7, 5, 3, TOFF(th->gps[12]));
135
0
    tiff_set(th, &th->ngps, 18, 2, 12, TOFF(th->gps[20]));
136
0
    tiff_set(th, &th->ngps, 29, 2, 12, TOFF(th->gps[23]));
137
0
    memcpy(th->gps, gpsdata, sizeof th->gps);
138
0
  }
139
0
}
140
141
void LibRaw::jpeg_thumb_writer(FILE *tfp, char *t_humb, int t_humb_length)
142
0
{
143
0
  ushort exif[5];
144
0
  struct tiff_hdr th;
145
0
  fputc(0xff, tfp);
146
0
  fputc(0xd8, tfp);
147
0
  if (strcmp(t_humb + 6, "Exif"))
148
0
  {
149
0
    memcpy(exif, "\xff\xe1  Exif\0\0", 10);
150
0
    exif[1] = htons(8 + sizeof th);
151
0
    fwrite(exif, 1, sizeof exif, tfp);
152
0
    tiff_head(&th, 0);
153
0
    fwrite(&th, 1, sizeof th, tfp);
154
0
  }
155
0
  fwrite(t_humb + 2, 1, t_humb_length - 2, tfp);
156
0
}
157
void LibRaw::write_ppm_tiff()
158
0
{
159
0
    try
160
0
    {
161
0
        struct tiff_hdr th;
162
0
        ushort *ppm2;
163
0
        int c, row, col, soff, rstep, cstep;
164
0
        int perc, val, total, t_white = 0x2000;
165
166
0
        perc = int(width * height * auto_bright_thr);
167
168
0
        if (fuji_width)
169
0
            perc /= 2;
170
0
        if (!((highlight & ~2) || no_auto_bright))
171
0
            for (t_white = c = 0; c < colors; c++)
172
0
            {
173
0
                for (val = 0x2000, total = 0; --val > 32;)
174
0
                    if ((total += histogram[c][val]) > perc)
175
0
                        break;
176
0
                if (t_white < val)
177
0
                    t_white = val;
178
0
            }
179
0
        gamma_curve(gamm[0], gamm[1], 2, int((t_white << 3) / bright));
180
0
        iheight = height;
181
0
        iwidth = width;
182
0
        if (flip & 4)
183
0
            SWAP(height, width);
184
185
0
        std::vector<uchar> ppm(width * colors * output_bps / 8);
186
0
        ppm2 = (ushort *)ppm.data();
187
0
        if (output_tiff)
188
0
        {
189
0
            tiff_head(&th, 1);
190
0
            fwrite(&th, sizeof th, 1, ofp);
191
0
            if (oprof)
192
0
                fwrite(oprof, ntohl(oprof[0]), 1, ofp);
193
0
        }
194
0
        else if (colors > 3)
195
0
  {
196
0
      if(imgdata.params.output_flags & LIBRAW_OUTPUT_FLAGS_PPMMETA)
197
0
        fprintf(ofp,
198
0
              "P7\n# EXPTIME=%0.5f\n# TIMESTAMP=%d\n# ISOSPEED=%d\n"
199
0
              "# APERTURE=%0.1f\n# FOCALLEN=%0.1f\n# MAKE=%s\n# MODEL=%s\n"
200
0
              "WIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
201
0
              shutter, (int)timestamp, (int)iso_speed,aperture, 
202
0
        focal_len, make, model,
203
0
        width, height, colors, (1 << output_bps) - 1, cdesc);
204
0
      else
205
0
            fprintf(
206
0
                ofp,
207
0
                "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
208
0
                width, height, colors, (1 << output_bps) - 1, cdesc);
209
0
  }
210
0
        else
211
0
  {
212
0
      if(imgdata.params.output_flags & LIBRAW_OUTPUT_FLAGS_PPMMETA)
213
0
        fprintf(ofp, "P%d\n# EXPTIME=%0.5f\n# TIMESTAMP=%d\n"
214
0
    "# ISOSPEED=%d\n# APERTURE=%0.1f\n# FOCALLEN=%0.1f\n"
215
0
    "# MAKE=%s\n# MODEL=%s\n%d %d\n%d\n",
216
0
                colors/2+5,
217
0
    shutter, (int)timestamp, (int)iso_speed,aperture,focal_len,
218
0
    make,model,
219
0
    width, height, (1 << output_bps)-1);
220
0
      else
221
0
             fprintf(ofp, "P%d\n%d %d\n%d\n", colors / 2 + 5, width, height,
222
0
            (1 << output_bps) - 1);
223
0
        }
224
0
        soff = flip_index(0, 0);
225
0
        cstep = flip_index(0, 1) - soff;
226
0
        rstep = flip_index(1, 0) - flip_index(0, width);
227
0
        for (row = 0; row < height; row++, soff += rstep)
228
0
        {
229
0
            for (col = 0; col < width; col++, soff += cstep)
230
0
                if (output_bps == 8)
231
0
                    FORCC ppm[col * colors + c] = curve[image[soff][c]] >> 8;
232
0
                else
233
0
                    FORCC ppm2[col * colors + c] = curve[image[soff][c]];
234
0
            if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
235
0
                libraw_swab(ppm2, width * colors * 2);
236
0
            fwrite(ppm.data(), colors * output_bps / 8, width, ofp);
237
0
        }
238
0
    }
239
0
    catch (...)
240
0
    {
241
0
      throw LIBRAW_EXCEPTION_ALLOC; // rethrow
242
0
    }
243
0
}
244
#if 0
245
void LibRaw::ppm_thumb()
246
{
247
    try
248
    {
249
        thumb_length = thumb_width * thumb_height * 3;
250
        std::vector<char> thumb(thumb_length);
251
        fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
252
        fread(thumb.data(), 1, thumb_length, ifp);
253
        fwrite(thumb.data(), 1, thumb_length, ofp);
254
    }
255
    catch (...)
256
    {
257
      throw LIBRAW_EXCEPTION_ALLOC; // rethrow
258
    }
259
}
260
261
void LibRaw::ppm16_thumb()
262
{
263
    try
264
    {
265
        unsigned i;
266
        thumb_length = thumb_width * thumb_height * 3;
267
        std::vector<char> thumb(thumb_length * 2, 0);
268
        read_shorts((ushort *)thumb.data(), thumb_length);
269
        for (i = 0; i < thumb_length; i++)
270
            thumb[i] = ((ushort *)thumb.data())[i] >> 8;
271
        fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
272
        fwrite(thumb.data(), 1, thumb_length, ofp);
273
    }
274
    catch (...)
275
    {
276
      throw LIBRAW_EXCEPTION_ALLOC; // rethrow
277
    }
278
}
279
280
void LibRaw::layer_thumb()
281
{
282
    try
283
    {
284
        unsigned int i;
285
        int c;
286
        char map[][4] = { "012", "102" };
287
288
        colors = thumb_misc >> 5 & 7;
289
        thumb_length = thumb_width * thumb_height;
290
        std::vector<char> thumb(colors * thumb_length, 0);
291
        fprintf(ofp, "P%d\n%d %d\n255\n", 5 + (colors >> 1), thumb_width,
292
            thumb_height);
293
        fread(thumb.data(), thumb_length, colors, ifp);
294
        for (i = 0; i < thumb_length; i++)
295
            FORCC putc(thumb[i + thumb_length * (map[thumb_misc >> 8][c] - '0')], ofp);
296
    }
297
    catch (...)
298
    {
299
      throw LIBRAW_EXCEPTION_ALLOC; // rethrow
300
    }
301
}
302
303
void LibRaw::rollei_thumb()
304
{
305
    try
306
    {
307
        unsigned i;
308
        thumb_length = thumb_width * thumb_height;
309
        std::vector<ushort> thumb(thumb_length, 0);
310
        fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
311
        read_shorts(thumb.data(), thumb_length);
312
        for (i = 0; i < thumb_length; i++)
313
        {
314
            putc(thumb[i] << 3, ofp);
315
            putc(thumb[i] >> 5 << 2, ofp);
316
            putc(thumb[i] >> 11 << 3, ofp);
317
        }
318
    }
319
    catch (...)
320
    {
321
      throw LIBRAW_EXCEPTION_ALLOC; // rethrow
322
    }
323
}
324
325
void LibRaw::jpeg_thumb()
326
{
327
    try
328
    {
329
        std::vector<char> thumb(thumb_length);
330
        fread(thumb.data(), 1, thumb_length, ifp);
331
        jpeg_thumb_writer(ofp, thumb.data(), thumb_length);
332
    }
333
    catch (...)
334
    {
335
      throw LIBRAW_EXCEPTION_ALLOC; // rethrow
336
    }
337
}
338
#endif