Hi all,
I'm a newcomer to RawSpeed (and raw decoding in general, for that
matter), but I was hoping I might be able to port the Phase One sensor
correction functionality in dcraw to RawSpeed's IiqDecoder. I think I've
pretty well figured out how the correction I'm concerned with works: the
RAW file includes four sets of control points (one for each quadrant of
the image) that define curves to apply to all the pixels in each
respective quadrant (this is to compensate for the fact that the
"sensor" in these cameras is actually four separate sensors being read
at the same time, and they can have slight variations).
The trickiest part for me right now, aside from making sure I get all
the RS conventions and formatting right (which I'm hoping I'll get
hammered into me in PR comments), is actually calculating the curves.
dcraw does it with a cubic spline function, but I can't find any
comparable function looking through the Doxygen for RS. I did find
curve_tools.c/h in Darktable, which looks promising. So, a couple
questions:
1. Will any of those curve_tools functions in DT do what the
cubic_spline function in dcraw (reproduced below for reference) does?
I'm not really familiar with calculating curves, but I'm a bit worried
that it seems like they're all geared towards interpolating a single
point on a curve, which I'm assuming would be very slow compared to the
approach dcraw takes of calculating all the points on the curve and then
just doing a lookup for each pixel.
2. Assuming one of those is useful, how should I go about reusing it in
RS? Should I just copy/paste it? I could always make it a public
function in RawSpeed and then use it from DT, but it seems like it would
be odd to have a single utility function like that call out to the raw
decoding library. My intuition is it's probably just okay to have them
live in both places, but I'm open to suggestions.
Thanks,
Robby
dcraw's cubic_spline implementation follows:
-----------------------------------
void CLASS cubic_spline (const int *x_, const int *y_, const int len)
{
float **A, *b, *c, *d, *x, *y;
int i, j;
A = (float **) calloc (((2*len + 4)*sizeof **A + sizeof *A), 2*len);
if (!A) return;
A[0] = (float *) (A + 2*len);
for (i = 1; i < 2*len; i++)
A[i] = A[0] + 2*len*i;
y = len + (x = i + (d = i + (c = i + (b = A[0] + i*i))));
for (i = 0; i < len; i++) {
x[i] = x_[i] / 65535.0;
y[i] = y_[i] / 65535.0;
}
for (i = len-1; i > 0; i--) {
b[i] = (y[i] - y[i-1]) / (x[i] - x[i-1]);
d[i-1] = x[i] - x[i-1];
}
for (i = 1; i < len-1; i++) {
A[i][i] = 2 * (d[i-1] + d[i]);
if (i > 1) {
A[i][i-1] = d[i-1];
A[i-1][i] = d[i-1];
}
A[i][len-1] = 6 * (b[i+1] - b[i]);
}
for(i = 1; i < len-2; i++) {
float v = A[i+1][i] / A[i][i];
for(j = 1; j <= len-1; j++)
A[i+1][j] -= v * A[i][j];
}
for(i = len-2; i > 0; i--) {
float acc = 0;
for(j = i; j <= len-2; j++)
acc += A[i][j]*c[j];
c[i] = (A[i][len-1] - acc) / A[i][i];
}
for (i = 0; i < 0x10000; i++) {
float x_out = (float)(i / 65535.0);
float y_out = 0;
for (j = 0; j < len-1; j++) {
if (x[j] <= x_out && x_out <= x[j+1]) {
float v = x_out - x[j];
y_out = y[j] +
((y[j+1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j+1] * d[j])/6) * v
+ (c[j] * 0.5) * v*v + ((c[j+1] - c[j]) / (6 * d[j])) * v*v*v;
}
}
curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 :
(ushort)(y_out * 65535.0 + 0.5));
}
free (A);
}
___________________________________________________________________________
darktable developer mailing list
to unsubscribe send a mail to darktable-dev+unsubscr...@lists.darktable.org