[Jdlraw-discussion] jdlRaw/Sources jdlDcbDemosaicing.i, NONE, 1.1 jdlConstants.h, 1.14, 1.15 jdlDcR
Status: Beta
Brought to you by:
jdla
|
From: Jos De L. <jd...@us...> - 2010-04-24 17:31:00
|
Update of /cvsroot/jdlraw/jdlRaw/Sources In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv20320/Sources Modified Files: jdlConstants.h jdlDcRaw.cpp jdlDcRaw.h jdlDcRaw.i jdlGuiOptions.cpp jdlMain.cpp jdlMain.h jdlSettings.cpp jdlThumbnailer.cpp Added Files: jdlDcbDemosaicing.i Log Message: *) Rough addition of Jacek Gozdz' DCB demosaicing. Index: jdlMain.cpp =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlMain.cpp,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** jdlMain.cpp 18 Apr 2010 14:26:26 -0000 1.24 --- jdlMain.cpp 24 Apr 2010 17:30:51 -0000 1.25 *************** *** 1734,1737 **** --- 1734,1761 ---- } + void jdlMain::CB_DCBIterations(const QVariant) { + m_TheProcessor->m_TriggerUpdateExifInfoAtEnd = 0; + m_TheProcessor->m_TriggerZoomFitAtEnd = 0; + m_TheProcessor->RunFixed(jdlProcessorPhase_Demosaic); + } + + void jdlMain::CB_DCBEnhance(const QVariant) { + m_TheProcessor->m_TriggerUpdateExifInfoAtEnd = 0; + m_TheProcessor->m_TriggerZoomFitAtEnd = 0; + m_TheProcessor->RunFixed(jdlProcessorPhase_Demosaic); + } + + void jdlMain::CB_FBDD(const QVariant) { + m_TheProcessor->m_TriggerUpdateExifInfoAtEnd = 0; + m_TheProcessor->m_TriggerZoomFitAtEnd = 0; + m_TheProcessor->RunFixed(jdlProcessorPhase_Demosaic); + } + + void jdlMain::CB_BalanceGreens(const QVariant) { + m_TheProcessor->m_TriggerUpdateExifInfoAtEnd = 0; + m_TheProcessor->m_TriggerZoomFitAtEnd = 0; + m_TheProcessor->RunFixed(jdlProcessorPhase_Demosaic); + } + void jdlMain::CB_FourColorRGB(const QVariant) { m_TheProcessor->m_TriggerUpdateExifInfoAtEnd = 0; *************** *** 1835,1838 **** --- 1859,1866 ---- M_Dispatch(Interpolation) M_Dispatch(FourColorRGB) + M_Dispatch(DCBIterations) + M_Dispatch(DCBEnhance) + M_Dispatch(FBDD) + M_Dispatch(BalanceGreens) M_Dispatch(MedianPasses) M_Dispatch(ClipMode) Index: jdlGuiOptions.cpp =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlGuiOptions.cpp,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** jdlGuiOptions.cpp 13 Apr 2010 19:49:11 -0000 1.8 --- jdlGuiOptions.cpp 24 Apr 2010 17:30:51 -0000 1.9 *************** *** 121,124 **** --- 121,125 ---- {jdlInterpolation_PPG, QObject::tr("PPG") }, {jdlInterpolation_AHD, QObject::tr("AHD") }, + {jdlInterpolation_DCB, QObject::tr("DCB") }, {-1,NULL}}; Index: jdlDcRaw.cpp =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlDcRaw.cpp,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** jdlDcRaw.cpp 18 Apr 2010 14:26:26 -0000 1.14 --- jdlDcRaw.cpp 24 Apr 2010 17:30:51 -0000 1.15 *************** *** 61,64 **** --- 61,65 ---- // The class. #define CLASS DcRaw:: + CLASS DcRaw() { // This were the original global variables initialized. *************** *** 73,76 **** --- 74,81 ---- m_UserSetting_HalfSize=0; m_UserSetting_FourColorRGB=0; + m_UserSetting_BalanceGreens=0; + m_UserSetting_DCBIterations=0; + m_UserSetting_DCBEnhance=0; + m_UserSetting_FBDD = 0; m_UserSetting_AutoWb=0; m_UserSetting_CameraWb=0; *************** *** 82,86 **** m_UserSetting_jdlRaw_ClipMode = jdlClipMode_Clip; m_UserSetting_jdlRaw_ClipParameter = 0; ! m_UserSetting_Quality = 3; m_UserSetting_BlackPoint = -1; m_UserSetting_Saturation = -1; --- 87,91 ---- m_UserSetting_jdlRaw_ClipMode = jdlClipMode_Clip; m_UserSetting_jdlRaw_ClipParameter = 0; ! m_UserSetting_Interpolation = 3; m_UserSetting_BlackPoint = -1; m_UserSetting_Saturation = -1; *************** *** 182,186 **** m_Kodak_cbpp = zero_after_ff = m_DNG_Version = m_Load_Flags = 0; m_TimeStamp = m_ShotOrder = m_Tiff_Samples = m_BlackLevel = m_IsFoveon = 0; ! m_MixGreen = m_ProfileLength = data_error = m_ZeroIsBad = 0; m_PixelAspect = m_IsRaw = m_RawColor = 1; m_TileWidth = m_TileLength = INT_MAX; --- 187,191 ---- m_Kodak_cbpp = zero_after_ff = m_DNG_Version = m_Load_Flags = 0; m_TimeStamp = m_ShotOrder = m_Tiff_Samples = m_BlackLevel = m_IsFoveon = 0; ! m_FourColorRGB = m_ProfileLength = data_error = m_ZeroIsBad = 0; m_PixelAspect = m_IsRaw = m_RawColor = 1; m_TileWidth = m_TileLength = INT_MAX; *************** *** 243,252 **** --- 248,284 ---- */ + // + // In the 2X8 assumption, FC returns the color 0..3 on a position(row,col) + // The shift argument for m_Filters is probably better readable as : + // 4*(row & 0b111)+2*(col & 1) : + // 0 2 + // 4 6 + // 8 10 + // 12 14 + // 16 18 + // 20 22 + // 24 26 + // 28 30 + // + // The 32 bit Filter word represents the 8X2=16 times 2 bit color + // representation. + // + #define FC(row,col) \ (m_Filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) + // + // This is then obviously the bayern pattern in the m_Image + // Remark the m_Shrink which is active in half size and + // basically makes interpolation unnecessary. + // + #define BAYER(row,col) \ m_Image[((row) >> m_Shrink)*m_OutWidth + ((col) >> m_Shrink)][FC(row,col)] + // + // Idem for 16X16 patterns, that use then fc function rather than FC above. + // + #define BAYER2(row,col) \ m_Image[((row) >> m_Shrink)*m_OutWidth + ((col) >> m_Shrink)][fc(row,col)] *************** *** 3864,3868 **** // Or restore via HSV, as in ufraw. } else if (jdlClipMode_HSV == ClipMode) { ! // FIXME / TODO : can this not break in some 4 colour modes ? short MaxChannel,MidChannel,MinChannel; if (m_Image[Pos][0] > m_Image[Pos][1] && --- 3896,3900 ---- // Or restore via HSV, as in ufraw. } else if (jdlClipMode_HSV == ClipMode) { ! // FIXME / TODO : can this not break in some 4 color modes ? short MaxChannel,MidChannel,MinChannel; if (m_Image[Pos][0] > m_Image[Pos][1] && *************** *** 3954,3962 **** } ! void CLASS pre_interpolate() ! { ! int row, col; ! TRACEKEYVALS("pre_interpolate","%s",""); if (m_Shrink) { --- 3986,4051 ---- } ! //////////////////////////////////////////////////////////////////////////////// ! // ! // BalanceGreens() ! // This does some bilinear interpolations on the Greens before ! // the actual demosaicing. ! // ! // Niels Kristian Bech Jensen patch ! // ! //////////////////////////////////////////////////////////////////////////////// ! void CLASS BalanceGreens() { ! ! if (m_UserSetting_HalfSize && !m_UserSetting_Detail) return; ! ! TRACEKEYVALS("BalanceGreens","%s",""); ! ! uint16_t* Img = (uint16_t *) CALLOC(m_Width*m_Height, sizeof *Img); ! merror(Img,"BalanceGreens()"); ! ! // Bilinear interpolate G1 and G2 channels at green locations (diagonal only) ! for (uint16_t Row=1; Row<m_Height-1; Row++) { ! uint16_t Col; ! uint16_t Offset; ! short c; ! for (Col=1+(FC(Row,0) & 1), c=FC(Row+1,Col+1), Offset=Row*m_Width+Col; ! Col<m_Width-1; ! Col+=2, Offset+=2) { ! uint16_t Offset1 = Offset - m_Width - 1; ! uint16_t Offset2 = Offset - m_Width + 1; ! uint16_t Offset3 = Offset + m_Width - 1; ! uint16_t Offset4 = Offset + m_Width + 1; ! Img[Offset] = ((m_Image[Offset1][c] + ! m_Image[Offset2][c] + ! m_Image[Offset3][c] + ! m_Image[Offset4][c]) >> 2); ! } ! } ! ! // Mix green channels ! for (uint16_t Row=1; Row<m_Height-1; Row++) { ! uint16_t Col; ! uint16_t Offset; ! short c; ! for (Col=1+(FC(Row,0) & 1), c=FC(Row,Col), Offset=Row*m_Width+Col; ! Col<m_Width-1; ! Col+=2, Offset+=2) { ! m_Image[Offset][c] = ((m_Image[Offset][c] + Img[Offset]) >> 1); ! } ! } ! ! FREE(Img); ! } ! ! //////////////////////////////////////////////////////////////////////////////// ! // ! // PreInterpolate ! // ! //////////////////////////////////////////////////////////////////////////////// ! ! void CLASS PreInterpolate() { ! ! TRACEKEYVALS("PreInterpolate","%s",""); if (m_Shrink) { *************** *** 3973,3985 **** } if (m_Filters && m_Colors == 3) { ! if (m_MixGreen) { m_Colors++; ! } ! else { ! // Seems like making the G1 equal to G2 ! // (and adapting the filter from fi BG1G2R to BGGR) ! for (row = FC(1,0) >> 1; row < m_Height; row+=2) ! for (col = FC(row,1) & 1; col < m_Width; col+=2) m_Image[row*m_Width+col][1] = m_Image[row*m_Width+col][3]; m_Filters &= ~((m_Filters & 0x55555555) << 1); } --- 4062,4077 ---- } if (m_Filters && m_Colors == 3) { ! if (m_FourColorRGB) { ! // Even if this is not a four color camera ! // (as in RGBE) we are going to treat it as a four color one. m_Colors++; ! } else { ! // Make G1 equal to G2. ! for (int row = FC(1,0) >> 1; row < m_Height; row+=2) ! for (int col = FC(row,1) & 1; col < m_Width; col+=2) m_Image[row*m_Width+col][1] = m_Image[row*m_Width+col][3]; + // Complex one, probably done via Karnaugh tables, but + // the result is that in a filter, per 2 bits following occurs : + // 00(R)->00(R) 01(G)->01(G) 10(B)->10(B) 11(G2)->01(G) m_Filters &= ~((m_Filters & 0x55555555) << 1); } *************** *** 4040,4051 **** const uint16_t c_DetailBorder = 2; ! int Code[16][16][32], Sum[4]; TRACEKEYVALS("Bilinear interpolation","%s",""); BorderInterpolate(1); ! // On the 16X16 corner precalculate 'Code'. ! // XXX JDLA : not fully clear : ! // precalculation as where to fetch the neighbours. for (uint16_t Row=0; Row < 16; Row++) { for (uint16_t Col=0; Col < 16; Col++) { --- 4132,4155 ---- const uint16_t c_DetailBorder = 2; ! // 16X16 is a maximum recurrent pattern in the bayer arrays. ! // 32 is an ad hoc coding for each of those positions of : ! // 0 : Where to fetch the neighboring same color for this position. ! // 1 : Shift (Weight) : ! // 0 1 0 ! // 1 X 1 ! // 0 1 0 ! // 2 : Color ! // Above 8 times repeated for the eight neighbours. ! // ! // 25..31 ??? XXX JDLA c,256/Sum[c] , 4 times repeated for the four colours. ! // ! ! int Code[16][16][32]; ! int Sum[4]; TRACEKEYVALS("Bilinear interpolation","%s",""); BorderInterpolate(1); ! // Precalculate Code in the 16x16 array. for (uint16_t Row=0; Row < 16; Row++) { for (uint16_t Col=0; Col < 16; Col++) { *************** *** 4063,4066 **** --- 4167,4171 ---- } } + // XXX JDLA , not fully clear. for (short c=0; c < m_Colors; c++) { if (c != fc(Row,Col)) { *************** *** 4094,4100 **** --- 4199,4208 ---- int *ip = Code[Row & 15][Col & 15]; memset(Sum, 0, sizeof Sum); + // Summing over the 8 neighbours using elements of Code + // i.e. position and weight. for (short i=8; i--; ip+=3) { Sum[ip[2]] += Pix[ip[0]] << ip[1]; } + // Normalization of weight (? XXX JDLA) for (short i=m_Colors; --i; ip+=2) { Pix[ip[0]] = Sum[ip[0]] * ip[1] >> 8; *************** *** 8365,8371 **** // Copied from earlier to here also. // Enables Phase3 to reenter with a different FourColorRGB setting. ! m_MixGreen = m_UserSetting_HalfSize && !m_UserSetting_Detail ? 0 : m_UserSetting_FourColorRGB; assert (!m_IsFoveon); // if (m_IsFoveon ) foveon_interpolate(); --- 8473,8484 ---- // Copied from earlier to here also. // Enables Phase3 to reenter with a different FourColorRGB setting. ! m_FourColorRGB = m_UserSetting_HalfSize && !m_UserSetting_Detail ? 0 : m_UserSetting_FourColorRGB; + // Add on : Balance greens before interpolation. + if (m_UserSetting_BalanceGreens && m_Colors < 4 && !m_IsFoveon) { + BalanceGreens(); + } + assert (!m_IsFoveon); // if (m_IsFoveon ) foveon_interpolate(); *************** *** 8378,8382 **** TRACEKEYVALS("Colors","%d",m_Colors); ! pre_interpolate(); if (m_Stop) return 0; --- 8491,8495 ---- TRACEKEYVALS("Colors","%d",m_Colors); ! PreInterpolate(); if (m_Stop) return 0; *************** *** 8386,8396 **** // Interpolation/demosaicing according to one of the algorithms. if (m_Filters) { ! if (m_UserSetting_Quality == 0) ! LinearInterpolate(); ! else if (m_UserSetting_Quality == 1 || m_Colors > 3) ! VNGInterpolate(); ! else if (m_UserSetting_Quality == 2) ! PPGInterpolate(); ! else AHDInterpolate(); } --- 8499,8522 ---- // Interpolation/demosaicing according to one of the algorithms. if (m_Filters) { ! if (m_UserSetting_FBDD) fbdd(m_UserSetting_FBDD); ! switch (m_UserSetting_Interpolation) { ! case jdlInterpolation_Linear : ! LinearInterpolate(); ! break; ! case jdlInterpolation_VNG : ! VNGInterpolate(); ! break; ! case jdlInterpolation_PPG : ! PPGInterpolate(); ! break; ! case jdlInterpolation_AHD : ! AHDInterpolate(); ! break; ! case jdlInterpolation_DCB : ! DCBInterpolate(m_UserSetting_DCBIterations,m_UserSetting_DCBEnhance); ! break; ! default : ! assert(0); ! } } *************** *** 8425,8429 **** // Green mixing (==m_UserSetting_FourColorRGB); ! if (m_MixGreen) { for (uint32_t i=0; i < (uint32_t) m_Height*m_Width; i++) m_Image[i][1] = ((uint32_t) m_Image[i][1] + m_Image[i][3]) >> 1; --- 8551,8555 ---- // Green mixing (==m_UserSetting_FourColorRGB); ! if (m_FourColorRGB) { for (uint32_t i=0; i < (uint32_t) m_Height*m_Width; i++) m_Image[i][1] = ((uint32_t) m_Image[i][1] + m_Image[i][3]) >> 1; *************** *** 9020,9022 **** --- 9146,9156 ---- //////////////////////////////////////////////////////////////////////////////// + // + // Custom addition dcb_demosaic + // + //////////////////////////////////////////////////////////////////////////////// + + #include "jdlDcbDemosaicing.i" + + //////////////////////////////////////////////////////////////////////////////// Index: jdlConstants.h =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlConstants.h,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** jdlConstants.h 14 Apr 2010 20:09:12 -0000 1.14 --- jdlConstants.h 24 Apr 2010 17:30:51 -0000 1.15 *************** *** 191,194 **** --- 191,195 ---- const short jdlInterpolation_PPG = 2; const short jdlInterpolation_AHD = 3; + const short jdlInterpolation_DCB = 4; // Clip modes; Index: jdlDcRaw.i =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlDcRaw.i,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** jdlDcRaw.i 27 Feb 2010 19:02:41 -0000 1.3 --- jdlDcRaw.i 24 Apr 2010 17:30:51 -0000 1.4 *************** *** 183,186 **** --- 183,214 ---- _("White point in raw")}, + {"Fixed_Interpolation", + "DCBIterations", + jdlGT_Input, + 2, + 1, + 1, + 0, + 0, + 5, + 1, + 0, + _("DCB Iterations"), + _("DCB Iterations")}, + + {"Fixed_Interpolation", + "FBDD", + jdlGT_Input, + 2, + 1, + 1, + 0, + 0, + 2, + 1, + 0, + _("FBDD Denoising"), + _("FBDD Denoising")}, + #endif *************** *** 280,283 **** --- 308,329 ---- {"Fixed_Interpolation", + "DCBEnhance", + jdlGT_Check, + 2, + 1, + 0, + _("Enhance DCB"), + _("Enable DCB Enhancement algorithm")}, + + {"Fixed_Interpolation", + "BalanceGreens", + jdlGT_Check, + 2, + 1, + 0, + _("Balance Greens"), + _("Balance Greens before interpolation")}, + + {"Fixed_Interpolation", "FourColorRGB", jdlGT_Check, Index: jdlDcRaw.h =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlDcRaw.h,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** jdlDcRaw.h 10 Apr 2010 11:52:46 -0000 1.9 --- jdlDcRaw.h 24 Apr 2010 17:30:51 -0000 1.10 *************** *** 152,156 **** // Each of them corresponds roughly to a command line parameter of dcraw. ! // Quality. // Please remark that most probably dcraw implementation and // manual/documentation differ here. --- 152,156 ---- // Each of them corresponds roughly to a command line parameter of dcraw. ! // Interpolation. // Please remark that most probably dcraw implementation and // manual/documentation differ here. *************** *** 164,168 **** // 2 : Use Patterned Pixel Grouping (PPG) interpolation. // 3 : Use Adaptive Homogeneity-Directed (AHD) interpolation. ! short m_UserSetting_Quality; // Output half-size color image. Doubles speed (no interpolation needed) --- 164,168 ---- // 2 : Use Patterned Pixel Grouping (PPG) interpolation. // 3 : Use Adaptive Homogeneity-Directed (AHD) interpolation. ! short m_UserSetting_Interpolation; // Output half-size color image. Doubles speed (no interpolation needed) *************** *** 176,179 **** --- 176,188 ---- short m_UserSetting_FourColorRGB; + // Balance the greens before the interpolation + short m_UserSetting_BalanceGreens; + + // DCB Interpolation paramters + short m_UserSetting_DCBIterations; + short m_UserSetting_DCBEnhance; + // FBDD denoise + short m_UserSetting_FBDD; + // Automatic white balance. The default is to use a fixed color // balance based on a white card photographed in sunlight *************** *** 430,434 **** unsigned m_WhiteLevel; unsigned m_WhiteLevel_AfterPhase1; ! unsigned m_MixGreen; unsigned m_RawColor; unsigned m_ZeroIsBad; --- 439,443 ---- unsigned m_WhiteLevel; unsigned m_WhiteLevel_AfterPhase1; ! unsigned m_FourColorRGB; unsigned m_RawColor; unsigned m_ZeroIsBad; *************** *** 554,558 **** void LinearInterpolate(); void BorderInterpolate(uint16_t border); ! void pre_interpolate(); void hat_transform(float *temp,float *base,int st,int size,int sc); void cam_xyz_coeff(double cam_xyz[4][3]); --- 563,568 ---- void LinearInterpolate(); void BorderInterpolate(uint16_t border); ! void BalanceGreens(); ! void PreInterpolate(); void hat_transform(float *temp,float *base,int st,int size,int sc); void cam_xyz_coeff(double cam_xyz[4][3]); *************** *** 671,674 **** --- 681,707 ---- #endif int fc(int row,int col); + + // Additional stuff for jdlDcbDemosaicing + void dcb_pp(); + void copy_to_buffer(float (*)[3]); + void restore_from_buffer(float (*)[3]); + void hid(); + void hid2(); + void dcb_color(); + void dcb_color_full(); + void dcb_map(); + void dcb_correction(); + void dcb_correction2(); + void dcb_refinement(); + void rgb_to_lch(double (*)[3]); + void lch_to_rgb(double (*)[3]); + void fbdd_green2(); + void fbdd_correction(); + void fbdd_correction2(double (*)[3]); + void fbdd_green(); + void fbdd_color(); + void fbdd(const short FBDD); + void DCBInterpolate(const short Iterations, const short Enhance); + }; Index: jdlMain.h =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlMain.h,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** jdlMain.h 18 Apr 2010 14:26:26 -0000 1.9 --- jdlMain.h 24 Apr 2010 17:30:51 -0000 1.10 *************** *** 169,173 **** --- 169,177 ---- void CB_Interpolation(const QVariant); + void CB_DCBIterations(const QVariant); + void CB_DCBEnhance(const QVariant); + void CB_FBDD(const QVariant); void CB_FourColorRGB(const QVariant); + void CB_BalanceGreens(const QVariant); void CB_MedianPasses(const QVariant); Index: jdlThumbnailer.cpp =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlThumbnailer.cpp,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** jdlThumbnailer.cpp 18 Apr 2010 14:26:26 -0000 1.9 --- jdlThumbnailer.cpp 24 Apr 2010 17:30:51 -0000 1.10 *************** *** 280,284 **** // Interpolation ! TheDcRaw->m_UserSetting_Quality = jdlInterpolation_Linear; // Speed ! // White balance settings. : Just from Camera. --- 280,284 ---- // Interpolation ! TheDcRaw->m_UserSetting_Interpolation = jdlInterpolation_Linear; // Speed ! // White balance settings. : Just from Camera. Index: jdlSettings.cpp =================================================================== RCS file: /cvsroot/jdlraw/jdlRaw/Sources/jdlSettings.cpp,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** jdlSettings.cpp 27 Feb 2010 19:02:42 -0000 1.14 --- jdlSettings.cpp 24 Apr 2010 17:30:51 -0000 1.15 *************** *** 1021,1029 **** // Interpolation ! TheDcRaw->m_UserSetting_Quality = GetInt("Interpolation"); // Four Color RGB TheDcRaw->m_UserSetting_FourColorRGB = GetInt("FourColorRGB"); // White balance settings. switch (GetInt("WhiteBalance")) { --- 1021,1039 ---- // Interpolation ! TheDcRaw->m_UserSetting_Interpolation = GetInt("Interpolation"); // Four Color RGB TheDcRaw->m_UserSetting_FourColorRGB = GetInt("FourColorRGB"); + // DCB settings + TheDcRaw->m_UserSetting_DCBIterations = GetInt("DCBIterations"); + TheDcRaw->m_UserSetting_DCBEnhance = GetInt("DCBEnhance"); + + // FBDD Settings + TheDcRaw->m_UserSetting_FBDD = GetInt("FBDD"); + + // BalanceGreens + TheDcRaw->m_UserSetting_BalanceGreens = GetInt("BalanceGreens"); + // White balance settings. switch (GetInt("WhiteBalance")) { --- NEW FILE: jdlDcbDemosaicing.i --- /* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of the author nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // If you want to use the code, you need to display name of the original authors in // your software! /* DCB demosaicing by Jacek Gozdz (cu...@kf...) * the implementation is not speed optimised * the code is open source (BSD licence) */ /* FBDD denoising by Jacek Gozdz (cu...@kf...) and Luis Sanz RodrÃguez (lui...@gm...) * the implementation is not speed optimised * the code is open source (BSD licence) */ // R and B smoothing using green contrast, all pixels except 2 pixel wide border void CLASS dcb_pp() { int g1, r1, b1, u=m_Width, indx, row, col; for (row=2; row < m_Height-2; row++) for (col=2, indx=row*u+col; col < m_Width-2; col++, indx++) { r1 = ( m_Image[indx-1][0] + m_Image[indx+1][0] + m_Image[indx-u][0] + m_Image[indx+u][0] + m_Image[indx-u-1][0] + m_Image[indx+u+1][0] + m_Image[indx-u+1][0] + m_Image[indx+u-1][0])/8.0; g1 = ( m_Image[indx-1][1] + m_Image[indx+1][1] + m_Image[indx-u][1] + m_Image[indx+u][1] + m_Image[indx-u-1][1] + m_Image[indx+u+1][1] + m_Image[indx-u+1][1] + m_Image[indx+u-1][1])/8.0; b1 = ( m_Image[indx-1][2] + m_Image[indx+1][2] + m_Image[indx-u][2] + m_Image[indx+u][2] + m_Image[indx-u-1][2] + m_Image[indx+u+1][2] + m_Image[indx-u+1][2] + m_Image[indx+u-1][2])/8.0; m_Image[indx][0] = CLIP(r1 + ( m_Image[indx][1] - g1 )); m_Image[indx][2] = CLIP(b1 + ( m_Image[indx][1] - g1 )); } } // saves red and blue void CLASS copy_to_buffer(float (*m_Image2)[3]) { int indx; for (indx=0; indx < m_Height*m_Width; indx++) { m_Image2[indx][0]=m_Image[indx][0]; //R m_Image2[indx][2]=m_Image[indx][2]; //B } } // restores red and blue void CLASS restore_from_buffer(float (*m_Image2)[3]) { int indx; for (indx=0; indx < m_Height*m_Width; indx++) { m_Image[indx][0]=m_Image2[indx][0]; //R m_Image[indx][2]=m_Image2[indx][2]; //B } } // fast green interpolation void CLASS hid() { int row, col, c, u=m_Width, v=2*u, indx; for (row=2; row < m_Height-2; row++) { for (col=2, indx=row*m_Width+col; col < m_Width-2; col++, indx++) { c = fc(row,col); if(c != 1) { m_Image[indx][1] = CLIP((m_Image[indx+u][1] + m_Image[indx-u][1] + m_Image[indx-1][1] + m_Image[indx+1][1])/4.0 + (m_Image[indx][c] - ( m_Image[indx+v][c] + m_Image[indx-v][c] + m_Image[indx-2][c] + m_Image[indx+2][c])/4.0)/2.0); } } } } // green correction void CLASS hid2() { int row, col, c, u=m_Width, v=2*u, indx; for (row=4; row < m_Height-4; row++) { for (col=4, indx=row*m_Width+col; col < m_Width-4; col++, indx++) { c = fc(row,col); if (c != 1) { m_Image[indx][1] = CLIP((m_Image[indx+v][1] + m_Image[indx-v][1] + m_Image[indx-2][1] + m_Image[indx+2][1])/4.0 + m_Image[indx][c] - ( m_Image[indx+v][c] + m_Image[indx-v][c] + m_Image[indx-2][c] + m_Image[indx+2][c])/4.0); } } } } // missing colors are interpolated void CLASS dcb_color() { int row, col, c, d, u=m_Width, indx; for (row=1; row < m_Height-1; row++) for (col=1+(FC(row,1) & 1), indx=row*m_Width+col, c=2-FC(row,col); col < u-1; col+=2, indx+=2) { m_Image[indx][c] = CLIP(( 4*m_Image[indx][1] - m_Image[indx+u+1][1] - m_Image[indx+u-1][1] - m_Image[indx-u+1][1] - m_Image[indx-u-1][1] + m_Image[indx+u+1][c] + m_Image[indx+u-1][c] + m_Image[indx-u+1][c] + m_Image[indx-u-1][c] )/4.0); } for (row=1; row<m_Height-1; row++) for (col=1+(FC(row,2)&1), indx=row*m_Width+col,c=FC(row,col+1),d=2-c; col<m_Width-1; col+=2, indx+=2) { m_Image[indx][c] = CLIP((2*m_Image[indx][1] - m_Image[indx+1][1] - m_Image[indx-1][1] + m_Image[indx+1][c] + m_Image[indx-1][c])/2.0); m_Image[indx][d] = CLIP((2*m_Image[indx][1] - m_Image[indx+u][1] - m_Image[indx-u][1] + m_Image[indx+u][d] + m_Image[indx-u][d])/2.0); } } // missing colors are interpolated using high quality algorithm by Luis Sanz RodrÃguez void CLASS dcb_color_full() { int row,col,c,d,u=m_Width,w=3*u,indx; float f[4],g[4],(*chroma)[2]; chroma = (float (*)[2]) calloc(m_Width*m_Height,sizeof *chroma); merror (chroma, "dcb_color_full()"); for (row=1; row < m_Height-1; row++) for (col=1+(FC(row,1)&1),indx=row*m_Width+col,c=FC(row,col),d=c/2; col < u-1; col+=2,indx+=2) chroma[indx][d]=m_Image[indx][c]-m_Image[indx][1]; for (row=3; row<m_Height-3; row++) for (col=3+(FC(row,1)&1),indx=row*m_Width+col,c=1-FC(row,col)/2,d=1-c; col<u-3; col+=2,indx+=2) { f[0]=1.0/(float)(1.0+fabs(chroma[indx-u-1][c]-chroma[indx+u+1][c])+fabs(chroma[indx-u-1][c]-chroma[indx-w-3][c])+fabs(chroma[indx+u+1][c]-chroma[indx-w-3][c])); f[1]=1.0/(float)(1.0+fabs(chroma[indx-u+1][c]-chroma[indx+u-1][c])+fabs(chroma[indx-u+1][c]-chroma[indx-w+3][c])+fabs(chroma[indx+u-1][c]-chroma[indx-w+3][c])); f[2]=1.0/(float)(1.0+fabs(chroma[indx+u-1][c]-chroma[indx-u+1][c])+fabs(chroma[indx+u-1][c]-chroma[indx+w+3][c])+fabs(chroma[indx-u+1][c]-chroma[indx+w-3][c])); f[3]=1.0/(float)(1.0+fabs(chroma[indx+u+1][c]-chroma[indx-u-1][c])+fabs(chroma[indx+u+1][c]-chroma[indx+w-3][c])+fabs(chroma[indx-u-1][c]-chroma[indx+w+3][c])); g[0]=1.325*chroma[indx-u-1][c]-0.175*chroma[indx-w-3][c]-0.075*chroma[indx-w-1][c]-0.075*chroma[indx-u-3][c]; g[1]=1.325*chroma[indx-u+1][c]-0.175*chroma[indx-w+3][c]-0.075*chroma[indx-w+1][c]-0.075*chroma[indx-u+3][c]; g[2]=1.325*chroma[indx+u-1][c]-0.175*chroma[indx+w-3][c]-0.075*chroma[indx+w-1][c]-0.075*chroma[indx+u-3][c]; g[3]=1.325*chroma[indx+u+1][c]-0.175*chroma[indx+w+3][c]-0.075*chroma[indx+w+1][c]-0.075*chroma[indx+u+3][c]; chroma[indx][c]=(f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3]); } for (row=3; row<m_Height-3; row++) for (col=3+(FC(row,2)&1),indx=row*m_Width+col,c=FC(row,col+1)/2; col<u-3; col+=2,indx+=2) for(d=0;d<=1;c=1-c,d++){ f[0]=1.0/(float)(1.0+fabs(chroma[indx-u][c]-chroma[indx+u][c])+fabs(chroma[indx-u][c]-chroma[indx-w][c])+fabs(chroma[indx+u][c]-chroma[indx-w][c])); f[1]=1.0/(float)(1.0+fabs(chroma[indx+1][c]-chroma[indx-1][c])+fabs(chroma[indx+1][c]-chroma[indx+3][c])+fabs(chroma[indx-1][c]-chroma[indx+3][c])); f[2]=1.0/(float)(1.0+fabs(chroma[indx-1][c]-chroma[indx+1][c])+fabs(chroma[indx-1][c]-chroma[indx-3][c])+fabs(chroma[indx+1][c]-chroma[indx-3][c])); f[3]=1.0/(float)(1.0+fabs(chroma[indx+u][c]-chroma[indx-u][c])+fabs(chroma[indx+u][c]-chroma[indx+w][c])+fabs(chroma[indx-u][c]-chroma[indx+w][c])); g[0]=0.875*chroma[indx-u][c]+0.125*chroma[indx-w][c]; g[1]=0.875*chroma[indx+1][c]+0.125*chroma[indx+3][c]; g[2]=0.875*chroma[indx-1][c]+0.125*chroma[indx-3][c]; g[3]=0.875*chroma[indx+u][c]+0.125*chroma[indx+w][c]; chroma[indx][c]=(f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3]); } for(row=3; row<m_Height-3; row++) for(col=3,indx=row*m_Width+col; col<m_Width-3; col++,indx++){ m_Image[indx][0]=CLIP(chroma[indx][0]+m_Image[indx][1]); m_Image[indx][2]=CLIP(chroma[indx][1]+m_Image[indx][1]); } free(chroma); } // green is used to create // an interpolation direction map // 1 = vertical // 0 = horizontal // saved in m_Image[][3] void CLASS dcb_map() { int row, col, u=m_Width, indx; for (row=2; row < m_Height-2; row++) { for (col=2, indx=row*m_Width+col; col < m_Width-2; col++, indx++) { if (m_Image[indx][1] > ( m_Image[indx-1][1] + m_Image[indx+1][1] + m_Image[indx-u][1] + m_Image[indx+u][1])/4.0) m_Image[indx][3] = ((MIN( m_Image[indx-1][1], m_Image[indx+1][1]) + m_Image[indx-1][1] + m_Image[indx+1][1] ) < (MIN( m_Image[indx-u][1], m_Image[indx+u][1]) + m_Image[indx-u][1] + m_Image[indx+u][1])); else m_Image[indx][3] = ((MAX( m_Image[indx-1][1], m_Image[indx+1][1]) + m_Image[indx-1][1] + m_Image[indx+1][1] ) > (MAX( m_Image[indx-u][1], m_Image[indx+u][1]) + m_Image[indx-u][1] + m_Image[indx+u][1])) ; } } } // interpolated green pixels are corrected using the map void CLASS dcb_correction() { int current, row, col, c, u=m_Width, v=2*u, indx; for (row=4; row < m_Height-4; row++) { for (col=4, indx=row*m_Width+col; col < m_Width-4; col++, indx++) { c = FC(row,col); if (c != 1) { current = 4*m_Image[indx][3] + 2*(m_Image[indx+u][3] + m_Image[indx-u][3] + m_Image[indx+1][3] + m_Image[indx-1][3]) + m_Image[indx+v][3] + m_Image[indx-v][3] + m_Image[indx+2][3] + m_Image[indx-2][3]; m_Image[indx][1] = ((16-current)*(m_Image[indx-1][1] + m_Image[indx+1][1])/2.0 + current*(m_Image[indx-u][1] + m_Image[indx+u][1])/2.0)/16.0; } } } } // interpolated green pixels are corrected using the map // with correction void CLASS dcb_correction2() { int current, row, col, c, u=m_Width, v=2*u, indx; for (row=4; row < m_Height-4; row++) { for (col=4, indx=row*m_Width+col; col < m_Width-4; col++, indx++) { c = FC(row,col); if (c != 1) { current = 4*m_Image[indx][3] + 2*(m_Image[indx+u][3] + m_Image[indx-u][3] + m_Image[indx+1][3] + m_Image[indx-1][3]) + m_Image[indx+v][3] + m_Image[indx-v][3] + m_Image[indx+2][3] + m_Image[indx-2][3]; m_Image[indx][1] = CLIP(((16-current)*((m_Image[indx-1][1] + m_Image[indx+1][1])/2.0 + m_Image[indx][c] - (m_Image[indx+2][c] + m_Image[indx-2][c])/2.0) + current*((m_Image[indx-u][1] + m_Image[indx+u][1])/2.0 + m_Image[indx][c] - (m_Image[indx+v][c] + m_Image[indx-v][c])/2.0))/16.0); } } } } // m_Image refinement void CLASS dcb_refinement() { int row, col, c, u=m_Width, v=2*u,indx, max, min; float f[4], g[4]; for (row=5; row < m_Height-5; row++) for (col=5+(FC(row,1)&1),indx=row*m_Width+col,c=FC(row,col); col < u-5; col+=2,indx+=2) { // Cubic Spline Interpolation by Li and Randhawa, modified by Jacek Gozdz and Luis Sanz RodrÃguez f[0]=1.0/(1.0+abs(m_Image[indx-u][c]-m_Image[indx][c])+abs(m_Image[indx-u][1]-m_Image[indx][1])); f[1]=1.0/(1.0+abs(m_Image[indx+1][c]-m_Image[indx][c])+abs(m_Image[indx+1][1]-m_Image[indx][1])); f[2]=1.0/(1.0+abs(m_Image[indx-1][c]-m_Image[indx][c])+abs(m_Image[indx-1][1]-m_Image[indx][1])); f[3]=1.0/(1.0+abs(m_Image[indx+u][c]-m_Image[indx][c])+abs(m_Image[indx+u][1]-m_Image[indx][1])); g[0]=CLIP(m_Image[indx-u][1]+0.5*(m_Image[indx][c]-m_Image[indx-u][c]) + 0.25*(m_Image[indx][c]-m_Image[indx-v][c])); g[1]=CLIP(m_Image[indx+1][1]+0.5*(m_Image[indx][c]-m_Image[indx+1][c]) + 0.25*(m_Image[indx][c]-m_Image[indx+2][c])); g[2]=CLIP(m_Image[indx-1][1]+0.5*(m_Image[indx][c]-m_Image[indx-1][c]) + 0.25*(m_Image[indx][c]-m_Image[indx-2][c])); g[3]=CLIP(m_Image[indx+u][1]+0.5*(m_Image[indx][c]-m_Image[indx+u][c]) + 0.25*(m_Image[indx][c]-m_Image[indx+v][c])); m_Image[indx][1]=CLIP(((f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3]) )); // get rid of the overshooted pixels min = MIN(m_Image[indx+1+u][1], MIN(m_Image[indx+1-u][1], MIN(m_Image[indx-1+u][1], MIN(m_Image[indx-1-u][1], MIN(m_Image[indx-1][1], MIN(m_Image[indx+1][1], MIN(m_Image[indx-u][1], m_Image[indx+u][1]))))))); max = MAX(m_Image[indx+1+u][1], MAX(m_Image[indx+1-u][1], MAX(m_Image[indx-1+u][1], MAX(m_Image[indx-1-u][1], MAX(m_Image[indx-1][1], MAX(m_Image[indx+1][1], MAX(m_Image[indx-u][1], m_Image[indx+u][1]))))))); m_Image[indx][1] = ULIM(m_Image[indx][1], max, min); } } /* m_Image[indx][0] = CLIP(65536.0*(1.0 - (1.0-m_Image[indx][0]/65536.0)*(1.0-m_Image[indx][0]/65536.0))); m_Image[indx][1] = CLIP(65536.0*(1.0 - (1.0-m_Image[indx][1]/65536.0)*(1.0-m_Image[indx][1]/65536.0))); m_Image[indx][2] = CLIP(65536.0*(1.0 - (1.0-m_Image[indx][2]/65536.0)*(1.0-m_Image[indx][2]/65536.0))); */ // converts RGB to LCH colorspace and saves it to m_Image3 void CLASS rgb_to_lch(double (*m_Image3)[3]) { int indx; for (indx=0; indx < m_Height*m_Width; indx++) { m_Image3[indx][0] = m_Image[indx][0] + m_Image[indx][1] + m_Image[indx][2]; // L m_Image3[indx][1] = 1.732050808 *(m_Image[indx][0] - m_Image[indx][1]); // C m_Image3[indx][2] = 2.0*m_Image[indx][2] - m_Image[indx][0] - m_Image[indx][1]; // H } } // converts LCH to RGB colorspace and saves it back to m_Image void CLASS lch_to_rgb(double (*m_Image3)[3]) { int indx; for (indx=0; indx < m_Height*m_Width; indx++) { m_Image[indx][0] = CLIP(m_Image3[indx][0] / 3.0 - m_Image3[indx][2] / 6.0 + m_Image3[indx][1] / 3.464101615); m_Image[indx][1] = CLIP(m_Image3[indx][0] / 3.0 - m_Image3[indx][2] / 6.0 - m_Image3[indx][1] / 3.464101615); m_Image[indx][2] = CLIP(m_Image3[indx][0] / 3.0 + m_Image3[indx][2] / 3.0); } } // fast green interpolation void CLASS fbdd_green2() { int row, col, c, u=m_Width, v=2*u, w=3*u, indx, current, min, max, g1, g2; for (row=4; row < m_Height-4; row++) { for (col=4, indx=row*m_Width+col; col < m_Width-4; col++, indx++) { c = fc(row,col); if(c != 1) { current = m_Image[indx][c] - (m_Image[indx+v][c] + m_Image[indx-v][c] + m_Image[indx-2][c] + m_Image[indx+2][c])/4.0; g2 = (m_Image[indx+u][1] + m_Image[indx-u][1] + m_Image[indx-1][1] + m_Image[indx+1][1])/4.0; g1 = (m_Image[indx+w][1] + m_Image[indx-w][1] + m_Image[indx-3][1] + m_Image[indx+3][1])/4.0; m_Image[indx][1] = CLIP((g2+g1)/2.0 + current); min = MIN(m_Image[indx-1][1], MIN(m_Image[indx+1][1], MIN(m_Image[indx-u][1], m_Image[indx+u][1]))); max = MAX(m_Image[indx-1][1], MAX(m_Image[indx+1][1], MAX(m_Image[indx-u][1], m_Image[indx+u][1]))); m_Image[indx][1] = ULIM(m_Image[indx][1], max, min); } } } } // denoising using interpolated neighbours void CLASS fbdd_correction() { int row, col, c, u=m_Width, indx; for (row=2; row < m_Height-2; row++) { for (col=2, indx=row*m_Width+col; col < m_Width-2; col++, indx++) { c = fc(row,col); m_Image[indx][c] = ULIM(m_Image[indx][c], MAX(m_Image[indx-1][c], MAX(m_Image[indx+1][c], MAX(m_Image[indx-u][c], m_Image[indx+u][c]))), MIN(m_Image[indx-1][c], MIN(m_Image[indx+1][c], MIN(m_Image[indx-u][c], m_Image[indx+u][c])))); } } } // corrects chroma noise void CLASS fbdd_correction2(double (*m_Image3)[3]) { int indx, v=2*m_Width; double Co, Ho, ratio; for (indx=2+v; indx < m_Height*m_Width-(2+v); indx++) { if ( m_Image3[indx][1]*m_Image3[indx][2] != 0 ) { Co = (m_Image3[indx+v][1] + m_Image3[indx-v][1] + m_Image3[indx-2][1] + m_Image3[indx+2][1] - MAX(m_Image3[indx-2][1], MAX(m_Image3[indx+2][1], MAX(m_Image3[indx-v][1], m_Image3[indx+v][1]))) - MIN(m_Image3[indx-2][1], MIN(m_Image3[indx+2][1], MIN(m_Image3[indx-v][1], m_Image3[indx+v][1]))))/2.0; Ho = (m_Image3[indx+v][2] + m_Image3[indx-v][2] + m_Image3[indx-2][2] + m_Image3[indx+2][2] - MAX(m_Image3[indx-2][2], MAX(m_Image3[indx+2][2], MAX(m_Image3[indx-v][2], m_Image3[indx+v][2]))) - MIN(m_Image3[indx-2][2], MIN(m_Image3[indx+2][2], MIN(m_Image3[indx-v][2], m_Image3[indx+v][2]))))/2.0; ratio = sqrt ((Co*Co+Ho*Ho) / (m_Image3[indx][1]*m_Image3[indx][1] + m_Image3[indx][2]*m_Image3[indx][2])); if (ratio < 0.85){ m_Image3[indx][1] = Co; m_Image3[indx][2] = Ho; } } } } // Cubic Spline Interpolation by Li and Randhawa, modified by Jacek Gozdz and Luis Sanz RodrÃguez void CLASS fbdd_green() { int row, col, c, u=m_Width, v=2*u, w=3*u, x=4*u, y=5*u, indx, min, max; float f[4], g[4]; for (row=5; row < m_Height-5; row++) for (col=5+(FC(row,1)&1),indx=row*m_Width+col,c=FC(row,col); col < u-5; col+=2,indx+=2) { f[0]=1.0/(1.0+abs(m_Image[indx-u][1]-m_Image[indx-w][1])+abs(m_Image[indx-w][1]-m_Image[indx+y][1])); f[1]=1.0/(1.0+abs(m_Image[indx+1][1]-m_Image[indx+3][1])+abs(m_Image[indx+3][1]-m_Image[indx-5][1])); f[2]=1.0/(1.0+abs(m_Image[indx-1][1]-m_Image[indx-3][1])+abs(m_Image[indx-3][1]-m_Image[indx+5][1])); f[3]=1.0/(1.0+abs(m_Image[indx+u][1]-m_Image[indx+w][1])+abs(m_Image[indx+w][1]-m_Image[indx-y][1])); g[0]=CLIP((23*m_Image[indx-u][1]+23*m_Image[indx-w][1]+2*m_Image[indx-y][1]+8*(m_Image[indx-v][c]-m_Image[indx-x][c])+40*(m_Image[indx][c]-m_Image[indx-v][c]))/48.0); g[1]=CLIP((23*m_Image[indx+1][1]+23*m_Image[indx+3][1]+2*m_Image[indx+5][1]+8*(m_Image[indx+2][c]-m_Image[indx+4][c])+40*(m_Image[indx][c]-m_Image[indx+2][c]))/48.0); g[2]=CLIP((23*m_Image[indx-1][1]+23*m_Image[indx-3][1]+2*m_Image[indx-5][1]+8*(m_Image[indx-2][c]-m_Image[indx-4][c])+40*(m_Image[indx][c]-m_Image[indx-2][c]))/48.0); g[3]=CLIP((23*m_Image[indx+u][1]+23*m_Image[indx+w][1]+2*m_Image[indx+y][1]+8*(m_Image[indx+v][c]-m_Image[indx+x][c])+40*(m_Image[indx][c]-m_Image[indx+v][c]))/48.0); m_Image[indx][1]=CLIP((f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3])); min = MIN(m_Image[indx+1+u][1], MIN(m_Image[indx+1-u][1], MIN(m_Image[indx-1+u][1], MIN(m_Image[indx-1-u][1], MIN(m_Image[indx-1][1], MIN(m_Image[indx+1][1], MIN(m_Image[indx-u][1], m_Image[indx+u][1]))))))); max = MAX(m_Image[indx+1+u][1], MAX(m_Image[indx+1-u][1], MAX(m_Image[indx-1+u][1], MAX(m_Image[indx-1-u][1], MAX(m_Image[indx-1][1], MAX(m_Image[indx+1][1], MAX(m_Image[indx-u][1], m_Image[indx+u][1]))))))); m_Image[indx][1] = ULIM(m_Image[indx][1], max, min); } } // red and blue interpolation by Luis Sanz RodrÃguez void CLASS fbdd_color() { int row,col,c,d,u=m_Width,w=3*u,indx,(*chroma)[2]; float f[4]; chroma = (int (*)[2]) calloc(m_Width*m_Height,sizeof *chroma); merror (chroma, "fbdd_color2()"); for (row=2; row < m_Height-2; row++) for (col=2+(FC(row,2)&1),indx=row*m_Width+col,c=FC(row,col),d=c/2; col<u-2; col+=2,indx+=2) chroma[indx][d]=m_Image[indx][c]-m_Image[indx][1]; for (row=3; row<m_Height-3; row++) for (col=3+(FC(row,1)&1),indx=row*m_Width+col,d=1-FC(row,col)/2,c=2*d; col<u-3; col+=2,indx+=2) { f[0]=1.0/(1.0+abs(chroma[indx-u-1][d]-chroma[indx+u+1][d])+abs(chroma[indx-u-1][d]-chroma[indx-w-3][d])+abs(chroma[indx+u+1][d]-chroma[indx-w-3][d])); f[1]=1.0/(1.0+abs(chroma[indx-u+1][d]-chroma[indx+u-1][d])+abs(chroma[indx-u+1][d]-chroma[indx-w+3][d])+abs(chroma[indx+u-1][d]-chroma[indx-w+3][d])); f[2]=1.0/(1.0+abs(chroma[indx+u-1][d]-chroma[indx-u+1][d])+abs(chroma[indx+u-1][d]-chroma[indx+w+3][d])+abs(chroma[indx-u+1][d]-chroma[indx+w-3][d])); f[3]=1.0/(1.0+abs(chroma[indx+u+1][d]-chroma[indx-u-1][d])+abs(chroma[indx+u+1][d]-chroma[indx+w-3][d])+abs(chroma[indx-u-1][d]-chroma[indx+w+3][d])); chroma[indx][d]=(f[0]*chroma[indx-u-1][d]+f[1]*chroma[indx-u+1][d]+f[2]*chroma[indx+u-1][d]+f[3]*chroma[indx+u+1][d])/(f[0]+f[1]+f[2]+f[3]); m_Image[indx][c]=CLIP(chroma[indx][d]+m_Image[indx][1]); } for (row=3; row<m_Height-3; row++) for (col=3+(FC(row,2)&1),indx=row*m_Width+col; col<u-3; col+=2,indx+=2) for(c=d=0;d<=1;c+=2,d++){ f[0]=1.0/(1.0+abs(chroma[indx-u][d]-chroma[indx+u][d])+abs(chroma[indx-u][d]-chroma[indx-w][d])+abs(chroma[indx+u][d]-chroma[indx-w][d])); f[1]=1.0/(1.0+abs(chroma[indx+1][d]-chroma[indx-1][d])+abs(chroma[indx+1][d]-chroma[indx+3][d])+abs(chroma[indx-1][d]-chroma[indx+3][d])); f[2]=1.0/(1.0+abs(chroma[indx-1][d]-chroma[indx+1][d])+abs(chroma[indx-1][d]-chroma[indx-3][d])+abs(chroma[indx+1][d]-chroma[indx-3][d])); f[3]=1.0/(1.0+abs(chroma[indx+u][d]-chroma[indx-u][d])+abs(chroma[indx+u][d]-chroma[indx+w][d])+abs(chroma[indx-u][d]-chroma[indx+w][d])); m_Image[indx][c]=CLIP((f[0]*chroma[indx-u][d]+f[1]*chroma[indx+1][d]+f[2]*chroma[indx-1][d]+f[3]*chroma[indx+u][d])/(f[0]+f[1]+f[2]+f[3])+m_Image[indx][1]); } free(chroma); } // FBDD (Fake Before Demosaicing Denoising) void CLASS fbdd(const short noiserd) { double (*m_Image3)[3]; m_Image3 = (double (*)[3]) calloc(m_Width*m_Height, sizeof *m_Image3); BorderInterpolate(4); if (noiserd>1) { TRACEKEYVALS("FBDD full noise rduction","%s",""); fbdd_green(); fbdd_color(); fbdd_correction(); dcb_color(); rgb_to_lch(m_Image3); fbdd_correction2(m_Image3); fbdd_correction2(m_Image3); lch_to_rgb(m_Image3); fbdd_green(); fbdd_color(); fbdd_correction(); } else { TRACEKEYVALS("FBDD noise reduction","%s",""); fbdd_green(); fbdd_color(); fbdd_correction(); } } // DCB demosaicing main routine (sharp version) void CLASS DCBInterpolate(const short Iterations, const short dcb_enhance) { float (*m_Image2)[3]; m_Image2 = (float (*)[3]) calloc(m_Width*m_Height, sizeof *m_Image2); TRACEKEYVALS("DCB demosaicing","%s",""); BorderInterpolate(2); copy_to_buffer(m_Image2); hid(); dcb_color(); for (short i=0; i<Iterations; i++) { TRACEKEYVALS("DCB correction pass","%d",i); hid2(); hid2(); hid2(); dcb_map(); dcb_correction(); } dcb_color(); dcb_pp(); hid2(); hid2(); hid2(); TRACEKEYVALS("Finishing DCB","%s",""); dcb_map(); dcb_correction2(); restore_from_buffer(m_Image2); dcb_map(); dcb_correction(); dcb_color(); dcb_pp(); dcb_map(); dcb_correction(); dcb_map(); dcb_correction(); restore_from_buffer(m_Image2); dcb_color(); if (dcb_enhance) { TRACEKEYVALS("Optional DCB refinement","%s",""); dcb_refinement(); dcb_color_full(); } free(m_Image2); } |