/src/libraw/src/utils/utils_dcraw.cpp
Line | Count | Source |
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 | | |
21 | | int LibRaw::fcol(int row, int col) |
22 | 686M | { |
23 | 686M | static const char filter[16][16] = { |
24 | 686M | {2, 1, 1, 3, 2, 3, 2, 0, 3, 2, 3, 0, 1, 2, 1, 0}, |
25 | 686M | {0, 3, 0, 2, 0, 1, 3, 1, 0, 1, 1, 2, 0, 3, 3, 2}, |
26 | 686M | {2, 3, 3, 2, 3, 1, 1, 3, 3, 1, 2, 1, 2, 0, 0, 3}, |
27 | 686M | {0, 1, 0, 1, 0, 2, 0, 2, 2, 0, 3, 0, 1, 3, 2, 1}, |
28 | 686M | {3, 1, 1, 2, 0, 1, 0, 2, 1, 3, 1, 3, 0, 1, 3, 0}, |
29 | 686M | {2, 0, 0, 3, 3, 2, 3, 1, 2, 0, 2, 0, 3, 2, 2, 1}, |
30 | 686M | {2, 3, 3, 1, 2, 1, 2, 1, 2, 1, 1, 2, 3, 0, 0, 1}, |
31 | 686M | {1, 0, 0, 2, 3, 0, 0, 3, 0, 3, 0, 3, 2, 1, 2, 3}, |
32 | 686M | {2, 3, 3, 1, 1, 2, 1, 0, 3, 2, 3, 0, 2, 3, 1, 3}, |
33 | 686M | {1, 0, 2, 0, 3, 0, 3, 2, 0, 1, 1, 2, 0, 1, 0, 2}, |
34 | 686M | {0, 1, 1, 3, 3, 2, 2, 1, 1, 3, 3, 0, 2, 1, 3, 2}, |
35 | 686M | {2, 3, 2, 0, 0, 1, 3, 0, 2, 0, 1, 2, 3, 0, 1, 0}, |
36 | 686M | {1, 3, 1, 2, 3, 2, 3, 2, 0, 2, 0, 1, 1, 0, 3, 0}, |
37 | 686M | {0, 2, 0, 3, 1, 0, 0, 1, 1, 3, 3, 2, 3, 2, 2, 1}, |
38 | 686M | {2, 1, 3, 2, 3, 1, 2, 1, 0, 3, 0, 2, 0, 2, 0, 2}, |
39 | 686M | {0, 3, 1, 0, 0, 2, 0, 3, 2, 1, 3, 1, 1, 3, 1, 3}}; |
40 | | |
41 | 686M | if (filters == 1) |
42 | 148k | return filter[(row + top_margin) & 15][(col + left_margin) & 15]; |
43 | 686M | if (filters == 9) |
44 | 196M | return xtrans[(row + 6) % 6][(col + 6) % 6]; |
45 | 489M | return FC(row, col); |
46 | 686M | } |
47 | | |
48 | | size_t LibRaw::strnlen(const char *s, size_t n) |
49 | 126k | { |
50 | 126k | #if !defined(__FreeBSD__) && !defined(__OpenBSD__) |
51 | 126k | const char *p = (const char *)memchr(s, 0, n); |
52 | 126k | return (p ? p - s : n); |
53 | | #else |
54 | | return ::strnlen(s, n); |
55 | | #endif |
56 | 126k | } |
57 | | |
58 | | void *LibRaw::memmem(char *haystack, size_t haystacklen, char *needle, |
59 | | size_t needlelen) |
60 | 55.4k | { |
61 | | #if !defined(__GLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) |
62 | | char *c; |
63 | | for (c = haystack; c <= haystack + haystacklen - needlelen; c++) |
64 | | if (!memcmp(c, needle, needlelen)) |
65 | | return c; |
66 | | return 0; |
67 | | #else |
68 | 55.4k | return ::memmem(haystack, haystacklen, needle, needlelen); |
69 | 55.4k | #endif |
70 | 55.4k | } |
71 | | |
72 | | char *LibRaw::strcasestr(char *haystack, const char *needle) |
73 | 1.09M | { |
74 | 1.09M | char *c; |
75 | 9.90M | for (c = haystack; *c; c++) |
76 | 8.85M | if (!strncasecmp(c, needle, strlen(needle))) |
77 | 48.9k | return c; |
78 | 1.04M | return 0; |
79 | 1.09M | } |
80 | | |
81 | | void LibRaw::initdata() |
82 | 0 | { |
83 | 0 | tiff_flip = flip = filters = UINT_MAX; /* unknown */ |
84 | 0 | raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0; |
85 | 0 | maximum = height = width = top_margin = left_margin = 0; |
86 | 0 | cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0; |
87 | 0 | iso_speed = shutter = aperture = focal_len = 0; |
88 | 0 | unique_id = 0ULL; |
89 | 0 | tiff_nifds = 0; |
90 | 0 | memset(tiff_ifd, 0, sizeof tiff_ifd); |
91 | 0 | for (int i = 0; i < LIBRAW_IFD_MAXCOUNT; i++) |
92 | 0 | { |
93 | 0 | tiff_ifd[i].dng_color[0].illuminant = tiff_ifd[i].dng_color[1].illuminant = |
94 | 0 | 0xffff; |
95 | 0 | for (int c = 0; c < 4; c++) |
96 | 0 | tiff_ifd[i].dng_levels.analogbalance[c] = 1.0f; |
97 | 0 | } |
98 | 0 | for (int i = 0; i < 0x10000; i++) |
99 | 0 | curve[i] = i; |
100 | 0 | memset(gpsdata, 0, sizeof gpsdata); |
101 | 0 | memset(cblack, 0, sizeof cblack); |
102 | 0 | memset(white, 0, sizeof white); |
103 | 0 | memset(mask, 0, sizeof mask); |
104 | 0 | thumb_offset = thumb_length = thumb_width = thumb_height = 0; |
105 | 0 | load_raw = 0; |
106 | 0 | thumb_format = LIBRAW_INTERNAL_THUMBNAIL_JPEG; // default to JPEG |
107 | 0 | data_offset = meta_offset = meta_length = tiff_bps = tiff_compress = 0; |
108 | 0 | kodak_cbpp = zero_after_ff = dng_version = load_flags = 0; |
109 | 0 | timestamp = shot_order = tiff_samples = black = is_foveon = 0; |
110 | 0 | mix_green = profile_length = data_error = zero_is_bad = 0; |
111 | 0 | pixel_aspect = is_raw = raw_color = 1; |
112 | 0 | tile_width = tile_length = 0; |
113 | 0 | metadata_blocks = 0; |
114 | 0 | is_NikonTransfer = 0; |
115 | 0 | is_Olympus = 0; |
116 | 0 | OlympusDNG_SubDirOffsetValid = 0; |
117 | 0 | is_Sony = 0; |
118 | 0 | is_pana_raw = 0; |
119 | 0 | maker_index = LIBRAW_CAMERAMAKER_Unknown; |
120 | 0 | FujiCropMode = 0; |
121 | 0 | is_PentaxRicohMakernotes = 0; |
122 | 0 | normalized_model[0] = 0; |
123 | 0 | normalized_make[0] = 0; |
124 | 0 | CM_found = 0; |
125 | 0 | } |
126 | | |
127 | | void LibRaw::aRGB_coeff(double aRGB_cam[3][3]) |
128 | 268 | { |
129 | 268 | static const double rgb_aRGB[3][3] = { |
130 | 268 | {1.39828313770000, -0.3982830047, 9.64980900741708E-8}, |
131 | 268 | {6.09219200572997E-8, 0.9999999809, 1.33230799934103E-8}, |
132 | 268 | {2.17237099975343E-8, -0.0429383201, 1.04293828050000}}; |
133 | | |
134 | 268 | double cmatrix_tmp[3][3] = { |
135 | 268 | {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; |
136 | 268 | int i, j, k; |
137 | | |
138 | 1.07k | for (i = 0; i < 3; i++) |
139 | 3.21k | for (j = 0; j < 3; j++) |
140 | 2.41k | { |
141 | 9.64k | for (k = 0; k < 3; k++) |
142 | 7.23k | cmatrix_tmp[i][j] += rgb_aRGB[i][k] * aRGB_cam[k][j]; |
143 | 2.41k | cmatrix[i][j] = (float)cmatrix_tmp[i][j]; |
144 | 2.41k | } |
145 | 268 | } |
146 | | |
147 | | void LibRaw::romm_coeff(float romm_cam[3][3]) |
148 | 393 | { |
149 | 393 | static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */ |
150 | 393 | {{2.034193f, -0.727420f, -0.306766f}, |
151 | 393 | {-0.228811f, 1.231729f, -0.002922f}, |
152 | 393 | {-0.008565f, -0.153273f, 1.161839f}}; |
153 | 393 | int i, j, k; |
154 | | |
155 | 1.57k | for (i = 0; i < 3; i++) |
156 | 4.71k | for (j = 0; j < 3; j++) |
157 | 14.1k | for (cmatrix[i][j] = 0.f, k = 0; k < 3; k++) |
158 | 10.6k | cmatrix[i][j] += float(rgb_romm[i][k] * romm_cam[k][j]); |
159 | 393 | } |
160 | | |
161 | | void LibRaw::remove_zeroes() |
162 | 62 | { |
163 | 62 | unsigned row, col, tot, n; |
164 | 62 | int r, c; |
165 | | |
166 | 62 | RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 0, 2); |
167 | | |
168 | 23.2k | for (row = 0; row < height; row++) |
169 | 6.52M | for (col = 0; col < width; col++) |
170 | 6.50M | if (BAYER(row, col) == 0) |
171 | 2.75M | { |
172 | 2.75M | tot = n = 0; |
173 | 16.5M | for (r = (int)row - 2; r <= (int)row + 2; r++) |
174 | 82.6M | for (c = (int)col - 2; c <= (int)col + 2; c++) |
175 | 68.8M | if (r >= 0 && r < height && c >= 0 && c < width && |
176 | 68.8M | FC(r, c) == FC(row, col) && BAYER(r, c)) |
177 | 2.89M | tot += (n++, BAYER(r, c)); |
178 | 2.75M | if (n) |
179 | 2.75M | BAYER(row, col) = tot / n; |
180 | 2.75M | } |
181 | 62 | RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 1, 2); |
182 | 62 | } |
183 | | void LibRaw::crop_masked_pixels() |
184 | 1.57k | { |
185 | 1.57k | int row, col; |
186 | 1.57k | unsigned c, m, zero, val; |
187 | 5.88M | #define mblack imgdata.color.black_stat |
188 | | |
189 | 1.57k | if (mask[0][3] > 0) |
190 | 27 | goto mask_set; |
191 | 1.54k | if (load_raw == &LibRaw::canon_load_raw || |
192 | 1.51k | load_raw == &LibRaw::lossless_jpeg_load_raw || |
193 | 1.50k | load_raw == &LibRaw::crxLoadRaw) |
194 | 39 | { |
195 | 39 | mask[0][1] = mask[1][1] += 2; |
196 | 39 | mask[0][3] -= 2; |
197 | 39 | goto sides; |
198 | 39 | } |
199 | 1.50k | if (load_raw == &LibRaw::canon_600_load_raw || |
200 | 1.50k | load_raw == &LibRaw::sony_load_raw || |
201 | 1.50k | (load_raw == &LibRaw::eight_bit_load_raw && strncmp(model, "DC2", 3)) || |
202 | 1.50k | load_raw == &LibRaw::kodak_262_load_raw || |
203 | 1.32k | (load_raw == &LibRaw::packed_load_raw && (load_flags & 32))) |
204 | 182 | { |
205 | 221 | sides: |
206 | 221 | mask[0][0] = mask[1][0] = top_margin; |
207 | 221 | mask[0][2] = mask[1][2] = top_margin + height; |
208 | 221 | mask[0][3] += left_margin; |
209 | 221 | mask[1][1] += left_margin + width; |
210 | 221 | mask[1][3] += raw_width; |
211 | 221 | } |
212 | 1.54k | if (load_raw == &LibRaw::nokia_load_raw) |
213 | 110 | { |
214 | 110 | mask[0][2] = top_margin; |
215 | 110 | mask[0][3] = width; |
216 | 110 | } |
217 | 1.54k | if (load_raw == &LibRaw::broadcom_load_raw) |
218 | 0 | { |
219 | 0 | mask[0][2] = top_margin; |
220 | 0 | mask[0][3] = width; |
221 | 0 | } |
222 | 1.57k | mask_set: |
223 | 1.57k | memset(mblack, 0, sizeof mblack); |
224 | 14.1k | for (zero = m = 0; m < 8; m++) |
225 | 316k | for (row = MAX(mask[m][0], 0); row < MIN(mask[m][2], raw_height); row++) |
226 | 3.24M | for (col = MAX(mask[m][1], 0); col < MIN(mask[m][3], raw_width); col++) |
227 | 2.94M | { |
228 | | /* No need to subtract margins because full area and active area filters are the same */ |
229 | 2.94M | c = FC(row, col); |
230 | 2.94M | mblack[c] += val = raw_image[(row)*raw_pitch / 2 + (col)]; |
231 | 2.94M | mblack[4 + c]++; |
232 | 2.94M | zero += !val; |
233 | 2.94M | } |
234 | 1.57k | if (load_raw == &LibRaw::canon_600_load_raw && width < raw_width) |
235 | 0 | { |
236 | 0 | black = (mblack[0] + mblack[1] + mblack[2] + mblack[3]) / |
237 | 0 | MAX(1, (mblack[4] + mblack[5] + mblack[6] + mblack[7])) - |
238 | 0 | 4; |
239 | 0 | } |
240 | 1.57k | else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) |
241 | 16 | { |
242 | 64 | FORC4 cblack[c] = mblack[c] / MAX(1, mblack[4 + c]); |
243 | 16 | black = cblack[4] = cblack[5] = cblack[6] = 0; |
244 | 16 | } |
245 | 1.57k | } |
246 | | #undef mblack |
247 | | |
248 | | void LibRaw::pseudoinverse(double (*in)[3], double (*out)[3], int size) |
249 | 1.74k | { |
250 | 1.74k | double work[3][6], num; |
251 | 1.74k | int i, j, k; |
252 | | |
253 | 6.99k | for (i = 0; i < 3; i++) |
254 | 5.24k | { |
255 | 36.7k | for (j = 0; j < 6; j++) |
256 | 31.4k | work[i][j] = j == i + 3; |
257 | 20.9k | for (j = 0; j < 3; j++) |
258 | 63.3k | for (k = 0; k < size && k < 4; k++) |
259 | 47.6k | work[i][j] += in[k][i] * in[k][j]; |
260 | 5.24k | } |
261 | 6.99k | for (i = 0; i < 3; i++) |
262 | 5.24k | { |
263 | 5.24k | num = work[i][i]; |
264 | 36.7k | for (j = 0; j < 6; j++) |
265 | 31.4k | if (fabs(num) > 0.00001f) |
266 | 23.6k | work[i][j] /= num; |
267 | 20.9k | for (k = 0; k < 3; k++) |
268 | 15.7k | { |
269 | 15.7k | if (k == i) |
270 | 5.24k | continue; |
271 | 10.4k | num = work[k][i]; |
272 | 73.4k | for (j = 0; j < 6; j++) |
273 | 62.9k | work[k][j] -= work[i][j] * num; |
274 | 10.4k | } |
275 | 5.24k | } |
276 | 7.04k | for (i = 0; i < size && i < 4; i++) |
277 | 21.1k | for (j = 0; j < 3; j++) |
278 | 63.5k | for (out[i][j] = k = 0; k < 3; k++) |
279 | 47.6k | out[i][j] += work[j][k + 3] * in[i][k]; |
280 | 1.74k | } |
281 | | |
282 | | void LibRaw::cam_xyz_coeff(float _rgb_cam[3][4], double cam_xyz[4][3]) |
283 | 1.53k | { |
284 | 1.53k | double cam_rgb[4][3], inverse[4][3], num; |
285 | 1.53k | int i, j, k; |
286 | | |
287 | 6.20k | for (i = 0; i < colors && i < 4; i++) /* Multiply out XYZ colorspace */ |
288 | 18.6k | for (j = 0; j < 3; j++) |
289 | 55.9k | for (cam_rgb[i][j] = k = 0; k < 3; k++) |
290 | 41.9k | cam_rgb[i][j] += cam_xyz[i][k] * LibRaw_constants::xyz_rgb[k][j]; |
291 | | |
292 | 6.20k | for (i = 0; i < colors && i < 4; i++) |
293 | 4.66k | { /* Normalize cam_rgb so that */ |
294 | 18.6k | for (num = j = 0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */ |
295 | 13.9k | num += cam_rgb[i][j]; |
296 | 4.66k | if (num > 0.00001) |
297 | 3.44k | { |
298 | 13.7k | for (j = 0; j < 3; j++) |
299 | 10.3k | cam_rgb[i][j] /= num; |
300 | 3.44k | pre_mul[i] = float(1.0 / num); |
301 | 3.44k | } |
302 | 1.21k | else |
303 | 1.21k | { |
304 | 4.87k | for (j = 0; j < 3; j++) |
305 | 3.65k | cam_rgb[i][j] = 0.0; |
306 | 1.21k | pre_mul[i] = 1.0; |
307 | 1.21k | } |
308 | 4.66k | } |
309 | 1.53k | pseudoinverse(cam_rgb, inverse, colors); |
310 | 6.15k | for (i = 0; i < 3; i++) |
311 | 18.6k | for (j = 0; j < colors && j < 4; j++) |
312 | 13.9k | _rgb_cam[i][j] = float(inverse[j][i]); |
313 | 1.53k | } |
314 | | |
315 | | void LibRaw::tiff_get(INT64 base, unsigned *tag, unsigned *type, |
316 | | unsigned *len, INT64 *save) |
317 | 67.3M | { |
318 | 67.3M | #ifdef LIBRAW_IOSPACE_CHECK |
319 | 67.3M | INT64 pos = ftell(ifp); |
320 | 67.3M | INT64 fsize = ifp->size(); |
321 | 67.3M | if (fsize < 12 || (fsize - pos) < 12) |
322 | 11.3k | throw LIBRAW_EXCEPTION_IO_EOF; |
323 | 67.3M | #endif |
324 | 67.3M | *tag = get2(); |
325 | 67.3M | *type = get2(); |
326 | 67.3M | *len = get4(); |
327 | 67.3M | *save = ftell(ifp) + 4LL; |
328 | 67.3M | if (*len * tagtype_dataunit_bytes[(*type <= LIBRAW_EXIFTAG_TYPE_IFD8) ? *type : 0] > 4) |
329 | 57.8M | fseek(ifp, INT64(get4()) + base, SEEK_SET); |
330 | 67.3M | } |