#include "stdafx.h" #include "type.h" #include #include #include "Ccnlv.h" /////////////////////////////////////////////////////////// //Construct/Destruct/////////////////////////////////////// // -------------------------------------------------------- // Description: Construct - default Ccnlv::Ccnlv () // -------------------------------------------------------- { m_pKern = NULL; m_iKrnWid = 0; m_iRc = 0; m_sRc.Empty(); } // -------------------------------------------------------- // Description: Destruct - default Ccnlv::~Ccnlv() // -------------------------------------------------------- { Empty(); } // -------------------------------------------------------- // Description: Empty object of image void Ccnlv::Empty() // -------------------------------------------------------- { if ( m_pKern ) delete m_pKern; m_pKern = NULL; m_iKrnWid = 0; m_iRc = 0; m_sRc.Empty(); } // -------------------------------------------------------- // Description: Is the object empty? // // Return: TRUE if object is empty // FALSE if object is not empty bool Ccnlv::IsEmpty() // -------------------------------------------------------- { if ( m_pKern ) return false; else return true; } /////////////////////////////////////////////////////////// // Initialization ////////////////////////////////////////// // -------------------------------------------------------- // Description: Create kernel as specified // // Input: Type of kernel desired // Output: A kernel containing numerics as specified. // // Return: TRUE if success // (-) upon error int Ccnlv::SetKernel ( int iType ) //[in] kernel type // -------------------------------------------------------- { int i; m_iKrnWid = 3; if ( m_pKern ) delete m_pKern; m_pKern = new double[m_iKrnWid*m_iKrnWid]; memset ( &m_pKern[0], 0, sizeof(double)*m_iKrnWid*m_iKrnWid ); // Create Kernel switch (iType) { case LAPLACIAN: m_pKern[1] = -1; m_pKern[3] = -1; m_pKern[5] = -1; m_pKern[7] = -1; m_pKern[4] = 4; break; case SOBEL_X: m_pKern[0] = -1; m_pKern[2] = 1; m_pKern[3] = -2; m_pKern[5] = 2; m_pKern[6] = -1; m_pKern[8] = 1; break; case SOBEL_Y: m_pKern[0] = -1; m_pKern[1] = -2; m_pKern[2] = -1; m_pKern[6] = 1; m_pKern[7] = 2; m_pKern[8] = 1; break; case ROBERTS_45: m_pKern[0] = 1; m_pKern[4] = -1; break; case ROBERTS_135: m_pKern[2] = 1; m_pKern[4] = -1; break; case PREWITT_X: m_pKern[0] = -1; m_pKern[2] = 1; m_pKern[3] = -1; m_pKern[5] = 1; m_pKern[6] = -1; m_pKern[8] = 1; break; case PREWITT_Y: m_pKern[0] = -1; m_pKern[1] = -1; m_pKern[2] = -1; m_pKern[6] = 1; m_pKern[7] = 1; m_pKern[8] = 1; break; case LOW_PASS: case UNSHARP_MASK: delete m_pKern; m_iKrnWid = 5; m_pKern = new double[m_iKrnWid*m_iKrnWid]; for ( i = 0; i < m_iKrnWid*m_iKrnWid; i ++ ) m_pKern[i] = 1; break; case HIGH_PASS: for ( i = 0; i < m_iKrnWid*m_iKrnWid; i ++ ) m_pKern[i] = -1; m_pKern[4] = 8; break; default: // Not recognized m_sRc.Insert ( 0, "Ccnlv::CreateKernel() - Bad Type\n" ); return ( m_iRc = CCNLV_BAD_KERNEL_TYPE ); }; return true; } // -------------------------------------------------------- // Description: Set Kernel for convolution, manual load // // Return: TRUE if success // (-) upon error int Ccnlv::SetKernel ( int len // [in]kernel width , double pKern[] ) // [in]kernel members // -------------------------------------------------------- { // Set up the kernel if ( m_pKern ) { delete m_pKern; m_pKern = NULL; } m_iKrnWid = (int)sqrt ( (double)len ); if ( len != (m_iKrnWid*m_iKrnWid) ) { m_sRc = "SetKernel() -Invalid kernel array length\n"; return ( m_iRc = CCNLV_INVALID_KERNEL_LENGTH ); } m_pKern = new double[len]; for ( int i = 0; i < len; i ++ ) m_pKern[i] = pKern[i]; return true; } // -------------------------------------------------------- // Description: Get access to image. // convert or parse if needed // // Return: TRUE if object is empty // (-) upon error int Ccnlv::LoadImage ( uchar *pImage //[in] point->image , int iNofp //[in] number of planes , long lWid //[in] pixel width , long lLen ) //[in] pixel length // -------------------------------------------------------- { if( ( !pImage ) || ( lWid < 3 ) || ( lLen < 3 ) || (iNofp <1 ) || ( iNofp> 4 ) ) { m_sRc = "LoadImage() - Invalid entry\n"; return ( m_iRc = CCNLV_INVALID_ENTRY ); } m_lImgWid = lWid; m_lImgLen = lLen; m_iNofp = iNofp; m_pImg = pImage; return true; } /////////////////////////////////////////////////////////// // various filters for application //////////////////////// // -------------------------------------------------------- // Description: // // Return: true if success // (-) upon failure int Ccnlv::Convolve() // -------------------------------------------------------- { double dSum = 0; double dTotal = 0; uchar *pTmp; long p; long i, j; int x, y, k; if ( ( !m_pKern ) || ( m_iKrnWid % 2 == 0 ) || ( m_iKrnWid == 0 ) ) { m_sRc = "Convolve() -Invalid Kernel \n"; return ( m_iRc = CCNLV_INVALID_KERNEL ); } int y_pad = m_iKrnWid / 2; int x_pad = m_iKrnWid / 2; if ( ( ! m_pImg ) || ( m_lImgWid < (m_iKrnWid/2) ) || ( m_lImgLen < (m_iKrnWid/2) ) ) { m_sRc.Insert ( 0, "Cconvolution::Apply() - Bad Image or type \n" ); return ( m_iRc = CCNLV_BAD_IMAGE ); } for ( int m = 0; m < m_iKrnWid*m_iKrnWid; m ++ ) dTotal += m_pKern[m]; if ( dTotal == 0 ) dTotal = 1; // A temporary image to store convolved image pTmp = new uchar[m_lImgWid*m_lImgLen*m_iNofp]; // Do convolution here for ( j = 0; j < m_lImgLen - m_iKrnWid; j ++ ) { for ( i = 0; i < m_lImgWid - m_iKrnWid; i ++ ) { for ( k = 0; k < m_iNofp; k ++ ) { dSum = 0; p = (j+y_pad+1)*m_lImgWid*m_iNofp; // index to center line of kernel for ( y = 0; y < m_iKrnWid; y ++ ) { for ( x = 0; x < m_iKrnWid; x ++ ) { dSum += m_pImg[ (j+y) * (m_lImgWid*m_iNofp) + (i*m_iNofp) + (x*m_iNofp) + k ] * m_pKern[y*m_iKrnWid+x]; } } pTmp[ p + (i+x_pad+1)*m_iNofp + k ] = Absol ( dSum / dTotal ); } } } // copy convolved image over original memcpy ( m_pImg, pTmp, m_lImgWid*m_lImgLen*m_iNofp ); delete pTmp; return true; } // -------------------------------------------------------- // Description: Original + ( original - lowpass ) // // Return: true if success // (-) upon failure int Ccnlv::UnSharpMask() // -------------------------------------------------------- { double dSum = 0; double dTotal = 0; uchar *pTmp; long p, pos; long i, j; int x, y, k; if ( ( !m_pKern ) || ( m_iKrnWid % 2 == 0 ) || ( m_iKrnWid == 0 ) ) { m_sRc = "Convolve() -Invalid Kernel \n"; return ( m_iRc = CCNLV_INVALID_KERNEL ); } int y_pad = m_iKrnWid / 2; int x_pad = m_iKrnWid / 2; if ( ( ! m_pImg ) || ( m_lImgWid < (m_iKrnWid/2) ) || ( m_lImgLen < (m_iKrnWid/2) ) ) { m_sRc.Insert ( 0, "Cconvolution::Apply() - Bad Image or type \n" ); return ( m_iRc = CCNLV_BAD_IMAGE ); } for ( int m = 0; m < m_iKrnWid*m_iKrnWid; m ++ ) dTotal += m_pKern[m]; if ( dTotal == 0 ) dTotal = 1; // A temporary image to store convolved image pTmp = new uchar[m_lImgWid*m_lImgLen*m_iNofp]; memcpy ( pTmp, m_pImg, m_lImgWid*m_lImgLen*m_iNofp ); // Do convolution here for ( j = 0; j < m_lImgLen - m_iKrnWid; j ++ ) { for ( i = 0; i < m_lImgWid - m_iKrnWid; i ++ ) { for ( k = 0; k < m_iNofp; k ++ ) { dSum = 0; p = (j+y_pad+1)*m_lImgWid*m_iNofp; // index to center line of kernel for ( y = 0; y < m_iKrnWid; y ++ ) { for ( x = 0; x < m_iKrnWid; x ++ ) { dSum += m_pImg[ (j+y) * (m_lImgWid*m_iNofp) + (i*m_iNofp) + (x*m_iNofp) + k ] * m_pKern[y*m_iKrnWid+x]; } } pos = p + (i+x_pad+1)*m_iNofp + k; pTmp[pos] = Requant ( pTmp[pos] + pTmp[pos] - Absol ( dSum / dTotal ) ); } } } // copy convolved image over original memcpy ( m_pImg, pTmp, m_lImgWid*m_lImgLen*m_iNofp ); delete pTmp; return true; return true; } // -------------------------------------------------------- // Description: Original + ( original - lowpass ) // Enter plane number to be sharpen... // i.e. plane = 0 for first image plane, // plane = 1 for second image plane. // // Return: true if success // (-) upon failure int Ccnlv::UnSharpMask( int plane ) // [in] image plane # // -------------------------------------------------------- { double dSum = 0; double dTotal = 0; uchar *pTmp; long p, pos; long i, j; int x, y; if ( ( !m_pKern ) || ( m_iKrnWid % 2 == 0 ) || ( m_iKrnWid == 0 ) ) { m_sRc = "Convolve() -Invalid Kernel \n"; return ( m_iRc = CCNLV_INVALID_KERNEL ); } int y_pad = m_iKrnWid / 2; int x_pad = m_iKrnWid / 2; if ( ( ! m_pImg ) || ( m_lImgWid < (m_iKrnWid/2) ) || ( m_lImgLen < (m_iKrnWid/2) ) ) { m_sRc.Insert ( 0, "Cconvolution::Apply() - Bad Image or type \n" ); return ( m_iRc = CCNLV_BAD_IMAGE ); } for ( int m = 0; m < m_iKrnWid*m_iKrnWid; m ++ ) dTotal += m_pKern[m]; if ( dTotal == 0 ) dTotal = 1; // A temporary image to store convolved image pTmp = new uchar[m_lImgWid*m_lImgLen*m_iNofp]; memcpy ( pTmp, m_pImg, m_lImgWid*m_lImgLen*m_iNofp ); // Do convolution here for ( j = 0; j < m_lImgLen - m_iKrnWid; j ++ ) { for ( i = 0; i < m_lImgWid - m_iKrnWid; i ++ ) { dSum = 0; p = (j+y_pad+1)*m_lImgWid*m_iNofp; // index to center line of kernel for ( y = 0; y < m_iKrnWid; y ++ ) { for ( x = 0; x < m_iKrnWid; x ++ ) { dSum += m_pImg[ (j+y) * (m_lImgWid*m_iNofp) + (i*m_iNofp) + (x*m_iNofp) + plane ] * m_pKern[y*m_iKrnWid+x]; } } pos = p + (i+x_pad+1)*m_iNofp + plane; pTmp[pos] = Requant ( pTmp[pos] + pTmp[pos] - Absol ( dSum / dTotal ) ); } } // copy convolved image over original memcpy ( m_pImg, pTmp, m_lImgWid*m_lImgLen*m_iNofp ); delete pTmp; return true; return true; } /////////////////////////////////////////////////////////// // PRIVATE //////////////////////////////////////////////// // -------------------------------------------------------- // Description: return absolute value...get rid of the (-) // // Input: integer // Return: (+) integer int Ccnlv::Absol( int value ) // -------------------------------------------------------- { if ( value < 0 ) return (int)( value * -1.0 ); return value; } // -------------------------------------------------------- // Description: return absolute value...get rid of the (-) // // Input: integer // Return: (+) integer int Ccnlv::Absol( double value ) // -------------------------------------------------------- { if ( value < 0.0 ) return (int)( value * -1.0 ); return (int)value; } // -------------------------------------------------------- // Description: Requantize value to be in the range of an uchar // 0 to 255 // // Input: integer // Return: (+) integer int Ccnlv::Requant ( int value ) // -------------------------------------------------------- { if ( value > 255 ) return 255; if ( value < 0 ) return 0; return value; }