/src/LibRaw/src/decoders/fp_dng.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | * Copyright 2019-2025 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 | | |
17 | | inline unsigned int __DNG_HalfToFloat(ushort halfValue) |
18 | 34.5M | { |
19 | 34.5M | int sign = (halfValue >> 15) & 0x00000001; |
20 | 34.5M | int exponent = (halfValue >> 10) & 0x0000001f; |
21 | 34.5M | int mantissa = halfValue & 0x000003ff; |
22 | 34.5M | if (exponent == 0) |
23 | 16.3M | { |
24 | 16.3M | if (mantissa == 0) |
25 | 7.76M | { |
26 | 7.76M | return (unsigned int)(sign << 31); |
27 | 7.76M | } |
28 | 8.61M | else |
29 | 8.61M | { |
30 | 50.8M | while (!(mantissa & 0x00000400)) |
31 | 42.2M | { |
32 | 42.2M | mantissa <<= 1; |
33 | 42.2M | exponent -= 1; |
34 | 42.2M | } |
35 | 8.61M | exponent += 1; |
36 | 8.61M | mantissa &= ~0x00000400; |
37 | 8.61M | } |
38 | 16.3M | } |
39 | 18.2M | else if (exponent == 31) |
40 | 3.29M | { |
41 | 3.29M | if (mantissa == 0) |
42 | 68.1k | { |
43 | 68.1k | return (unsigned int)((sign << 31) | ((0x1eL + 127 - 15) << 23) | |
44 | 68.1k | (0x3ffL << 13)); |
45 | 68.1k | } |
46 | 3.23M | else |
47 | 3.23M | { |
48 | 3.23M | return 0; |
49 | 3.23M | } |
50 | 3.29M | } |
51 | 23.5M | exponent += (127 - 15); |
52 | 23.5M | mantissa <<= 13; |
53 | 23.5M | return (unsigned int)((sign << 31) | (exponent << 23) | mantissa); |
54 | 34.5M | } |
55 | | |
56 | | inline unsigned int __DNG_FP24ToFloat(const unsigned char *input) |
57 | 277k | { |
58 | 277k | int sign = (input[0] >> 7) & 0x01; |
59 | 277k | int exponent = (input[0]) & 0x7F; |
60 | 277k | int mantissa = (((int)input[1]) << 8) | input[2]; |
61 | 277k | if (exponent == 0) |
62 | 79.7k | { |
63 | 79.7k | if (mantissa == 0) |
64 | 29.0k | { |
65 | 29.0k | return (unsigned int)(sign << 31); |
66 | 29.0k | } |
67 | 50.6k | else |
68 | 50.6k | { |
69 | 413k | while (!(mantissa & 0x00010000)) |
70 | 362k | { |
71 | 362k | mantissa <<= 1; |
72 | 362k | exponent -= 1; |
73 | 362k | } |
74 | 50.6k | exponent += 1; |
75 | 50.6k | mantissa &= ~0x00010000; |
76 | 50.6k | } |
77 | 79.7k | } |
78 | 198k | else if (exponent == 127) |
79 | 17.0k | { |
80 | 17.0k | if (mantissa == 0) |
81 | 1.29k | { |
82 | 1.29k | return (unsigned int)((sign << 31) | ((0x7eL + 128 - 64) << 23) | |
83 | 1.29k | (0xffffL << 7)); |
84 | 1.29k | } |
85 | 15.7k | else |
86 | 15.7k | { |
87 | | // Nan -- Just set to zero. |
88 | 15.7k | return 0; |
89 | 15.7k | } |
90 | 17.0k | } |
91 | 231k | exponent += (128 - 64); |
92 | 231k | mantissa <<= 7; |
93 | 231k | return (uint32_t)((sign << 31) | (exponent << 23) | mantissa); |
94 | 277k | } |
95 | | |
96 | | inline void DecodeDeltaBytes(unsigned char *bytePtr, int cols, int channels) |
97 | 0 | { |
98 | 0 | if (channels == 1) |
99 | 0 | { |
100 | 0 | unsigned char b0 = bytePtr[0]; |
101 | 0 | bytePtr += 1; |
102 | 0 | for (int col = 1; col < cols; ++col) |
103 | 0 | { |
104 | 0 | b0 += bytePtr[0]; |
105 | 0 | bytePtr[0] = b0; |
106 | 0 | bytePtr += 1; |
107 | 0 | } |
108 | 0 | } |
109 | 0 | else if (channels == 3) |
110 | 0 | { |
111 | 0 | unsigned char b0 = bytePtr[0]; |
112 | 0 | unsigned char b1 = bytePtr[1]; |
113 | 0 | unsigned char b2 = bytePtr[2]; |
114 | 0 | bytePtr += 3; |
115 | 0 | for (int col = 1; col < cols; ++col) |
116 | 0 | { |
117 | 0 | b0 += bytePtr[0]; |
118 | 0 | b1 += bytePtr[1]; |
119 | 0 | b2 += bytePtr[2]; |
120 | 0 | bytePtr[0] = b0; |
121 | 0 | bytePtr[1] = b1; |
122 | 0 | bytePtr[2] = b2; |
123 | 0 | bytePtr += 3; |
124 | 0 | } |
125 | 0 | } |
126 | 0 | else if (channels == 4) |
127 | 0 | { |
128 | 0 | unsigned char b0 = bytePtr[0]; |
129 | 0 | unsigned char b1 = bytePtr[1]; |
130 | 0 | unsigned char b2 = bytePtr[2]; |
131 | 0 | unsigned char b3 = bytePtr[3]; |
132 | 0 | bytePtr += 4; |
133 | 0 | for (int col = 1; col < cols; ++col) |
134 | 0 | { |
135 | 0 | b0 += bytePtr[0]; |
136 | 0 | b1 += bytePtr[1]; |
137 | 0 | b2 += bytePtr[2]; |
138 | 0 | b3 += bytePtr[3]; |
139 | 0 | bytePtr[0] = b0; |
140 | 0 | bytePtr[1] = b1; |
141 | 0 | bytePtr[2] = b2; |
142 | 0 | bytePtr[3] = b3; |
143 | 0 | bytePtr += 4; |
144 | 0 | } |
145 | 0 | } |
146 | 0 | else |
147 | 0 | { |
148 | 0 | for (int col = 1; col < cols; ++col) |
149 | 0 | { |
150 | 0 | for (int chan = 0; chan < channels; ++chan) |
151 | 0 | { |
152 | 0 | bytePtr[chan + channels] += bytePtr[chan]; |
153 | 0 | } |
154 | 0 | bytePtr += channels; |
155 | 0 | } |
156 | 0 | } |
157 | 0 | } |
158 | | |
159 | | #ifdef USE_ZLIB |
160 | | static void DecodeFPDelta(unsigned char *input, unsigned char *output, int cols, |
161 | | int channels, int bytesPerSample) |
162 | 0 | { |
163 | 0 | DecodeDeltaBytes(input, cols * bytesPerSample, channels); |
164 | 0 | int32_t rowIncrement = cols * channels; |
165 | |
|
166 | 0 | if (bytesPerSample == 2) |
167 | 0 | { |
168 | |
|
169 | | #if LibRawBigEndian |
170 | | const unsigned char *input0 = input; |
171 | | const unsigned char *input1 = input + rowIncrement; |
172 | | #else |
173 | 0 | const unsigned char *input1 = input; |
174 | 0 | const unsigned char *input0 = input + rowIncrement; |
175 | 0 | #endif |
176 | 0 | for (int col = 0; col < rowIncrement; ++col) |
177 | 0 | { |
178 | 0 | output[0] = input0[col]; |
179 | 0 | output[1] = input1[col]; |
180 | 0 | output += 2; |
181 | 0 | } |
182 | 0 | } |
183 | 0 | else if (bytesPerSample == 3) |
184 | 0 | { |
185 | 0 | const unsigned char *input0 = input; |
186 | 0 | const unsigned char *input1 = input + rowIncrement; |
187 | 0 | const unsigned char *input2 = input + rowIncrement * 2; |
188 | 0 | for (int col = 0; col < rowIncrement; ++col) |
189 | 0 | { |
190 | 0 | output[0] = input0[col]; |
191 | 0 | output[1] = input1[col]; |
192 | 0 | output[2] = input2[col]; |
193 | 0 | output += 3; |
194 | 0 | } |
195 | 0 | } |
196 | 0 | else |
197 | 0 | { |
198 | | #if LibRawBigEndian |
199 | | const unsigned char *input0 = input; |
200 | | const unsigned char *input1 = input + rowIncrement; |
201 | | const unsigned char *input2 = input + rowIncrement * 2; |
202 | | const unsigned char *input3 = input + rowIncrement * 3; |
203 | | #else |
204 | 0 | const unsigned char *input3 = input; |
205 | 0 | const unsigned char *input2 = input + rowIncrement; |
206 | 0 | const unsigned char *input1 = input + rowIncrement * 2; |
207 | 0 | const unsigned char *input0 = input + rowIncrement * 3; |
208 | 0 | #endif |
209 | 0 | for (int col = 0; col < rowIncrement; ++col) |
210 | 0 | { |
211 | 0 | output[0] = input0[col]; |
212 | 0 | output[1] = input1[col]; |
213 | 0 | output[2] = input2[col]; |
214 | 0 | output[3] = input3[col]; |
215 | 0 | output += 4; |
216 | 0 | } |
217 | 0 | } |
218 | 0 | } |
219 | | #endif |
220 | | |
221 | | static float expandFloats(unsigned char *dst, int tileWidth, int bytesps) |
222 | 123k | { |
223 | 123k | float max = 0.f; |
224 | 123k | if (bytesps == 2) |
225 | 121k | { |
226 | 121k | uint16_t *dst16 = (ushort *)dst; |
227 | 121k | uint32_t *dst32 = (unsigned int *)dst; |
228 | 121k | float *f32 = (float *)dst; |
229 | 34.7M | for (int index = tileWidth - 1; index >= 0; --index) |
230 | 34.5M | { |
231 | 34.5M | dst32[index] = __DNG_HalfToFloat(dst16[index]); |
232 | 34.5M | max = MAX(max, f32[index]); |
233 | 34.5M | } |
234 | 121k | } |
235 | 1.71k | else if (bytesps == 3) |
236 | 1.55k | { |
237 | 1.55k | uint8_t *dst8 = ((unsigned char *)dst) + (tileWidth - 1) * 3; |
238 | 1.55k | uint32_t *dst32 = (unsigned int *)dst; |
239 | 1.55k | float *f32 = (float *)dst; |
240 | 279k | for (int index = tileWidth - 1; index >= 0; --index, dst8 -= 3) |
241 | 277k | { |
242 | 277k | dst32[index] = __DNG_FP24ToFloat(dst8); |
243 | 277k | max = MAX(max, f32[index]); |
244 | 277k | } |
245 | 1.55k | } |
246 | 155 | else if (bytesps == 4) |
247 | 155 | { |
248 | 155 | float *f32 = (float *)dst; |
249 | 9.50k | for (int index = 0; index < tileWidth; index++) |
250 | 9.35k | max = MAX(max, f32[index]); |
251 | 155 | } |
252 | 123k | return max; |
253 | 123k | } |
254 | | |
255 | | struct tile_stripe_data_t |
256 | | { |
257 | | bool tiled, striped; |
258 | | int tileCnt; |
259 | | unsigned tileWidth, tileHeight, tilesH, tilesV; |
260 | | INT64 maxBytesInTile; |
261 | | std::vector<INT64> tOffsets, tBytes; |
262 | 127 | tile_stripe_data_t() : tiled(false), striped(false),tileCnt(0), |
263 | 127 | tileWidth(0),tileHeight(0),tilesH(0),tilesV(0), |
264 | 127 | maxBytesInTile(0){} |
265 | | void init(tiff_ifd_t *ifd, const libraw_image_sizes_t&, const unpacker_data_t&, |
266 | | short _order, |
267 | | LibRaw_abstract_datastream *stream); |
268 | | }; |
269 | | |
270 | | static unsigned static_get4(LibRaw_abstract_datastream *stream, short _order) |
271 | 0 | { |
272 | 0 | uchar str[4] = { 0xff, 0xff, 0xff, 0xff }; |
273 | 0 | stream->read(str, 1, 4); |
274 | 0 | return libraw_sget4_static(_order, str); |
275 | 0 | } |
276 | | |
277 | | |
278 | | void tile_stripe_data_t::init(tiff_ifd_t *ifd, const libraw_image_sizes_t& sizes, |
279 | | const unpacker_data_t& unpacker_data, short _order, LibRaw_abstract_datastream *stream) |
280 | 127 | { |
281 | 127 | tiled = (unpacker_data.tile_width <= sizes.raw_width) && (unpacker_data.tile_length <= sizes.raw_height); |
282 | 127 | striped = (ifd->rows_per_strip > 0 && ifd->rows_per_strip < sizes.raw_height) && ifd->strip_byte_counts_count > 0; |
283 | | |
284 | 127 | tileWidth = tiled ? unpacker_data.tile_width : sizes.raw_width; |
285 | 127 | tileHeight = tiled ? unpacker_data.tile_length :(striped ? ifd->rows_per_strip : sizes.raw_height); |
286 | 127 | tilesH = tiled ? (sizes.raw_width + tileWidth - 1) / tileWidth : 1; |
287 | 127 | tilesV = tiled ? (sizes.raw_height + tileHeight - 1) / tileHeight : |
288 | 127 | (striped ? ((sizes.raw_height + ifd->rows_per_strip - 1) / ifd->rows_per_strip) : 1); |
289 | 127 | tileCnt = tilesH * tilesV; |
290 | | |
291 | 127 | if (tileCnt < 1 || tileCnt > 1000000) |
292 | 0 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
293 | | |
294 | 127 | tOffsets = std::vector<INT64>(tileCnt,0); |
295 | 127 | tBytes = std::vector <INT64>(tileCnt,0); |
296 | | |
297 | 127 | if (tiled) |
298 | 0 | for (int t = 0; t < tileCnt; ++t) |
299 | 0 | tOffsets[t] = static_get4(stream, _order); |
300 | 127 | else if (striped) |
301 | 306 | for (int t = 0; t < tileCnt && t < ifd->strip_offsets_count; ++t) |
302 | 267 | tOffsets[t] = ifd->strip_offsets[t]; |
303 | 88 | else |
304 | 88 | tOffsets[0] = ifd->offset; |
305 | | |
306 | 127 | maxBytesInTile = 0; |
307 | | |
308 | 127 | if (tileCnt == 1 || (!tiled && !striped)) |
309 | 88 | tBytes[0] = maxBytesInTile = ifd->bytes; |
310 | 39 | else if (tiled) |
311 | 0 | { |
312 | | // ifd->bytes points to tile size table if more than 1 tile exists |
313 | 0 | stream->seek(ifd->bytes, SEEK_SET); |
314 | 0 | for (int t = 0; t < tileCnt; ++t) |
315 | 0 | { |
316 | 0 | tBytes[t] = static_get4(stream, _order); ; |
317 | 0 | maxBytesInTile = MAX(maxBytesInTile, tBytes[t]); |
318 | 0 | } |
319 | 0 | } |
320 | 39 | else if (striped) |
321 | 493 | for (int t = 0; t < tileCnt && t < ifd->strip_byte_counts_count; ++t) |
322 | 454 | { |
323 | 454 | tBytes[t] = ifd->strip_byte_counts[t]; |
324 | 454 | maxBytesInTile = MAX(maxBytesInTile, tBytes[t]); |
325 | 454 | } |
326 | 127 | } |
327 | | |
328 | | #ifdef USE_ZLIB |
329 | | void LibRaw::deflate_dng_load_raw() |
330 | 11 | { |
331 | 11 | int iifd = find_ifd_by_offset(libraw_internal_data.unpacker_data.data_offset); |
332 | 11 | if(iifd < 0 || iifd > (int)libraw_internal_data.identify_data.tiff_nifds) |
333 | 0 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
334 | 11 | struct tiff_ifd_t *ifd = &tiff_ifd[iifd]; |
335 | | |
336 | 11 | float *float_raw_image = 0; |
337 | 11 | float max = 0.f; |
338 | | |
339 | 11 | if (ifd->samples != 1 && ifd->samples != 3 && ifd->samples != 4) |
340 | 2 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
341 | | |
342 | 9 | if (libraw_internal_data.unpacker_data.tiff_samples != (unsigned)ifd->samples) |
343 | 0 | throw LIBRAW_EXCEPTION_DECODE_RAW; // Wrong IFD |
344 | | |
345 | 9 | if (imgdata.idata.filters && ifd->samples > 1) |
346 | 2 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
347 | | |
348 | 7 | tile_stripe_data_t tiles; |
349 | 7 | tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, libraw_internal_data.unpacker_data.order, |
350 | 7 | libraw_internal_data.internal_data.input); |
351 | | |
352 | 7 | if (tiles.tBytes.size() < 1) |
353 | 0 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
354 | | |
355 | | // Ensure less then 2GB per compressed tile |
356 | 7 | INT64 maxcomprlen = tiles.tBytes[0]; |
357 | 7 | for (int i = 1; i < tiles.tBytes.size(); i++) |
358 | 0 | maxcomprlen = MAX(maxcomprlen, tiles.tBytes[i]); |
359 | | |
360 | 7 | if(maxcomprlen >= (1LL << 31) || maxcomprlen < 0) |
361 | 1 | throw LIBRAW_EXCEPTION_TOOBIG; |
362 | | |
363 | | // Max bytes: 2^16 raw width * 2^2 bytes/pixel * 2^2 channels = 2^20, so check against 2^22 |
364 | 6 | INT64 rowbytes = INT64(MAX(tiles.tileWidth, imgdata.sizes.raw_width)) * 4ULL * INT64(ifd->samples); |
365 | 6 | if (rowbytes > (1LL << 22)) |
366 | 0 | throw LIBRAW_EXCEPTION_TOOBIG; |
367 | | |
368 | 6 | if (ifd->sample_format == 3) |
369 | 4 | { |
370 | 4 | INT64 raw_bytes = INT64(tiles.tileCnt) * INT64(tiles.tileWidth) * INT64(tiles.tileHeight) * INT64(ifd->samples) * sizeof(float); |
371 | 4 | if (raw_bytes > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024)) |
372 | 0 | throw LIBRAW_EXCEPTION_TOOBIG; |
373 | 4 | float_raw_image = (float *)calloc(raw_bytes, 1); |
374 | 4 | } |
375 | 2 | else |
376 | 2 | throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported |
377 | | |
378 | 4 | int xFactor; |
379 | 4 | switch (ifd->predictor) |
380 | 4 | { |
381 | 0 | case 3: |
382 | 4 | default: |
383 | 4 | xFactor = 1; |
384 | 4 | break; |
385 | 0 | case 34894: |
386 | 0 | xFactor = 2; |
387 | 0 | break; |
388 | 0 | case 34895: |
389 | 0 | xFactor = 4; |
390 | 0 | break; |
391 | 4 | } |
392 | | |
393 | 4 | INT64 tilePixels = INT64(tiles.tileWidth) * INT64(tiles.tileHeight); |
394 | 4 | unsigned pixelSize = sizeof(float) * ifd->samples; |
395 | 4 | INT64 tileBytes = tilePixels * INT64(pixelSize); |
396 | 4 | INT64 tileRowBytes = INT64(tiles.tileWidth) * INT64(pixelSize); |
397 | | |
398 | 4 | if(INT64(tiles.maxBytesInTile) > INT64(imgdata.rawparams.max_raw_memory_mb) * 1024LL * 1024LL ) |
399 | 0 | throw LIBRAW_EXCEPTION_TOOBIG; |
400 | | |
401 | 4 | if (tileBytes + tileRowBytes > INT64(imgdata.rawparams.max_raw_memory_mb) * 1024LL * 1024LL) |
402 | 0 | throw LIBRAW_EXCEPTION_TOOBIG; |
403 | | |
404 | 4 | std::vector<uchar> cBuffer(tiles.maxBytesInTile,0); |
405 | 4 | std::vector<uchar> uBuffer(tileBytes + tileRowBytes,0); // extra row for decoding |
406 | | |
407 | 5 | for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += tiles.tileHeight) |
408 | 4 | { |
409 | 5 | for (size_t x = 0; x < imgdata.sizes.raw_width; x += tiles.tileWidth, ++t) |
410 | 4 | { |
411 | 4 | libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET); |
412 | 4 | int bytesread = libraw_internal_data.internal_data.input->read(cBuffer.data(), 1, tiles.tBytes[t]); |
413 | 4 | if (bytesread < tiles.tBytes[t]) |
414 | 1 | derror(); |
415 | 4 | unsigned long dstLen = tileBytes; |
416 | 4 | int err = |
417 | 4 | uncompress(uBuffer.data() + tileRowBytes, &dstLen, cBuffer.data(), (unsigned long)tiles.tBytes[t]); |
418 | 4 | if (err != Z_OK) |
419 | 3 | { |
420 | 3 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
421 | 0 | return; |
422 | 3 | } |
423 | 1 | else |
424 | 1 | { |
425 | 1 | int bytesps = ifd->bps >> 3; |
426 | 1 | size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight; |
427 | 1 | size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth; |
428 | | |
429 | 1 | for (size_t row = 0; row < rowsInTile; ++row) // do not process full tile if not needed |
430 | 0 | { |
431 | 0 | unsigned char *dst = uBuffer.data() + row * tiles.tileWidth * bytesps * ifd->samples; |
432 | 0 | unsigned char *src = dst + tileRowBytes; |
433 | 0 | DecodeFPDelta(src, dst, tiles.tileWidth / xFactor, ifd->samples * xFactor, bytesps); |
434 | 0 | float lmax = expandFloats(dst, tiles.tileWidth * ifd->samples, bytesps); |
435 | 0 | max = MAX(max, lmax); |
436 | 0 | unsigned char *dst2 = (unsigned char *)&float_raw_image |
437 | 0 | [((y + row) * imgdata.sizes.raw_width + x) * ifd->samples]; |
438 | 0 | memmove(dst2, dst, colsInTile * ifd->samples * sizeof(float)); |
439 | 0 | } |
440 | 1 | } |
441 | 4 | } |
442 | 4 | } |
443 | | |
444 | 1 | imgdata.color.fmaximum = max; |
445 | | |
446 | | // Set fields according to data format |
447 | | |
448 | 1 | imgdata.rawdata.raw_alloc = float_raw_image; |
449 | 1 | if (ifd->samples == 1) |
450 | 0 | { |
451 | 0 | imgdata.rawdata.float_image = float_raw_image; |
452 | 0 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
453 | 0 | imgdata.sizes.raw_width * 4; |
454 | 0 | } |
455 | 1 | else if (ifd->samples == 3) |
456 | 0 | { |
457 | 0 | imgdata.rawdata.float3_image = (float(*)[3])float_raw_image; |
458 | 0 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
459 | 0 | imgdata.sizes.raw_width * 12; |
460 | 0 | } |
461 | 1 | else if (ifd->samples == 4) |
462 | 0 | { |
463 | 0 | imgdata.rawdata.float4_image = (float(*)[4])float_raw_image; |
464 | 0 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
465 | 0 | imgdata.sizes.raw_width * 16; |
466 | 0 | } |
467 | | |
468 | 1 | if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT) |
469 | 0 | convertFloatToInt(); // with default settings |
470 | 1 | } |
471 | | #else |
472 | | void LibRaw::deflate_dng_load_raw() { throw LIBRAW_EXCEPTION_DECODE_RAW; } |
473 | | #endif |
474 | | |
475 | | int LibRaw::is_floating_point() |
476 | 0 | { |
477 | 0 | struct tiff_ifd_t *ifd = &tiff_ifd[0]; |
478 | 0 | while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] && |
479 | 0 | ifd->offset != libraw_internal_data.unpacker_data.data_offset) |
480 | 0 | ++ifd; |
481 | 0 | if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds]) |
482 | 0 | return 0; |
483 | | |
484 | 0 | return ifd->sample_format == 3; |
485 | 0 | } |
486 | | |
487 | | int LibRaw::have_fpdata() |
488 | 0 | { |
489 | 0 | return imgdata.rawdata.float_image || imgdata.rawdata.float3_image || |
490 | 0 | imgdata.rawdata.float4_image; |
491 | 0 | } |
492 | | |
493 | | void LibRaw::convertFloatToInt(float dmin /* =4096.f */, |
494 | | float dmax /* =32767.f */, |
495 | | float dtarget /*= 16383.f */) |
496 | 39 | { |
497 | 39 | int samples = 0; |
498 | 39 | float *data = 0; |
499 | 39 | void *orawalloc = imgdata.rawdata.raw_alloc; |
500 | 39 | if (imgdata.rawdata.float_image) |
501 | 12 | { |
502 | 12 | samples = 1; |
503 | 12 | data = imgdata.rawdata.float_image; |
504 | 12 | } |
505 | 27 | else if (imgdata.rawdata.float3_image) |
506 | 26 | { |
507 | 26 | samples = 3; |
508 | 26 | data = (float *)imgdata.rawdata.float3_image; |
509 | 26 | } |
510 | 1 | else if (imgdata.rawdata.float4_image) |
511 | 1 | { |
512 | 1 | samples = 4; |
513 | 1 | data = (float *)imgdata.rawdata.float4_image; |
514 | 1 | } |
515 | 0 | else |
516 | 0 | return; |
517 | | |
518 | 39 | ushort *raw_alloc = (ushort *)malloc( |
519 | 39 | imgdata.sizes.raw_height * imgdata.sizes.raw_width * |
520 | 39 | libraw_internal_data.unpacker_data.tiff_samples * sizeof(ushort)); |
521 | 39 | float tmax = float(MAX(imgdata.color.maximum, 1)); |
522 | 39 | float datamax = imgdata.color.fmaximum; |
523 | | |
524 | 39 | tmax = MAX(tmax, datamax); |
525 | 39 | tmax = MAX(tmax, 1.f); |
526 | | |
527 | 39 | float multip = 1.f; |
528 | 39 | if (tmax < dmin || tmax > dmax) |
529 | 39 | { |
530 | 39 | imgdata.rawdata.color.fnorm = imgdata.color.fnorm = multip = dtarget / tmax; |
531 | 39 | imgdata.rawdata.color.maximum = imgdata.color.maximum = unsigned(dtarget); |
532 | 39 | imgdata.rawdata.color.black = imgdata.color.black = |
533 | 39 | unsigned((float)imgdata.color.black * multip); |
534 | 39 | for (int i = 0; |
535 | 160k | i < int(sizeof(imgdata.color.cblack)/sizeof(imgdata.color.cblack[0])); |
536 | 160k | i++) |
537 | 160k | if (i != 4 && i != 5) |
538 | 159k | imgdata.rawdata.color.cblack[i] = imgdata.color.cblack[i] = |
539 | 159k | unsigned((float)imgdata.color.cblack[i] * multip); |
540 | 39 | } |
541 | 0 | else |
542 | 0 | imgdata.rawdata.color.fnorm = imgdata.color.fnorm = 0.f; |
543 | | |
544 | 34.6M | for (size_t i = 0; i < imgdata.sizes.raw_height * imgdata.sizes.raw_width * |
545 | 34.6M | libraw_internal_data.unpacker_data.tiff_samples; |
546 | 34.6M | ++i) |
547 | 34.6M | { |
548 | 34.6M | float val = MAX(data[i], 0.f); |
549 | 34.6M | raw_alloc[i] = (ushort)(val * multip); |
550 | 34.6M | } |
551 | | |
552 | 39 | if (samples == 1) |
553 | 12 | { |
554 | 12 | imgdata.rawdata.raw_alloc = imgdata.rawdata.raw_image = raw_alloc; |
555 | 12 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
556 | 12 | imgdata.sizes.raw_width * 2; |
557 | 12 | } |
558 | 27 | else if (samples == 3) |
559 | 26 | { |
560 | 26 | imgdata.rawdata.raw_alloc = imgdata.rawdata.color3_image = |
561 | 26 | (ushort(*)[3])raw_alloc; |
562 | 26 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
563 | 26 | imgdata.sizes.raw_width * 6; |
564 | 26 | } |
565 | 1 | else if (samples == 4) |
566 | 1 | { |
567 | 1 | imgdata.rawdata.raw_alloc = imgdata.rawdata.color4_image = |
568 | 1 | (ushort(*)[4])raw_alloc; |
569 | 1 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
570 | 1 | imgdata.sizes.raw_width * 8; |
571 | 1 | } |
572 | 39 | if(orawalloc) |
573 | 39 | free(orawalloc); // remove old allocation |
574 | 39 | imgdata.rawdata.float_image = 0; |
575 | 39 | imgdata.rawdata.float3_image = 0; |
576 | 39 | imgdata.rawdata.float4_image = 0; |
577 | 39 | } |
578 | | |
579 | | static |
580 | | #if (defined(_MSC_VER) && !defined(__clang__)) |
581 | | _forceinline |
582 | | #else |
583 | | inline |
584 | | #endif |
585 | | void libraw_swap24(uchar *data, int len) |
586 | 1.55k | { |
587 | 279k | for (int i = 0; i < len - 2; i += 3) |
588 | 277k | { |
589 | 277k | uchar t = data[i]; |
590 | 277k | data[i] = data[i + 2]; |
591 | 277k | data[i + 2] = t; |
592 | 277k | } |
593 | 1.55k | } |
594 | | |
595 | | static |
596 | | #if (defined(_MSC_VER) && !defined(__clang__)) |
597 | | _forceinline |
598 | | #else |
599 | | inline |
600 | | #endif |
601 | | void libraw_swap32(uchar *data, int len) |
602 | 0 | { |
603 | 0 | unsigned *d = (unsigned*)data; |
604 | 0 | for (int i = 0; i < len / 4; i++) |
605 | 0 | { |
606 | 0 | unsigned x = d[i]; |
607 | 0 | d[i] = (x << 24) + ((x << 8) & 0x00FF0000) + |
608 | 0 | ((x >> 8) & 0x0000FF00) + (x >> 24); |
609 | 0 | } |
610 | 0 | } |
611 | | |
612 | | |
613 | | void LibRaw::uncompressed_fp_dng_load_raw() |
614 | 125 | { |
615 | 125 | int iifd = find_ifd_by_offset(libraw_internal_data.unpacker_data.data_offset); |
616 | 125 | if (iifd < 0 || iifd > (int)libraw_internal_data.identify_data.tiff_nifds) |
617 | 1 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
618 | 124 | struct tiff_ifd_t *ifd = &tiff_ifd[iifd]; |
619 | | |
620 | 124 | float *float_raw_image = 0; |
621 | | |
622 | 124 | if (ifd->samples != 1 && ifd->samples != 3 && ifd->samples != 4) |
623 | 1 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
624 | | |
625 | 123 | if(imgdata.idata.filters && ifd->samples > 1) |
626 | 1 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
627 | | |
628 | 122 | if ((int)libraw_internal_data.unpacker_data.tiff_samples != ifd->samples) |
629 | 1 | throw LIBRAW_EXCEPTION_DECODE_RAW; // Wrong IFD |
630 | | |
631 | 121 | int bytesps = (ifd->bps + 7) >> 3; // round to upper value |
632 | | |
633 | 121 | if(bytesps < 1 || bytesps > 4) |
634 | 1 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
635 | | |
636 | 120 | tile_stripe_data_t tiles; |
637 | 120 | tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, libraw_internal_data.unpacker_data.order, |
638 | 120 | libraw_internal_data.internal_data.input); |
639 | | |
640 | | // Max bytes: 2^16 raw width * 2^2 bytes/pixel * 2^2 channels = 2^20, so check against 2^22 |
641 | 120 | INT64 rowbytes = INT64(MAX(tiles.tileWidth, imgdata.sizes.raw_width)) * INT64(MAX(bytesps,4)) * INT64(ifd->samples); |
642 | 120 | if(rowbytes > (1LL << 22)) |
643 | 0 | throw LIBRAW_EXCEPTION_TOOBIG; |
644 | | |
645 | 120 | INT64 allocsz = INT64(tiles.tileCnt) * INT64(tiles.tileWidth) * INT64(tiles.tileHeight) * INT64(ifd->samples) * INT64(sizeof(float)); |
646 | 120 | if (allocsz > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024)) |
647 | 3 | throw LIBRAW_EXCEPTION_TOOBIG; |
648 | | |
649 | 117 | if (ifd->sample_format == 3) |
650 | 116 | float_raw_image = (float *)calloc(allocsz,1); |
651 | 1 | else |
652 | 1 | throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float supported |
653 | | |
654 | 116 | bool difford = (libraw_internal_data.unpacker_data.order == 0x4949) == (ntohs(0x1234) == 0x1234); |
655 | 116 | float max = 0.f; |
656 | | |
657 | 116 | std::vector<uchar> rowbuf(tiles.tileWidth *sizeof(float) * ifd->samples,0); // line buffer for last tile in tile row |
658 | | |
659 | 24.4k | for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += tiles.tileHeight) |
660 | 24.3k | { |
661 | 48.7k | for (unsigned x = 0; x < imgdata.sizes.raw_width && t < (unsigned)tiles.tileCnt; x += tiles.tileWidth, ++t) |
662 | 24.3k | { |
663 | 24.3k | libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET); |
664 | 24.3k | size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight; |
665 | 24.3k | size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth; |
666 | | |
667 | | // inrowbytes is less then 2^22 (see above) so conversion to int is safe |
668 | 24.3k | size_t inrowbytes = colsInTile * bytesps * ifd->samples; |
669 | 24.3k | int fullrowbytes = tiles.tileWidth *bytesps * ifd->samples; |
670 | 24.3k | size_t outrowbytes = colsInTile * sizeof(float) * ifd->samples; |
671 | | |
672 | 147k | for (size_t row = 0; row < rowsInTile; ++row) // do not process full tile if not needed |
673 | 123k | { |
674 | 123k | unsigned char *dst = fullrowbytes > int(inrowbytes) ? rowbuf.data(): // last tile in row, use buffer |
675 | 123k | (unsigned char *)&float_raw_image |
676 | 123k | [((y + row) * imgdata.sizes.raw_width + x) * ifd->samples]; |
677 | 123k | int bytesread = libraw_internal_data.internal_data.input->read(dst, 1, fullrowbytes); |
678 | 123k | if (bytesread < fullrowbytes) |
679 | 77 | derror(); |
680 | 123k | if (bytesps == 2 && difford) |
681 | 0 | libraw_swab(dst, fullrowbytes); |
682 | 123k | else if (bytesps == 3 && (libraw_internal_data.unpacker_data.order == 0x4949)) // II-16bit |
683 | 1.55k | libraw_swap24(dst, fullrowbytes); |
684 | 123k | if (bytesps == 4 && difford) |
685 | 0 | libraw_swap32(dst, fullrowbytes); |
686 | | |
687 | 123k | float lmax = expandFloats( |
688 | 123k | dst, |
689 | 123k | tiles.tileWidth * ifd->samples, |
690 | 123k | bytesps); |
691 | 123k | if (fullrowbytes > int(inrowbytes)) // last tile in row: copy buffer to destination |
692 | 0 | memmove(&float_raw_image[((y + row) * imgdata.sizes.raw_width + x) * ifd->samples], dst, outrowbytes); |
693 | 123k | max = MAX(max, lmax); |
694 | 123k | } |
695 | 24.3k | } |
696 | 24.3k | } |
697 | | |
698 | 116 | imgdata.color.fmaximum = max; |
699 | | |
700 | | // setup outpuf fields |
701 | 116 | imgdata.rawdata.raw_alloc = float_raw_image; |
702 | 116 | if (ifd->samples == 1) |
703 | 12 | { |
704 | 12 | imgdata.rawdata.float_image = float_raw_image; |
705 | 12 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
706 | 12 | imgdata.sizes.raw_width * 4; |
707 | 12 | } |
708 | 104 | else if (ifd->samples == 3) |
709 | 26 | { |
710 | 26 | imgdata.rawdata.float3_image = (float(*)[3])float_raw_image; |
711 | 26 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
712 | 26 | imgdata.sizes.raw_width * 12; |
713 | 26 | } |
714 | 78 | else if (ifd->samples == 4) |
715 | 1 | { |
716 | 1 | imgdata.rawdata.float4_image = (float(*)[4])float_raw_image; |
717 | 1 | imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = |
718 | 1 | imgdata.sizes.raw_width * 16; |
719 | 1 | } |
720 | | |
721 | 116 | if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT) |
722 | 39 | convertFloatToInt(); |
723 | 116 | } |