From a3c123cd58aabd81d83b121d895442bcd7733b75 Mon Sep 17 00:00:00 2001 From: natureh Date: Tue, 8 Nov 2011 17:40:09 +0100 Subject: [PATCH] Solving issue 1103: I can't process my 16MPix images (RT crash because it lacks memory) --- rtengine/dirpyrLab_denoise.cc | 21 +- rtengine/imagesource.h | 14 +- rtengine/rawimagesource.cc | 26 ++ rtengine/rawimagesource.h | 14 +- rtengine/simpleprocess.cc | 435 +++++++++++++++++----------------- 5 files changed, 269 insertions(+), 241 deletions(-) diff --git a/rtengine/dirpyrLab_denoise.cc b/rtengine/dirpyrLab_denoise.cc index bba868369..5aec19fc1 100644 --- a/rtengine/dirpyrLab_denoise.cc +++ b/rtengine/dirpyrLab_denoise.cc @@ -245,9 +245,16 @@ namespace rtengine { scale = scales[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*/ ); - - + + // 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, \ diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 637b5f286..757c6f1ca 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -59,7 +59,7 @@ class ImageSource : public InitialImage { int references; protected: - cmsHPROFILE embProfile; + cmsHPROFILE embProfile; Glib::ustring fileName; ImageData* idata; @@ -70,9 +70,11 @@ class ImageSource : public InitialImage { virtual int load (Glib::ustring fname, bool batch = false) =0; virtual void preprocess (const RAWParams &raw){}; virtual void demosaic (const RAWParams &raw){}; + virtual void flushRawData (){}; + virtual void flushRGB (){}; 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 void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hlp, ColorManagementParams cmp, RAWParams raw) {} @@ -81,9 +83,9 @@ class ImageSource : public InitialImage { virtual ColorTemp getSpotWB (std::vector red, std::vector green, std::vector& blue, int tran) =0; virtual double getDefGain () { return 1.0; } - + virtual double getGamma () { return 0.0; } - + virtual void getFullSize (int& w, int& h, int tr = TR_NONE) {} virtual void getSize (int tran, PreviewProps pp, int& w, int& h) {} @@ -96,7 +98,7 @@ class ImageSource : public InitialImage { virtual void getAutoExpHistogram (LUTu & histogram, int& histcompr)=0; virtual void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) { histRedRaw.clear(); histGreenRaw.clear(); histBlueRaw.clear(); // only some sources will supply this - } + } // functions inherited from the InitialImage interface virtual Glib::ustring getFileName () { return fileName; } diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index ed9697215..c3e668cbf 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1132,6 +1132,32 @@ void RawImageSource::demosaic(const RAWParams &raw) } } +void RawImageSource::flushRawData() { + if(cache) { + delete [] cache; + cache = 0; + } + if (rawData) { + freeArray(rawData, H); + rawData = 0; + } +} + +void RawImageSource::flushRGB() { + if (green) { + freeArray(green, H); + green = 0; + } + if (red) { + freeArray(red, H); + red = 0; + } + if (blue) { + freeArray(blue, H); + blue = 0; + } +} + void RawImageSource::HLRecovery_Global(HRecParams hrp ) { //color propagation highlight recovery diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 48e0e3a4d..7636a8767 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -102,7 +102,7 @@ class RawImageSource : public ImageSource { double* cache; 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: float** green; @@ -134,15 +134,17 @@ class RawImageSource : public ImageSource { int load (Glib::ustring fname, bool batch = false); void preprocess (const RAWParams &raw); void demosaic (const RAWParams &raw); - void HLRecovery_Global (HRecParams hrp); - void refinement_lassus (); + void flushRawData (); + 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 cfaboxblur (RawImage *riFlatFile, float* cfablur, int boxH, int boxW ); void scaleColors (int winx,int winy,int winw,int winh, const RAWParams &raw);// raw for cblack - + void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw); ColorTemp getWB () { return wb; } ColorTemp getAutoWB (); @@ -151,7 +153,7 @@ class RawImageSource : public ImageSource { double getDefGain () { return defGain; } double getGamma () { return CurveFactory::sRGBGamma; } - + void getFullSize (int& w, int& h, int tr = TR_NONE); void getSize (int tran, PreviewProps pp, int& w, int& h); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index dc53d11aa..b94cd620a 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -110,7 +110,6 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm, params.raw); if (pl) pl->setProgress (0.45); - // perform first analysis LUTu hist16 (65536); ipf.firstAnalysis (baseImg, ¶ms, 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); } + // 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 curve2 (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.vibrance(labView); - ipf.impulsedenoise (labView); + ipf.impulsedenoise (labView); ipf.defringe (labView); - ipf.dirpyrdenoise (labView); + ipf.dirpyrdenoise (labView); if (params.sharpenEdge.enabled) { ipf.MLsharpen(labView); - } + } if (params.sharpenMicro.enabled) { - ipf.MLmicrocontrast (labView); - } + ipf.MLmicrocontrast (labView); + } if (params.sharpening.enabled) { float** buffer = new float*[fh]; for (int i=0; isetProgress (0.70); - int drapeau=0; - // get the resize parameters - int refw, refh; - double tmpScale; - Glib::ustring chpro, outProfile; - int present_space[7]={0,0,0,0,0,0,0}; - std::vector opnames = iccStore->getOutputProfiles (); - //test if files are in system - 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 ?? - if(j==0) chpro=options.rtSettings.prophoto; - else if(j==1) chpro=options.rtSettings.adobe; - else if(j==2) chpro=options.rtSettings.widegamut; - else if(j==3) chpro=options.rtSettings.beta; - else if(j==4) chpro=options.rtSettings.best; - else if(j==5) chpro=options.rtSettings.bruce; - else if(j==6) chpro=options.rtSettings.srgb; - for (int i=0; isetProgressStr ("Missing file..");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() + if(params.icm.gamma != "default" || params.icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8 + //or selected Free gamma + 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); + readyImgP=readyImg; + delete labView; + if (pl) pl->setProgress (0.70); + int drapeau=0; + // get the resize parameters + int refw, refh; + double tmpScale; + Glib::ustring chpro, outProfile; + int present_space[7]={0,0,0,0,0,0,0}; + std::vector opnames = iccStore->getOutputProfiles (); + //test if files are in system + 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 ?? + if(j==0) chpro=options.rtSettings.prophoto; + else if(j==1) chpro=options.rtSettings.adobe; + else if(j==2) chpro=options.rtSettings.widegamut; + else if(j==3) chpro=options.rtSettings.beta; + else if(j==4) chpro=options.rtSettings.best; + else if(j==5) chpro=options.rtSettings.bruce; + else if(j==6) chpro=options.rtSettings.srgb; + for (int i=0; isetProgressStr ("Missing file.."); + 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 - 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=="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=="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== "sRGB" && present_space[6]==1) outProfile=options.rtSettings.srgb; - //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; } - - if (settings->verbose && drapeau==0) printf("Output profile: %s \n", outProfile.c_str()); //c_str() - + // 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... + 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=="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=="BruceRGB" && present_space[5]==1) outProfile=options.rtSettings.bruce; + else if (params.icm.working== "sRGB" && present_space[6]==1) outProfile=options.rtSettings.srgb; + //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; } - if (params.resize.enabled) { - - if (params.crop.enabled && params.resize.appliesTo == "Cropped area") { - // the resize values applies to the crop dimensions - refw = cw; - refh = ch; - } - else { - // the resize values applies to the image dimensions - // if a crop exists, it will be resized to the calculated scale - refw = fw; - refh = fh; - } - - switch(params.resize.dataspec) { - case (1): - // Width - tmpScale = (double)params.resize.width/(double)refw; - break; - case (2): - // Height - tmpScale = (double)params.resize.height/(double)refh; - break; - case (3): - // FitBox - if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height) { - tmpScale = (double)params.resize.width/(double)refw; - } - else { - tmpScale = (double)params.resize.height/(double)refh; - } - break; - default: - // Scale - tmpScale = params.resize.scale; - break; - } - - // resize image - if (fabs(tmpScale-1.0)>1e-5) - { - int imw, imh; - if (params.crop.enabled && params.resize.appliesTo == "Full image") { - imw = cw; - imh = ch; - } - else { - imw = refw; - imh = refh; - } - imw = (int)( (double)imw * tmpScale + 0.5 ); - imh = (int)( (double)imh * tmpScale + 0.5 ); - Image16* tempImage = new Image16 (imw, imh); - ipf.resize (readyImg, tempImage, tmpScale); - delete readyImg; - readyImg = tempImage; - } - } + if (settings->verbose && drapeau==0) printf("Output profile: %s \n", outProfile.c_str()); //c_str() - if (tunnelMetaData) - readyImg->setMetadata (ii->getMetaData()->getExifData ()); - else - readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); - + if (params.resize.enabled) { - 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 - - readyImg->setOutputProfile (pc.data, pc.length); - - delete baseImg; - - if (!job->initialImage) - ii->decreaseRef (); + if (params.crop.enabled && params.resize.appliesTo == "Cropped area") { + // the resize values applies to the crop dimensions + refw = cw; + refh = ch; + } + else { + // the resize values applies to the image dimensions + // if a crop exists, it will be resized to the calculated scale + refw = fw; + refh = fh; + } - delete job; - if (pl) - pl->setProgress (0.75); - - return readyImg; - } - 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 - Image16* readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output); - delete labView; - if (pl) pl->setProgress (0.70); + switch(params.resize.dataspec) { + case (1): + // Width + tmpScale = (double)params.resize.width/(double)refw; + break; + case (2): + // Height + tmpScale = (double)params.resize.height/(double)refh; + break; + case (3): + // FitBox + if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height) + tmpScale = (double)params.resize.width/(double)refw; + else + tmpScale = (double)params.resize.height/(double)refh; + break; + default: + // Scale + tmpScale = params.resize.scale; + break; + } - // get the resize parameters - int refw, refh; - double tmpScale; - - if (params.resize.enabled) { - - if (params.crop.enabled && params.resize.appliesTo == "Cropped area") { - // the resize values applies to the crop dimensions - refw = cw; - refh = ch; - } - else { - // the resize values applies to the image dimensions - // if a crop exists, it will be resized to the calculated scale - refw = fw; - refh = fh; - } - - switch(params.resize.dataspec) { - case (1): - // Width - tmpScale = (double)params.resize.width/(double)refw; - break; - case (2): - // Height - tmpScale = (double)params.resize.height/(double)refh; - break; - case (3): - // FitBox - if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height) { - tmpScale = (double)params.resize.width/(double)refw; - } - else { - tmpScale = (double)params.resize.height/(double)refh; - } - break; - default: - // Scale - tmpScale = params.resize.scale; - break; - } - - // resize image - if (fabs(tmpScale-1.0)>1e-5) - { - int imw, imh; - if (params.crop.enabled && params.resize.appliesTo == "Full image") { - imw = cw; - imh = ch; - } - else { - imw = refw; - imh = refh; - } - imw = (int)( (double)imw * tmpScale + 0.5 ); - imh = (int)( (double)imh * tmpScale + 0.5 ); - Image16* tempImage = new Image16 (imw, imh); - ipf.resize (readyImg, tempImage, tmpScale); - delete readyImg; - readyImg = tempImage; - } - } + // resize image + if (fabs(tmpScale-1.0)>1e-5) { + int imw, imh; + if (params.crop.enabled && params.resize.appliesTo == "Full image") { + imw = cw; + imh = ch; + } + else { + imw = refw; + imh = refh; + } + imw = (int)( (double)imw * tmpScale + 0.5 ); + imh = (int)( (double)imh * tmpScale + 0.5 ); + Image16* tempImage = new Image16 (imw, imh); + ipf.resize (readyImg, tempImage, tmpScale); + delete readyImg; + readyImg = tempImage; + } + } - if (tunnelMetaData) - readyImg->setMetadata (ii->getMetaData()->getExifData ()); - else - readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); - + if (tunnelMetaData) + readyImg->setMetadata (ii->getMetaData()->getExifData ()); + else + readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); - ProfileContent pc; - if (params.icm.output!="" && params.icm.output!=ColorManagementParams::NoICMString) - pc = iccStore->getContent (params.icm.output); - - readyImg->setOutputProfile (pc.data, pc.length); - - delete baseImg; - - if (!job->initialImage) - ii->decreaseRef (); - delete job; - if (pl) - pl->setProgress (0.75); - - return readyImg; - - } + 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 + + readyImg->setOutputProfile (pc.data, pc.length); + + delete baseImg; + + if (!job->initialImage) + ii->decreaseRef (); + + delete job; + if (pl) + pl->setProgress (0.75); + + return readyImg; + } + 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 + Image16* readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output); + delete labView; + if (pl) pl->setProgress (0.70); + + // get the resize parameters + int refw, refh; + double tmpScale; + + if (params.resize.enabled) { + + if (params.crop.enabled && params.resize.appliesTo == "Cropped area") { + // the resize values applies to the crop dimensions + refw = cw; + refh = ch; + } + else { + // the resize values applies to the image dimensions + // if a crop exists, it will be resized to the calculated scale + refw = fw; + refh = fh; + } + + switch(params.resize.dataspec) { + case (1): + // Width + tmpScale = (double)params.resize.width/(double)refw; + break; + case (2): + // Height + tmpScale = (double)params.resize.height/(double)refh; + break; + case (3): + // FitBox + if ((double)refw/(double)refh > (double)params.resize.width/(double)params.resize.height) + tmpScale = (double)params.resize.width/(double)refw; + else + tmpScale = (double)params.resize.height/(double)refh; + break; + default: + // Scale + tmpScale = params.resize.scale; + break; + } + + // resize image + if (fabs(tmpScale-1.0)>1e-5) { + int imw, imh; + if (params.crop.enabled && params.resize.appliesTo == "Full image") { + imw = cw; + imh = ch; + } + else { + imw = refw; + imh = refh; + } + imw = (int)( (double)imw * tmpScale + 0.5 ); + imh = (int)( (double)imh * tmpScale + 0.5 ); + Image16* tempImage = new Image16 (imw, imh); + ipf.resize (readyImg, tempImage, tmpScale); + delete readyImg; + readyImg = tempImage; + } + } + + + if (tunnelMetaData) + readyImg->setMetadata (ii->getMetaData()->getExifData ()); + else + readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); + + + ProfileContent pc; + if (params.icm.output!="" && params.icm.output!=ColorManagementParams::NoICMString) + pc = iccStore->getContent (params.icm.output); + + readyImg->setOutputProfile (pc.data, pc.length); + + delete baseImg; + + if (!job->initialImage) + ii->decreaseRef (); + + delete job; + if (pl) + pl->setProgress (0.75); + + return readyImg; + + } } void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData) {