1 /* -*- C++ -*-
2 * Copyright 2019-2020 LibRaw LLC (info@libraw.org)
3 *
4 LibRaw is free software; you can redistribute it and/or modify
5 it under the terms of the one of two licenses as you choose:
6
7 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
8 (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
9
10 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
11 (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
12
13 */
14
15 #include "../../internal/libraw_cxx_defs.h"
16
dcraw_make_mem_thumb(int * errcode)17 libraw_processed_image_t *LibRaw::dcraw_make_mem_thumb(int *errcode)
18 {
19 if (!T.thumb)
20 {
21 if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 &&
22 load_raw == &LibRaw::broadcom_load_raw) // RPi
23 )
24 {
25 if (errcode)
26 *errcode = LIBRAW_NO_THUMBNAIL;
27 }
28 else
29 {
30 if (errcode)
31 *errcode = LIBRAW_OUT_OF_ORDER_CALL;
32 }
33 return NULL;
34 }
35
36 if (T.tlength < 64u)
37 {
38 if (errcode)
39 *errcode = EINVAL;
40 return NULL;
41 }
42
43 if (INT64(T.tlength) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB)
44 {
45 if (errcode)
46 *errcode = LIBRAW_TOO_BIG;
47 return NULL;
48 }
49
50 if (T.tformat == LIBRAW_THUMBNAIL_BITMAP)
51 {
52 libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
53 sizeof(libraw_processed_image_t) + T.tlength);
54
55 if (!ret)
56 {
57 if (errcode)
58 *errcode = ENOMEM;
59 return NULL;
60 }
61
62 memset(ret, 0, sizeof(libraw_processed_image_t));
63 ret->type = LIBRAW_IMAGE_BITMAP;
64 ret->height = T.theight;
65 ret->width = T.twidth;
66 ret->colors = 3;
67 ret->bits = 8;
68 ret->data_size = T.tlength;
69 memmove(ret->data, T.thumb, T.tlength);
70 if (errcode)
71 *errcode = 0;
72 return ret;
73 }
74 else if (T.tformat == LIBRAW_THUMBNAIL_JPEG)
75 {
76 ushort exif[5];
77 int mk_exif = 0;
78 if (strcmp(T.thumb + 6, "Exif"))
79 mk_exif = 1;
80
81 int dsize = T.tlength + mk_exif * (sizeof(exif) + sizeof(tiff_hdr));
82
83 libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
84 sizeof(libraw_processed_image_t) + dsize);
85
86 if (!ret)
87 {
88 if (errcode)
89 *errcode = ENOMEM;
90 return NULL;
91 }
92
93 memset(ret, 0, sizeof(libraw_processed_image_t));
94
95 ret->type = LIBRAW_IMAGE_JPEG;
96 ret->data_size = dsize;
97
98 ret->data[0] = 0xff;
99 ret->data[1] = 0xd8;
100 if (mk_exif)
101 {
102 struct tiff_hdr th;
103 memcpy(exif, "\xff\xe1 Exif\0\0", 10);
104 exif[1] = htons(8 + sizeof th);
105 memmove(ret->data + 2, exif, sizeof(exif));
106 tiff_head(&th, 0);
107 memmove(ret->data + (2 + sizeof(exif)), &th, sizeof(th));
108 memmove(ret->data + (2 + sizeof(exif) + sizeof(th)), T.thumb + 2,
109 T.tlength - 2);
110 }
111 else
112 {
113 memmove(ret->data + 2, T.thumb + 2, T.tlength - 2);
114 }
115 if (errcode)
116 *errcode = 0;
117 return ret;
118 }
119 else
120 {
121 if (errcode)
122 *errcode = LIBRAW_UNSUPPORTED_THUMBNAIL;
123 return NULL;
124 }
125 }
126
127 // jlb
128 // macros for copying pixels to either BGR or RGB formats
129 #define FORBGR for (c = P1.colors - 1; c >= 0; c--)
130 #define FORRGB for (c = 0; c < P1.colors; c++)
131
get_mem_image_format(int * width,int * height,int * colors,int * bps) const132 void LibRaw::get_mem_image_format(int *width, int *height, int *colors,
133 int *bps) const
134
135 {
136 *width = S.width;
137 *height = S.height;
138 if (imgdata.progress_flags < LIBRAW_PROGRESS_FUJI_ROTATE)
139 {
140 if (O.use_fuji_rotate)
141 {
142 if (IO.fuji_width)
143 {
144 int fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
145 *width = (ushort)(fuji_width / sqrt(0.5));
146 *height = (ushort)((*height - fuji_width) / sqrt(0.5));
147 }
148 else
149 {
150 if (S.pixel_aspect < 0.995)
151 *height = (ushort)(*height / S.pixel_aspect + 0.5);
152 if (S.pixel_aspect > 1.005)
153 *width = (ushort)(*width * S.pixel_aspect + 0.5);
154 }
155 }
156 }
157 if (S.flip & 4)
158 {
159 std::swap(*width, *height);
160 }
161 *colors = P1.colors;
162 *bps = O.output_bps;
163 }
164
copy_mem_image(void * scan0,int stride,int bgr)165 int LibRaw::copy_mem_image(void *scan0, int stride, int bgr)
166
167 {
168 // the image memory pointed to by scan0 is assumed to be in the format
169 // returned by get_mem_image_format
170 if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) <
171 LIBRAW_PROGRESS_PRE_INTERPOLATE)
172 return LIBRAW_OUT_OF_ORDER_CALL;
173
174 if (libraw_internal_data.output_data.histogram)
175 {
176 int perc, val, total, t_white = 0x2000, c;
177 perc = S.width * S.height * O.auto_bright_thr;
178 if (IO.fuji_width)
179 perc /= 2;
180 if (!((O.highlight & ~2) || O.no_auto_bright))
181 for (t_white = c = 0; c < P1.colors; c++)
182 {
183 for (val = 0x2000, total = 0; --val > 32;)
184 if ((total += libraw_internal_data.output_data.histogram[c][val]) >
185 perc)
186 break;
187 if (t_white < val)
188 t_white = val;
189 }
190 gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright);
191 }
192
193 int s_iheight = S.iheight;
194 int s_iwidth = S.iwidth;
195 int s_width = S.width;
196 int s_hwight = S.height;
197
198 S.iheight = S.height;
199 S.iwidth = S.width;
200
201 if (S.flip & 4)
202 SWAP(S.height, S.width);
203 uchar *ppm;
204 ushort *ppm2;
205 int c, row, col, soff, rstep, cstep;
206
207 soff = flip_index(0, 0);
208 cstep = flip_index(0, 1) - soff;
209 rstep = flip_index(1, 0) - flip_index(0, S.width);
210
211 for (row = 0; row < S.height; row++, soff += rstep)
212 {
213 uchar *bufp = ((uchar *)scan0) + row * stride;
214 ppm2 = (ushort *)(ppm = bufp);
215 // keep trivial decisions in the outer loop for speed
216 if (bgr)
217 {
218 if (O.output_bps == 8)
219 {
220 for (col = 0; col < S.width; col++, soff += cstep)
221 FORBGR *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8;
222 }
223 else
224 {
225 for (col = 0; col < S.width; col++, soff += cstep)
226 FORBGR *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]];
227 }
228 }
229 else
230 {
231 if (O.output_bps == 8)
232 {
233 for (col = 0; col < S.width; col++, soff += cstep)
234 FORRGB *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8;
235 }
236 else
237 {
238 for (col = 0; col < S.width; col++, soff += cstep)
239 FORRGB *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]];
240 }
241 }
242
243 // bufp += stride; // go to the next line
244 }
245
246 S.iheight = s_iheight;
247 S.iwidth = s_iwidth;
248 S.width = s_width;
249 S.height = s_hwight;
250
251 return 0;
252 }
253 #undef FORBGR
254 #undef FORRGB
255
dcraw_make_mem_image(int * errcode)256 libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode)
257
258 {
259 int width, height, colors, bps;
260 get_mem_image_format(&width, &height, &colors, &bps);
261 int stride = width * (bps / 8) * colors;
262 unsigned ds = height * stride;
263 libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(
264 sizeof(libraw_processed_image_t) + ds);
265 if (!ret)
266 {
267 if (errcode)
268 *errcode = ENOMEM;
269 return NULL;
270 }
271 memset(ret, 0, sizeof(libraw_processed_image_t));
272
273 // metadata init
274 ret->type = LIBRAW_IMAGE_BITMAP;
275 ret->height = height;
276 ret->width = width;
277 ret->colors = colors;
278 ret->bits = bps;
279 ret->data_size = ds;
280 copy_mem_image(ret->data, stride, 0);
281
282 return ret;
283 }
284
dcraw_clear_mem(libraw_processed_image_t * p)285 void LibRaw::dcraw_clear_mem(libraw_processed_image_t *p)
286 {
287 if (p)
288 ::free(p);
289 }
290