From b86d108d0b80e8e06c97ad5d886efa1e0e6dab40 Mon Sep 17 00:00:00 2001 From: torger Date: Fri, 20 Jun 2014 15:19:20 +0200 Subject: [PATCH] Added support for monochrome cameras (like Leica Monochrome) and IR-modified bayer cameras through new demosaicer "mono" --- rtengine/demosaic_algos.cc | 9 ++- rtengine/improccoordinator.cc | 2 +- rtengine/procparams.cc | 2 +- rtengine/procparams.h | 2 +- rtengine/rawimage.cc | 22 +++++++- rtengine/rawimagesource.cc | 100 +++++++++++++++++++++++++++------- rtengine/rawimagesource.h | 10 +--- rtengine/rtthumbnail.cc | 41 +++++++++++--- 8 files changed, 147 insertions(+), 41 deletions(-) diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 08922adb4..8de8d9074 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -2351,17 +2351,22 @@ void RawImageSource::ahd_demosaic(int winx, int winy, int winw, int winh) } #undef TS -void RawImageSource::nodemosaic() +void RawImageSource::nodemosaic(bool bw) { red(W,H); green(W,H); blue(W,H); +#pragma omp parallel for for (int i=0; i WBParams::wbEntries; diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 14792d859..e4948a1ea 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -778,7 +778,7 @@ class RAWParams { public: // enum eMethod{eahd,hphd,vng4,dcb,amaze,ahd,IGV_noise,fast, // numMethods }; // This MUST be the last enum - enum eMethod{amaze,igv,lmmse,eahd,hphd,vng4,dcb,ahd,fast,none, + enum eMethod{amaze,igv,lmmse,eahd,hphd,vng4,dcb,ahd,fast,mono,none, numMethods }; // This MUST be the last enum static const char *methodstring[numMethods]; diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 010d8f438..5056105b8 100755 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -129,6 +129,9 @@ skip_block2: ; for(int c=0;c<4;c++) dsum[c] -= cblack_[c] * dsum[c+4]; + } else if (colors == 1) { + for (int c = 0; c < 4; c++) + pre_mul_[c] = 1; } else { for (row = 0; row < H; row += 8) for (col = 0; col < W ; col += 8) { @@ -181,6 +184,10 @@ skip_block: ; if (pre_mul_[3] == 0) pre_mul_[3] = this->get_colors() < 4 ? pre_mul_[1] : 1; + if (colors == 1) + for (c = 1; c < 4; c++) + cblack_[c] = cblack_[0]; + bool multiple_whites = false; int largest_white = this->get_white(0); for (c = 1; c < 4; c++) { @@ -209,7 +216,7 @@ skip_block: ; } for (c = 0; c < 4; c++) { - int sat = this->get_white(c) - this->get_cblack(c); + int sat = this->get_white(c) - cblack_[c]; scale_mul_[c] = (pre_mul_[c] /= dmax) * 65535.0 / sat; } if (settings->verbose) { @@ -428,6 +435,14 @@ float** RawImage::compress_image() for (int i = 0; i < height; i++) data[i] = allocation + i * width; } + } else if (colors == 1) { + // Monochrome + if (!allocation) { + allocation = new float[height * width]; + data = new float*[height]; + for (int i = 0; i < height; i++) + data[i] = allocation + i * width; + } } else { if (!allocation) { allocation = new float[3 * height * width]; @@ -450,6 +465,11 @@ float** RawImage::compress_image() 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 if (colors == 1) { + #pragma omp parallel for + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) + this->data[row][col] = image[row * width + col][0]; } else { #pragma omp parallel for for (int row = 0; row < height; row++) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index b4e8bc1df..0900fa850 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -204,18 +204,24 @@ void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &s //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% static float -calculate_scale_mul(float scale_mul[4], const float pre_mul_[4], const float c_white[4], const float c_black[4]) +calculate_scale_mul(float scale_mul[4], const float pre_mul_[4], const float c_white[4], const float c_black[4], const RAWParams &raw, int colors) { - float pre_mul[4]; - for (int c = 0; c < 4; c++) { - pre_mul[c] = pre_mul_[c]; // G2 == G1 - } - if (pre_mul[3] == 0) { - pre_mul[3] = pre_mul[1]; - } - float maxpremul = max(pre_mul[0], pre_mul[1], pre_mul[2], pre_mul[3]); - for (int c = 0; c < 4; c++) { - scale_mul[c] = (pre_mul[c] / maxpremul) * 65535.0 / (c_white[c] - c_black[c]); + if (raw.dmethod == RAWParams::methodstring[RAWParams::mono] || colors == 1) { + for (int c = 0; c < 4; c++) { + scale_mul[c] = 65535.0 / (c_white[c] - c_black[c]); + } + } else { + float pre_mul[4]; + for (int c = 0; c < 4; c++) { + pre_mul[c] = pre_mul_[c]; + } + if (pre_mul[3] == 0) { + pre_mul[3] = pre_mul[1]; // G2 == G1 + } + float maxpremul = max(pre_mul[0], pre_mul[1], pre_mul[2], pre_mul[3]); + for (int c = 0; c < 4; c++) { + scale_mul[c] = (pre_mul[c] / maxpremul) * 65535.0 / (c_white[c] - c_black[c]); + } } float gain = max(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); return gain; @@ -239,7 +245,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre // adjust gain so the maximum raw value of the least scaled channel just hits max const float new_pre_mul[4] = { ri->get_pre_mul(0) / rm, ri->get_pre_mul(1) / gm, ri->get_pre_mul(2) / bm, ri->get_pre_mul(3) / gm }; float new_scale_mul[4]; - float gain = calculate_scale_mul(new_scale_mul, new_pre_mul, c_white, cblacksom); + float gain = calculate_scale_mul(new_scale_mul, new_pre_mul, c_white, cblacksom, raw, ri->get_colors()); rm = new_scale_mul[0] / scale_mul[0] * gain; gm = new_scale_mul[1] / scale_mul[1] * gain; bm = new_scale_mul[2] / scale_mul[2] * gain; @@ -314,7 +320,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre #pragma omp for #endif for (int ix=0; ix=maxy-skip) i=maxy-skip-1; // avoid trouble - if (ri->isBayer()) { + if (ri->isBayer() || ri->get_colors() == 1) { for (int j=0,jx=sx1; j=maxx-skip) jx=maxx-skip-1; // avoid trouble float rtot,gtot,btot; rtot=gtot=btot=0; @@ -1177,15 +1183,20 @@ void RawImageSource::demosaic(const RAWParams &raw) lmmse_interpolate_omp(W,H,raw.lmmse_iterations); else if (raw.dmethod == RAWParams::methodstring[RAWParams::fast] ) fast_demosaic (0,0,W,H); - //nodemosaic();//for testing - else - nodemosaic(); + else if (raw.dmethod == RAWParams::methodstring[RAWParams::mono] ) + nodemosaic(true); + else + nodemosaic(false); t2.set(); if( settings->verbose ) printf("Demosaicing: %s - %d usec\n",raw.dmethod.c_str(), t2.etime(t1)); //if (raw.all_enhance) refinement_lassus(); + rgbSourceModified = false; + } else if (ri->get_colors() == 1) { + // Monochrome + nodemosaic(true); rgbSourceModified = false; } } @@ -1333,6 +1344,23 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw } // flatfield + } else if (ri->get_colors() == 1) { + // Monochrome + if (!rawData) rawData(W,H); + + if (riDark && W == riDark->get_width() && H == riDark->get_height()) { + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + rawData[row][col] = max(src->data[row][col]+black[0] - riDark->data[row][col], 0.0f); + } + } + } else { + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + rawData[row][col] = src->data[row][col]; + } + } + } } else { // No bayer pattern // TODO: Is there a flat field correction possible? @@ -1544,7 +1572,7 @@ void RawImageSource::scaleColors(int winx,int winy,int winw,int winh, const RAWP black_lev[3]=raw.blackthree;//G2 (only used with a Bayer filter) for(int i=0; i<4 ;i++) cblacksom[i] = max( c_black[i]+black_lev[i], 0.0f ); // adjust black level - initialGain = calculate_scale_mul(scale_mul, ref_pre_mul, c_white, cblacksom); // recalculate scale colors with adjusted levels + initialGain = calculate_scale_mul(scale_mul, ref_pre_mul, c_white, cblacksom, raw, ri->get_colors()); // recalculate scale colors with adjusted levels //fprintf(stderr, "recalc: %f [%f %f %f %f]\n", initialGain, scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); // this seems strange, but it works @@ -1576,6 +1604,26 @@ void RawImageSource::scaleColors(int winx,int winy,int winw,int winh, const RAWP chmax[1] = max(tmpchmax[1],chmax[1]); chmax[2] = max(tmpchmax[2],chmax[2]); } +} + }else if ( ri->get_colors() == 1 ) { +#pragma omp parallel +{ + float tmpchmax = 0.0f; + +#pragma omp for nowait + for (int row = winy; row < winy+winh; row ++){ + for (int col = winx; col < winx+winw; col++) { + float val = rawData[row][col]; + val -= cblacksom[0]; + val *= scale_mul[0]; + rawData[row][col] = (val); + tmpchmax = max(tmpchmax,val); + } + } +#pragma omp critical +{ + chmax[0] = chmax[1] = chmax[2] = chmax[3] = max(tmpchmax,chmax[0]); +} } }else{ #pragma omp parallel @@ -1849,7 +1897,7 @@ lab2ProphotoRgbD50(float L, float A, float B, float& r, float& g, float& b) } // Converts raw image including ICC input profile to working space - floating point version -void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams &cmp, ColorTemp &wb, double pre_mul[3], float rawWhitePoint, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], const std::string &camName) { +void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParams &cmp, ColorTemp &wb, double pre_mul[3], const RAWParams &raw, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], const std::string &camName) { //MyTime t1, t2, t3; //t1.set (); @@ -1862,7 +1910,7 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams if (dcpProf!=NULL) { // DCP processing - dcpProf->Apply(im, cmp.dcpIlluminant, cmp.working, wb, pre_mul, camMatrix, rawWhitePoint, cmp.toneCurve); + dcpProf->Apply(im, cmp.dcpIlluminant, cmp.working, wb, pre_mul, camMatrix, raw.expos, cmp.toneCurve); return; } @@ -2528,6 +2576,10 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) { else if (ri->ISRED(i,j)) tmphistogram[CLIP((int)(refwb_red* rawData[i][j]))>>histcompr]+=4; else if (ri->ISBLUE(i,j)) tmphistogram[CLIP((int)(refwb_blue* rawData[i][j]))>>histcompr]+=4; } + } else if (ri->get_colors() == 1) { + for (int j=start; j>histcompr]++; + } } else { for (int j=start; j>histcompr]++; @@ -2586,6 +2638,12 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU if(jdata[i][j]]++; } + } else if (ri->get_colors() == 1) { + for (int j=start; jdata[i][j]]++; + } + } } else { for (int j=start; jget_colors() == 1) { + rm = gm = bm = 1; + return; + } if (redAWBMul != -1.) { rm = redAWBMul; gm = greenAWBMul; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 6b60cae5d..a5d438a09 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -68,7 +68,7 @@ class RawImageSource : public ImageSource { static LUTf invGrad; // for fast_demosaic static LUTf initInvGrad (); static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in); - static void colorSpaceConversion (Imagefloat* im, ColorManagementParams &cmp, ColorTemp &wb, double pre_mul[3], float rawWhitePoint, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName); + static void colorSpaceConversion_ (Imagefloat* im, ColorManagementParams &cmp, ColorTemp &wb, double pre_mul[3], const RAWParams &raw, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName); protected: MyMutex getImageMutex; // locks getImage @@ -180,12 +180,8 @@ class RawImageSource : public ImageSource { void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw); void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb, RAWParams raw); - //static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName); - static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName) { - colorSpaceConversion (im, cmp, wb, pre_mul, 0.0f, embedded, camprofile, cam, camName); - } static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, ColorTemp &wb, double pre_mul[3], RAWParams raw, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName) { - colorSpaceConversion (im, cmp, wb, pre_mul, float(raw.expos), embedded, camprofile, cam, camName); + colorSpaceConversion_ (im, cmp, wb, pre_mul, raw, embedded, camprofile, cam, camName); } static void inverse33 (const double (*coeff)[3], double (*icoeff)[3]); @@ -228,7 +224,7 @@ class RawImageSource : public ImageSource { void green_equilibrate (float greenthresh);//Emil's green equilibration - void nodemosaic(); + void nodemosaic(bool bw); void eahd_demosaic(); void hphd_demosaic(); void vng4_demosaic(); diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 74d34a94f..50202dfb2 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -325,6 +325,15 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati tmpImg->b(y,x) = b; } } + } else if (ri->get_colors() == 1) { + for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) { + rofs = row * width; + for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col + += hskip, x++) { + int ofs = rofs + col; + tmpImg->r(y,x) = tmpImg->g(y,x) = tmpImg->b(y,x) = image[ofs][0]; + } + } } else { for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) { rofs = row * width; @@ -398,13 +407,21 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati start = 8; end = width - 8; } - for (int j = start; j < end; j++) - if (FISGREEN(filter,i,j)) - tpp->aeHistogram[((int)(tpp->camwbGreen*image[i* width+j][1]))>>tpp->aeHistCompression]+=gadd; - else if (FISRED(filter,i,j)) - tpp->aeHistogram[((int)(tpp->camwbRed * image[i* width+j][0]))>>tpp->aeHistCompression]+=radd; - else if (FISBLUE(filter,i,j)) - tpp->aeHistogram[((int)(tpp->camwbBlue *image[i* width+j][2]))>>tpp->aeHistCompression]+=badd; + if (ri->get_colors() == 1) { + for (int j = start; j < end; j++) { + tpp->aeHistogram[((int)(image[i* width+j][0]))>>tpp->aeHistCompression]+=radd; + tpp->aeHistogram[((int)(image[i* width+j][0]))>>tpp->aeHistCompression]+=gadd; + tpp->aeHistogram[((int)(image[i* width+j][0]))>>tpp->aeHistCompression]+=badd; + } + } else { + for (int j = start; j < end; j++) + if (FISGREEN(filter,i,j)) + tpp->aeHistogram[((int)(tpp->camwbGreen*image[i* width+j][1]))>>tpp->aeHistCompression]+=gadd; + else if (FISRED(filter,i,j)) + tpp->aeHistogram[((int)(tpp->camwbRed * image[i* width+j][0]))>>tpp->aeHistCompression]+=radd; + else if (FISBLUE(filter,i,j)) + tpp->aeHistogram[((int)(tpp->camwbBlue *image[i* width+j][2]))>>tpp->aeHistCompression]+=badd; + } } // generate autoWB @@ -426,7 +443,13 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati end = width - 32; } for (int j = start; j < end; j++) { - if (FISGREEN(filter,i,j)) { + if (!filter) { + double d = tpp->defGain * image[i * width + j][0]; + if (d > 64000.) + continue; + avg_g += d; avg_r += d; avg_b += d; + rn++; gn++; bn++; + } else if (FISGREEN(filter,i,j)) { double d = tpp->defGain * image[i * width + j][1]; if (d > 64000.) continue; @@ -673,7 +696,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei // perform color space transformation if (isRaw) { double pre_mul[3] = { redMultiplier, greenMultiplier, blueMultiplier }; - RawImageSource::colorSpaceConversion (baseImg, params.icm, currWB, pre_mul, embProfile, camProfile, cam2xyz, camName ); + RawImageSource::colorSpaceConversion (baseImg, params.icm, currWB, pre_mul, params.raw, embProfile, camProfile, cam2xyz, camName ); } else { StdImageSource::colorSpaceConversion (baseImg, params.icm, embProfile, thumbImg->getSampleFormat()); }