File indexing completed on 2025-01-05 03:56:54
0001 /* -*- C++ -*- 0002 * Copyright 2019-2021 LibRaw LLC (info@libraw.org) 0003 * 0004 LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder, 0005 dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net. 0006 LibRaw do not use RESTRICTED code from dcraw.c 0007 0008 LibRaw is free software; you can redistribute it and/or modify 0009 it under the terms of the one of two licenses as you choose: 0010 0011 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 0012 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 0013 0014 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 0015 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). 0016 0017 */ 0018 0019 #include "../../internal/dcraw_defs.h" 0020 0021 #define HOLE(row) ((holes >> (((row)-raw_height) & 7)) & 1) 0022 0023 /* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */ 0024 void LibRaw::smal_decode_segment(unsigned seg[2][2], int holes) 0025 { 0026 uchar hist[3][13] = {{7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0}, 0027 {7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0}, 0028 {3, 3, 0, 0, 63, 47, 31, 15, 0}}; 0029 int low, high = 0xff, carry = 0, nbits = 8; 0030 int s, count, bin, next, i, sym[3]; 0031 unsigned pix; 0032 uchar diff, pred[] = {0, 0}; 0033 ushort data = 0, range = 0; 0034 0035 fseek(ifp, seg[0][1] + 1, SEEK_SET); 0036 getbits(-1); 0037 if (seg[1][0] > unsigned(raw_width * raw_height)) 0038 seg[1][0] = raw_width * raw_height; 0039 for (pix = seg[0][0]; pix < seg[1][0]; pix++) 0040 { 0041 for (s = 0; s < 3; s++) 0042 { 0043 data = data << nbits | getbits(nbits); 0044 if (carry < 0) 0045 carry = (nbits += carry + 1) < 1 ? nbits - 1 : 0; 0046 while (--nbits >= 0) 0047 if ((data >> nbits & 0xff) == 0xff) 0048 break; 0049 if (nbits > 0) 0050 data = 0051 ((data & ((1 << (nbits - 1)) - 1)) << 1) | 0052 ((data + (((data & (1 << (nbits - 1)))) << 1)) & ((~0u) << nbits)); 0053 if (nbits >= 0) 0054 { 0055 data += getbits(1); 0056 carry = nbits - 8; 0057 } 0058 count = ((((data - range + 1) & 0xffff) << 2) - 1) / (high >> 4); 0059 for (bin = 0; hist[s][bin + 5] > count; bin++) 0060 ; 0061 low = hist[s][bin + 5] * (high >> 4) >> 2; 0062 if (bin) 0063 high = hist[s][bin + 4] * (high >> 4) >> 2; 0064 high -= low; 0065 for (nbits = 0; high << nbits < 128; nbits++) 0066 ; 0067 range = (range + low) << nbits; 0068 high <<= nbits; 0069 next = hist[s][1]; 0070 if (++hist[s][2] > hist[s][3]) 0071 { 0072 next = (next + 1) & hist[s][0]; 0073 hist[s][3] = (hist[s][next + 4] - hist[s][next + 5]) >> 2; 0074 hist[s][2] = 1; 0075 } 0076 if (hist[s][hist[s][1] + 4] - hist[s][hist[s][1] + 5] > 1) 0077 { 0078 if (bin < hist[s][1]) 0079 for (i = bin; i < hist[s][1]; i++) 0080 hist[s][i + 5]--; 0081 else if (next <= bin) 0082 for (i = hist[s][1]; i < bin; i++) 0083 hist[s][i + 5]++; 0084 } 0085 hist[s][1] = next; 0086 sym[s] = bin; 0087 } 0088 diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3); 0089 if (sym[0] & 4) 0090 diff = diff ? -diff : 0x80; 0091 if (ftell(ifp) + 12 >= seg[1][1]) 0092 diff = 0; 0093 if (pix >= unsigned(raw_width * raw_height)) 0094 throw LIBRAW_EXCEPTION_IO_CORRUPT; 0095 raw_image[pix] = pred[pix & 1] += diff; 0096 if (!(pix & 1) && HOLE(pix / raw_width)) 0097 pix += 2; 0098 } 0099 maximum = 0xff; 0100 } 0101 0102 void LibRaw::smal_v6_load_raw() 0103 { 0104 unsigned seg[2][2]; 0105 0106 fseek(ifp, 16, SEEK_SET); 0107 seg[0][0] = 0; 0108 seg[0][1] = get2(); 0109 seg[1][0] = raw_width * raw_height; 0110 seg[1][1] = INT_MAX; 0111 smal_decode_segment(seg, 0); 0112 } 0113 0114 int LibRaw::median4(int *p) 0115 { 0116 int min, max, sum, i; 0117 0118 min = max = sum = p[0]; 0119 for (i = 1; i < 4; i++) 0120 { 0121 sum += p[i]; 0122 if (min > p[i]) 0123 min = p[i]; 0124 if (max < p[i]) 0125 max = p[i]; 0126 } 0127 return (sum - min - max) >> 1; 0128 } 0129 0130 void LibRaw::fill_holes(int holes) 0131 { 0132 int row, col, val[4]; 0133 0134 for (row = 2; row < height - 2; row++) 0135 { 0136 if (!HOLE(row)) 0137 continue; 0138 for (col = 1; col < width - 1; col += 4) 0139 { 0140 val[0] = RAW(row - 1, col - 1); 0141 val[1] = RAW(row - 1, col + 1); 0142 val[2] = RAW(row + 1, col - 1); 0143 val[3] = RAW(row + 1, col + 1); 0144 RAW(row, col) = median4(val); 0145 } 0146 for (col = 2; col < width - 2; col += 4) 0147 if (HOLE(row - 2) || HOLE(row + 2)) 0148 RAW(row, col) = (RAW(row, col - 2) + RAW(row, col + 2)) >> 1; 0149 else 0150 { 0151 val[0] = RAW(row, col - 2); 0152 val[1] = RAW(row, col + 2); 0153 val[2] = RAW(row - 2, col); 0154 val[3] = RAW(row + 2, col); 0155 RAW(row, col) = median4(val); 0156 } 0157 } 0158 } 0159 0160 void LibRaw::smal_v9_load_raw() 0161 { 0162 unsigned seg[256][2], offset, nseg, holes, i; 0163 0164 fseek(ifp, 67, SEEK_SET); 0165 offset = get4(); 0166 nseg = (uchar)fgetc(ifp); 0167 fseek(ifp, offset, SEEK_SET); 0168 for (i = 0; i < nseg * 2; i++) 0169 ((unsigned *)seg)[i] = get4() + data_offset * (i & 1); 0170 fseek(ifp, 78, SEEK_SET); 0171 holes = fgetc(ifp); 0172 fseek(ifp, 88, SEEK_SET); 0173 seg[nseg][0] = raw_height * raw_width; 0174 seg[nseg][1] = get4() + data_offset; 0175 for (i = 0; i < nseg; i++) 0176 smal_decode_segment(seg + i, holes); 0177 if (holes) 0178 fill_holes(holes); 0179 } 0180 0181 #undef HOLE