Solving issue 1103: I can't process my 16MPix images (RT crash because it lacks memory)

This commit is contained in:
natureh
2011-11-08 17:40:09 +01:00
parent 47df7710b0
commit a3c123cd58
5 changed files with 269 additions and 241 deletions

View File

@@ -245,8 +245,15 @@ namespace rtengine {
scale = scales[0]; scale = scales[0];
pitch = pitches[0]; pitch = pitches[0];
// freeing as much memory as possible since the next call to idirpyr will need lots
for(int i = 1; i < maxlevel; i++) {
delete dirpyrLablo[i];
}
idirpyr(dirpyrLablo[0], dst, 0, rangefn_L, nrwt_l, nrwt_ab, pitch, scale, dnparams.luma, dnparams.chroma/*, Lcurve, abcurve*/ ); idirpyr(dirpyrLablo[0], dst, 0, rangefn_L, nrwt_l, nrwt_ab, pitch, scale, dnparams.luma, dnparams.chroma/*, Lcurve, abcurve*/ );
// freeing the last bunch of memory
delete dirpyrLablo[0];
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -271,16 +278,6 @@ namespace rtengine {
} }
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for(int i = 0; i < maxlevel; i++)
{
delete dirpyrLablo[i];
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}; };
void ImProcFunctions::dirpyr(LabImage* data_fine, LabImage* data_coarse, int level, \ void ImProcFunctions::dirpyr(LabImage* data_fine, LabImage* data_coarse, int level, \

View File

@@ -59,7 +59,7 @@ class ImageSource : public InitialImage {
int references; int references;
protected: protected:
cmsHPROFILE embProfile; cmsHPROFILE embProfile;
Glib::ustring fileName; Glib::ustring fileName;
ImageData* idata; ImageData* idata;
@@ -70,8 +70,10 @@ class ImageSource : public InitialImage {
virtual int load (Glib::ustring fname, bool batch = false) =0; virtual int load (Glib::ustring fname, bool batch = false) =0;
virtual void preprocess (const RAWParams &raw){}; virtual void preprocess (const RAWParams &raw){};
virtual void demosaic (const RAWParams &raw){}; virtual void demosaic (const RAWParams &raw){};
virtual void flushRawData (){};
virtual void flushRGB (){};
virtual void HLRecovery_Global (HRecParams hrp){}; virtual void HLRecovery_Global (HRecParams hrp){};
virtual void HLRecovery_inpaint (float** red, float** green, float** blue){}; virtual void HLRecovery_inpaint (float** red, float** green, float** blue){};
virtual bool IsrgbSourceModified() =0; // tracks whether cached rgb output of demosaic has been modified virtual bool IsrgbSourceModified() =0; // tracks whether cached rgb output of demosaic has been modified

View File

@@ -1132,6 +1132,32 @@ void RawImageSource::demosaic(const RAWParams &raw)
} }
} }
void RawImageSource::flushRawData() {
if(cache) {
delete [] cache;
cache = 0;
}
if (rawData) {
freeArray<float>(rawData, H);
rawData = 0;
}
}
void RawImageSource::flushRGB() {
if (green) {
freeArray<float>(green, H);
green = 0;
}
if (red) {
freeArray<float>(red, H);
red = 0;
}
if (blue) {
freeArray<float>(blue, H);
blue = 0;
}
}
void RawImageSource::HLRecovery_Global(HRecParams hrp ) void RawImageSource::HLRecovery_Global(HRecParams hrp )
{ {
//color propagation highlight recovery //color propagation highlight recovery

View File

@@ -102,7 +102,7 @@ class RawImageSource : public ImageSource {
double* cache; double* cache;
int threshold; int threshold;
float** rawData; // holds preprocessed pixel values, data[i][j] corresponds to the ith row and jth column float** rawData; // holds preprocessed pixel values, rowData[i][j] corresponds to the ith row and jth column
// the interpolated green plane: // the interpolated green plane:
float** green; float** green;
@@ -134,10 +134,12 @@ class RawImageSource : public ImageSource {
int load (Glib::ustring fname, bool batch = false); int load (Glib::ustring fname, bool batch = false);
void preprocess (const RAWParams &raw); void preprocess (const RAWParams &raw);
void demosaic (const RAWParams &raw); void demosaic (const RAWParams &raw);
void HLRecovery_Global (HRecParams hrp); void flushRawData ();
void refinement_lassus (); void flushRGB ();
void HLRecovery_Global (HRecParams hrp);
void refinement_lassus ();
bool IsrgbSourceModified() {return rgbSourceModified;} // tracks whether cached rgb output of demosaic has been modified bool IsrgbSourceModified() {return rgbSourceModified;} // tracks whether cached rgb output of demosaic has been modified
void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile ); void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile );
void cfaboxblur (RawImage *riFlatFile, float* cfablur, int boxH, int boxW ); void cfaboxblur (RawImage *riFlatFile, float* cfablur, int boxH, int boxW );

View File

@@ -110,7 +110,6 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm, params.raw); imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm, params.raw);
if (pl) pl->setProgress (0.45); if (pl) pl->setProgress (0.45);
// perform first analysis // perform first analysis
LUTu hist16 (65536); LUTu hist16 (65536);
ipf.firstAnalysis (baseImg, &params, hist16, imgsrc->getGamma()); ipf.firstAnalysis (baseImg, &params, hist16, imgsrc->getGamma());
@@ -145,6 +144,12 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl); ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl);
} }
// at this stage, we can flush the raw data to free up quite an important amount of memory
imgsrc->flushRawData();
// at this stage, we can flush the raw data to free up quite an important amount of memory
imgsrc->flushRGB();
LUTf curve1 (65536,0); LUTf curve1 (65536,0);
LUTf curve2 (65536,0); LUTf curve2 (65536,0);
LUTf curve (65536,0); LUTf curve (65536,0);
@@ -181,15 +186,15 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
ipf.chrominanceCurve (labView, labView, curve1, curve2, satcurve); ipf.chrominanceCurve (labView, labView, curve1, curve2, satcurve);
ipf.vibrance(labView); ipf.vibrance(labView);
ipf.impulsedenoise (labView); ipf.impulsedenoise (labView);
ipf.defringe (labView); ipf.defringe (labView);
ipf.dirpyrdenoise (labView); ipf.dirpyrdenoise (labView);
if (params.sharpenEdge.enabled) { if (params.sharpenEdge.enabled) {
ipf.MLsharpen(labView); ipf.MLsharpen(labView);
} }
if (params.sharpenMicro.enabled) { if (params.sharpenMicro.enabled) {
ipf.MLmicrocontrast (labView); ipf.MLmicrocontrast (labView);
} }
if (params.sharpening.enabled) { if (params.sharpening.enabled) {
float** buffer = new float*[fh]; float** buffer = new float*[fh];
for (int i=0; i<fh; i++) for (int i=0; i<fh; i++)
@@ -216,229 +221,225 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
cw = params.crop.w; cw = params.crop.w;
ch = params.crop.h; ch = params.crop.h;
} }
if(params.icm.gamma != "default" || params.icm.freegamma) if(params.icm.gamma != "default" || params.icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8
{ // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8 //or selected Free gamma
//or selected Free gamma Image16* readyImgP;
Image16* readyImgP; Image16* readyImg = ipf.lab2rgb16b (labView, cx, cy, cw, ch, params.icm.output, params.icm.working, params.icm.gamma, params.icm.freegamma, params.icm.gampos, params.icm.slpos);
Image16* readyImg = ipf.lab2rgb16b (labView, cx, cy, cw, ch, params.icm.output, params.icm.working, params.icm.gamma, params.icm.freegamma, params.icm.gampos, params.icm.slpos); readyImgP=readyImg;
readyImgP=readyImg; delete labView;
delete labView; if (pl) pl->setProgress (0.70);
if (pl) pl->setProgress (0.70); int drapeau=0;
int drapeau=0; // get the resize parameters
// get the resize parameters int refw, refh;
int refw, refh; double tmpScale;
double tmpScale; Glib::ustring chpro, outProfile;
Glib::ustring chpro, outProfile; int present_space[7]={0,0,0,0,0,0,0};
int present_space[7]={0,0,0,0,0,0,0}; std::vector<std::string> opnames = iccStore->getOutputProfiles ();
std::vector<std::string> opnames = iccStore->getOutputProfiles (); //test if files are in system
//test if files are in system for (int j=0; j<7;j++) {
for (int j=0; j<7;j++) { // one can modify "option" [Color Management] to adapt name of profile if there are different for windows, MacOS, Linux ??
// one can modify "option" [Color Management] to adapt name of profile if there are different for windows, MacOS, Linux ?? if(j==0) chpro=options.rtSettings.prophoto;
if(j==0) chpro=options.rtSettings.prophoto; else if(j==1) chpro=options.rtSettings.adobe;
else if(j==1) chpro=options.rtSettings.adobe; else if(j==2) chpro=options.rtSettings.widegamut;
else if(j==2) chpro=options.rtSettings.widegamut; else if(j==3) chpro=options.rtSettings.beta;
else if(j==3) chpro=options.rtSettings.beta; else if(j==4) chpro=options.rtSettings.best;
else if(j==4) chpro=options.rtSettings.best; else if(j==5) chpro=options.rtSettings.bruce;
else if(j==5) chpro=options.rtSettings.bruce; else if(j==6) chpro=options.rtSettings.srgb;
else if(j==6) chpro=options.rtSettings.srgb; for (int i=0; i<opnames.size(); i++) {
for (int i=0; i<opnames.size(); i++){ if(chpro.compare(opnames[i]) ==0) present_space[j]=1;
if(chpro.compare(opnames[i]) ==0) present_space[j]=1; } }
if (present_space[j]==0) { if (present_space[j]==0) {
if (pl) pl->setProgressStr ("Missing file..");pl->setProgress (0.0);// display file not present: not very good display information...!! if (pl) pl->setProgressStr ("Missing file..");
if (settings->verbose) printf("Missing file: %s \n", chpro.c_str());} //c_str() pl->setProgress (0.0);// display file not present: not very good display information...!!
if (settings->verbose) printf("Missing file: %s \n", chpro.c_str());
} //c_str()
} }
// Check that output profiles exist, otherwise use LCMS2 // Check that output profiles exist, otherwise use LCMS2
if (params.icm.working=="ProPhoto" && present_space[0]==1) outProfile=options.rtSettings.prophoto;//in option we can change the name of file - if different... if (params.icm.working=="ProPhoto" && present_space[0]==1) outProfile=options.rtSettings.prophoto;//in option we can change the name of file - if different...
else if (params.icm.working=="Adobe RGB" && present_space[1]==1) outProfile=options.rtSettings.adobe; else if (params.icm.working=="Adobe RGB" && present_space[1]==1) outProfile=options.rtSettings.adobe;
else if (params.icm.working=="WideGamut" && present_space[2]==1) outProfile=options.rtSettings.widegamut; else if (params.icm.working=="WideGamut" && present_space[2]==1) outProfile=options.rtSettings.widegamut;
else if (params.icm.working=="Beta RGB" && present_space[3]==1) outProfile=options.rtSettings.beta; else if (params.icm.working=="Beta RGB" && present_space[3]==1) outProfile=options.rtSettings.beta;
else if (params.icm.working=="BestRGB" && present_space[4]==1) outProfile=options.rtSettings.best; else if (params.icm.working=="BestRGB" && present_space[4]==1) outProfile=options.rtSettings.best;
else if (params.icm.working=="BruceRGB" && present_space[5]==1) outProfile=options.rtSettings.bruce; else if (params.icm.working=="BruceRGB" && present_space[5]==1) outProfile=options.rtSettings.bruce;
else if (params.icm.working== "sRGB" && present_space[6]==1) outProfile=options.rtSettings.srgb; else if (params.icm.working== "sRGB" && present_space[6]==1) outProfile=options.rtSettings.srgb;
//OutProfile become Profile's system //OutProfile become Profile's system
else {if (settings->verbose) printf("No file:%s in system - use LCMS2 substitution\n",params.icm.working.c_str() ); drapeau=1; } else {if (settings->verbose) printf("No file:%s in system - use LCMS2 substitution\n",params.icm.working.c_str() ); drapeau=1; }
if (settings->verbose && drapeau==0) printf("Output profile: %s \n", outProfile.c_str()); //c_str() if (settings->verbose && drapeau==0) printf("Output profile: %s \n", outProfile.c_str()); //c_str()
if (params.resize.enabled) { if (params.resize.enabled) {
if (params.crop.enabled && params.resize.appliesTo == "Cropped area") { if (params.crop.enabled && params.resize.appliesTo == "Cropped area") {
// the resize values applies to the crop dimensions // the resize values applies to the crop dimensions
refw = cw; refw = cw;
refh = ch; refh = ch;
} }
else { else {
// the resize values applies to the image dimensions // the resize values applies to the image dimensions
// if a crop exists, it will be resized to the calculated scale // if a crop exists, it will be resized to the calculated scale
refw = fw; refw = fw;
refh = fh; refh = fh;
} }
switch(params.resize.dataspec) { switch(params.resize.dataspec) {
case (1): case (1):
// Width // Width
tmpScale = (double)params.resize.width/(double)refw; tmpScale = (double)params.resize.width/(double)refw;
break; break;
case (2): case (2):
// Height // Height
tmpScale = (double)params.resize.height/(double)refh; tmpScale = (double)params.resize.height/(double)refh;
break; break;
case (3): case (3):
// FitBox // FitBox
if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height) { if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height)
tmpScale = (double)params.resize.width/(double)refw; tmpScale = (double)params.resize.width/(double)refw;
} else
else { tmpScale = (double)params.resize.height/(double)refh;
tmpScale = (double)params.resize.height/(double)refh; break;
} default:
break; // Scale
default: tmpScale = params.resize.scale;
// Scale break;
tmpScale = params.resize.scale; }
break;
}
// resize image // resize image
if (fabs(tmpScale-1.0)>1e-5) if (fabs(tmpScale-1.0)>1e-5) {
{ int imw, imh;
int imw, imh; if (params.crop.enabled && params.resize.appliesTo == "Full image") {
if (params.crop.enabled && params.resize.appliesTo == "Full image") { imw = cw;
imw = cw; imh = ch;
imh = ch; }
} else {
else { imw = refw;
imw = refw; imh = refh;
imh = refh; }
} imw = (int)( (double)imw * tmpScale + 0.5 );
imw = (int)( (double)imw * tmpScale + 0.5 ); imh = (int)( (double)imh * tmpScale + 0.5 );
imh = (int)( (double)imh * tmpScale + 0.5 ); Image16* tempImage = new Image16 (imw, imh);
Image16* tempImage = new Image16 (imw, imh); ipf.resize (readyImg, tempImage, tmpScale);
ipf.resize (readyImg, tempImage, tmpScale); delete readyImg;
delete readyImg; readyImg = tempImage;
readyImg = tempImage; }
} }
}
if (tunnelMetaData) if (tunnelMetaData)
readyImg->setMetadata (ii->getMetaData()->getExifData ()); readyImg->setMetadata (ii->getMetaData()->getExifData ());
else else
readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);
ProfileContent pc; ProfileContent pc;
if (drapeau==0) pc = iccStore->getContent (outProfile);// use profile in system (Prophoto.icm, sRGB.icm, etc.) if present, otherwise use LCMS2 profile generate by lab2rgb16b if (drapeau==0) pc = iccStore->getContent (outProfile);// use profile in system (Prophoto.icm, sRGB.icm, etc.) if present, otherwise use LCMS2 profile generate by lab2rgb16b
readyImg->setOutputProfile (pc.data, pc.length); readyImg->setOutputProfile (pc.data, pc.length);
delete baseImg; delete baseImg;
if (!job->initialImage) if (!job->initialImage)
ii->decreaseRef (); ii->decreaseRef ();
delete job; delete job;
if (pl) if (pl)
pl->setProgress (0.75); pl->setProgress (0.75);
return readyImg; return readyImg;
} }
else else {
{//if default mode : profil = selection by choice in list (Prophoto.icm, sRGB.icm, etc., etc.) , gamma = gamma of profile or not selected Free gamma //if default mode : profil = selection by choice in list (Prophoto.icm, sRGB.icm, etc., etc.) , gamma = gamma of profile or not selected Free gamma
Image16* readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output); Image16* readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output);
delete labView; delete labView;
if (pl) pl->setProgress (0.70); if (pl) pl->setProgress (0.70);
// get the resize parameters // get the resize parameters
int refw, refh; int refw, refh;
double tmpScale; double tmpScale;
if (params.resize.enabled) { if (params.resize.enabled) {
if (params.crop.enabled && params.resize.appliesTo == "Cropped area") { if (params.crop.enabled && params.resize.appliesTo == "Cropped area") {
// the resize values applies to the crop dimensions // the resize values applies to the crop dimensions
refw = cw; refw = cw;
refh = ch; refh = ch;
} }
else { else {
// the resize values applies to the image dimensions // the resize values applies to the image dimensions
// if a crop exists, it will be resized to the calculated scale // if a crop exists, it will be resized to the calculated scale
refw = fw; refw = fw;
refh = fh; refh = fh;
} }
switch(params.resize.dataspec) { switch(params.resize.dataspec) {
case (1): case (1):
// Width // Width
tmpScale = (double)params.resize.width/(double)refw; tmpScale = (double)params.resize.width/(double)refw;
break; break;
case (2): case (2):
// Height // Height
tmpScale = (double)params.resize.height/(double)refh; tmpScale = (double)params.resize.height/(double)refh;
break; break;
case (3): case (3):
// FitBox // FitBox
if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height) { if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height)
tmpScale = (double)params.resize.width/(double)refw; tmpScale = (double)params.resize.width/(double)refw;
} else
else { tmpScale = (double)params.resize.height/(double)refh;
tmpScale = (double)params.resize.height/(double)refh; break;
} default:
break; // Scale
default: tmpScale = params.resize.scale;
// Scale break;
tmpScale = params.resize.scale; }
break;
}
// resize image // resize image
if (fabs(tmpScale-1.0)>1e-5) if (fabs(tmpScale-1.0)>1e-5) {
{ int imw, imh;
int imw, imh; if (params.crop.enabled && params.resize.appliesTo == "Full image") {
if (params.crop.enabled && params.resize.appliesTo == "Full image") { imw = cw;
imw = cw; imh = ch;
imh = ch; }
} else {
else { imw = refw;
imw = refw; imh = refh;
imh = refh; }
} imw = (int)( (double)imw * tmpScale + 0.5 );
imw = (int)( (double)imw * tmpScale + 0.5 ); imh = (int)( (double)imh * tmpScale + 0.5 );
imh = (int)( (double)imh * tmpScale + 0.5 ); Image16* tempImage = new Image16 (imw, imh);
Image16* tempImage = new Image16 (imw, imh); ipf.resize (readyImg, tempImage, tmpScale);
ipf.resize (readyImg, tempImage, tmpScale); delete readyImg;
delete readyImg; readyImg = tempImage;
readyImg = tempImage; }
} }
}
if (tunnelMetaData) if (tunnelMetaData)
readyImg->setMetadata (ii->getMetaData()->getExifData ()); readyImg->setMetadata (ii->getMetaData()->getExifData ());
else else
readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);
ProfileContent pc; ProfileContent pc;
if (params.icm.output!="" && params.icm.output!=ColorManagementParams::NoICMString) if (params.icm.output!="" && params.icm.output!=ColorManagementParams::NoICMString)
pc = iccStore->getContent (params.icm.output); pc = iccStore->getContent (params.icm.output);
readyImg->setOutputProfile (pc.data, pc.length); readyImg->setOutputProfile (pc.data, pc.length);
delete baseImg; delete baseImg;
if (!job->initialImage) if (!job->initialImage)
ii->decreaseRef (); ii->decreaseRef ();
delete job; delete job;
if (pl) if (pl)
pl->setProgress (0.75); pl->setProgress (0.75);
return readyImg; return readyImg;
} }
} }
void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData) { void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData) {