diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc
index 2e78254f9..6349f999e 100644
--- a/rtengine/CA_correct_RT.cc
+++ b/rtengine/CA_correct_RT.cc
@@ -21,9 +21,6 @@
// along with this program. If not, see .
//
////////////////////////////////////////////////////////////////
-
-
-
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
int RawImageSource::LinEqSolve(int nDim, float* pfMatr, float* pfVect, float* pfSolution)
{
@@ -106,8 +103,6 @@ void RawImageSource::CA_correct_RT() {
#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} }
#define SQR(x) ((x)*(x))
- //static const float pre_mul[3] = {MIN(ri->red_multiplier,ri->green_multiplier), ri->green_multiplier, \
- MIN(ri->blue_multiplier,ri->green_multiplier)};
static const float clip_pt = ri->defgain;
@@ -117,8 +112,8 @@ void RawImageSource::CA_correct_RT() {
float (*Gtmp);
Gtmp = (float (*)) calloc ((height)*(width), sizeof *Gtmp);
- static const int border=8;
- static const int border2=16;
+ const int border=8;
+ const int border2=16;
//order of 2d polynomial fit (polyord), and numpar=polyord^2
int polyord=4, numpar=16;
//number of blocks used in the fit
@@ -140,7 +135,7 @@ void RawImageSource::CA_correct_RT() {
//flag indicating success or failure of polynomial fit
int res;
//shifts to location of vertical and diagonal neighbors
- static const int v1=TS, v2=2*TS, v3=3*TS, v4=4*TS;//, p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3;
+ const int v1=TS, v2=2*TS, /* v3=3*TS,*/ v4=4*TS;//, p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3;
float eps=1e-5; //tolerance to avoid dividing by zero
@@ -151,13 +146,13 @@ void RawImageSource::CA_correct_RT() {
//measured CA shift parameters for a tile
float CAshift[2][3];
//polynomial fit coefficients
- float polymat[3][2][1296], shiftmat[3][2][36], fitparams[3][2][36];
+ float polymat[3][2][256], shiftmat[3][2][16], fitparams[3][2][16];
//residual CA shift amount within a plaquette
float shifthfrac[3], shiftvfrac[3];
//temporary storage for median filter
float temp, p[9];
//temporary parameters for tile CA evaluation
- float gdiff, deltgrb, denom;
+ float gdiff, deltgrb;
//interpolated G at edge of plaquette
float Ginthfloor, Ginthceil, Gint, RBint, gradwt;
//interpolated color difference at edge of plaquette
@@ -165,20 +160,15 @@ void RawImageSource::CA_correct_RT() {
//data for evaluation of block CA shift variance
float blockave[2][3]={{0,0,0},{0,0,0}}, blocksqave[2][3]={{0,0,0},{0,0,0}}, blockdenom[2][3]={{0,0,0},{0,0,0}}, blockvar[2][3];
//low and high pass 1D filters of G in vertical/horizontal directions
- float glpfh, glpfv, ghpfh, ghpfv;
+ float glpfh, glpfv;
//max allowed CA shift
- static const float bslim = 3.99;
+ const float bslim = 3.99;
//gaussians for low pass filtering of G and R/B
- static const float gaussg[5] = {0.171582, 0.15839, 0.124594, 0.083518, 0.0477063};//sig=2.5
- static const float gaussrb[3] = {0.332406, 0.241376, 0.0924212};//sig=1.25
+ //static const float gaussg[5] = {0.171582, 0.15839, 0.124594, 0.083518, 0.0477063};//sig=2.5
+ //static const float gaussrb[3] = {0.332406, 0.241376, 0.0924212};//sig=1.25
//block CA shift values and weight assigned to block
- //char *buffer1; // vblsz*hblsz*3*2
- //float (*blockshifts)[3][2]; // vblsz*hblsz*3*2
- float blockshifts[10000][3][2]; //fixed memory allocation
- float blockwt[10000]; //fixed memory allocation
-
char *buffer; // TS*TS*16
//rgb data in a tile
@@ -225,11 +215,19 @@ void RawImageSource::CA_correct_RT() {
vblsz=ceil((float)(height+border2)/(TS-border2)+2+vz1);
hblsz=ceil((float)(width+border2)/(TS-border2)+2+hz1);
- /*buffer1 = (char *) malloc(vblsz*hblsz*3*2*sizeof(float));
- merror(buffer1,"CA_correct()");
- memset(buffer1,0,vblsz*hblsz*3*2*sizeof(float));
- // block CA shifts
- blockshifts = (float (*)[3][2]) buffer1;*/
+ //block CA shift values and weight assigned to block
+ char *buffer1; // vblsz*hblsz*(3*2+1)
+ float (*blockwt); // vblsz*hblsz
+ float (*blockshifts)[3][2]; // vblsz*hblsz*3*2
+ //float blockshifts[1000][3][2]; //fixed memory allocation
+ //float blockwt[1000]; //fixed memory allocation
+
+ buffer1 = (char *) malloc(vblsz*hblsz*(3*2+1)*sizeof(float));
+ //merror(buffer1,"CA_correct()");
+ memset(buffer1,0,vblsz*hblsz*(3*2+1)*sizeof(float));
+ // block CA shifts
+ blockwt = (float (*)) (buffer1);
+ blockshifts = (float (*)[3][2]) (buffer1+(vblsz*hblsz*sizeof(float)));
@@ -257,7 +255,7 @@ void RawImageSource::CA_correct_RT() {
c = FC(rr,cc);
indx=row*width+col;
indx1=rr*TS+cc;
- rgb[indx1][c] = (ri->data[row][col])/65535.0f;
+ rgb[indx1][c] = (rawData[row][col])/65535.0f;
//rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation
}
@@ -274,7 +272,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[(height-rr-2)][left+cc])/65535.0f;
+ rgb[(rrmax+rr)*TS+cc][c] = (rawData[(height-rr-2)][left+cc])/65535.0f;
//rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+left+cc][c])/65535.0f;//for dcraw implementation
}
}
@@ -289,7 +287,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=rrmin; rrdata[(top+rr)][(width-cc-2)])/65535.0f;
+ rgb[rr*TS+ccmax+cc][c] = (rawData[(top+rr)][(width-cc-2)])/65535.0f;
//rgb[rr*TS+ccmax+cc][c] = (image[(top+rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
}
}
@@ -299,7 +297,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[border2-rr][border2-cc])/65535.0f;
+ rgb[(rr)*TS+cc][c] = (rawData[border2-rr][border2-cc])/65535.0f;
//rgb[(rr)*TS+cc][c] = (rgb[(border2-rr)*TS+(border2-cc)][c]);//for dcraw implementation
}
}
@@ -307,7 +305,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[(height-rr-2)][(width-cc-2)])/65535.0f;
+ rgb[(rrmax+rr)*TS+ccmax+cc][c] = (rawData[(height-rr-2)][(width-cc-2)])/65535.0f;
//rgb[(rrmax+rr)*TS+ccmax+cc][c] = (image[(height-rr-2)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
}
}
@@ -315,7 +313,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[(border2-rr)][(width-cc-2)])/65535.0f;
+ rgb[(rr)*TS+ccmax+cc][c] = (rawData[(border2-rr)][(width-cc-2)])/65535.0f;
//rgb[(rr)*TS+ccmax+cc][c] = (image[(border2-rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
}
}
@@ -323,7 +321,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[(height-rr-2)][(border2-cc)])/65535.0f;
+ rgb[(rrmax+rr)*TS+cc][c] = (rawData[(height-rr-2)][(border2-cc)])/65535.0f;
//rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(border2-cc)][c])/65535.0f;//for dcraw implementation
}
}
@@ -370,14 +368,6 @@ void RawImageSource::CA_correct_RT() {
fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx][1]-rgb[indx][c])) - \
fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx+4][1]-rgb[indx+4][c])));
- /*ghpfv = fabs(fabs(rgb[indx][1]-rgb[indx+v4][1])+fabs(rgb[indx][1]-rgb[indx-v4][1]) - \
- fabs(rgb[indx+v4][1]-rgb[indx-v4][1]));
- ghpfh = fabs(fabs(rgb[indx][1]-rgb[indx+4][1])+fabs(rgb[indx][1]-rgb[indx-4][1]) - \
- fabs(rgb[indx+4][1]-rgb[indx-4][1]));
- rbhpfv[indx] = fabs(ghpfv - fabs(fabs(rgb[indx][c]-rgb[indx+v4][c])+fabs(rgb[indx][c]-rgb[indx-v4][c]) - \
- fabs(rgb[indx+v4][c]-rgb[indx-v4][c])));
- rbhpfh[indx] = fabs(ghpfh - fabs(fabs(rgb[indx][c]-rgb[indx+4][c])+fabs(rgb[indx][c]-rgb[indx-4][c]) - \
- fabs(rgb[indx+4][c]-rgb[indx-4][c])));*/
glpfv = 0.25*(2*rgb[indx][1]+rgb[indx+v2][1]+rgb[indx-v2][1]);
glpfh = 0.25*(2*rgb[indx][1]+rgb[indx+2][1]+rgb[indx-2][1]);
@@ -485,6 +475,7 @@ void RawImageSource::CA_correct_RT() {
if (blockdenom[j][c]) {
blockvar[j][c] = blocksqave[j][c]/blockdenom[j][c]-SQR(blockave[j][c]/blockdenom[j][c]);
} else {
+ fprintf (stderr,"blockdenom vanishes");
return;
}
}
@@ -515,8 +506,8 @@ void RawImageSource::CA_correct_RT() {
//end of filling border pixels of blockshift array
//initialize fit arrays
- for (i=0; i<1296; i++) {polymat[0][0][i] = polymat[0][1][i] = polymat[2][0][i] = polymat[2][1][i] = 0;}
- for (i=0; i<36; i++) {shiftmat[0][0][i] = shiftmat[0][1][i] = shiftmat[2][0][i] = shiftmat[2][1][i] = 0;}
+ for (i=0; i<256; i++) {polymat[0][0][i] = polymat[0][1][i] = polymat[2][0][i] = polymat[2][1][i] = 0;}
+ for (i=0; i<16; i++) {shiftmat[0][0][i] = shiftmat[0][1][i] = shiftmat[2][0][i] = shiftmat[2][1][i] = 0;}
for (vblock=1; vblockdata[row][col])/65535.0f;
+ rgb[indx1][c] = (rawData[row][col])/65535.0f;
//rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation
if ((c&1)==0) rgb[indx1][1] = Gtmp[indx];
@@ -628,7 +623,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[(height-rr-2)][left+cc])/65535.0f;
+ rgb[(rrmax+rr)*TS+cc][c] = (rawData[(height-rr-2)][left+cc])/65535.0f;
//rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+left+cc][c])/65535.0f;//for dcraw implementation
rgb[(rrmax+rr)*TS+cc][1] = Gtmp[(height-rr-2)*width+left+cc];
@@ -646,7 +641,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=rrmin; rrdata[(top+rr)][(width-cc-2)])/65535.0f;
+ rgb[rr*TS+ccmax+cc][c] = (rawData[(top+rr)][(width-cc-2)])/65535.0f;
//rgb[rr*TS+ccmax+cc][c] = (image[(top+rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
rgb[rr*TS+ccmax+cc][1] = Gtmp[(top+rr)*width+(width-cc-2)];
@@ -658,7 +653,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[border2-rr][border2-cc])/65535.0f;
+ rgb[(rr)*TS+cc][c] = (rawData[border2-rr][border2-cc])/65535.0f;
//rgb[(rr)*TS+cc][c] = (rgb[(border2-rr)*TS+(border2-cc)][c]);//for dcraw implementation
rgb[(rr)*TS+cc][1] = Gtmp[(border2-rr)*width+border2-cc];
@@ -668,7 +663,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[(height-rr-2)][(width-cc-2)])/65535.0f;
+ rgb[(rrmax+rr)*TS+ccmax+cc][c] = (rawData[(height-rr-2)][(width-cc-2)])/65535.0f;
//rgb[(rrmax+rr)*TS+ccmax+cc][c] = (image[(height-rr-2)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
rgb[(rrmax+rr)*TS+ccmax+cc][1] = Gtmp[(height-rr-2)*width+(width-cc-2)];
@@ -678,7 +673,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[(border2-rr)][(width-cc-2)])/65535.0f;
+ rgb[(rr)*TS+ccmax+cc][c] = (rawData[(border2-rr)][(width-cc-2)])/65535.0f;
//rgb[(rr)*TS+ccmax+cc][c] = (image[(border2-rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
rgb[(rr)*TS+ccmax+cc][1] = Gtmp[(border2-rr)*width+(width-cc-2)];
@@ -688,7 +683,7 @@ void RawImageSource::CA_correct_RT() {
for (rr=0; rrdata[(height-rr-2)][(border2-cc)])/65535.0f;
+ rgb[(rrmax+rr)*TS+cc][c] = (rawData[(height-rr-2)][(border2-cc)])/65535.0f;
//rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(border2-cc)][c])/65535.0f;//for dcraw implementation
rgb[(rrmax+rr)*TS+cc][1] = Gtmp[(height-rr-2)*width+(border2-cc)];
@@ -791,7 +786,7 @@ void RawImageSource::CA_correct_RT() {
indx = row*width + col;
c = FC(row,col);
- ri->data[row][col] = CLIP((int)(65535.0f*rgb[(rr)*TS+cc][c] + 0.5f));
+ rawData[row][col] = CLIP((int)(65535.0f*rgb[(rr)*TS+cc][c] + 0.5f));
//image[indx][c] = CLIP((int)(65535.0*rgb[(rr)*TS+cc][c] + 0.5));//for dcraw implementation
}
@@ -803,7 +798,7 @@ void RawImageSource::CA_correct_RT() {
// clean up
free(buffer);
free(Gtmp);
- //free(buffer1);
+ free(buffer1);
diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index d5cae4e78..6442a3091 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -7,7 +7,7 @@ link_directories (${CMAKE_CURRENT_SOURCE_DIR}/../rtexif ${EXTRA_LIBDIR} ${GTHREA
${GOBJECT_LIBRARY_DIRS} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS}
${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS})
-set (RTENGINESOURCEFILES colortemp.cc curves.cc dcraw.cc iccstore.cc
+set (RTENGINESOURCEFILES colortemp.cc curves.cc dcraw.cc iccstore.cc dfmanager.cc
image8.cc image16.cc imagedata.cc imageio.cc improcfun.cc init.cc dcrop.cc
loadinitial.cc procparams.cc rawimagesource.cc shmap.cc simpleprocess.cc refreshmap.cc
stdimagesource.cc myfile.cc iccjpeg.c hlmultipliers.cc improccoordinator.cc
diff --git a/rtengine/amaze_interpolate_RT.cc b/rtengine/amaze_interpolate_RT.cc
index a223ddea5..ed59989ea 100644
--- a/rtengine/amaze_interpolate_RT.cc
+++ b/rtengine/amaze_interpolate_RT.cc
@@ -35,20 +35,7 @@ void RawImageSource::amaze_demosaic_RT() {
#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
//#define CLIP(x) LIM(x,0,65535)
- //allocate outpute arrays
int width=W, height=H;
- red = new unsigned short*[H];
- for (int i=0; idefgain;
@@ -239,7 +226,7 @@ void RawImageSource::amaze_demosaic_RT() {
}
// Main algorithm: Tile loop
- //#pragma omp parallel for shared(ri->data,height,width,red,green,blue) private(top,left) schedule(dynamic)
+ //#pragma omp parallel for shared(rawData,height,width,red,green,blue) private(top,left) schedule(dynamic)
//code is openmp ready; just have to pull local tile variable declarations inside the tile loop
#pragma omp for schedule(dynamic) nowait
for (top=-16; top < height; top += TS-32)
@@ -340,7 +327,7 @@ void RawImageSource::amaze_demosaic_RT() {
c = FC(rr,cc);
indx=row*width+col;
indx1=rr*TS+cc;
- rgb[indx1][c] = (ri->data[row][col])/65535.0f;
+ rgb[indx1][c] = (rawData[row][col])/65535.0f;
//rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation
cfa[indx1] = rgb[indx1][c];
@@ -359,7 +346,7 @@ void RawImageSource::amaze_demosaic_RT() {
for (rr=0; rr<16; rr++)
for (cc=ccmin; ccdata[(height-rr-2)][left+cc])/65535.0f;
+ rgb[(rrmax+rr)*TS+cc][c] = (rawData[(height-rr-2)][left+cc])/65535.0f;
//rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+left+cc][c])/65535.0f;//for dcraw implementation
cfa[(rrmax+rr)*TS+cc] = rgb[(rrmax+rr)*TS+cc][c];
}
@@ -376,7 +363,7 @@ void RawImageSource::amaze_demosaic_RT() {
for (rr=rrmin; rrdata[(top+rr)][(width-cc-2)])/65535.0f;
+ rgb[rr*TS+ccmax+cc][c] = (rawData[(top+rr)][(width-cc-2)])/65535.0f;
//rgb[rr*TS+ccmax+cc][c] = (image[(top+rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
cfa[rr*TS+ccmax+cc] = rgb[rr*TS+ccmax+cc][c];
}
@@ -387,7 +374,7 @@ void RawImageSource::amaze_demosaic_RT() {
for (rr=0; rr<16; rr++)
for (cc=0; cc<16; cc++) {
c=FC(rr,cc);
- rgb[(rr)*TS+cc][c] = (ri->data[32-rr][32-cc])/65535.0f;
+ rgb[(rr)*TS+cc][c] = (rawData[32-rr][32-cc])/65535.0f;
//rgb[(rr)*TS+cc][c] = (rgb[(32-rr)*TS+(32-cc)][c]);//for dcraw implementation
cfa[(rr)*TS+cc] = rgb[(rr)*TS+cc][c];
}
@@ -396,7 +383,7 @@ void RawImageSource::amaze_demosaic_RT() {
for (rr=0; rr<16; rr++)
for (cc=0; cc<16; cc++) {
c=FC(rr,cc);
- rgb[(rrmax+rr)*TS+ccmax+cc][c] = (ri->data[(height-rr-2)][(width-cc-2)])/65535.0f;
+ rgb[(rrmax+rr)*TS+ccmax+cc][c] = (rawData[(height-rr-2)][(width-cc-2)])/65535.0f;
//rgb[(rrmax+rr)*TS+ccmax+cc][c] = (image[(height-rr-2)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
cfa[(rrmax+rr)*TS+ccmax+cc] = rgb[(rrmax+rr)*TS+ccmax+cc][c];
}
@@ -405,7 +392,7 @@ void RawImageSource::amaze_demosaic_RT() {
for (rr=0; rr<16; rr++)
for (cc=0; cc<16; cc++) {
c=FC(rr,cc);
- rgb[(rr)*TS+ccmax+cc][c] = (ri->data[(32-rr)][(width-cc-2)])/65535.0f;
+ rgb[(rr)*TS+ccmax+cc][c] = (rawData[(32-rr)][(width-cc-2)])/65535.0f;
//rgb[(rr)*TS+ccmax+cc][c] = (image[(32-rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation
cfa[(rr)*TS+ccmax+cc] = rgb[(rr)*TS+ccmax+cc][c];
}
@@ -414,7 +401,7 @@ void RawImageSource::amaze_demosaic_RT() {
for (rr=0; rr<16; rr++)
for (cc=0; cc<16; cc++) {
c=FC(rr,cc);
- rgb[(rrmax+rr)*TS+cc][c] = (ri->data[(height-rr-2)][(32-cc)])/65535.0f;
+ rgb[(rrmax+rr)*TS+cc][c] = (rawData[(height-rr-2)][(32-cc)])/65535.0f;
//rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(32-cc)][c])/65535.0f;//for dcraw implementation
cfa[(rrmax+rr)*TS+cc] = rgb[(rrmax+rr)*TS+cc][c];
}
diff --git a/rtengine/cfa_linedn_RT.cc b/rtengine/cfa_linedn_RT.cc
index 0c38f01a3..2050c0f77 100644
--- a/rtengine/cfa_linedn_RT.cc
+++ b/rtengine/cfa_linedn_RT.cc
@@ -101,7 +101,7 @@ void RawImageSource::CLASS cfa_linedn(float noise)
// load CFA data; data should be in linear gamma space, before white balance multipliers are applied
for (rr=top; rr < top+numrows; rr++)
for (cc=left, indx=(rr-top)*TS; cc < left+numcols; cc++, indx++) {
- cfain[indx] = ri->data[rr][cc];
+ cfain[indx] = rawData[rr][cc];
}
//pad the block to a multiple of 16 on both sides
@@ -189,7 +189,7 @@ void RawImageSource::CLASS cfa_linedn(float noise)
for (rr=16; rr < numrows-16; rr++) {
row = rr + top;
for (col=16+left, indx=rr*TS+16; indx < rr*TS+numcols-16; indx++, col++) {
- ri->data[row][col] = CLIP((int)(cfadn[indx]+ 0.5));
+ rawData[row][col] = CLIP((int)(cfadn[indx]+ 0.5));
}
}
if(plistener) plistener->setProgress(fabs((float)top/height));
diff --git a/rtengine/common.h b/rtengine/common.h
index 61b5d4720..760a2144f 100644
--- a/rtengine/common.h
+++ b/rtengine/common.h
@@ -36,32 +36,49 @@
#define CMAXVAL 65535
#include
+#include
+
+namespace rtengine {
+
+struct badPix
+{
+ int x;
+ int y;
+ badPix( int xc, int yc ):x(xc),y(yc){}
+};
struct RawImage {
- int width;
- int height;
+ Glib::ustring fname; // complete filename
+ int width; // with of the image as reported by dcraw
+ int height; // height of the image as reported by dcraw
- unsigned filters;
+ unsigned filters; // sequence of Bayer filter colors: 2bit for each of 2x8 pixels grid indicate 0=Red,1=Green1,2=Blue,(3=green2)
+ int colors; // Number of colors of bayer filter (3 or 4)
- double red_multiplier;
- double green_multiplier;
- double blue_multiplier;
-
- double camwb_red;
- double camwb_green;
- double camwb_blue;
-
- int blackpoint;
- int rgb_max;
- int rotate_deg;
+ int black_point; // Black offset taken from dslr info by dcraw
+ int cblack[4]; // Black for each color.
+ unsigned short white[8][8]; // square of white registered by camera
+ float cam_mul[4]; // Camera color multiplier taken from exif by dcraw
+ float pre_mul[4];
+ int maximum; // White (maximum) point taken from dslr info
+ int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif
int fuji_width;
double defgain;
-
+ double iso_speed;
+ double shutter;
+ double aperture;
+ double focal_len;
+ time_t timestamp;
char *make, *model;
int exifbase, prefilters, ciff_base, ciff_len;
+ int thumbLength;
+ int thumbOffset;
+ int thumbType;
+ int thumbWidth;
+ int thumbHeight;
unsigned short* allocation;
unsigned short** data; // holds pixel values, data[i][j] corresponds to the ith row and jth column
@@ -70,7 +87,43 @@ struct RawImage {
float icoeff[3][3];
int profile_len;
- char* profile_data;
+ char* profile_data; // Embedded ICC color profile
+
+ RawImage( const Glib::ustring name):allocation(NULL),data(NULL),profile_data(NULL),fname(name)
+ {
+ }
+ ~RawImage()
+ {
+ if(allocation){ delete [] allocation; allocation=NULL;}
+ if(data){ delete [] data; data=NULL;}
+ if(profile_data){ delete [] profile_data; profile_data=NULL;}
+ }
+
+ int loadRaw (bool loadData=true);
+
+ void allocData()
+ {
+ if (filters) {
+ if (!allocation) {
+ allocation = new unsigned short[height * width];
+ data = new unsigned short*[height];
+ for (int i = 0; i < height; i++)
+ data[i] = allocation + i * width;
+ }
+ }else{
+ if (!allocation) {
+ allocation = new unsigned short[3 * height * width];
+ data = new unsigned short*[height];
+ for (int i = 0; i < height; i++)
+ data[i] = allocation + 3 * i * width;
+ }
+ }
+ if(profile_len)
+ profile_data = new char[profile_len];
+ }
+
};
+}
+
#endif
diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc
index 9a934c85f..defb860cb 100644
--- a/rtengine/dcraw.cc
+++ b/rtengine/dcraw.cc
@@ -3777,16 +3777,18 @@ void CLASS pre_interpolate()
}
}
if (filters && colors == 3) {
- if ((mix_green = four_color_rgb)) colors++;
- else {
- for (row = FC(1,0) >> 1; row < height; row+=2)
- for (col = FC(row,1) & 1; col < width; col+=2)
- image[row*width+col][1] = image[row*width+col][3];
-/*RT*/ pre_filters = filters;
- filters &= ~((filters & 0x55555555) << 1);
- }
- }
- if (half_size) filters = 0;
+ if ((mix_green = four_color_rgb))
+ colors++;
+ else {
+ for (row = FC(1,0) >> 1; row < height; row += 2)
+ for (col = FC(row,1) & 1; col < width; col += 2)
+ image[row * width + col][1] = image[row * width + col][3];
+ /*RT*/ pre_filters = filters;
+ filters &= ~((filters & 0x55555555) << 1);
+ }
+ }
+ if (half_size)
+ filters = 0;
}
void CLASS border_interpolate (int border)
@@ -8915,7 +8917,6 @@ cleanup:
#include
#include
-#include
#include
#include
#include
@@ -8926,150 +8927,148 @@ extern Settings* settings;
Glib::Mutex* dcrMutex=NULL;
-int loadRaw (const char* fname, struct RawImage *ri) {
+int RawImage::loadRaw (bool loadData) {
- static const double xyzd50_srgb[3][3] =
- { { 0.436083, 0.385083, 0.143055 },
- { 0.222507, 0.716888, 0.060608 },
- { 0.013930, 0.097097, 0.714022 } };
+ Glib::Mutex::Lock lock(*dcrMutex); // auto unlock
-dcrMutex->lock ();
-
- ifname = fname;//strdup (fname);
+ ifname = fname.c_str();
image = NULL;
-
exif_base = -1;
ciff_base = -1;
ciff_len = -1;
verbose = settings->verbose;
oprof = NULL;
- ri->data = NULL;
- ri->allocation = NULL;
- ri->profile_data = NULL;
- ifp = gfopen (fname);
- if (!ifp) {
- dcrMutex->unlock ();
- return 3;
- }
+ ifp = gfopen (fname.c_str());
+ if (!ifp)
+ return 3;
+
+ thumb_length = 0;
+ thumb_offset = 0;
+ thumb_load_raw = 0;
use_camera_wb = 0;
highlight = 1;
half_size = 0;
+ //***************** Read ALL raw file info
identify ();
- use_camera_wb = 1;
if (!is_raw) {
fclose(ifp);
- dcrMutex->unlock ();
return 2;
}
+ this->filters = ::filters;
+ this->height = ::height;
+ this->width = ::width;
+ this->colors = ::colors;
+ this->profile_len = ::profile_length;
- shrink = 0;
+ int i = ::cblack[3];
+ for (int c=0; c <3; c++)
+ if (i > ::cblack[c])
+ i = ::cblack[c];
+ for (int c=0; c < 4; c++)
+ ::cblack[c] -= i;
+ ::black += i;
+ for (int c=0; c < 4; c++) this->cblack[c] = ::cblack[c];
+ for (int c=0; c < 4; c++) this->cam_mul[c] = ::cam_mul[c];
+ for (int c=0; c < 4; c++) this->pre_mul[c] = ::pre_mul[c];
+ for (int a = 0; a < 3; a++)
+ for (int b = 0; b < 3; b++)
+ this->coeff[a][b] = ::rgb_cam[a][b];
- if (settings->verbose) printf ("Loading %s %s image from %s...\n", make, model, fname);
- iheight = height;
- iwidth = width;
+ this->black_point = ::black;
+ this->maximum = ::maximum;
+ this->fuji_width = ::fuji_width;
- image = (UshORt (*)[4])calloc (height*width*sizeof *image + meta_length, 1);
- meta_data = (char *) (image + height*width);
-
- if (setjmp (failure)) {
- if (image)
- free (image);
- if (ri->data)
- free(ri->data);
- fclose (ifp);
- dcrMutex->unlock ();
- return 100;
- }
-
- fseek (ifp, data_offset, SEEK_SET);
- (*load_raw)();
-
- ri->profile_len = 0;
- ri->profile_data = NULL;
- if (profile_length) {
- ri->profile_len = profile_length;
- ri->profile_data = (char *) malloc (profile_length);
- fseek (ifp, profile_offset, SEEK_SET);
- fread (ri->profile_data, 1, profile_length, ifp);
- }
-
- fclose(ifp);
- if (zero_is_bad) remove_zeroes();
-
- ri->red_multiplier = pre_mul[0];
- ri->green_multiplier = pre_mul[1];
- ri->blue_multiplier = pre_mul[2];
-
- scale_colors();
- pre_interpolate ();
-
- ri->width = width;
- ri->height = height;
- ri->filters = filters;
-
- if (filters) {
- ri->allocation = (short unsigned int*)calloc(height*width, sizeof(unsigned short));
- ri->data = (unsigned short**)calloc(height, sizeof(unsigned short*));
- for (int i=0; idata[i] = ri->allocation + i*width;
- for (int row = 0; row < height; row++)
- for (int col = 0; col < width; col++)
- if (ISGREEN(ri,row,col))
- ri->data[row][col] = image[row*width+col][1];
- else if (ISRED(ri,row,col))
- ri->data[row][col] = image[row*width+col][0];
- else
- ri->data[row][col] = image[row*width+col][2];
- }
- else {
- ri->allocation = (short unsigned int*)calloc(3*height*width, sizeof(unsigned short));
- ri->data = (unsigned short**)calloc(height, sizeof(unsigned short*));
- for (int i=0; idata[i] = ri->allocation + 3*i*width;
- for (int row = 0; row < height; row++)
- for (int col = 0; col < width; col++) {
- ri->data[row][3*col+0] = image[row*width+col][0];
- ri->data[row][3*col+1] = image[row*width+col][1];
- ri->data[row][3*col+2] = image[row*width+col][2];
- }
- }
+ for(int i=0; i<8;i++)
+ for(int j=0;j<8;j++)
+ this->white[i][j] = ::white[i][j];
if (flip==5)
- ri->rotate_deg = 270;
+ this->rotate_deg = 270;
else if (flip==3)
- ri->rotate_deg = 180;
+ this->rotate_deg = 180;
else if (flip==6)
- ri->rotate_deg = 90;
+ this->rotate_deg = 90;
else
- ri->rotate_deg = 0;
+ this->rotate_deg = 0;
- ri->make = strdup (make);
- ri->model = strdup (model);
+ this->make = strdup (::make);
+ this->model = strdup (::model);
+ this->iso_speed = ::iso_speed;
+ this->shutter = ::shutter;
+ this->aperture = ::aperture;
+ this->focal_len = ::focal_len;
+ this->timestamp = ::timestamp;
+ this->exifbase = ::exif_base;
+ this->ciff_base = ::ciff_base;
+ this->ciff_len = ::ciff_len;
+ this->thumbOffset = ::thumb_offset;
+ this->thumbLength = ::thumb_length;
+ this->thumbHeight = ::thumb_height;
+ this->thumbWidth = ::thumb_width;
+ if (!thumb_load_raw && thumb_offset && write_thumb == jpeg_thumb)
+ this->thumbType = 1;
+ else if (!thumb_load_raw && thumb_offset && write_thumb == ppm_thumb)
+ this->thumbType = 2;
+ else {
+ this->thumbType = 0;
+ this->thumbWidth = ::width;
+ this->thumbHeight = ::height;
+ }
- ri->exifbase = exif_base;
- ri->prefilters = pre_filters;
- ri->ciff_base = ciff_base;
- ri->ciff_len = ciff_len;
+ if( loadData ){
+ allocData();
+ use_camera_wb = 1;
+ shrink = 0;
+ if (settings->verbose) printf ("Loading %s %s image from %s...\n", make, model, fname.c_str());
+ iheight = height;
+ iwidth = width;
- ri->camwb_red = ri->red_multiplier / pre_mul[0];
- ri->camwb_green = ri->green_multiplier / pre_mul[1];
- ri->camwb_blue = ri->blue_multiplier / pre_mul[2];
+ // dcraw needs this global variable to hold pixel data
+ image = (UshORt (*)[4])calloc (height*width*sizeof *image + meta_length, 1);
+ meta_data = (char *) (image + height*width);
+ if(!image)
+ return 200;
- ri->defgain = 1.0 / MIN(MIN(pre_mul[0],pre_mul[1]),pre_mul[2]);
+ if (setjmp (failure)) {
+ if (image)
+ free (image);
+ fclose (ifp);
+ return 100;
+ }
- ri->fuji_width = fuji_width;
+ // Load raw pixels data
+ fseek (ifp, data_offset, SEEK_SET);
+ (*load_raw)();
- for (int a=0; a < 3; a++)
- for (int b=0; b < 3; b++)
- ri->coeff[a][b] = rgb_cam[a][b];
+ // Load embedded profile
+ if (profile_length) {
+ fseek (ifp, profile_offset, SEEK_SET);
+ fread ( this->profile_data, 1, this->profile_len, ifp);
+ }
+ fclose(ifp);
- free (image);
-dcrMutex->unlock ();
+ // copy pixel raw data: the compressed format earns space
+ if (this->filters) {
+ for (int row = 0; row < height; row++)
+ for (int col = 0; col < width; col++)
+ this->data[row][col] = image[row * width + col][FC(row,col)];
+ } else {
+ for (int row = 0; row < height; row++)
+ for (int col = 0; col < width; col++) {
+ this->data[row][3 * col + 0] = image[row * width + col][0];
+ this->data[row][3 * col + 1] = image[row * width + col][1];
+ this->data[row][3 * col + 2] = image[row * width + col][2];
+ }
+ }
+ free(image); // we don't need this anymore
+ }
return 0;
}
+
+
int getRawFileBasicInfo (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int& rotation, int& thumbWidth, int& thumbHeight, int& thumbOffset, int& thumbType) {
int status=0;
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index 4a54fdcee..3a1c2fdf5 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -108,7 +108,7 @@ void Crop::update (int todo, bool internal) {
if (!needsinitupdate)
setCropSizes (rqcropx, rqcropy, rqcropw, rqcroph, skip, true);
PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip);
- parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.hlrecovery, params.icm);
+ parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.hlrecovery, params.icm, params.raw );
if (fabs(params.resize.scale-1.0)<1e-7) {
if (resizeCrop) {
diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc
new file mode 100644
index 000000000..86f08704b
--- /dev/null
+++ b/rtengine/dfmanager.cc
@@ -0,0 +1,353 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace rtengine{
+
+extern Settings* settings;
+
+// *********************** class dfInfo **************************************
+
+inline dfInfo& dfInfo::operator =(const dfInfo &o){
+ pathname = o.pathname;
+ maker = o.maker;
+ model = o.model;
+ iso = o.iso;
+ shutter = o.shutter;
+ timestamp = o.timestamp;
+ if( ri ){
+ delete ri;
+ ri = NULL;
+ }
+ return *this;
+}
+
+bool dfInfo::operator <(const dfInfo &e2) const
+{
+ if( this->maker.compare( e2.maker) >=0 )
+ return false;
+ if( this->model.compare( e2.model) >=0 )
+ return false;
+ if( this->iso >= e2.iso )
+ return false;
+ if( this->shutter >= e2.shutter )
+ return false;
+ if( this->timestamp >= e2.timestamp )
+ return false;
+ return true;
+}
+
+std::string dfInfo::key(const std::string &mak, const std::string &mod, int iso, double shut )
+{
+ std::ostringstream s;
+ s << mak << " " << mod << " ";
+ s.width(5);
+ s << iso << "ISO ";
+ s.precision( 2 );
+ s.width(4);
+ s << shut << "s";
+ return s.str();
+}
+
+double dfInfo::distance(const std::string &mak, const std::string &mod, int iso, double shutter) const
+{
+ if( this->maker.compare( mak) != 0 )
+ return INFINITY;
+ if( this->model.compare( mod) != 0 )
+ return INFINITY;
+ double dISO= (log(this->iso/100.) - log(iso/100.))/log(2);
+ double dShutter = (log(this->shutter) - log(shutter))/log(2);
+ return sqrt( dISO*dISO + dShutter*dShutter);
+}
+
+RawImage* dfInfo::getRawImage()
+{
+ if(ri)
+ return ri;
+ updateRawImage();
+ updateBadPixelList( ri );
+
+ return ri;
+}
+
+std::list& dfInfo::getBadPixels()
+{
+ if( !ri ){
+ updateRawImage();
+ updateBadPixelList( ri );
+ }
+ return badPixels;
+}
+/* updateRawImage() load into ri the actual pixel data from pathname if there is a single shot
+ * otherwise load each file from the pathNames list and extract a template from the media;
+ * the first file is used also for reading all information other than pixels
+ */
+void dfInfo::updateRawImage()
+{
+ typedef unsigned int acc_t;
+ if( pathNames.size() >0 ){
+ std::list::iterator iName = pathNames.begin();
+ ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. )
+ if( ri->loadRaw(true)){
+ delete ri;
+ ri=NULL;
+ }else{
+
+ acc_t **acc = new acc_t*[ri->height];
+ for( int row=0; rowheight;row++)
+ acc[row] = new acc_t[ri->width*(ri->filters?1:3)];
+
+ // copy first image into accumulators
+ for (int row = 0; row < ri->height; row++)
+ for (int col = 0; col < ri->width * (ri->filters ? 1 : 3); col++)
+ acc[row][col] = ri->data[row][col];
+ int nFiles = 1; // First file data already loaded
+
+ for( iName++; iName != pathNames.end(); iName++){
+ RawImage* temp = new RawImage(*iName);
+ if( !temp->loadRaw(true)){
+ nFiles++;
+ if( ri->filters ){
+ for( int row=0; rowheight;row++){
+ for( int col=0; col < ri->width;col++)
+ acc[row][col] += temp->data[row][col];
+ }
+ }else{
+ for( int row=0; rowheight;row++){
+ for( int col=0; col < ri->width;col++){
+ acc[row][3*col+0] += temp->data[row][3*col+0];
+ acc[row][3*col+1] += temp->data[row][3*col+1];
+ acc[row][3*col+2] += temp->data[row][3*col+2];
+ }
+ }
+ }
+ }
+ delete temp;
+ }
+ for (int row = 0; row < ri->height; row++){
+ for (int col = 0; col < ri->width * (ri->filters ? 1 : 3); col++)
+ ri->data[row][col] = acc[row][col] / nFiles;
+ delete [] acc[row];
+ }
+ delete [] acc;
+ }
+ }else{
+ ri = new RawImage(pathname);
+ if( ri->loadRaw(true)){
+ delete ri;
+ ri=NULL;
+ }
+ }
+}
+
+void dfInfo::updateBadPixelList( RawImage *df )
+{
+ const int threshold=10;
+ if( df->filters ){
+ for( int row=2; rowheight-2; row++)
+ for( int col=2; col < df->width-2; col++){
+ int m = (df->data[row-2][col-2] + df->data[row-2][col] + df->data[row-2][col+2]+
+ df->data[row][col-2] + df->data[row][col+2]+
+ df->data[row+2][col-2] + df->data[row+2][col] + df->data[row+2][col+2])/8;
+ if( df->data[row][col]/threshold > m )
+ badPixels.push_back( badPix(col,row) );
+ }
+ }else{
+ for( int row=1; rowheight-1; row++)
+ for( int col=1; col < df->width-1; col++){
+ int m[3];
+ for( int c=0; c<3;c++){
+ m[c] = (df->data[row-1][3*(col-1)+c] + df->data[row-1][3*col+c] + df->data[row-1][3*(col+1)+c]+
+ df->data[row] [3*(col-1)+c] + df->data[row] [3*col+c]+
+ df->data[row+1][3*(col-1)+c] + df->data[row+1][3*col+c] + df->data[row+1][3*(col+1)+c])/8;
+ }
+ if( df->data[row][3*col]/threshold > m[0] || df->data[row][3*col+1]/threshold > m[1] || df->data[row][3*col+2]/threshold > m[2])
+ badPixels.push_back( badPix(col,row) );
+ }
+ }
+ if( settings->verbose ){
+ for (std::list::iterator iter = badPixels.begin(); iter !=badPixels.end(); iter ++)
+ printf( "(%d,%d) ",iter->x, iter->y);
+ printf( "Tot: %d\n", badPixels.size() );
+ }
+}
+
+
+// ************************* class DFManager *********************************
+
+void DFManager::init( Glib::ustring pathname )
+{
+ std::vector names;
+ Glib::RefPtr dir = Gio::File::create_for_path (pathname);
+ if( dir && !dir->query_exists())
+ return;
+ safe_build_file_list (dir, names, pathname);
+
+ dfList.clear();
+ for (int i=0; isecond;
+ if( i.pathNames.size()>0 && !i.pathname.empty() ){
+ i.pathNames.push_back( i.pathname );
+ i.pathname.clear();
+ }
+ if( !i.pathname.empty() )
+ printf( "%s: %s\n",i.key().c_str(),i.pathname.c_str());
+ else{
+ printf( "%s: MEAN of \n ",i.key().c_str());
+ for( std::list::iterator iter = i.pathNames.begin(); iter != i.pathNames.end();iter++ )
+ printf( "%s, ", iter->c_str() );
+ printf("\n");
+ }
+ }
+ currentPath = pathname;
+ return;
+}
+
+bool DFManager::addFileInfo(const Glib::ustring &filename )
+{
+ Glib::RefPtr file = Gio::File::create_for_path(filename);
+ if (!file )
+ return false;
+ if( !file->query_exists())
+ return false;
+ Glib::RefPtr info = safe_query_file_info(file);
+ if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) {
+ int lastdot = info->get_name().find_last_of ('.');
+ if (options.is_extention_enabled(lastdot!=Glib::ustring::npos ? info->get_name().substr (lastdot+1) : "")){
+ RawImage ri(filename);
+ int res = ri.loadRaw(false); // Read informations about shot
+ if( !res ){
+ /* Files are added in the map, divided by same maker/model,ISO and shutter*/
+ std::string key( dfInfo::key(ri.make, ri.model,(int)ri.iso_speed,ri.shutter) );
+ dfList_t::iterator iter = dfList.find( key );
+ if( iter == dfList.end() ){
+ dfInfo n(filename, ri.make, ri.model,(int)ri.iso_speed,ri.shutter,ri.timestamp);
+ dfList.insert(std::pair< std::string,dfInfo>( key,n ) );
+ }else{
+ while( iter != dfList.end() && iter->second.key() == key && ABS(iter->second.timestamp - ri.timestamp) >60*60*6 ) // 6 hour difference
+ iter++;
+
+ if( iter != dfList.end() )
+ iter->second.pathNames.push_back( filename );
+ else{
+ dfInfo n(filename, ri.make, ri.model,(int)ri.iso_speed,ri.shutter,ri.timestamp);
+ dfList.insert(std::pair< std::string,dfInfo>( key,n ) );
+ }
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void DFManager::getStat( int &totFiles, int &totTemplates)
+{
+ totFiles=0;
+ totTemplates=0;
+ for( dfList_t::iterator iter = dfList.begin(); iter != dfList.end();iter++ ){
+ dfInfo &i = iter->second;
+ if( i.pathname.empty() ){
+ totTemplates++;
+ totFiles += i.pathNames.size();
+ }else
+ totFiles++;
+ }
+}
+
+/* The search for the best match is twofold:
+ * if perfect matches for iso and shutter are found, then the list is scanned for lesser distance in time
+ * otherwise if no match is found, the whole list is searched for lesser distance in iso and shutter
+ */
+dfInfo& DFManager::find( const std::string &mak, const std::string &mod, int isospeed, double shut, time_t t )
+{
+ if( dfList.size() == 0 )
+ throw std::exception();
+ std::string key( dfInfo::key(mak,mod,isospeed,shut) );
+ dfList_t::iterator iter = dfList.find( key );
+
+ if( iter != dfList.end() ){
+ dfList_t::iterator bestMatch = iter;
+ time_t bestDeltaTime = ABS(iter->second.timestamp - t);
+ for(iter++; iter != dfList.end() && !key.compare( iter->second.key() ); iter++ ){
+ time_t d = ABS(iter->second.timestamp - t );
+ if( d< bestDeltaTime ){
+ bestMatch = iter;
+ bestDeltaTime = d;
+ }
+ }
+ return bestMatch->second;
+ }else{
+ iter = dfList.begin();
+ dfList_t::iterator bestMatch = iter;
+ double bestD = iter->second.distance( mak, mod, isospeed, shut );
+ for( iter++; iter != dfList.end();iter++ ){
+ double d = iter->second.distance( mak, mod, isospeed, shut );
+ if( d < bestD ){
+ bestD = d;
+ bestMatch = iter;
+ }
+ }
+ return bestMatch->second;
+ }
+}
+
+RawImage* DFManager::searchDarkFrame( const std::string &mak, const std::string &mod, int iso, double shut, time_t t )
+{
+ try{
+ dfInfo &df = find( mak, mod, iso, shut, t );
+ return df.getRawImage();
+ }catch( std::exception e){
+ return NULL;
+ }
+}
+
+RawImage* DFManager::searchDarkFrame( Glib::ustring filename )
+{
+ for ( dfList_t::iterator iter = dfList.begin(); iter != dfList.end();iter++ ){
+ if( iter->second.pathname.compare( filename )==0 )
+ return iter->second.getRawImage();
+ }
+}
+
+std::list DFManager::searchBadPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t )
+{
+ try{
+ dfInfo &df = find( mak, mod, iso, shut, t );
+ return df.getBadPixels();
+ }catch( std::exception e){
+ return std::list();
+ }
+}
+
+// Global variable
+DFManager dfm;
+
+
+}
diff --git a/rtengine/dfmanager.h b/rtengine/dfmanager.h
new file mode 100644
index 000000000..f15070b06
--- /dev/null
+++ b/rtengine/dfmanager.h
@@ -0,0 +1,89 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+#include
+#include
+#include