/src/libraw/src/decoders/olympus14.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- C++ -*- |
2 | | * File: pana8.cpp |
3 | | * Copyright (C) 2024 Alex Tutubalin, LibRaw LLC |
4 | | * |
5 | | Olympus/OM System 12/14-bit file decoder |
6 | | |
7 | | LibRaw is free software; you can redistribute it and/or modify |
8 | | it under the terms of the one of two licenses as you choose: |
9 | | |
10 | | 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
11 | | (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
12 | | |
13 | | 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
14 | | (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
15 | | |
16 | | */ |
17 | | |
18 | | #include "../../internal/libraw_cxx_defs.h" |
19 | | #include <vector> |
20 | | |
21 | | |
22 | | struct buffered_bitpump_t |
23 | | { |
24 | | uint32_t bitcount; |
25 | | uint32_t bitstorage; |
26 | | LibRaw_abstract_datastream *input; |
27 | | std::vector<uint8_t> buffer; |
28 | | uint8_t *bufp; |
29 | | int pos, datasz; |
30 | | bool is_buf; |
31 | 0 | buffered_bitpump_t(LibRaw_abstract_datastream *in, int bufsz) : bitcount(0), bitstorage(0), input(in), |
32 | 0 | buffer(bufsz),pos(0),datasz(0) |
33 | 0 | { |
34 | 0 | is_buf = input->is_buffered(); |
35 | 0 | input->buffering_off(); |
36 | 0 | bufp = buffer.data(); |
37 | 0 | } |
38 | | ~buffered_bitpump_t() |
39 | 0 | { |
40 | 0 | if (is_buf) |
41 | 0 | input->buffering_on(); |
42 | 0 | } |
43 | | void skip_bit(uint32_t &vbits) |
44 | 0 | { |
45 | 0 | if (!vbits) |
46 | 0 | { |
47 | 0 | replace_data(); |
48 | 0 | vbits = --bitcount; |
49 | 0 | } |
50 | 0 | else |
51 | 0 | bitcount = --vbits; |
52 | 0 | } |
53 | | void replace_data() |
54 | 0 | { |
55 | 0 | bitstorage = get4(); |
56 | 0 | bitcount = 32; |
57 | 0 | } |
58 | | |
59 | | uint32_t add_data() |
60 | 0 | { |
61 | 0 | uint32_t bb = get2(); |
62 | 0 | bitstorage = bitstorage << 16 | bb; |
63 | 0 | bitcount += 16; |
64 | 0 | return bitcount; |
65 | 0 | } |
66 | | uint32_t getbits(unsigned wbits) |
67 | 0 | { |
68 | 0 | while (bitcount < wbits) |
69 | 0 | add_data(); |
70 | 0 | uint32_t ret = bitstorage << (32 - (bitcount & 0x1f)) >> (32 - wbits); |
71 | 0 | bitcount -= wbits; |
72 | 0 | return ret; |
73 | 0 | } |
74 | | uint32_t get2() |
75 | 0 | { |
76 | 0 | if (pos < datasz - 1) |
77 | 0 | { |
78 | 0 | uint32_t ret = bufp[pos] << 8 | bufp[pos + 1]; |
79 | 0 | pos += 2; |
80 | 0 | return ret; |
81 | 0 | } |
82 | 0 | uint8_t b[2]; |
83 | 0 | int i = 0; |
84 | 0 | while (pos < datasz) |
85 | 0 | b[i++] = bufp[pos++]; |
86 | 0 | refill(2); |
87 | 0 | for (; i < 2; i++) |
88 | 0 | b[i] = bufp[pos++]; |
89 | 0 | return b[0] << 8 | b[1]; |
90 | 0 | } |
91 | | |
92 | | uint32_t get4() |
93 | 0 | { |
94 | 0 | if (pos < datasz - 3) |
95 | 0 | { |
96 | 0 | uint32_t ret = bufp[pos] << 24 | bufp[pos + 1] << 16 | bufp[pos + 2] << 8 | bufp[pos + 3]; |
97 | 0 | pos += 4; |
98 | 0 | return ret; |
99 | 0 | } |
100 | 0 | uint8_t b[4]; |
101 | 0 | int i = 0; |
102 | 0 | while (pos < datasz) |
103 | 0 | b[i++] = bufp[pos++]; |
104 | 0 | refill(4); |
105 | 0 | for (; i < 4; i++) |
106 | 0 | b[i] = bufp[pos++]; |
107 | 0 | return b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; |
108 | 0 | } |
109 | | void refill(int b) |
110 | 0 | { |
111 | 0 | int r = input->read(bufp, 1, buffer.size()); |
112 | 0 | pos = 0; |
113 | 0 | datasz = r > b ? r : b; |
114 | 0 | } |
115 | | }; |
116 | | |
117 | | |
118 | | static bool checkhdr(LibRaw_abstract_datastream *ifp, int bytes) |
119 | 5 | { |
120 | 5 | if (bytes <= 0) return false; |
121 | 0 | uint64_t b64 = 0ULL; |
122 | 0 | for(int i = 0; i < bytes; i++) |
123 | 0 | { |
124 | 0 | uint8_t databyte1 = (uint8_t)ifp->get_char(); |
125 | 0 | uint64_t q = (b64 << 8) | databyte1; |
126 | 0 | b64 = q; |
127 | 0 | } |
128 | 0 | if (b64 != 1ULL) |
129 | 0 | return false; |
130 | 0 | if (ifp->get_char() | ifp->get_char()) |
131 | 0 | return false; |
132 | 0 | return true; |
133 | 0 | } |
134 | | |
135 | | static |
136 | | #ifdef _MSC_VER |
137 | | __forceinline |
138 | | #else |
139 | | inline |
140 | | #endif |
141 | 0 | int32_t _local_iabs(int32_t x){ return (x ^ (x >> 31)) - (x >> 31);} |
142 | | |
143 | | static |
144 | | #ifdef _MSC_VER |
145 | | __forceinline |
146 | | #else |
147 | | inline |
148 | | #endif |
149 | | int32_t oly_code(buffered_bitpump_t *th, unsigned int wbits, unsigned int tag0x640, |
150 | | unsigned int tag0x643, int tag0x652, |
151 | | int *glc, int *t640bits, int *t643bits) |
152 | 0 | { |
153 | 0 | int highdatabit; |
154 | |
|
155 | 0 | if (!th->bitcount) |
156 | 0 | th->replace_data(); |
157 | |
|
158 | 0 | int v = --th->bitcount; |
159 | 0 | highdatabit = (th->bitstorage >> v) & 1; |
160 | 0 | *t643bits = tag0x643 ? th->getbits(tag0x643) : 0; |
161 | 0 | *t640bits = tag0x640 ? th->getbits(tag0x640) : 0; |
162 | |
|
163 | 0 | uint32_t vbits = th->bitcount; |
164 | 0 | uint32_t high = 0; |
165 | 0 | uint32_t low = 0; |
166 | |
|
167 | 0 | while (1) |
168 | 0 | { |
169 | 0 | th->skip_bit(vbits); |
170 | 0 | if ((th->bitstorage >> vbits) & 1) |
171 | 0 | break; |
172 | 0 | if ((uint32_t)tag0x652 == ++high) |
173 | 0 | { |
174 | 0 | high = 0; |
175 | 0 | if (wbits != 15) |
176 | 0 | { |
177 | 0 | uint32_t i; |
178 | 0 | for (i = 15 - wbits; vbits < i;) |
179 | 0 | vbits = th->add_data(); |
180 | |
|
181 | 0 | high = th->bitstorage << (32 - (vbits & 0x1f)) >> (wbits + 17); |
182 | 0 | vbits -= i; |
183 | 0 | th->bitcount = vbits; |
184 | 0 | } |
185 | 0 | th->skip_bit(vbits); |
186 | 0 | break; |
187 | 0 | } |
188 | 0 | } |
189 | | |
190 | 0 | if (wbits < 1) |
191 | 0 | low = 0; |
192 | 0 | else |
193 | 0 | { |
194 | 0 | while (vbits < wbits) |
195 | 0 | vbits = th->add_data(); |
196 | 0 | low = th->bitstorage << (32 - (vbits & 0x1f)) >> (32 - (wbits & 0x1f)); |
197 | 0 | th->bitcount = vbits - wbits; |
198 | 0 | } |
199 | 0 | *glc = low | (high << wbits); |
200 | 0 | int32_t result = *glc ^ (unsigned int)(-highdatabit); |
201 | 0 | return result; |
202 | 0 | } |
203 | | |
204 | | |
205 | | |
206 | | void LibRaw::olympus14_load_raw() |
207 | 5 | { |
208 | 5 | if (!checkhdr(libraw_internal_data.internal_data.input, imgdata.makernotes.olympus.tagX653)) |
209 | 5 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
210 | | |
211 | 0 | const int32_t tag0x640 = imgdata.makernotes.olympus.tagX640; // usually 0 |
212 | 0 | const uint32_t tag0x643 = imgdata.makernotes.olympus.tagX643; // usually 2 |
213 | |
|
214 | 0 | uint32_t context[4] = { 0,0,0,0 }; |
215 | 0 | buffered_bitpump_t pump(libraw_internal_data.internal_data.input, 65536); |
216 | |
|
217 | 0 | const int32_t one_shl_tag0x641 = 1 << imgdata.makernotes.olympus.tagX641; |
218 | 0 | const int32_t tag0x642 = imgdata.makernotes.olympus.tagX642; |
219 | 0 | const int32_t tag0x644 = imgdata.makernotes.olympus.tagX644; |
220 | 0 | const int32_t one_shl_tag645 = 1 << (imgdata.makernotes.olympus.tagX645 & 0x1f); |
221 | 0 | const int32_t tag0x646 = imgdata.makernotes.olympus.tagX646; |
222 | 0 | const int32_t tag0x647 = imgdata.makernotes.olympus.tagX647; |
223 | 0 | const int32_t tag0x648 = imgdata.makernotes.olympus.tagX648; |
224 | 0 | const int32_t tag0x649 = imgdata.makernotes.olympus.tagX649; |
225 | 0 | const int32_t tag0x650 = imgdata.makernotes.olympus.tagX650; |
226 | 0 | const int32_t tag0x651 = imgdata.makernotes.olympus.tagX651; |
227 | 0 | const int32_t tag0x652 = MAX(1, imgdata.makernotes.olympus.tagX652); |
228 | 0 | const uint16_t datamax = 1<<imgdata.makernotes.olympus.ValidBits; |
229 | |
|
230 | 0 | const int32_t raw_width = imgdata.sizes.raw_width; |
231 | 0 | ushort * const raw_image = imgdata.rawdata.raw_image; |
232 | |
|
233 | 0 | std::vector<uint32_t> bitcounts(65536); |
234 | 0 | bitcounts[0] = 0; |
235 | 0 | for (int i = 0, n = 1; i < 16; i++) |
236 | 0 | for (int j = 0; j < 1 << i; j++) |
237 | 0 | bitcounts[n++] = i+1; |
238 | |
|
239 | 0 | int32_t lpred = 0, pred1 = 0, glc = 0, gcode=0; |
240 | |
|
241 | 0 | for (uint32_t row = 0; row < imgdata.sizes.raw_height; row++) |
242 | 0 | { |
243 | 0 | checkCancel(); |
244 | 0 | for (uint32_t col = 0; col < raw_width; col++) |
245 | 0 | { |
246 | 0 | int32_t wbits, vbits, t640bits, t643bits; |
247 | 0 | int32_t p = gcode; |
248 | 0 | gcode = glc; |
249 | 0 | int32_t psel = ((col>1) && one_shl_tag645 >= p) ? context[3] + 1 : 0; |
250 | 0 | context[3] = context[2]; |
251 | 0 | context[2] = psel; |
252 | 0 | if (col>1) |
253 | 0 | { |
254 | 0 | int highbitcount = bitcounts[p & 0xffff]; |
255 | 0 | int32_t T1 = ((col > 1) && (psel >= tag0x646)) ? tag0x648 : tag0x650; |
256 | 0 | int32_t T2 = ((col > 1) && (psel >= tag0x646)) ? tag0x647 : tag0x649; |
257 | 0 | int32_t TT = MAX((highbitcount - T1),-1); |
258 | 0 | wbits = T2 + TT + 1; |
259 | 0 | } |
260 | 0 | else |
261 | 0 | wbits = tag0x649; |
262 | |
|
263 | 0 | if (wbits > tag0x651) |
264 | 0 | wbits = tag0x651; |
265 | |
|
266 | 0 | int32_t gcode = oly_code(&pump, wbits, tag0x640, tag0x643, tag0x652, &glc, &t640bits, &t643bits); |
267 | 0 | if (tag0x643) |
268 | 0 | { |
269 | 0 | if (tag0x643 == 1) |
270 | 0 | { |
271 | 0 | int32_t v = col<2 ? 0 : pred1; |
272 | 0 | gcode = t643bits + 2 * (v + gcode); |
273 | 0 | vbits = v + (gcode >> 1); |
274 | 0 | } |
275 | 0 | else |
276 | 0 | { |
277 | 0 | int32_t v = col<2 ? 0 : pred1; |
278 | 0 | gcode = t643bits + 4 * (v + gcode); |
279 | 0 | vbits = ((gcode >> 1) & 0xFFFFFFFE) + v + (gcode >> 2); |
280 | 0 | } |
281 | 0 | } |
282 | 0 | else |
283 | 0 | vbits = 0; |
284 | |
|
285 | 0 | pred1 = context[0]; |
286 | 0 | context[0] = (tag0x644 == 15) ? 0 : vbits >> tag0x644; |
287 | 0 | int32_t W = col < 2 ? tag0x642 : context[1]; |
288 | 0 | int32_t N = row < 2 ? tag0x642 : raw_image[(row - 2) * raw_width + col] >> tag0x640; |
289 | 0 | int32_t NW = (row < 2 || col < 2)? tag0x642 : NW = raw_image[(row - 2) * raw_width + col - 2] >> tag0x640; |
290 | |
|
291 | 0 | context[1] = lpred; |
292 | 0 | if ((W < N) || (NW < W)) |
293 | 0 | { |
294 | 0 | if (NW <= N && W >= N) |
295 | 0 | N = W; |
296 | 0 | else if (NW < N || W >= N) |
297 | 0 | { |
298 | 0 | if (NW > W || W >= N) |
299 | 0 | { |
300 | 0 | if (_local_iabs(N - NW) > one_shl_tag0x641) |
301 | 0 | N += W - NW; |
302 | 0 | else if (_local_iabs(W - NW) <= one_shl_tag0x641) |
303 | 0 | N = (N + W) >> 1; |
304 | 0 | else |
305 | 0 | N = N + W - NW; |
306 | 0 | } |
307 | 0 | } |
308 | 0 | else |
309 | 0 | N = W; |
310 | 0 | } |
311 | 0 | lpred = gcode + N; |
312 | 0 | uint32_t pixel_final_value = t640bits + ((gcode + N) << tag0x640); |
313 | 0 | if(((raw_image[row * raw_width + col] = (ushort)pixel_final_value) > datamax) |
314 | 0 | && col >= imgdata.sizes.width) |
315 | 0 | derror(); |
316 | 0 | } |
317 | 0 | } |
318 | 0 | } |