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