File indexing completed on 2025-01-05 03:57:07
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 void LibRaw::cubic_spline(const int *x_, const int *y_, const int len) 0022 { 0023 float **A, *b, *c, *d, *x, *y; 0024 int i, j; 0025 0026 A = (float **)calloc(((2 * len + 4) * sizeof **A + sizeof *A), 2 * len); 0027 if (!A) 0028 return; 0029 A[0] = (float *)(A + 2 * len); 0030 for (i = 1; i < 2 * len; i++) 0031 A[i] = A[0] + 2 * len * i; 0032 y = len + (x = i + (d = i + (c = i + (b = A[0] + i * i)))); 0033 for (i = 0; i < len; i++) 0034 { 0035 x[i] = x_[i] / 65535.0; 0036 y[i] = y_[i] / 65535.0; 0037 } 0038 for (i = len - 1; i > 0; i--) 0039 { 0040 float _div = x[i] - x[i - 1]; 0041 if (fabs(_div) < 1.0e-15) 0042 _div = 1; 0043 b[i] = (y[i] - y[i - 1]) / _div; 0044 d[i - 1] = _div; 0045 } 0046 for (i = 1; i < len - 1; i++) 0047 { 0048 A[i][i] = 2 * (d[i - 1] + d[i]); 0049 if (i > 1) 0050 { 0051 A[i][i - 1] = d[i - 1]; 0052 A[i - 1][i] = d[i - 1]; 0053 } 0054 A[i][len - 1] = 6 * (b[i + 1] - b[i]); 0055 } 0056 for (i = 1; i < len - 2; i++) 0057 { 0058 float v = A[i + 1][i] / A[i][i]; 0059 for (j = 1; j <= len - 1; j++) 0060 A[i + 1][j] -= v * A[i][j]; 0061 } 0062 for (i = len - 2; i > 0; i--) 0063 { 0064 float acc = 0; 0065 for (j = i; j <= len - 2; j++) 0066 acc += A[i][j] * c[j]; 0067 c[i] = (A[i][len - 1] - acc) / A[i][i]; 0068 } 0069 for (i = 0; i < 0x10000; i++) 0070 { 0071 float x_out = (float)(i / 65535.0); 0072 float y_out = 0; 0073 for (j = 0; j < len - 1; j++) 0074 { 0075 if (x[j] <= x_out && x_out <= x[j + 1]) 0076 { 0077 float v = x_out - x[j]; 0078 y_out = y[j] + 0079 ((y[j + 1] - y[j]) / d[j] - 0080 (2 * d[j] * c[j] + c[j + 1] * d[j]) / 6) * 0081 v + 0082 (c[j] * 0.5) * v * v + 0083 ((c[j + 1] - c[j]) / (6 * d[j])) * v * v * v; 0084 } 0085 } 0086 curve[i] = y_out < 0.0 0087 ? 0 0088 : (y_out >= 1.0 ? 65535 : (ushort)(y_out * 65535.0 + 0.5)); 0089 } 0090 free(A); 0091 } 0092 void LibRaw::gamma_curve(double pwr, double ts, int mode, int imax) 0093 { 0094 int i; 0095 double g[6], bnd[2] = {0, 0}, r; 0096 0097 g[0] = pwr; 0098 g[1] = ts; 0099 g[2] = g[3] = g[4] = 0; 0100 bnd[g[1] >= 1] = 1; 0101 if (g[1] && (g[1] - 1) * (g[0] - 1) <= 0) 0102 { 0103 for (i = 0; i < 48; i++) 0104 { 0105 g[2] = (bnd[0] + bnd[1]) / 2; 0106 if (g[0]) 0107 bnd[(pow(g[2] / g[1], -g[0]) - 1) / g[0] - 1 / g[2] > -1] = g[2]; 0108 else 0109 bnd[g[2] / exp(1 - 1 / g[2]) < g[1]] = g[2]; 0110 } 0111 g[3] = g[2] / g[1]; 0112 if (g[0]) 0113 g[4] = g[2] * (1 / g[0] - 1); 0114 } 0115 if (g[0]) 0116 g[5] = 1 / (g[1] * SQR(g[3]) / 2 - g[4] * (1 - g[3]) + 0117 (1 - pow(g[3], 1 + g[0])) * (1 + g[4]) / (1 + g[0])) - 0118 1; 0119 else 0120 g[5] = 1 / (g[1] * SQR(g[3]) / 2 + 1 - g[2] - g[3] - 0121 g[2] * g[3] * (log(g[3]) - 1)) - 0122 1; 0123 if (!mode--) 0124 { 0125 memcpy(gamm, g, sizeof gamm); 0126 return; 0127 } 0128 for (i = 0; i < 0x10000; i++) 0129 { 0130 curve[i] = 0xffff; 0131 if ((r = (double)i / imax) < 1) 0132 curve[i] = 0133 0x10000 * 0134 (mode ? (r < g[3] ? r * g[1] 0135 : (g[0] ? pow(r, g[0]) * (1 + g[4]) - g[4] 0136 : log(r) * g[2] + 1)) 0137 : (r < g[2] ? r / g[1] 0138 : (g[0] ? pow((r + g[4]) / (1 + g[4]), 1 / g[0]) 0139 : exp((r - 1) / g[2])))); 0140 } 0141 } 0142 0143 void LibRaw::linear_table(unsigned len) 0144 { 0145 int i; 0146 if (len > 0x10000) 0147 len = 0x10000; 0148 else if (len < 1) 0149 return; 0150 read_shorts(curve, len); 0151 for (i = len; i < 0x10000; i++) 0152 curve[i] = curve[i - 1]; 0153 maximum = curve[len < 0x1000 ? 0xfff : len - 1]; 0154 }