1 /*
2 * This file is part of RawTherapee.
3 *
4 * RawTherapee is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * RawTherapee is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include <iostream>
19 #include "dcraw.h"
20
21 // Code adapted from libraw
22 /* -*- C++ -*-
23 * Copyright 2019 LibRaw LLC (info@libraw.org)
24 *
25 LibRaw is free software; you can redistribute it and/or modify
26 it under the terms of the one of two licenses as you choose:
27
28 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
29 (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
30
31 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
32 (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
33
34 */
35
operator ()(int nbits,unsigned * bytes)36 unsigned DCraw::pana_bits_t::operator() (int nbits, unsigned *bytes)
37 {
38 int byte;
39
40 if (!nbits && !bytes) {
41 return vbits=0;
42 }
43 if (!vbits) {
44 fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
45 fread (buf, 1, load_flags, ifp);
46 }
47 if (encoding == 5) {
48 for (byte = 0; byte < 16; byte++)
49 {
50 bytes[byte] = buf[vbits++];
51 vbits &= 0x3FFF;
52 }
53 return 0;
54 } else {
55 vbits = (vbits - nbits) & 0x1ffff;
56 byte = vbits >> 3 ^ 0x3ff0;
57 return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
58 }
59 }
60
61 class pana_cs6_page_decoder
62 {
63 unsigned int pixelbuffer[14], lastoffset, maxoffset;
64 unsigned char current, *buffer;
65 public:
pana_cs6_page_decoder(unsigned char * _buffer,unsigned int bsize)66 pana_cs6_page_decoder(unsigned char *_buffer, unsigned int bsize)
67 : pixelbuffer{}, lastoffset(0), maxoffset(bsize), current(0), buffer(_buffer)
68 {
69 }
70 void read_page(); // will throw IO error if not enough space in buffer
nextpixel()71 unsigned int nextpixel()
72 {
73 return current < 14 ? pixelbuffer[current++] : 0;
74 }
75 };
76
77 #define wbuffer(i) ((unsigned short)buffer[lastoffset + 15 - i])
78
read_page()79 void pana_cs6_page_decoder::read_page()
80 {
81 if (!buffer || (maxoffset - lastoffset < 16))
82 ;
83 pixelbuffer[0] = (wbuffer(0) << 6) | (wbuffer(1) >> 2); // 14 bit
84 pixelbuffer[1] = (((wbuffer(1) & 0x3) << 12) | (wbuffer(2) << 4) | (wbuffer(3) >> 4)) & 0x3fff;
85 pixelbuffer[2] = (wbuffer(3) >> 2) & 0x3;
86 pixelbuffer[3] = ((wbuffer(3) & 0x3) << 8) | wbuffer(4);
87 pixelbuffer[4] = (wbuffer(5) << 2) | (wbuffer(6) >> 6);
88 pixelbuffer[5] = ((wbuffer(6) & 0x3f) << 4) | (wbuffer(7) >> 4);
89 pixelbuffer[6] = (wbuffer(7) >> 2) & 0x3;
90 pixelbuffer[7] = ((wbuffer(7) & 0x3) << 8) | wbuffer(8);
91 pixelbuffer[8] = ((wbuffer(9) << 2) & 0x3fc) | (wbuffer(10) >> 6);
92 pixelbuffer[9] = ((wbuffer(10) << 4) | (wbuffer(11) >> 4)) & 0x3ff;
93 pixelbuffer[10] = (wbuffer(11) >> 2) & 0x3;
94 pixelbuffer[11] = ((wbuffer(11) & 0x3) << 8) | wbuffer(12);
95 pixelbuffer[12] = (((wbuffer(13) << 2) & 0x3fc) | wbuffer(14) >> 6) & 0x3ff;
96 pixelbuffer[13] = ((wbuffer(14) << 4) | (wbuffer(15) >> 4)) & 0x3ff;
97 current = 0;
98 lastoffset += 16;
99 }
100 #undef wbuffer
101
panasonic_load_raw()102 void DCraw::panasonic_load_raw()
103 {
104 int enc_blck_size = RT_pana_info.bpp == 12 ? 10 : 9;
105 if (RT_pana_info.encoding == 5) {
106 pana_bits_t pana_bits(ifp, load_flags, RT_pana_info.encoding);
107 pana_bits(0, 0);
108 unsigned bytes[16] = {};
109 for (int row = 0; row < raw_height; ++row) {
110 ushort* raw_block_data = raw_image + row * raw_width;
111
112 for (int col = 0; col < raw_width; col += enc_blck_size) {
113 pana_bits(0, bytes);
114
115 if (RT_pana_info.bpp == 12) {
116 raw_block_data[col] = ((bytes[1] & 0xF) << 8) + bytes[0];
117 raw_block_data[col + 1] = 16 * bytes[2] + (bytes[1] >> 4);
118 raw_block_data[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3];
119 raw_block_data[col + 3] = 16 * bytes[5] + (bytes[4] >> 4);
120 raw_block_data[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6];
121 raw_block_data[col + 5] = 16 * bytes[8] + (bytes[7] >> 4);
122 raw_block_data[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9];
123 raw_block_data[col + 7] = 16 * bytes[11] + (bytes[10] >> 4);
124 raw_block_data[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12];
125 raw_block_data[col + 9] = 16 * bytes[14] + (bytes[13] >> 4);
126 }
127 else if (RT_pana_info.bpp == 14) {
128 raw_block_data[col] = bytes[0] + ((bytes[1] & 0x3F) << 8);
129 raw_block_data[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) + ((bytes[3] & 0xF) << 10);
130 raw_block_data[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) + ((bytes[5] & 3) << 12);
131 raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6);
132 raw_block_data[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8);
133 raw_block_data[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10);
134 raw_block_data[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12);
135 raw_block_data[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6);
136 raw_block_data[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8);
137 }
138 }
139 }
140 } else if (RT_pana_info.encoding == 6) {
141 panasonicC6_load_raw();
142 } else if (RT_pana_info.encoding == 7) {
143 panasonicC7_load_raw();
144 } else {
145 pana_bits_t pana_bits(ifp, load_flags, RT_pana_info.encoding);
146 pana_bits(0, 0);
147 int sh = 0, pred[2], nonz[2];
148 for (int row = 0; row < height; ++row) {
149 for (int col = 0; col < raw_width; ++col) {
150 int i;
151 if ((i = col % 14) == 0) {
152 pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
153 }
154 if (i % 3 == 2) {
155 sh = 4 >> (3 - pana_bits(2));
156 }
157 if (nonz[i & 1]) {
158 int j;
159 if ((j = pana_bits(8))) {
160 if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) {
161 pred[i & 1] &= ~(-1 << sh);
162 }
163 pred[i & 1] += j << sh;
164 }
165 } else if ((nonz[i & 1] = pana_bits(8)) || i > 11) {
166 pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
167 }
168 if ((raw_image[(row)*raw_width+(col)] = pred[col & 1]) > 4098 && col < width) {
169 derror();
170 }
171 }
172 }
173 }
174 }
175
panasonicC6_load_raw()176 void DCraw::panasonicC6_load_raw()
177 {
178 constexpr int rowstep = 16;
179 const int blocksperrow = raw_width / 11;
180 const int rowbytes = blocksperrow * 16;
181 unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep);
182 merror(iobuf, "panasonicC6_load_raw()");
183
184 for (int row = 0; row < raw_height - rowstep + 1; row += rowstep) {
185 const int rowstoread = MIN(rowstep, raw_height - row);
186 fread(iobuf, rowbytes, rowstoread, ifp);
187 pana_cs6_page_decoder page(iobuf, rowbytes * rowstoread);
188 for (int crow = 0, col = 0; crow < rowstoread; ++crow, col = 0) {
189 unsigned short *rowptr = &raw_image[(row + crow) * raw_width];
190 for (int rblock = 0; rblock < blocksperrow; rblock++) {
191 page.read_page();
192 unsigned oddeven[2] = {0, 0}, nonzero[2] = {0, 0};
193 unsigned pmul = 0, pixel_base = 0;
194 for (int pix = 0; pix < 11; ++pix) {
195 if (pix % 3 == 2) {
196 unsigned base = page.nextpixel();
197 if (base > 3) {
198 derror();
199 }
200 if (base == 3) {
201 base = 4;
202 }
203 pixel_base = 0x200 << base;
204 pmul = 1 << base;
205 }
206 unsigned epixel = page.nextpixel();
207 if (oddeven[pix % 2]) {
208 epixel *= pmul;
209 if (pixel_base < 0x2000 && nonzero[pix % 2] > pixel_base) {
210 epixel += nonzero[pix % 2] - pixel_base;
211 }
212 nonzero[pix % 2] = epixel;
213 } else {
214 oddeven[pix % 2] = epixel;
215 if (epixel) {
216 nonzero[pix % 2] = epixel;
217 } else {
218 epixel = nonzero[pix % 2];
219 }
220 }
221 const unsigned spix = epixel - 0xf;
222 if (spix <= 0xffff) {
223 rowptr[col++] = spix & 0xffff;
224 } else {
225 epixel = (((signed int)(epixel + 0x7ffffff1)) >> 0x1f);
226 rowptr[col++] = epixel & 0x3fff;
227 }
228 }
229 }
230 }
231 }
232 free(iobuf);
233 tiff_bps = RT_pana_info.bpp;
234 }
235
panasonicC7_load_raw()236 void DCraw::panasonicC7_load_raw()
237 {
238 constexpr int rowstep = 16;
239 const int pixperblock = RT_pana_info.bpp == 14 ? 9 : 10;
240 const int rowbytes = raw_width / pixperblock * 16;
241
242 unsigned char *iobuf = (unsigned char *)malloc(rowbytes * rowstep);
243 merror(iobuf, "panasonicC7_load_raw()");
244 for (int row = 0; row < raw_height - rowstep + 1; row += rowstep) {
245 const int rowstoread = MIN(rowstep, raw_height - row);
246 fread (iobuf, rowbytes, rowstoread, ifp);
247 unsigned char *bytes = iobuf;
248 for (int crow = 0; crow < rowstoread; crow++) {
249 ushort *rowptr = &raw_image[(row + crow) * raw_width];
250 for (int col = 0; col < raw_width - pixperblock + 1; col += pixperblock, bytes += 16) {
251 if (RT_pana_info.bpp == 14) {
252 rowptr[col] = bytes[0] + ((bytes[1] & 0x3F) << 8);
253 rowptr[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) + ((bytes[3] & 0xF) << 10);
254 rowptr[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) + ((bytes[5] & 3) << 12);
255 rowptr[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6);
256 rowptr[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8);
257 rowptr[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10);
258 rowptr[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12);
259 rowptr[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6);
260 rowptr[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8);
261 } else if (RT_pana_info.bpp == 12) { // have not seen in the wild yet
262 rowptr[col] = ((bytes[1] & 0xF) << 8) + bytes[0];
263 rowptr[col + 1] = 16 * bytes[2] + (bytes[1] >> 4);
264 rowptr[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3];
265 rowptr[col + 3] = 16 * bytes[5] + (bytes[4] >> 4);
266 rowptr[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6];
267 rowptr[col + 5] = 16 * bytes[8] + (bytes[7] >> 4);
268 rowptr[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9];
269 rowptr[col + 7] = 16 * bytes[11] + (bytes[10] >> 4);
270 rowptr[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12];
271 rowptr[col + 9] = 16 * bytes[14] + (bytes[13] >> 4);
272 }
273 }
274 }
275 }
276 free(iobuf);
277 tiff_bps = RT_pana_info.bpp;
278 }
279