///////////////////////////////////////////////////////////////////////////// // // Image class for personale functions // // Copyright © 1998 // // IMM, Department of Mathematical Modelling // Technical University of Denmark, Building 321 // DK-2800 Lyngby, Denmark // http://www.imm.dtu.dk // // author: Rune Fisker // // Disclaimer: // // No guarantees of performance accompany this software, // nor is any responsibility assumed on the part of the author(s). // The software has been tested extensively and every effort has been // made to insure its reliability. // // This software is provided by IMM and the contributor(s) ``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 IMM or the contributor(s) 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. // // This software is partly based on the Microsoft Vision Software Developers Kit VisSDK // ///////////////////////////////////////////////////////////////////////////// //#include "stdafx.h" ///////////////////////////////////////////////////////////////////////////// // Conversion from Image to IplImage struct // // // author: Lars Pedersen (lap), 15/04/99 // Rune Fisker // template IplImage* CDImageIPL::Image2IplImage() { // TODO: Check up on ALL fields int nChannels,alphaChannel; char *colorModel, *channelSeq; if ((PixFmt() & evispixfmtGray)) { // set number of channels nChannels = 1*NBands(); // set alpha channel alphaChannel = 0; // set color model colorModel = "GRAY"; // set channel sequence channelSeq = "GRAY"; } else if ((PixFmt() & evispixfmtRGBA)) { // set number of channels nChannels = 4*NBands(); // set alpha channel alphaChannel = 4; // set color model colorModel = "RGBA"; // set channel sequence channelSeq = "BGRA"; } else throw CVisError("This function does not support this pixel format",eviserrorPixFmt,"Image2IplImage",__FILE__, __LINE__); int depth; switch (PixFmt()) { case evispixfmtGrayByte : // size 1 byte ~ 8-bit case evispixfmtGrayChar : case evispixfmtRGBAByte : case evispixfmtRGBAChar : depth = IPL_DEPTH_8U; break; case evispixfmtGrayShort : // size 2 bytes ~ 16-bit case evispixfmtGrayUShort : case evispixfmtRGBAShort : case evispixfmtRGBAUShort : depth = IPL_DEPTH_16U; break; case evispixfmtGrayInt : // size 4 bytes ~ 32-bit case evispixfmtGrayUInt : case evispixfmtGrayLong : case evispixfmtGrayULong : case evispixfmtRGBAInt : case evispixfmtRGBAUInt : case evispixfmtRGBALong : case evispixfmtRGBAULong : depth = IPL_DEPTH_32S; break; case evispixfmtGrayFloat : // size 4 bytes ~ 32-bit case evispixfmtRGBAFloat : depth = IPL_DEPTH_32F; break; /* Unfortunately IPL does not support double/64-bit (yet?) : case evispixfmtGrayDouble : // size 8 bytes ~ 64-bit case evispixfmtRGBADouble : depth = IPL_DEPTH_64U; break; */ default : throw CVisError("This function does not support this pixel format",eviserrorPixFmt,"Image2IplImage",__FILE__, __LINE__); } // end switch // set data order, always IPL_DATA_ORDER_PIXEL, i.e., RGBARGBARGBA instead of RRRGGGBBBAAA int dataOrder = IPL_DATA_ORDER_PIXEL; // set image origin int origin = IPL_ORIGIN_TL; int align; // set alignment of image data if ((sizeof(TPixel)*MemoryWidth() % 4) == 0) align = IPL_ALIGN_DWORD; // 4-byte align else if ((sizeof(TPixel)*MemoryWidth() % 8) == 0) align = IPL_ALIGN_QWORD; // 8-byte align else // TODO: Change eviserrorUnknown to something more appropriate throw CVisError("Image is neither 4-byte nor 8-byte aligned",eviserrorUnknown,"Image2IplImage",__FILE__, __LINE__); // set image height to the height of the memory block containing the image int height = MemoryHeight(); // set image width to the width of the memory block containing the image int width = MemoryWidth(); IplROI* roi; // pointer to ROI data if ((height == Height()) && (width == Width())) { // no ROI. set pointer to NULL roi = NULL; } else { roi = iplCreateROI(0, Left(), Top(), Width(), Height()); } // set pointer to maskROI IplImage* maskROI = NULL; // set image ID void* imageID = NULL; // set tile info IplTileInfo* tileInfo = NULL; // create IPL image header IplImage* ipl = iplCreateImageHeader(nChannels, alphaChannel, depth, colorModel, channelSeq, dataOrder, origin, align, width, height, roi, maskROI, imageID, tileInfo); if (ipl==NULL) throw CVisError("IPL Image could not be created",eviserrorUnknown,"Image2IplImage",__FILE__, __LINE__); // set pointer to image data ipl->imageData = (char*) PbPixel(0,0); // set border mode if (BorderMode() == evispadZero) SetBorderModeIpl(ipl); // if (roi != NULL) // iplDeleteROI(roi); return ipl; } ///////////////////////////////////////////////////////////////////////////// // Image mirror using Intel Image Processing Library // // // author: Lars Pedersen (lap), 16/04/99 // template void CDImageIPL::MirrorIpl(int nFlipAxis) { IplImage* iplSrc = Image2IplImage(); iplMirror(iplSrc, iplSrc, nFlipAxis); } ///////////////////////////////////////////////////////////////////////////// // Set bordermode using Intel Image Processing Library // // // author: Lars Pedersen (lap), 26/04/99 // Rune Fisker // template void CDImageIPL::SetBorderModeIpl(IplImage *src, int mode, int border, int constVal) { iplSetBorderMode(src, mode, border, constVal); } ///////////////////////////////////////////////////////////////////////////// // Set bordermode using Intel Image Processing Library // // // author: Lars Pedersen (lap), 26/04/99 // Rune Fisker // template void CDImageIPL::SetBorderModeIpl(IplImage *ipl) { switch (BorderMode()) { case evispadZero : SetBorderModeIpl(ipl, IPL_BORDER_CONSTANT, IPL_SIDE_ALL, 0); break; case evispadReplicate : SetBorderModeIpl(ipl, IPL_BORDER_REPLICATE, IPL_SIDE_ALL, 0); break; case evispadReflect : SetBorderModeIpl(ipl, IPL_BORDER_REFLECT, IPL_SIDE_ALL, 0); break; case evispadCyclic : SetBorderModeIpl(ipl, IPL_BORDER_WRAP, IPL_SIDE_ALL, 0); break; default : throw CVisError("Border mode not supported by IPL",eviserrorUnknown,"Image2IplImage",__FILE__, __LINE__); } } ///////////////////////////////////////////////////////////////////////////// // Threshold using Intel Image Processing Library // // // author: Lars Pedersen (lap), 15/04/99 // Rune Fisker // template void CDImageIPL::ThresholdIpl(int nThreshold) { IplImage* iplSrc = Image2IplImage(); iplThreshold(iplSrc, iplSrc, nThreshold); iplDeallocate(iplSrc, IPL_IMAGE_HEADER0); } ///////////////////////////////////////////////////////////////////////////// // Bilinear Warp using Intel Image Processing Library // // // author: Lars Pedersen (lap), 19/04/99 // template void CDImageIPL::WarpBilinearIpl(CDVector& va, CDVector& vb, int warpFlag, int interpolate) { IplImage* iplSrc = Image2IplImage(); // cast warp coefficients from 2 CDVectors to a 2x4 double matrix double coeffs[2][4]; coeffs[0][0] = va[0]; coeffs[0][1] = va[1]; coeffs[0][2] = va[2]; coeffs[0][3] = va[3]; coeffs[1][0] = vb[0]; coeffs[1][1] = vb[1]; coeffs[1][2] = vb[2]; coeffs[1][3] = vb[3]; // this doesn't work because the function is NOT in-place iplWarpBilinear(iplSrc, iplSrc, coeffs, warpFlag, interpolate); } ///////////////////////////////////////////////////////////////////////////// // Blur using Intel Image Processing Library // // input: // nCols,nRows: rows and cols for blur // // author: Rune Fisker, 22/04/99 // template void CDImageIPL::BlurIpl(int nCols, int nRows) { // create ipl structs IplImage* iplDest = Image2IplImage(); // create a copy of the image and the ipl struct CDImageIPL imageSrc; imageSrc.Copy(*this); imageSrc.SetRect(Rect()); IplImage* iplSrc = imageSrc.Image2IplImage(); // blur iplBlur(iplSrc, iplDest, nCols, nRows, nCols/2, nRows/2); // update history CString sHistory; sHistory.Format("DIVA: Mean filtering by %ix%i window (BlurIpl)",nCols,nRows); AddToHistory(sHistory); } ///////////////////////////////////////////////////////////////////////////// // create IPL filter kernel // // input: // imagefilter: filter kernel // // author: Rune Fisker, 03/05/99 template IplConvKernelFP* CDImageIPL::CreateConvKernelFPIpl(const CVisImage& imageFilter) { // move fliter coeff. from image to array float *pflValues = new float[imageFilter.Width()*imageFilter.Height()]; int iOut = 0; // copy the coefficeient. Note that the IPL kernel is flip horizontally // and vertically compared to the image for (int y=imageFilter.Bottom()-1;y>=imageFilter.Top();y--) { for (int x=imageFilter.Right()-1;x>=imageFilter.Left();x--) { pflValues[iOut++] = imageFilter.Pixel(x,y); } } // create kernel IplConvKernelFP* iplkernel = iplCreateConvKernelFP(imageFilter.Width(),imageFilter.Height(),imageFilter.Width()/2,imageFilter.Height()/2, pflValues); // free memory delete pflValues; // return kernel return iplkernel; } ///////////////////////////////////////////////////////////////////////////// // 2D convolve // // input: // imagefilter: filter kernel // // author: Rune Fisker, 18/05/99 template void CDImageIPL::Convolve2DFPIpl(const CVisImage& imageFilter) { if ((PixFmt() != evispixfmtGrayFloat) && (PixFmt() != evispixfmtRGBAFloat)) throw CVisError("This function only support float pixel formats",eviserrorPixFmt,"Convolve2DFPIpl",__FILE__, __LINE__); // create ipl structs IplImage* iplDest = Image2IplImage(); // create a copy of the image and the ipl struct CDImageIPL imageSrc; imageSrc.CopyFull(*this,evisnormalizeCopyBytesSameType); imageSrc.SetRect(Rect()); IplImage* iplSrc = imageSrc.Image2IplImage(); // create ipl conv. kernel IplConvKernelFP* iplkernelFPArray[1]; iplkernelFPArray[0] = CreateConvKernelFPIpl(imageFilter); // convolve iplConvolve2DFP(iplSrc, iplDest, iplkernelFPArray, 1, IPL_SUM); // free memory iplDeleteConvKernelFP(iplkernelFPArray[0]); // add to history CString strName(imageFilter.Name()); AddToHistory("DIVA: Filtering by " + strName + " (Convolve2DFPIpl)"); } ///////////////////////////////////////////////////////////////////////////// // 2D convolve // // input: // imagefilter: filter kernel // // author: Rune Fisker, 18/05/99 template void CDImageIPL::Convolve2DFPIpl(const CVisSequence& seqFilters, int iCombineMethod) { if ((PixFmt() != evispixfmtGrayFloat) && (PixFmt() != evispixfmtRGBAFloat)) throw CVisError("This function only support float pixel formats",eviserrorPixFmt,"Convolve2DFPIpl",__FILE__, __LINE__); // create ipl structs IplImage* iplDest = Image2IplImage(); // create a copy of the image and the ipl struct CDImageIPL imageSrc; imageSrc.CopyFull(*this,evisnormalizeCopyBytesSameType); imageSrc.SetRect(Rect()); IplImage* iplSrc = imageSrc.Image2IplImage(); // create ipl conv. kernel IplConvKernelFP** iplkernelFPArray = new IplConvKernelFP* [seqFilters.Length()]; for (int i=0; i void CDImageIPL::FixedFilterIpl(IplFilter filter) { // create ipl structs IplImage* iplDest = Image2IplImage(); // create a copy of the image and the ipl struct CDImageIPL imageSrc; imageSrc.Copy(*this); IplImage* iplSrc = imageSrc.Image2IplImage(); // convolve iplFixedFilter(iplSrc, iplDest, filter); // add to history is put in FixedFilter, because the filter name is unknown here } ///////////////////////////////////////////////////////////////////////////// // Arbitrary warp (remap) using Intel Image Processing Library // // // author: Lars Pedersen (lap), [19/12-2000] // template void CDImageIPL::RemapIpl(CDImageIPL& dx, CDImageIPL& dy, const int nInterpolate, CDImageIPL& destImage) { IplImage* iplSrc = Image2IplImage(); IplImage* iplDest = destImage.Image2IplImage(); IplImage* ipldx = dx.Image2IplImage(); IplImage* ipldy = dy.Image2IplImage(); iplRemap(iplSrc, ipldx, ipldy, iplDest, nInterpolate); }