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