// // PRConvolve55.m // PRICE // // Created by Riccardo Mottola on Sat Jan 18 2003. // Copyright (c) 2003-2005 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 #import #import "PRConvolve55.h" #import "PRGrayscaleFilter.h" @implementation PRConvolve55 - (PRImage *)convolveImage:(PRImage *)srcImage :(int[5][5])convMat :(int)offset :(float)scale :(BOOL)autoScale :(PRCProgress *)prPan { NSBitmapImageRep *srcImageRep; PRImage *destImage; NSBitmapImageRep *destImageRep; int w, h; int x, y; /* image scanning variables */ int i, j; /* convolve matrix scanning */ unsigned char *srcData; unsigned char *destData; int bytesPerPixel; float normalizeFactor; int minVal, maxVal; BOOL isColored; progressSteps = 0; totalProgressSteps = 2; if (autoScale) totalProgressSteps++; progPanel = prPan; /* get source image representation and associated information */ if (progPanel != nil) { [self setActivity:@"get image representation"]; [self advanceProgress]; } srcImageRep = [srcImage tiffRep]; w = [srcImageRep pixelsWide]; h = [srcImageRep pixelsHigh]; bytesPerPixel = [srcImageRep bitsPerPixel] /8; isColored = NO; if ([srcImageRep hasAlpha]) { if ([srcImageRep samplesPerPixel] == 2) { NSLog(@"Grayscale image with alpha"); return srcImage; } else { isColored = YES; NSLog(@"Color image with alpha"); return srcImage; } } else { if ([srcImageRep samplesPerPixel] == 1) { /* 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]; } else { NSLog(@"colored image without alpha"); isColored = YES; /* 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:3 hasAlpha:NO isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace bytesPerRow:0 bitsPerPixel:0]; } } srcData = [srcImageRep bitmapData]; destData = [destImageRep bitmapData]; if (isColored) { int convSumR, convSumG, convSumB; if (autoScale) { if (progPanel != nil) { [self setActivity:@"Evaluating range"]; [self advanceProgress]; } minVal = INT_MAX; maxVal = INT_MIN; /* calibrate output range */ for (y = 0 + 2; y < h - 3; y++) for (x = 0 + 2; x < w - 3; x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= 2; i++) for (j = -2; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } if (convSumR + convSumG + convSumB > maxVal) maxVal = convSumR + convSumG + convSumB; if (convSumR + convSumG + convSumB < minVal) minVal = convSumR + convSumG + convSumB; } maxVal = maxVal / 3; minVal = minVal / 3; printf("Max %d, min %d\n", maxVal, minVal); normalizeFactor = (float)fabs(maxVal -minVal)/(float)UCHAR_MAX; printf("normalize factor: %f\n", normalizeFactor); offset = -minVal; scale = normalizeFactor; } printf("offset: %d, scale:%f\n", offset, scale); if (progPanel != nil) { [self setActivity:@"convolving"]; [self advanceProgress]; } /* execute the actual filtering */ /* the borders */ for (y = 0; y < 0 + 2; y++) { /* top left corner */ for (x = 0; x < (0 + 2); x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= -1 - y; i++) { for (j = -2; j <= -1 - x; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+(-j-1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+(-j-1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+(-j-1)))*3 + 2]; } for (j = 0 - x; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3 + 2]; } } for (i = 0 - y; i <= 2; i++) { for (j = -2; j <= -1 - x; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3 + 2]; } for (j = 0 - x; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3 + 2] = (unsigned char)convSumB; } /* top band */ for (x = (0 + 2); x < (w - 3); x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= -1 - y; i++) for (j = -2; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3 + 2]; } for (i = 0 - y; i <= 2; i++) for (j = -2; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3 + 2] = (unsigned char)convSumB; } /* top right corner */ for (x = (w - 3); x < w; x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= -1 - y; i++) { for (j = -2; j <= -1 - (x - w); j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+j))*3 + 2]; } for (j = 0 - (x - w); j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+(-j+1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+(-j+1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i-1)) * w + (x+(-j+1)))*3 + 2]; } } for (i = 0 - y; i <= 2; i++) { for (j = -2; j <= -1 - (x - w); j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } for (j = 0 - (x - w); j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3 + 2]; } } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3 + 2] = (unsigned char)convSumB; } } for (y = 0 + 2; y < h - 3; y++) { /* left band */ for (x = 0; x < (0 + 2); x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= 2; i++) { for (j = -2; j <= -1 - x; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3 + 2]; } for (j = 0 - x; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3 + 2] = (unsigned char)convSumB; } /* right band */ for (x = (w - 3); x < w; x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= 2; i++) { for (j = -2; j <= -1 - (x - w); j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } for (j = 0 - (x - w); j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3 + 2]; } } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3 + 2] = (unsigned char)convSumB; } } for (y = h - 3; y < h; y++) { /* bottom left corner */ for (x = 0; x < (0 + 2); x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= -1 - (y - h); i++) { for (j = -2; j <= -1 - x; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j-1)))*3 + 2]; } for (j = 0 - x; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } } for (i = 0 - (y - h); i <= 2; i++) { for (j = -2; j <= -1 - x; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+(-j-1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+(-j-1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+(-j-1)))*3 + 2]; } for (j = 0 - x; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3 + 2]; } } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3 + 2] = (unsigned char)convSumB; } /* bottom band */ for (x = (0 + 2); x < (w - 3); x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= -1 - (y - h); i++) for (j = -2; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } for (i = 0 - (y - h); i <= 2; i++) for (j = -2; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3 + 2]; } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3+ 2] = (unsigned char)convSumB; } /* bottom right corner */ for (x = (w - 3); x < w; x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= -1 - (y - h); i++) { for (j = -2; j <= -1 - (x - w); j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } for (j = 0 - (x - w); j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+(-j+1)))*3 + 2]; } } for (i = 0 - (y - h); i <= 2; i++) { for (j = -2; j <= -1 - (x - w); j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+j))*3 + 2]; } for (j = 0 - (x - w); j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+(-j+1)))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+(-j+1)))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+(-i+1)) * w + (x+(-j+1)))*3 + 2]; } } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3 + 2] = (unsigned char)convSumB; } } /* the core */ for (y = 0 + 2; y < h - 3; y++) for (x = (0 + 2); x < (w - 3); x++) { convSumR = 0; convSumG = 0; convSumB = 0; for (i = -2; i <= 2; i++) for (j = -2; j <= 2; j++) { convSumR += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3]; convSumG += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 1]; convSumB += convMat[i+2][j+2] * (int)srcData[((y+i) * w + (x+j))*3 + 2]; } convSumR += offset; convSumG += offset; convSumB += offset; convSumR = (int)rint((float)convSumR / scale); convSumG = (int)rint((float)convSumG / scale); convSumB = (int)rint((float)convSumB / scale); if (convSumR < 0) convSumR = 0; if (convSumG < 0) convSumG = 0; if (convSumB < 0) convSumB = 0; if (convSumR > UCHAR_MAX) convSumR = UCHAR_MAX; if (convSumG > UCHAR_MAX) convSumG = UCHAR_MAX; if (convSumB > UCHAR_MAX) convSumB = UCHAR_MAX; destData[(y*w + x)*3] = (unsigned char)convSumR; destData[(y*w + x)*3 + 1] = (unsigned char)convSumG; destData[(y*w + x)*3 + 2] = (unsigned char)convSumB; } } else { int convSum; if (autoScale) { if (progPanel != nil) { [self setActivity:@"Evaluating range"]; [self advanceProgress]; } minVal = INT_MAX; maxVal = INT_MIN; /* calibrate output range */ 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 += convMat[i+2][j+2] * (int)srcData[(y-j) * w + (x-i)]; if (convSum > maxVal) maxVal = convSum; if (convSum < minVal) minVal = convSum; } printf("Max %d, min %d\n", maxVal, minVal); normalizeFactor = (float)fabs(maxVal -minVal)/(float)UCHAR_MAX; printf("normalize factor: %f\n", normalizeFactor); offset = -minVal; scale = normalizeFactor; } printf("offset: %d, scale:%f\n", offset, scale); if (progPanel != nil) { [self setActivity:@"convolving"]; [self advanceProgress]; } /* execute the actual filtering */ /* the borders */ for (y = 0; y < 0 + 2; y++) { /* top left corner */ for (x = 0; x < 0 + 2; x++) { convSum = 0; for (i = -2; i <= -1 - y; i++) { for (j = -2; j <= -1 - x; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * w + (x+(-j-1))]; for (j = 0 - x; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * w + (x+j)]; } for (i = 0 - y; i <= 2; i++) { for (j = -2; j <= -1 - x; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+(-j-1))]; for (j = 0 - x; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; } convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } /* top band */ for (x = 0 + 2; x < w - 3; x++) { convSum = 0; for (i = -2; i <= -1 - y; i++) for (j = -2; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * w + (x+j)]; for (i = 0 - y; i <= 2; i++) for (j = -2; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } /* top right corner */ for (x = w - 3; x < w; x++) { convSum = 0; for (i = -2; i <= -1 - y; i++) { for (j = -2; j <= -1 - (x - w); j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * w + (x+j)]; for (j = 0 - (x - w); j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * w + (x+(-j+1))]; } for (i = 0 - y; i <= 2; i++) { for (j = -2; j <= -1 - (x - w); j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; for (j = 0 - (x - w); j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+(-j+1))]; } convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } } for (y = 0 + 2; y < h - 3; y++) { /* left band */ for (x = 0; x < 0 + 2; x++) { convSum = 0; for (i = -2; i <= 2; i++) { for (j = -2; j <= -1 - x; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+(-j-1))]; for (j = 0 - x; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; } convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } /* right band */ for (x = w - 3; x < w; x++) { convSum = 0; for (i = -2; i <= 2; i++) { for (j = -2; j <= -1 - (x - w); j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; for (j = 0 - (x - w); j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+(-j+1))];; } convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } } for (y = h - 3; y < h; y++) { /* bottom left corner */ for (x = 0; x < 0 + 2; x++) { convSum = 0; for (i = -2; i <= -1 - (y - h); i++) { for (j = -2; j <= -1 - x; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+(-j-1))]; for (j = 0 - x; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; } for (i = 0 - (y - h); i <= 2; i++) { for (j = -2; j <= -1 - x; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * w + (x+(-j-1))]; for (j = 0 - x; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * w + (x+j)]; } convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } /* bottom band */ for (x = 0 + 2; x < w - 3; x++) { convSum = 0; for (i = -2; i <= -1 - (y - h); i++) for (j = -2; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; for (i = 0 - (y - h); i <= 2; i++) for (j = -2; j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * w + (x+j)]; convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } /* bottom right corner */ for (x = w - 3; x < w; x++) { convSum = 0; for (i = -2; i <= -1 - (y - h); i++) { for (j = -2; j <= -1 - (x - w); j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; for (j = 0 - (x - w); j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+(-j+1))]; } for (i = 0 - (y - h); i <= 2; i++) { for (j = -2; j <= -1 - (x - w); j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * w + (x+j)]; for (j = 0 - (x - w); j <= 2; j++) convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * w + (x+(-j+1))]; } convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } } /* 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 += convMat[i+2][j+2] * (int)srcData[(y+i) * w + (x+j)]; convSum += offset; convSum = (int)rint((float)convSum / scale); if (convSum < 0) convSum = 0; if (convSum > UCHAR_MAX) convSum = UCHAR_MAX; destData[y*w + x] = (unsigned char)convSum; } } if (progPanel != nil) { [self setActivity:@"Done"]; [self showProgress]; } [destImage addRepresentation:destImageRep]; [destImageRep release]; [destImage autorelease]; return destImage; } @end