// // PRTraceEdges.m // PRICE // // Created by Riccardo Mottola on Wed Jan 14 2004. // Copyright (c) 2004 Carduus. All rights reserved. // // This program is free software; you can redistribute it and/or modify it under the terms of the version 2 of the GNU General Public License as published by the .Free Software Foundation. // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. #import "PRTraceEdges.h" #import "PRGrayscaleFilter.h" #import #import @implementation PRTraceEdges - (PRImage *)edgeImage :(PRImage *)srcImage :(int)filterType :(BOOL)useThreshold :(float)thresholdLevel :(BOOL)useZeroCross { NSBitmapImageRep *srcImageRep; PRImage *destImage; NSBitmapImageRep *destImageRep; int w, h; int x, y; int i, j; unsigned char *srcData; unsigned char *destData; int bytesPerPixel; int pixNum; float *M, *N; unsigned char *p1; int convMatrix[5][5]; float convSum; /* get source image representation and associated information */ srcImageRep = [srcImage tiffRep]; w = [srcImageRep pixelsWide]; h = [srcImageRep pixelsHigh]; pixNum = h * w; bytesPerPixel = [srcImageRep bitsPerPixel] /8; /* check bith depth and color/greyscale image */ if ([srcImageRep hasAlpha]) { if ([srcImageRep samplesPerPixel] == 2) { printf("Grayscale image\n"); } else { printf("Color image\n"); return srcImage; } } else { if ([srcImageRep samplesPerPixel] == 1) { printf("Grayscale image\n"); } else { PRGrayscaleFilter *grayFilter; printf("Color image\n"); grayFilter = [[PRGrayscaleFilter alloc] init]; srcImage = [grayFilter filterImage:srcImage]; [grayFilter release]; NSLog (@"done greyscale converting"); /* we reget previous information that is no longer valid */ /* get source image representation and associated information */ srcImageRep = [NSBitmapImageRep imageRepWithData:[srcImage TIFFRepresentation]]; bytesPerPixel = [srcImageRep bitsPerPixel] /8; } } srcData = [srcImageRep bitmapData]; /* allocate float data */ M = (float *)calloc(h*w, sizeof(float)); N = (float *)calloc(h*w, sizeof(float)); /* copy the image to the float matrix */ for (y = 0; y < h; y++) { p1 = srcData + (y * w); /* the image is greyscale, no bit-depth displace */ for (x = 0; x < w; x++) { M[y*w + x] = (double)p1[x] / UCHAR_MAX; } } /* set the filter matrix */ for (i = 0; i < 5; i++) for (j = 0; j < 5; j++) convMatrix[i][j] = 0; /* see PRCTraceEdge.h for the filter correspondences */ // NSLog(@"%d", filterType); switch (filterType) { case 1: NSLog(@"Pixel difference"); convMatrix[1][1] = 0; convMatrix[1][2] = -1; convMatrix[1][3] = 0; convMatrix[2][1] = 0; convMatrix[2][2] = 2; convMatrix[2][3] = -1; break; case 2: NSLog(@"Separated pixel difference"); convMatrix[1][1] = 0; convMatrix[1][2] = -1; convMatrix[1][3] = 0; convMatrix[2][1] = 1; convMatrix[2][2] = 0; convMatrix[2][3] = -1; convMatrix[3][1] = 0; convMatrix[3][2] = 1; convMatrix[3][3] = 0; break; case 3: NSLog(@"Roberts"); convMatrix[1][1] = -1; convMatrix[1][2] = 0; convMatrix[1][3] = -1; convMatrix[2][1] = 0; convMatrix[2][2] = 2; convMatrix[2][3] = 0; break; case 4: NSLog(@"Prewitt"); convMatrix[1][1] = 0; convMatrix[1][2] = -1; convMatrix[1][3] = -2; convMatrix[2][1] = 1; convMatrix[2][2] = 0; convMatrix[2][3] = -1; convMatrix[3][1] = 2; convMatrix[3][2] = 1; convMatrix[3][3] = 0; break; case 5: NSLog(@"Sobel"); convMatrix[1][1] = 0; convMatrix[1][2] = -2; convMatrix[1][3] = -2; convMatrix[2][1] = 2; convMatrix[2][2] = 0; convMatrix[2][3] = -2; convMatrix[3][1] = 2; convMatrix[3][2] = 2; convMatrix[3][3] = 0; break; case 6: NSLog(@"Abdou x"); convMatrix[0][0] = 1; convMatrix[0][1] = 1; convMatrix[0][2] = 0; convMatrix[0][3] = -1; convMatrix[0][4] = -1; convMatrix[1][0] = 1; convMatrix[1][1] = 2; convMatrix[1][2] = 0; convMatrix[1][3] = -2; convMatrix[1][4] = -1; convMatrix[2][0] = 1; convMatrix[2][1] = 2; convMatrix[2][2] = 0; convMatrix[2][3] = -2; convMatrix[2][4] = -1; convMatrix[3][0] = 1; convMatrix[3][1] = 2; convMatrix[3][2] = 0; convMatrix[3][3] = -2; convMatrix[3][4] = -1; convMatrix[4][0] = 1; convMatrix[4][1] = 1; convMatrix[4][2] = 0; convMatrix[4][3] = -1; convMatrix[4][4] = -1; break; case 7: NSLog(@"Laplacian 1"); convMatrix[1][1] = 0; convMatrix[1][2] = -1; convMatrix[1][3] = 0; convMatrix[2][1] = -1; convMatrix[2][2] = 4; convMatrix[2][3] = -1; convMatrix[3][1] = 0; convMatrix[3][2] = -1; convMatrix[3][3] = 0; break; case 8: NSLog(@"Laplacian 2"); convMatrix[1][1] = -1; convMatrix[1][2] = 2; convMatrix[1][3] = -1; convMatrix[2][1] = 2; convMatrix[2][2] = -4; convMatrix[2][3] = 2; convMatrix[3][1] = -1; convMatrix[3][2] = 2; convMatrix[3][3] = -1; break; case 9: NSLog(@"Laplacian Prewitt"); convMatrix[1][1] = -1; convMatrix[1][2] = -1; convMatrix[1][3] = -1; convMatrix[2][1] = -1; convMatrix[2][2] = 8; convMatrix[2][3] = -1; convMatrix[3][1] = -1; convMatrix[3][2] = -1; convMatrix[3][3] = -1; break; default: NSLog(@"Unknown filter type for Trace Edges."); } /* the core */ for (y = 0 + 2; y < h - 3; y++) for (x = 0 + 2; x < w - 3; x++) { convSum = 0; for (i = -2; i <= 2; i++) for (j = -2; j <= 2; j++) convSum += convMatrix[i+2][j+2] * M[(y+i) * w + (x+j)]; N[y*w + x] = convSum; } /* allocate destination image and its representation */ destImage = [[PRImage alloc] initWithSize:NSMakeSize(w, h)]; destImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:w pixelsHigh:h bitsPerSample:8 samplesPerPixel:1 hasAlpha:NO isPlanar:NO colorSpaceName:NSCalibratedWhiteColorSpace bytesPerRow:0 bitsPerPixel:0]; destData = [destImageRep bitmapData]; /* copy the image back from the float matrix */ if (useThreshold) { if (useZeroCross) { /* zero crossing */ for (y = 0; y < h; y++) { p1 = destData + (y * w); for (x = 0; x < w; x++) { float temp; temp = fabs(N[y*w + x]); if (temp < thresholdLevel) p1[x] = UCHAR_MAX; else p1[x] = 0; } } } else { /* no zero crossing */ for (y = 0; y < h; y++) { p1 = destData + (y * w); for (x = 0; x < w; x++) { if (N[y*w + x] > thresholdLevel) p1[x] = 0; else p1[x] = UCHAR_MAX; } } } } else { /* thresholding to prevent clipping */ for (y = 0; y < h; y++) { p1 = destData + (y * w); for (x = 0; x < w; x++) { float temp; temp = fabs(N[y*w + x]); if (temp < 0) p1[x] = 0; else if (temp < 1) p1[x] = (unsigned char) rint(temp * UCHAR_MAX); else p1[x] = UCHAR_MAX; } } } /* let's free the float data */ free(M); free(N); [destImage addRepresentation:destImageRep]; [destImageRep release]; [destImage autorelease]; return destImage; } @end