/src/libraw/src/utils/utils_libraw.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | * Copyright 2019-2025 LibRaw LLC (info@libraw.org) |
3 | | * |
4 | | |
5 | | LibRaw is free software; you can redistribute it and/or modify |
6 | | it under the terms of the one of two licenses as you choose: |
7 | | |
8 | | 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
9 | | (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
10 | | |
11 | | 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
12 | | (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
13 | | |
14 | | */ |
15 | | |
16 | | #include "../../internal/libraw_cxx_defs.h" |
17 | | #include "../../internal/libraw_checked_buffer.h" |
18 | | |
19 | | #ifdef __cplusplus |
20 | | extern "C" |
21 | | { |
22 | | #endif |
23 | | |
24 | | void default_data_callback(void *, const char *file, const INT64 offset) |
25 | 2.72k | { |
26 | 2.72k | if (offset < 0) |
27 | 1.67k | fprintf(stderr, "%s: Unexpected end of file\n", |
28 | 1.67k | file ? file : "unknown file"); |
29 | 1.04k | else |
30 | 1.04k | fprintf(stderr, "%s: data corrupted at %lld\n", |
31 | 1.04k | file ? file : "unknown file", offset); |
32 | 2.72k | } |
33 | | const char *libraw_strerror(int e) |
34 | 0 | { |
35 | 0 | enum LibRaw_errors errorcode = (LibRaw_errors)e; |
36 | 0 | switch (errorcode) |
37 | 0 | { |
38 | 0 | case LIBRAW_SUCCESS: |
39 | 0 | return "No error"; |
40 | 0 | case LIBRAW_UNSPECIFIED_ERROR: |
41 | 0 | return "Unspecified error"; |
42 | 0 | case LIBRAW_FILE_UNSUPPORTED: |
43 | 0 | return "Unsupported file format or not RAW file"; |
44 | 0 | case LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE: |
45 | 0 | return "Request for nonexisting image number"; |
46 | 0 | case LIBRAW_OUT_OF_ORDER_CALL: |
47 | 0 | return "Out of order call of libraw function"; |
48 | 0 | case LIBRAW_NO_THUMBNAIL: |
49 | 0 | return "No thumbnail in file"; |
50 | 0 | case LIBRAW_UNSUPPORTED_THUMBNAIL: |
51 | 0 | return "Unsupported thumbnail format"; |
52 | 0 | case LIBRAW_INPUT_CLOSED: |
53 | 0 | return "No input stream, or input stream closed"; |
54 | 0 | case LIBRAW_NOT_IMPLEMENTED: |
55 | 0 | return "Decoder not implemented for this data format"; |
56 | 0 | case LIBRAW_REQUEST_FOR_NONEXISTENT_THUMBNAIL: |
57 | 0 | return "Request for nonexisting thumbnail number"; |
58 | 0 | case LIBRAW_MEMPOOL_OVERFLOW: |
59 | 0 | return "Libraw internal mempool overflowed"; |
60 | 0 | case LIBRAW_UNSUFFICIENT_MEMORY: |
61 | 0 | return "Unsufficient memory"; |
62 | 0 | case LIBRAW_DATA_ERROR: |
63 | 0 | return "Corrupted data or unexpected EOF"; |
64 | 0 | case LIBRAW_IO_ERROR: |
65 | 0 | return "Input/output error"; |
66 | 0 | case LIBRAW_CANCELLED_BY_CALLBACK: |
67 | 0 | return "Cancelled by user callback"; |
68 | 0 | case LIBRAW_BAD_CROP: |
69 | 0 | return "Bad crop box"; |
70 | 0 | case LIBRAW_TOO_BIG: |
71 | 0 | return "Image too big for processing"; |
72 | 0 | default: |
73 | 0 | return "Unknown error code"; |
74 | 0 | } |
75 | 0 | } |
76 | | |
77 | | #ifdef __cplusplus |
78 | | } |
79 | | #endif |
80 | | |
81 | | unsigned LibRaw::parse_custom_cameras(unsigned limit, |
82 | | libraw_custom_camera_t table[], |
83 | | char **list) |
84 | 20.0k | { |
85 | 20.0k | if (!list) |
86 | 20.0k | return 0; |
87 | 0 | unsigned index = 0; |
88 | 0 | for (unsigned i = 0; i < limit; i++) |
89 | 0 | { |
90 | 0 | if (!list[i]) |
91 | 0 | break; |
92 | 0 | if (strlen(list[i]) < 10) |
93 | 0 | continue; |
94 | 0 | char *string = (char *)malloc(strlen(list[i]) + 1); |
95 | 0 | strcpy(string, list[i]); |
96 | 0 | char *start = string; |
97 | 0 | memset(&table[index], 0, sizeof(table[0])); |
98 | 0 | for (int j = 0; start && j < 14; j++) |
99 | 0 | { |
100 | 0 | char *end = strchr(start, ','); |
101 | 0 | if (end) |
102 | 0 | { |
103 | 0 | *end = 0; |
104 | 0 | end++; |
105 | 0 | } // move to next char |
106 | 0 | while (isspace(*start) && *start) |
107 | 0 | start++; // skip leading spaces? |
108 | 0 | unsigned val = strtol(start, 0, 10); |
109 | 0 | switch (j) |
110 | 0 | { |
111 | 0 | case 0: |
112 | 0 | table[index].fsize = val; |
113 | 0 | break; |
114 | 0 | case 1: |
115 | 0 | table[index].rw = val; |
116 | 0 | break; |
117 | 0 | case 2: |
118 | 0 | table[index].rh = val; |
119 | 0 | break; |
120 | 0 | case 3: |
121 | 0 | table[index].lm = val; |
122 | 0 | break; |
123 | 0 | case 4: |
124 | 0 | table[index].tm = val; |
125 | 0 | break; |
126 | 0 | case 5: |
127 | 0 | table[index].rm = val; |
128 | 0 | break; |
129 | 0 | case 6: |
130 | 0 | table[index].bm = val; |
131 | 0 | break; |
132 | 0 | case 7: |
133 | 0 | table[index].lf = val; |
134 | 0 | break; |
135 | 0 | case 8: |
136 | 0 | table[index].cf = val; |
137 | 0 | break; |
138 | 0 | case 9: |
139 | 0 | table[index].max = val; |
140 | 0 | break; |
141 | 0 | case 10: |
142 | 0 | table[index].flags = val; |
143 | 0 | break; |
144 | 0 | case 11: |
145 | 0 | strncpy(table[index].t_make, start, sizeof(table[index].t_make) - 1); |
146 | 0 | break; |
147 | 0 | case 12: |
148 | 0 | strncpy(table[index].t_model, start, sizeof(table[index].t_model) - 1); |
149 | 0 | break; |
150 | 0 | case 13: |
151 | 0 | table[index].offset = val; |
152 | 0 | break; |
153 | 0 | default: |
154 | 0 | break; |
155 | 0 | } |
156 | 0 | start = end; |
157 | 0 | } |
158 | 0 | free(string); |
159 | 0 | if (table[index].t_make[0]) |
160 | 0 | index++; |
161 | 0 | } |
162 | 0 | return index; |
163 | 0 | } |
164 | | |
165 | | void LibRaw::derror() |
166 | 132M | { |
167 | 132M | if (!libraw_internal_data.unpacker_data.data_error && |
168 | 2.72k | libraw_internal_data.internal_data.input) |
169 | 2.72k | { |
170 | 2.72k | if (libraw_internal_data.internal_data.input->eof()) |
171 | 1.67k | { |
172 | 1.67k | if (callbacks.data_cb) |
173 | 1.67k | (*callbacks.data_cb)(callbacks.datacb_data, |
174 | 1.67k | libraw_internal_data.internal_data.input->fname(), |
175 | 1.67k | -1); |
176 | 1.67k | throw LIBRAW_EXCEPTION_IO_EOF; |
177 | 1.67k | } |
178 | 1.04k | else |
179 | 1.04k | { |
180 | 1.04k | if (callbacks.data_cb) |
181 | 1.04k | (*callbacks.data_cb)(callbacks.datacb_data, |
182 | 1.04k | libraw_internal_data.internal_data.input->fname(), |
183 | 1.04k | libraw_internal_data.internal_data.input->tell()); |
184 | | // throw LIBRAW_EXCEPTION_IO_CORRUPT; |
185 | 1.04k | } |
186 | 2.72k | } |
187 | 132M | libraw_internal_data.unpacker_data.data_error++; |
188 | 132M | } |
189 | | |
190 | 0 | const char *LibRaw::version() { return LIBRAW_VERSION_STR; } |
191 | 0 | int LibRaw::versionNumber() { return LIBRAW_VERSION; } |
192 | 0 | const char *LibRaw::strerror(int p) { return libraw_strerror(p); } |
193 | | |
194 | | unsigned LibRaw::capabilities() |
195 | 0 | { |
196 | 0 | unsigned ret = 0; |
197 | | #ifdef USE_RAWSPEED |
198 | | ret |= LIBRAW_CAPS_RAWSPEED; |
199 | | #endif |
200 | | #ifdef USE_RAWSPEED3 |
201 | | ret |= LIBRAW_CAPS_RAWSPEED3; |
202 | | #endif |
203 | | #ifdef USE_RAWSPEED_BITS |
204 | | ret |= LIBRAW_CAPS_RAWSPEED_BITS; |
205 | | #endif |
206 | | #ifdef USE_DNGSDK |
207 | | ret |= LIBRAW_CAPS_DNGSDK; |
208 | | #ifdef USE_GPRSDK |
209 | | ret |= LIBRAW_CAPS_GPRSDK; |
210 | | #endif |
211 | | #ifdef LIBRAW_WIN32_UNICODEPATHS |
212 | | ret |= LIBRAW_CAPS_UNICODEPATHS; |
213 | | #endif |
214 | | #endif |
215 | | #ifdef USE_X3FTOOLS |
216 | | ret |= LIBRAW_CAPS_X3FTOOLS; |
217 | | #endif |
218 | | #ifdef USE_6BY9RPI |
219 | | ret |= LIBRAW_CAPS_RPI6BY9; |
220 | | #endif |
221 | 0 | #ifdef USE_ZLIB |
222 | 0 | ret |= LIBRAW_CAPS_ZLIB; |
223 | 0 | #endif |
224 | | #ifdef USE_JPEG |
225 | | ret |= LIBRAW_CAPS_JPEG; |
226 | | #endif |
227 | 0 | return ret; |
228 | 0 | } |
229 | | |
230 | | int LibRaw::is_sraw() |
231 | 0 | { |
232 | 0 | return load_raw == &LibRaw::canon_sraw_load_raw || |
233 | 0 | load_raw == &LibRaw::nikon_load_sraw || |
234 | 0 | load_raw == &LibRaw::sony_ycbcr_load_raw; |
235 | 0 | } |
236 | | int LibRaw::is_coolscan_nef() |
237 | 0 | { |
238 | 0 | return load_raw == &LibRaw::nikon_coolscan_load_raw; |
239 | 0 | } |
240 | | int LibRaw::is_jpeg_thumb() |
241 | 0 | { |
242 | 0 | return libraw_internal_data.unpacker_data.thumb_format == LIBRAW_INTERNAL_THUMBNAIL_JPEG; |
243 | 0 | } |
244 | | |
245 | 0 | int LibRaw::is_nikon_sraw() { return load_raw == &LibRaw::nikon_load_sraw; } |
246 | | int LibRaw::sraw_midpoint() |
247 | 0 | { |
248 | 0 | if (load_raw == &LibRaw::canon_sraw_load_raw) |
249 | 0 | return 8192; |
250 | 0 | else if (load_raw == &LibRaw::sony_ycbcr_load_raw) |
251 | 0 | return 8192; // adjusted as in canon sRAW |
252 | 0 | else if (load_raw == &LibRaw::nikon_load_sraw) |
253 | 0 | return 2048; |
254 | 0 | else |
255 | 0 | return 0; |
256 | 0 | } |
257 | | |
258 | | void *LibRaw::malloc(size_t t) |
259 | 10.3k | { |
260 | 10.3k | void *p = memmgr.malloc(t); |
261 | 10.3k | if (!p) |
262 | 0 | throw LIBRAW_EXCEPTION_ALLOC; |
263 | 10.3k | return p; |
264 | 10.3k | } |
265 | | void *LibRaw::realloc(void *q, size_t t) |
266 | 8.06k | { |
267 | 8.06k | void *p = memmgr.realloc(q, t); |
268 | 8.06k | if (!p) |
269 | 0 | throw LIBRAW_EXCEPTION_ALLOC; |
270 | 8.06k | return p; |
271 | 8.06k | } |
272 | | |
273 | | void *LibRaw::calloc(size_t n, size_t t) |
274 | 228k | { |
275 | 228k | void *p = memmgr.calloc(n, t); |
276 | 228k | if (!p) |
277 | 0 | throw LIBRAW_EXCEPTION_ALLOC; |
278 | 228k | return p; |
279 | 228k | } |
280 | 210k | void LibRaw::free(void *p) { memmgr.free(p); } |
281 | | |
282 | | void LibRaw::recycle_datastream() |
283 | 49.4k | { |
284 | 49.4k | if (libraw_internal_data.internal_data.input && |
285 | 20.0k | libraw_internal_data.internal_data.input_internal) |
286 | 5.15k | { |
287 | 5.15k | delete libraw_internal_data.internal_data.input; |
288 | 5.15k | libraw_internal_data.internal_data.input = NULL; |
289 | 5.15k | } |
290 | 49.4k | libraw_internal_data.internal_data.input_internal = 0; |
291 | 49.4k | } |
292 | | |
293 | | void LibRaw::clearCancelFlag() |
294 | 0 | { |
295 | | #ifdef _MSC_VER |
296 | | InterlockedExchange(&_exitflag, 0); |
297 | | #else |
298 | 0 | __sync_fetch_and_and(&_exitflag, 0); |
299 | 0 | #endif |
300 | | #ifdef RAWSPEED_FASTEXIT |
301 | | if (_rawspeed_decoder) |
302 | | { |
303 | | RawSpeed::RawDecoder *d = |
304 | | static_cast<RawSpeed::RawDecoder *>(_rawspeed_decoder); |
305 | | d->resumeProcessing(); |
306 | | } |
307 | | #endif |
308 | 0 | } |
309 | | |
310 | | void LibRaw::setCancelFlag() |
311 | 0 | { |
312 | | #ifdef _MSC_VER |
313 | | InterlockedExchange(&_exitflag, 1); |
314 | | #else |
315 | 0 | __sync_fetch_and_add(&_exitflag, 1); |
316 | 0 | #endif |
317 | | #ifdef RAWSPEED_FASTEXIT |
318 | | if (_rawspeed_decoder) |
319 | | { |
320 | | RawSpeed::RawDecoder *d = |
321 | | static_cast<RawSpeed::RawDecoder *>(_rawspeed_decoder); |
322 | | d->cancelProcessing(); |
323 | | } |
324 | | #endif |
325 | 0 | } |
326 | | |
327 | | void LibRaw::checkCancel() |
328 | 19.1M | { |
329 | | #ifdef _MSC_VER |
330 | | if (InterlockedExchange(&_exitflag, 0)) |
331 | | throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; |
332 | | #else |
333 | 19.1M | if (__sync_fetch_and_and(&_exitflag, 0)) |
334 | 0 | throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; |
335 | 19.1M | #endif |
336 | 19.1M | } |
337 | | |
338 | | int LibRaw::is_curve_linear() |
339 | 0 | { |
340 | 0 | for (int i = 0; i < 0x10000; i++) |
341 | 0 | if (imgdata.color.curve[i] != i) |
342 | 0 | return 0; |
343 | 0 | return 1; |
344 | 0 | } |
345 | | |
346 | | void LibRaw::free_image(void) |
347 | 1.53k | { |
348 | 1.53k | if (imgdata.image) |
349 | 1.53k | { |
350 | 1.53k | free(imgdata.image); |
351 | 1.53k | imgdata.image = 0; |
352 | 1.53k | imgdata.progress_flags = LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN | |
353 | 1.53k | LIBRAW_PROGRESS_IDENTIFY | |
354 | 1.53k | LIBRAW_PROGRESS_SIZE_ADJUST | |
355 | 1.53k | LIBRAW_PROGRESS_LOAD_RAW; |
356 | 1.53k | } |
357 | 1.53k | } |
358 | | |
359 | | int LibRaw::is_phaseone_compressed() |
360 | 13.5k | { |
361 | 13.5k | return (load_raw == &LibRaw::phase_one_load_raw_c || |
362 | 12.9k | load_raw == &LibRaw::phase_one_load_raw_s || |
363 | 12.9k | load_raw == &LibRaw::phase_one_load_raw); |
364 | 13.5k | } |
365 | | |
366 | 0 | int LibRaw::is_canon_600() { return load_raw == &LibRaw::canon_600_load_raw; } |
367 | | const char *LibRaw::strprogress(enum LibRaw_progress p) |
368 | 0 | { |
369 | 0 | switch (p) |
370 | 0 | { |
371 | 0 | case LIBRAW_PROGRESS_START: |
372 | 0 | return "Starting"; |
373 | 0 | case LIBRAW_PROGRESS_OPEN: |
374 | 0 | return "Opening file"; |
375 | 0 | case LIBRAW_PROGRESS_IDENTIFY: |
376 | 0 | return "Reading metadata"; |
377 | 0 | case LIBRAW_PROGRESS_SIZE_ADJUST: |
378 | 0 | return "Adjusting size"; |
379 | 0 | case LIBRAW_PROGRESS_LOAD_RAW: |
380 | 0 | return "Reading RAW data"; |
381 | 0 | case LIBRAW_PROGRESS_REMOVE_ZEROES: |
382 | 0 | return "Clearing zero values"; |
383 | 0 | case LIBRAW_PROGRESS_BAD_PIXELS: |
384 | 0 | return "Removing dead pixels"; |
385 | 0 | case LIBRAW_PROGRESS_DARK_FRAME: |
386 | 0 | return "Subtracting dark frame data"; |
387 | 0 | case LIBRAW_PROGRESS_FOVEON_INTERPOLATE: |
388 | 0 | return "Interpolating Foveon sensor data"; |
389 | 0 | case LIBRAW_PROGRESS_SCALE_COLORS: |
390 | 0 | return "Scaling colors"; |
391 | 0 | case LIBRAW_PROGRESS_PRE_INTERPOLATE: |
392 | 0 | return "Pre-interpolating"; |
393 | 0 | case LIBRAW_PROGRESS_INTERPOLATE: |
394 | 0 | return "Interpolating"; |
395 | 0 | case LIBRAW_PROGRESS_MIX_GREEN: |
396 | 0 | return "Mixing green channels"; |
397 | 0 | case LIBRAW_PROGRESS_MEDIAN_FILTER: |
398 | 0 | return "Median filter"; |
399 | 0 | case LIBRAW_PROGRESS_HIGHLIGHTS: |
400 | 0 | return "Highlight recovery"; |
401 | 0 | case LIBRAW_PROGRESS_FUJI_ROTATE: |
402 | 0 | return "Rotating Fuji diagonal data"; |
403 | 0 | case LIBRAW_PROGRESS_FLIP: |
404 | 0 | return "Flipping image"; |
405 | 0 | case LIBRAW_PROGRESS_APPLY_PROFILE: |
406 | 0 | return "ICC conversion"; |
407 | 0 | case LIBRAW_PROGRESS_CONVERT_RGB: |
408 | 0 | return "Converting to RGB"; |
409 | 0 | case LIBRAW_PROGRESS_STRETCH: |
410 | 0 | return "Stretching image"; |
411 | 0 | case LIBRAW_PROGRESS_THUMB_LOAD: |
412 | 0 | return "Loading thumbnail"; |
413 | 0 | default: |
414 | 0 | return "Some strange things"; |
415 | 0 | } |
416 | 0 | } |
417 | | int LibRaw::adjust_sizes_info_only(void) |
418 | 0 | { |
419 | 0 | CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY); |
420 | | |
421 | 0 | raw2image_start(); |
422 | 0 | if (O.use_fuji_rotate) |
423 | 0 | { |
424 | 0 | if (IO.fuji_width) |
425 | 0 | { |
426 | 0 | IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink; |
427 | 0 | S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5)); |
428 | 0 | S.iheight = (ushort)((S.iheight - IO.fuji_width) / sqrt(0.5)); |
429 | 0 | } |
430 | 0 | else |
431 | 0 | { |
432 | 0 | if (S.pixel_aspect < 0.995) |
433 | 0 | S.iheight = (ushort)(S.iheight / S.pixel_aspect + 0.5); |
434 | 0 | if (S.pixel_aspect > 1.005) |
435 | 0 | S.iwidth = (ushort)(S.iwidth * S.pixel_aspect + 0.5); |
436 | 0 | } |
437 | 0 | } |
438 | 0 | SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE); |
439 | 0 | if (S.flip & 4) |
440 | 0 | { |
441 | 0 | unsigned short t = S.iheight; |
442 | 0 | S.iheight = S.iwidth; |
443 | 0 | S.iwidth = t; |
444 | 0 | SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP); |
445 | 0 | } |
446 | 0 | return 0; |
447 | 0 | } |
448 | | int LibRaw::adjust_maximum() |
449 | 8.31k | { |
450 | 8.31k | ushort real_max; |
451 | 8.31k | float auto_threshold; |
452 | | |
453 | 8.31k | if (O.adjust_maximum_thr < 0.00001) |
454 | 1.19k | return LIBRAW_SUCCESS; |
455 | 7.11k | else if (O.adjust_maximum_thr > 0.99999) |
456 | 314 | auto_threshold = LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD; |
457 | 6.80k | else |
458 | 6.80k | auto_threshold = O.adjust_maximum_thr; |
459 | | |
460 | 7.11k | real_max = C.data_maximum; |
461 | 7.11k | if (real_max > 0 && real_max < C.maximum && |
462 | 3.34k | real_max > C.maximum * auto_threshold) |
463 | 1.11k | { |
464 | 1.11k | C.maximum = real_max; |
465 | 1.11k | } |
466 | 7.11k | return LIBRAW_SUCCESS; |
467 | 8.31k | } |
468 | | void LibRaw::adjust_bl() |
469 | 10.1k | { |
470 | 10.1k | int clear_repeat = 0; |
471 | 10.1k | if (O.user_black >= 0) |
472 | 2.35k | { |
473 | 2.35k | C.black = O.user_black; |
474 | 2.35k | clear_repeat = 1; |
475 | 2.35k | } |
476 | 50.7k | for (int i = 0; i < 4; i++) |
477 | 40.6k | if (O.user_cblack[i] > -1000000) |
478 | 0 | { |
479 | 0 | C.cblack[i] = O.user_cblack[i]; |
480 | 0 | clear_repeat = 1; |
481 | 0 | } |
482 | | |
483 | 10.1k | if (clear_repeat) |
484 | 2.35k | C.cblack[4] = C.cblack[5] = 0; |
485 | | |
486 | | // Add common part to cblack[] early |
487 | 10.1k | if (imgdata.idata.filters > 1000 && (C.cblack[4] + 1) / 2 == 1 && |
488 | 214 | (C.cblack[5] + 1) / 2 == 1) |
489 | 178 | { |
490 | 178 | int clrs[4]; |
491 | 178 | int lastg = -1, gcnt = 0; |
492 | 890 | for (int c = 0; c < 4; c++) |
493 | 712 | { |
494 | 712 | clrs[c] = FC(c / 2, c % 2); |
495 | 712 | if (clrs[c] == 1) |
496 | 172 | { |
497 | 172 | gcnt++; |
498 | 172 | lastg = c; |
499 | 172 | } |
500 | 712 | } |
501 | 178 | if (gcnt > 1 && lastg >= 0) |
502 | 29 | clrs[lastg] = 3; |
503 | 890 | for (int c = 0; c < 4; c++) |
504 | 712 | C.cblack[clrs[c]] += |
505 | 712 | C.cblack[6 + c / 2 % C.cblack[4] * C.cblack[5] + c % 2 % C.cblack[5]]; |
506 | 178 | C.cblack[4] = C.cblack[5] = 0; |
507 | | // imgdata.idata.filters = sfilters; |
508 | 178 | } |
509 | 9.97k | else if (imgdata.idata.filters <= 1000 && C.cblack[4] == 1 && |
510 | 13 | C.cblack[5] == 1) // Fuji RAF dng |
511 | 13 | { |
512 | 65 | for (int c = 0; c < 4; c++) |
513 | 52 | C.cblack[c] += C.cblack[6]; |
514 | 13 | C.cblack[4] = C.cblack[5] = 0; |
515 | 13 | } |
516 | | // remove common part from C.cblack[] |
517 | 10.1k | int i = C.cblack[3]; |
518 | 10.1k | int c; |
519 | 40.6k | for (c = 0; c < 3; c++) |
520 | 30.4k | if (i > (int)C.cblack[c]) |
521 | 848 | i = C.cblack[c]; |
522 | | |
523 | 50.7k | for (c = 0; c < 4; c++) |
524 | 40.6k | C.cblack[c] -= i; // remove common part |
525 | 10.1k | C.black += i; |
526 | | |
527 | | // Now calculate common part for cblack[6+] part and move it to C.black |
528 | | |
529 | 10.1k | if (C.cblack[4] && C.cblack[5]) |
530 | 959 | { |
531 | 959 | i = C.cblack[6]; |
532 | 266k | for (c = 1; c < int(C.cblack[4] * C.cblack[5]); c++) |
533 | 265k | if (i > int(C.cblack[6 + c])) |
534 | 2.33k | i = C.cblack[6 + c]; |
535 | | // Remove i from cblack[6+] |
536 | 959 | int nonz = 0; |
537 | 267k | for (c = 0; c < int(C.cblack[4] * C.cblack[5]); c++) |
538 | 266k | { |
539 | 266k | C.cblack[6 + c] -= i; |
540 | 266k | if (C.cblack[6 + c]) |
541 | 234k | nonz++; |
542 | 266k | } |
543 | 959 | C.black += i; |
544 | 959 | if (!nonz) |
545 | 166 | C.cblack[4] = C.cblack[5] = 0; |
546 | 959 | } |
547 | 50.7k | for (c = 0; c < 4; c++) |
548 | 40.6k | C.cblack[c] += C.black; |
549 | 10.1k | } |
550 | | int LibRaw::getwords(char *line, char *words[], int maxwords, int maxlen) |
551 | 2.97k | { |
552 | 2.97k | line[maxlen - 1] = 0; |
553 | 2.97k | unsigned char *p = (unsigned char*)line; |
554 | 2.97k | int nwords = 0; |
555 | | |
556 | 4.90k | while (1) |
557 | 4.90k | { |
558 | 6.77k | while (isspace(*p)) |
559 | 1.87k | p++; |
560 | 4.90k | if (*p == '\0') |
561 | 987 | return nwords; |
562 | 3.92k | words[nwords++] = (char*)p; |
563 | 70.9k | while (!isspace(*p) && *p != '\0') |
564 | 67.0k | p++; |
565 | 3.92k | if (*p == '\0') |
566 | 1.75k | return nwords; |
567 | 2.17k | *p++ = '\0'; |
568 | 2.17k | if (nwords >= maxwords) |
569 | 235 | return nwords; |
570 | 2.17k | } |
571 | 2.97k | } |
572 | | int LibRaw::stread(char *buf, size_t len, LibRaw_abstract_datastream *fp) |
573 | 44.6k | { |
574 | 44.6k | if (len > 0) |
575 | 33.9k | { |
576 | 33.9k | int r = fp->read(buf, len, 1); |
577 | 33.9k | buf[len - 1] = 0; |
578 | 33.9k | return r; |
579 | 33.9k | } |
580 | 10.6k | else |
581 | 10.6k | return 0; |
582 | 44.6k | } |
583 | | |
584 | | int LibRaw::find_ifd_by_offset(INT64 o) |
585 | 1.22k | { |
586 | 2.08k | for(unsigned i = 0; i < libraw_internal_data.identify_data.tiff_nifds && i < LIBRAW_IFD_MAXCOUNT; i++) |
587 | 1.82k | if(tiff_ifd[i].offset == o) |
588 | 961 | return i; |
589 | 266 | return -1; |
590 | 1.22k | } |
591 | | |
592 | | short LibRaw::tiff_sget (unsigned save, uchar *buf, unsigned buf_len, INT64 *tag_offset, |
593 | | unsigned *tag_id, unsigned *tag_type, INT64 *tag_dataoffset, |
594 | 110 | unsigned *tag_datalen, int *tag_dataunitlen) { |
595 | 110 | uchar *pos = buf + *tag_offset; |
596 | 110 | if ((((*tag_offset) + 12) > buf_len) || (*tag_offset < 0)) { // abnormal, tag buffer overrun |
597 | 0 | return -1; |
598 | 0 | } |
599 | 110 | *tag_id = sget2(pos); pos += 2; |
600 | 110 | *tag_type = sget2(pos); pos += 2; |
601 | 110 | *tag_datalen = sget4(pos); pos += 4; |
602 | 110 | *tag_dataunitlen = tagtype_dataunit_bytes[(*tag_type <= LIBRAW_EXIFTAG_TYPE_IFD8) ? *tag_type : 0]; |
603 | 110 | if ((*tag_datalen * (*tag_dataunitlen)) > 4) { |
604 | 110 | *tag_dataoffset = sget4(pos) - save; |
605 | 110 | if ((*tag_dataoffset + *tag_datalen) > buf_len) { // abnormal, tag data buffer overrun |
606 | 110 | return -2; |
607 | 110 | } |
608 | 110 | } else *tag_dataoffset = *tag_offset + 8; |
609 | 0 | *tag_offset += 12; |
610 | 0 | return 0; |
611 | 110 | } |
612 | | |
613 | 0 | #define rICC imgdata.sizes.raw_inset_crops |
614 | 0 | #define S imgdata.sizes |
615 | 0 | #define RS imgdata.rawdata.sizes |
616 | | int LibRaw::adjust_to_raw_inset_crop(unsigned mask, float maxcrop) |
617 | | |
618 | 0 | { |
619 | 0 | int adjindex = -1; |
620 | 0 | int limwidth = int(S.width * maxcrop); |
621 | 0 | int limheight = int(S.height * maxcrop); |
622 | |
|
623 | 0 | for(int i = 1; i >= 0; i--) |
624 | 0 | if (mask & (1<<i)) |
625 | 0 | if (rICC[i].ctop < 0xffff && rICC[i].cleft < 0xffff |
626 | 0 | && rICC[i].cleft + rICC[i].cwidth <= S.raw_width |
627 | 0 | && rICC[i].ctop + rICC[i].cheight <= S.raw_height |
628 | 0 | && rICC[i].cwidth >= limwidth && rICC[i].cheight >= limheight) |
629 | 0 | { |
630 | 0 | adjindex = i; |
631 | 0 | break; |
632 | 0 | } |
633 | |
|
634 | 0 | if (adjindex >= 0) |
635 | 0 | { |
636 | 0 | RS.left_margin = S.left_margin = rICC[adjindex].cleft; |
637 | 0 | RS.top_margin = S.top_margin = rICC[adjindex].ctop; |
638 | 0 | RS.width = S.width = MIN(rICC[adjindex].cwidth, int(S.raw_width) - int(S.left_margin)); |
639 | 0 | RS.height = S.height = MIN(rICC[adjindex].cheight, int(S.raw_height) - int(S.top_margin)); |
640 | 0 | } |
641 | 0 | return adjindex + 1; |
642 | 0 | } |
643 | | |
644 | | char** LibRaw::malloc_omp_buffers(int buffer_count, size_t buffer_size) |
645 | 1.17k | { |
646 | 1.17k | char** buffers = (char**)calloc(sizeof(char*), buffer_count); |
647 | | |
648 | 2.35k | for (int i = 0; i < buffer_count; i++) |
649 | 1.17k | { |
650 | 1.17k | buffers[i] = (char*)calloc(buffer_size,1); |
651 | 1.17k | } |
652 | 1.17k | return buffers; |
653 | 1.17k | } |
654 | | |
655 | | void LibRaw::free_omp_buffers(char** buffers, int buffer_count) |
656 | 1.17k | { |
657 | 2.35k | for (int i = 0; i < buffer_count; i++) |
658 | 1.17k | if(buffers[i]) |
659 | 1.17k | free(buffers[i]); |
660 | 1.17k | free(buffers); |
661 | 1.17k | } |
662 | | |
663 | | void LibRaw::libraw_swab(void *arr, int len) |
664 | 71.0k | { |
665 | 71.0k | #ifdef LIBRAW_OWN_SWAB |
666 | 71.0k | uint16_t *array = (uint16_t*)arr; |
667 | 71.0k | int bytes = len/2; |
668 | 585k | for(; bytes; --bytes) |
669 | 514k | { |
670 | 514k | *array = ((*array << 8) & 0xff00) | ((*array >> 8) & 0xff); |
671 | 514k | array++; |
672 | 514k | } |
673 | | #else |
674 | | swab((char*)arr,(char*)arr,len); |
675 | | #endif |
676 | | |
677 | 71.0k | } |
678 | | |
679 | 14.6k | checked_buffer_t::checked_buffer_t(short ord, int size) : _order(ord), storage(size + 64) |
680 | 14.6k | { |
681 | 14.6k | _data = storage.data(); |
682 | 14.6k | _len = size; |
683 | 14.6k | } |
684 | 333 | checked_buffer_t::checked_buffer_t(short ord, unsigned char *dd, int ss) : _order(ord), _data(dd), _len(ss) {} |
685 | | |
686 | | ushort checked_buffer_t::sget2(int offset) |
687 | 3.63M | { |
688 | 3.63M | checkoffset(offset); |
689 | 3.63M | checkoffset(offset + 2); |
690 | 3.63M | return libraw_sget2_static(_order, _data + offset); |
691 | 3.63M | } |
692 | | void checked_buffer_t::checkoffset(int off) |
693 | 26.3M | { |
694 | 26.3M | if (off >= _len || off < 0) |
695 | 2.89k | throw LIBRAW_EXCEPTION_IO_EOF; |
696 | 26.3M | } |
697 | | unsigned char checked_buffer_t::operator[](int idx) |
698 | 9.69k | { |
699 | 9.69k | checkoffset(idx); |
700 | 9.69k | return _data[idx]; |
701 | 9.69k | } |
702 | | unsigned checked_buffer_t::sget4(int offset) |
703 | 118k | { |
704 | 118k | checkoffset(offset); |
705 | 118k | checkoffset(offset + 4); |
706 | 118k | return libraw_sget4_static(_order, _data + offset); |
707 | 118k | } |
708 | | |
709 | | double checked_buffer_t::sgetreal(int type, int offset) |
710 | 0 | { |
711 | 0 | checkoffset(offset); |
712 | 0 | int sz = libraw_tagtype_dataunit_bytes(type); |
713 | 0 | checkoffset(offset + sz); |
714 | 0 | return libraw_sgetreal_static(_order, type, _data + offset); |
715 | 0 | } |
716 | | |
717 | | int checked_buffer_t::tiff_sget(unsigned save, INT64 *tag_offset, unsigned *tag_id, unsigned *tag_type, INT64 *tag_dataoffset, |
718 | | unsigned *tag_datalen, int *tag_dataunitlen) |
719 | 2.82k | { |
720 | 2.82k | if ((((*tag_offset) + 12) > _len) || (*tag_offset < 0)) |
721 | 2.19k | { // abnormal, tag buffer overrun |
722 | 2.19k | return -1; |
723 | 2.19k | } |
724 | 628 | int pos = int(*tag_offset); |
725 | 628 | *tag_id = sget2(pos); |
726 | 628 | pos += 2; |
727 | 628 | *tag_type = sget2(pos); |
728 | 628 | pos += 2; |
729 | 628 | *tag_datalen = sget4(pos); |
730 | 628 | pos += 4; |
731 | 628 | *tag_dataunitlen = libraw_tagtype_dataunit_bytes(*tag_type); |
732 | 628 | if ((*tag_datalen * (*tag_dataunitlen)) > 4) |
733 | 628 | { |
734 | 628 | *tag_dataoffset = sget4(pos) - save; |
735 | 628 | if ((*tag_dataoffset + *tag_datalen) > _len) |
736 | 612 | { // abnormal, tag data buffer overrun |
737 | 612 | return -2; |
738 | 612 | } |
739 | 628 | } |
740 | 0 | else |
741 | 0 | *tag_dataoffset = *tag_offset + 8; |
742 | 16 | *tag_offset += 12; |
743 | 16 | return 0; |
744 | 628 | } |
745 | | |