1// 2// PRConvolve55.m 3// PRICE 4// 5// Created by Riccardo Mottola on Sat Jan 18 2003. 6// Copyright (c) 2003-2014 Carduus. All rights reserved. 7// 8// This application is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 9// 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. 10 11 12#include <math.h> 13#include <limits.h> 14 15#import "PRConvolve55.h" 16#import "PRGrayscaleFilter.h" 17 18@implementation PRConvolve55 19 20- (PRImage *)filterImage:(PRImage *)image with:(NSArray *)parameters progressPanel:(PRCProgress *)progressPanel 21{ 22 NSArray *convArray; 23 int convMat[5][5]; 24 int offset; 25 float scale; 26 BOOL autoScale; 27 int i, j, k; 28 29 /* interpret the parameters */ 30 convArray = [parameters objectAtIndex:0]; 31 32 k = 0; 33 for (i = 0; i < 5; i++) 34 for (j = 0; j < 5; j++) 35 convMat[i][j] = [[convArray objectAtIndex:k++] intValue]; 36 37 offset = [[parameters objectAtIndex:1] intValue]; 38 scale = [[parameters objectAtIndex:2] floatValue]; 39 autoScale = [[parameters objectAtIndex:3] boolValue]; 40 41 return [self convolveImage:image :convMat :offset :scale :autoScale :progressPanel]; 42} 43 44- (NSString *)actionName 45{ 46 return @"Convolve 5x5"; 47} 48 49- (PRImage *)convolveImage:(PRImage *)srcImage :(int[5][5])convMat :(int)offset :(float)scale :(BOOL)autoScale :(PRCProgress *)prPan 50{ 51 NSBitmapImageRep *srcImageRep; 52 PRImage *destImage; 53 NSBitmapImageRep *destImageRep; 54 NSInteger w, h; 55 NSInteger x, y; /* image scanning variables */ 56 NSInteger i, j; /* convolve matrix scanning */ 57 unsigned char *srcData; 58 unsigned char *destData; 59 NSInteger srcSamplesPerPixel; 60 NSInteger destSamplesPerPixel; 61 register NSInteger srcBytesPerRow; 62 register NSInteger destBytesPerRow; 63 register NSInteger srcBytesPerPixel; 64 register NSInteger destBytesPerPixel; 65 float normalizeFactor; 66 int minVal, maxVal; 67 BOOL hasAlpha; 68 69 progressSteps = 0; 70 totalProgressSteps = 2; 71 if (autoScale) 72 totalProgressSteps++; 73 progPanel = prPan; 74 75 /* get source image representation and associated information */ 76 if (progPanel != nil) 77 { 78 [self setActivity:@"get image representation"]; 79 [self advanceProgress]; 80 } 81 srcImageRep = [srcImage bitmapRep]; 82 83 w = [srcImageRep pixelsWide]; 84 h = [srcImageRep pixelsHigh]; 85 srcBytesPerRow = [srcImageRep bytesPerRow]; 86 srcSamplesPerPixel = [srcImageRep samplesPerPixel]; 87 srcBytesPerPixel = [srcImageRep bitsPerPixel] / 8; 88 destSamplesPerPixel = srcSamplesPerPixel; 89 90 /* check bith depth and color/greyscale image */ 91 hasAlpha = [srcImage hasAlpha]; 92 93 /* allocate destination image and its representation */ 94 destImage = [[PRImage alloc] initWithSize:NSMakeSize(w, h)]; 95 destImageRep = [[NSBitmapImageRep alloc] 96 initWithBitmapDataPlanes:NULL 97 pixelsWide:w 98 pixelsHigh:h 99 bitsPerSample:[srcImageRep bitsPerSample] 100 samplesPerPixel:[srcImageRep samplesPerPixel] 101 hasAlpha:hasAlpha 102 isPlanar:NO 103 colorSpaceName:[srcImageRep colorSpaceName] 104 bytesPerRow:0 105 bitsPerPixel:0]; 106 srcData = [srcImageRep bitmapData]; 107 destData = [destImageRep bitmapData]; 108 destBytesPerRow = [destImageRep bytesPerRow]; 109 destBytesPerPixel = [destImageRep bitsPerPixel] / 8; 110 111 if ([srcImage hasColor]) 112 { 113 int convSumR, convSumG, convSumB; 114 115 if (autoScale) 116 { 117 if (progPanel != nil) 118 { 119 [self setActivity:@"Evaluating range"]; 120 [self advanceProgress]; 121 } 122 minVal = INT_MAX; 123 maxVal = INT_MIN; 124 125 /* calibrate output range */ 126 for (y = 0 + 2; y < h - 3; y++) 127 for (x = 0 + 2; x < w - 3; x++) 128 { 129 convSumR = 0; 130 convSumG = 0; 131 convSumB = 0; 132 for (i = -2; i <= 2; i++) 133 for (j = -2; j <= 2; j++) 134 { 135 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 136 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 137 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 138 } 139 if (convSumR + convSumG + convSumB > maxVal) 140 maxVal = convSumR + convSumG + convSumB; 141 if (convSumR + convSumG + convSumB < minVal) 142 minVal = convSumR + convSumG + convSumB; 143 } 144 145 maxVal = maxVal / 3; 146 minVal = minVal / 3; 147 printf("Max %d, min %d\n", maxVal, minVal); 148 normalizeFactor = (float)fabs(maxVal -minVal)/(float)UCHAR_MAX; 149 printf("normalize factor: %f\n", normalizeFactor); 150 offset = -minVal; 151 scale = normalizeFactor; 152 } 153 154 printf("offset: %d, scale:%f\n", offset, scale); 155 156 if (progPanel != nil) 157 { 158 [self setActivity:@"convolving"]; 159 [self advanceProgress]; 160 } 161 /* execute the actual filtering */ 162 /* the borders */ 163 for (y = 0; y < 0 + 2; y++) 164 { 165 /* top left corner */ 166 for (x = 0; x < (0 + 2); x++) 167 { 168 convSumR = 0; 169 convSumG = 0; 170 convSumB = 0; 171 for (i = -2; i <= -1 - y; i++) 172 { 173 for (j = -2; j <= -1 - x; j++) 174 { 175 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 176 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 1]; 177 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 2]; 178 } 179 for (j = 0 - x; j <= 2; j++) 180 { 181 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 182 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 183 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 184 } 185 } 186 for (i = 0 - y; i <= 2; i++) 187 { 188 for (j = -2; j <= -1 - x; j++) 189 { 190 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 191 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 1]; 192 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 2]; 193 } 194 for (j = 0 - x; j <= 2; j++) 195 { 196 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 197 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 198 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 199 } 200 } 201 convSumR += offset; 202 convSumG += offset; 203 convSumB += offset; 204 convSumR = (int)rint((float)convSumR / scale); 205 convSumG = (int)rint((float)convSumG / scale); 206 convSumB = (int)rint((float)convSumB / scale); 207 if (convSumR < 0) 208 convSumR = 0; 209 if (convSumG < 0) 210 convSumG = 0; 211 if (convSumB < 0) 212 convSumB = 0; 213 if (convSumR > UCHAR_MAX) 214 convSumR = UCHAR_MAX; 215 if (convSumG > UCHAR_MAX) 216 convSumG = UCHAR_MAX; 217 if (convSumB > UCHAR_MAX) 218 convSumB = UCHAR_MAX; 219 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 220 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 221 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 222 } 223 /* top band */ 224 for (x = (0 + 2); x < (w - 3); x++) 225 { 226 convSumR = 0; 227 convSumG = 0; 228 convSumB = 0; 229 for (i = -2; i <= -1 - y; i++) 230 for (j = -2; j <= 2; j++) 231 { 232 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 233 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 234 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 235 } 236 for (i = 0 - y; i <= 2; i++) 237 for (j = -2; j <= 2; j++) 238 { 239 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 240 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 241 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 242 } 243 convSumR += offset; 244 convSumG += offset; 245 convSumB += offset; 246 convSumR = (int)rint((float)convSumR / scale); 247 convSumG = (int)rint((float)convSumG / scale); 248 convSumB = (int)rint((float)convSumB / scale); 249 if (convSumR < 0) 250 convSumR = 0; 251 if (convSumG < 0) 252 convSumG = 0; 253 if (convSumB < 0) 254 convSumB = 0; 255 if (convSumR > UCHAR_MAX) 256 convSumR = UCHAR_MAX; 257 if (convSumG > UCHAR_MAX) 258 convSumG = UCHAR_MAX; 259 if (convSumB > UCHAR_MAX) 260 convSumB = UCHAR_MAX; 261 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 262 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 263 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 264 } 265 /* top right corner */ 266 for (x = (w - 3); x < w; x++) 267 { 268 convSumR = 0; 269 convSumG = 0; 270 convSumB = 0; 271 for (i = -2; i <= -1 - y; i++) 272 { 273 for (j = -2; j <= -1 - (x - w); j++) 274 { 275 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 276 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 277 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 278 } 279 for (j = 0 - (x - w); j <= 2; j++) 280 { 281 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 282 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 1]; 283 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 2]; 284 } 285 } 286 for (i = 0 - y; i <= 2; i++) 287 { 288 for (j = -2; j <= -1 - (x - w); j++) 289 { 290 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 291 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 292 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 293 } 294 for (j = 0 - (x - w); j <= 2; j++) 295 { 296 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 297 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 1]; 298 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 2]; 299 } 300 } 301 convSumR += offset; 302 convSumG += offset; 303 convSumB += offset; 304 convSumR = (int)rint((float)convSumR / scale); 305 convSumG = (int)rint((float)convSumG / scale); 306 convSumB = (int)rint((float)convSumB / scale); 307 if (convSumR < 0) 308 convSumR = 0; 309 if (convSumG < 0) 310 convSumG = 0; 311 if (convSumB < 0) 312 convSumB = 0; 313 if (convSumR > UCHAR_MAX) 314 convSumR = UCHAR_MAX; 315 if (convSumG > UCHAR_MAX) 316 convSumG = UCHAR_MAX; 317 if (convSumB > UCHAR_MAX) 318 convSumB = UCHAR_MAX; 319 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 320 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 321 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 322 } 323 } 324 for (y = 0 + 2; y < h - 3; y++) 325 { 326 /* left band */ 327 for (x = 0; x < (0 + 2); x++) 328 { 329 convSumR = 0; 330 convSumG = 0; 331 convSumB = 0; 332 for (i = -2; i <= 2; i++) 333 { 334 for (j = -2; j <= -1 - x; j++) 335 { 336 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 337 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 1]; 338 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 2]; 339 } 340 for (j = 0 - x; j <= 2; j++) 341 { 342 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 343 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 344 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 345 } 346 } 347 convSumR += offset; 348 convSumG += offset; 349 convSumB += offset; 350 convSumR = (int)rint((float)convSumR / scale); 351 convSumG = (int)rint((float)convSumG / scale); 352 convSumB = (int)rint((float)convSumB / scale); 353 if (convSumR < 0) 354 convSumR = 0; 355 if (convSumG < 0) 356 convSumG = 0; 357 if (convSumB < 0) 358 convSumB = 0; 359 if (convSumR > UCHAR_MAX) 360 convSumR = UCHAR_MAX; 361 if (convSumG > UCHAR_MAX) 362 convSumG = UCHAR_MAX; 363 if (convSumB > UCHAR_MAX) 364 convSumB = UCHAR_MAX; 365 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 366 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 367 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 368 } 369 /* right band */ 370 for (x = (w - 3); x < w; x++) 371 { 372 convSumR = 0; 373 convSumG = 0; 374 convSumB = 0; 375 for (i = -2; i <= 2; i++) 376 { 377 for (j = -2; j <= -1 - (x - w); j++) 378 { 379 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 380 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 381 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 382 } 383 for (j = 0 - (x - w); j <= 2; j++) 384 { 385 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 386 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 1]; 387 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 2]; 388 } 389 } 390 convSumR += offset; 391 convSumG += offset; 392 convSumB += offset; 393 convSumR = (int)rint((float)convSumR / scale); 394 convSumG = (int)rint((float)convSumG / scale); 395 convSumB = (int)rint((float)convSumB / scale); 396 if (convSumR < 0) 397 convSumR = 0; 398 if (convSumG < 0) 399 convSumG = 0; 400 if (convSumB < 0) 401 convSumB = 0; 402 if (convSumR > UCHAR_MAX) 403 convSumR = UCHAR_MAX; 404 if (convSumG > UCHAR_MAX) 405 convSumG = UCHAR_MAX; 406 if (convSumB > UCHAR_MAX) 407 convSumB = UCHAR_MAX; 408 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 409 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 410 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 411 } 412 } 413 for (y = h - 3; y < h; y++) 414 { 415 /* bottom left corner */ 416 for (x = 0; x < (0 + 2); x++) 417 { 418 convSumR = 0; 419 convSumG = 0; 420 convSumB = 0; 421 for (i = -2; i <= -1 - (y - h); i++) 422 { 423 for (j = -2; j <= -1 - x; j++) 424 { 425 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 426 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 1]; 427 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 2]; 428 } 429 for (j = 0 - x; j <= 2; j++) 430 { 431 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 432 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 433 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 434 } 435 } 436 for (i = 0 - (y - h); i <= 2; i++) 437 { 438 for (j = -2; j <= -1 - x; j++) 439 { 440 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 441 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 1]; 442 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel + 2]; 443 } 444 for (j = 0 - x; j <= 2; j++) 445 { 446 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 447 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 448 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 449 } 450 } 451 convSumR += offset; 452 convSumG += offset; 453 convSumB += offset; 454 convSumR = (int)rint((float)convSumR / scale); 455 convSumG = (int)rint((float)convSumG / scale); 456 convSumB = (int)rint((float)convSumB / scale); 457 if (convSumR < 0) 458 convSumR = 0; 459 if (convSumG < 0) 460 convSumG = 0; 461 if (convSumB < 0) 462 convSumB = 0; 463 if (convSumR > UCHAR_MAX) 464 convSumR = UCHAR_MAX; 465 if (convSumG > UCHAR_MAX) 466 convSumG = UCHAR_MAX; 467 if (convSumB > UCHAR_MAX) 468 convSumB = UCHAR_MAX; 469 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 470 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 471 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 472 } 473 /* bottom band */ 474 for (x = (0 + 2); x < (w - 3); x++) 475 { 476 convSumR = 0; 477 convSumG = 0; 478 convSumB = 0; 479 for (i = -2; i <= -1 - (y - h); i++) 480 for (j = -2; j <= 2; j++) 481 { 482 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 483 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 484 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 485 } 486 for (i = 0 - (y - h); i <= 2; i++) 487 for (j = -2; j <= 2; j++) 488 { 489 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 490 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 491 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 492 } 493 convSumR += offset; 494 convSumG += offset; 495 convSumB += offset; 496 convSumR = (int)rint((float)convSumR / scale); 497 convSumG = (int)rint((float)convSumG / scale); 498 convSumB = (int)rint((float)convSumB / scale); 499 if (convSumR < 0) 500 convSumR = 0; 501 if (convSumG < 0) 502 convSumG = 0; 503 if (convSumB < 0) 504 convSumB = 0; 505 if (convSumR > UCHAR_MAX) 506 convSumR = UCHAR_MAX; 507 if (convSumG > UCHAR_MAX) 508 convSumG = UCHAR_MAX; 509 if (convSumB > UCHAR_MAX) 510 convSumB = UCHAR_MAX; 511 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 512 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 513 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 514 } 515 /* bottom right corner */ 516 for (x = (w - 3); x < w; x++) 517 { 518 convSumR = 0; 519 convSumG = 0; 520 convSumB = 0; 521 for (i = -2; i <= -1 - (y - h); i++) 522 { 523 for (j = -2; j <= -1 - (x - w); j++) 524 { 525 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 526 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 527 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 528 } 529 for (j = 0 - (x - w); j <= 2; j++) 530 { 531 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 532 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 1]; 533 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 2]; 534 } 535 } 536 for (i = 0 - (y - h); i <= 2; i++) 537 { 538 for (j = -2; j <= -1 - (x - w); j++) 539 { 540 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 541 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 542 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 543 } 544 for (j = 0 - (x - w); j <= 2; j++) 545 { 546 convSumR += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 547 convSumG += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 1]; 548 convSumB += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel + 2]; 549 } 550 } 551 convSumR += offset; 552 convSumG += offset; 553 convSumB += offset; 554 convSumR = (int)rint((float)convSumR / scale); 555 convSumG = (int)rint((float)convSumG / scale); 556 convSumB = (int)rint((float)convSumB / scale); 557 if (convSumR < 0) 558 convSumR = 0; 559 if (convSumG < 0) 560 convSumG = 0; 561 if (convSumB < 0) 562 convSumB = 0; 563 if (convSumR > UCHAR_MAX) 564 convSumR = UCHAR_MAX; 565 if (convSumG > UCHAR_MAX) 566 convSumG = UCHAR_MAX; 567 if (convSumB > UCHAR_MAX) 568 convSumB = UCHAR_MAX; 569 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 570 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 571 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 572 } 573 } 574 575 576 /* the core */ 577 for (y = 0 + 2; y < h - 3; y++) 578 for (x = (0 + 2); x < (w - 3); x++) 579 { 580 convSumR = 0; 581 convSumG = 0; 582 convSumB = 0; 583 for (i = -2; i <= 2; i++) 584 for (j = -2; j <= 2; j++) 585 { 586 convSumR += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 587 convSumG += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 1]; 588 convSumB += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel + 2]; 589 } 590 convSumR += offset; 591 convSumG += offset; 592 convSumB += offset; 593 convSumR = (int)rint((float)convSumR / scale); 594 convSumG = (int)rint((float)convSumG / scale); 595 convSumB = (int)rint((float)convSumB / scale); 596 if (convSumR < 0) 597 convSumR = 0; 598 if (convSumG < 0) 599 convSumG = 0; 600 if (convSumB < 0) 601 convSumB = 0; 602 if (convSumR > UCHAR_MAX) 603 convSumR = UCHAR_MAX; 604 if (convSumG > UCHAR_MAX) 605 convSumG = UCHAR_MAX; 606 if (convSumB > UCHAR_MAX) 607 convSumB = UCHAR_MAX; 608 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSumR; 609 destData[destBytesPerRow * y + destBytesPerPixel * x + 1] = (unsigned char)convSumG; 610 destData[destBytesPerRow * y + destBytesPerPixel * x + 2] = (unsigned char)convSumB; 611 } 612 } else 613 { 614 int convSum; 615 616 if (autoScale) 617 { 618 if (progPanel != nil) 619 { 620 [self setActivity:@"Evaluating range"]; 621 [self advanceProgress]; 622 } 623 minVal = INT_MAX; 624 maxVal = INT_MIN; 625 626 /* calibrate output range */ 627 for (y = 0 + 2; y < h - 3; y++) 628 for (x = 0 + 2; x < w - 3; x++) 629 { 630 convSum = 0; 631 for (i = -2; i <= 2; i++) 632 for (j = -2; j <= 2; j++) 633 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 634 635 if (convSum > maxVal) 636 maxVal = convSum; 637 if (convSum < minVal) 638 minVal = convSum; 639 } 640 printf("Max %d, min %d\n", maxVal, minVal); 641 normalizeFactor = (float)fabs(maxVal -minVal)/(float)UCHAR_MAX; 642 printf("normalize factor: %f\n", normalizeFactor); 643 offset = -minVal; 644 scale = normalizeFactor; 645 } 646 647 printf("offset: %d, scale:%f\n", offset, scale); 648 649 if (progPanel != nil) 650 { 651 [self setActivity:@"convolving"]; 652 [self advanceProgress]; 653 } 654 655 /* execute the actual filtering */ 656 /* the borders */ 657 for (y = 0; y < 0 + 2; y++) 658 { 659 /* top left corner */ 660 for (x = 0; x < 0 + 2; x++) 661 { 662 convSum = 0; 663 for (i = -2; i <= -1 - y; i++) 664 { 665 for (j = -2; j <= -1 - x; j++) 666 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 667 for (j = 0 - x; j <= 2; j++) 668 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 669 } 670 for (i = 0 - y; i <= 2; i++) 671 { 672 for (j = -2; j <= -1 - x; j++) 673 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 674 for (j = 0 - x; j <= 2; j++) 675 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 676 } 677 convSum += offset; 678 convSum = (int)rint((float)convSum / scale); 679 if (convSum < 0) 680 convSum = 0; 681 if (convSum > UCHAR_MAX) 682 convSum = UCHAR_MAX; 683 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 684 } 685 /* top band */ 686 for (x = 0 + 2; x < w - 3; x++) 687 { 688 convSum = 0; 689 for (i = -2; i <= -1 - y; i++) 690 for (j = -2; j <= 2; j++) 691 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 692 for (i = 0 - y; i <= 2; i++) 693 for (j = -2; j <= 2; j++) 694 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 695 convSum += offset; 696 convSum = (int)rint((float)convSum / scale); 697 if (convSum < 0) 698 convSum = 0; 699 if (convSum > UCHAR_MAX) 700 convSum = UCHAR_MAX; 701 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 702 } 703 /* top right corner */ 704 for (x = w - 3; x < w; x++) 705 { 706 convSum = 0; 707 for (i = -2; i <= -1 - y; i++) 708 { 709 for (j = -2; j <= -1 - (x - w); j++) 710 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 711 for (j = 0 - (x - w); j <= 2; j++) 712 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i-1)) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 713 } 714 for (i = 0 - y; i <= 2; i++) 715 { 716 for (j = -2; j <= -1 - (x - w); j++) 717 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 718 for (j = 0 - (x - w); j <= 2; j++) 719 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 720 } 721 convSum += offset; 722 convSum = (int)rint((float)convSum / scale); 723 if (convSum < 0) 724 convSum = 0; 725 if (convSum > UCHAR_MAX) 726 convSum = UCHAR_MAX; 727 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 728 } 729 } 730 for (y = 0 + 2; y < h - 3; y++) 731 { 732 /* left band */ 733 for (x = 0; x < 0 + 2; x++) 734 { 735 convSum = 0; 736 for (i = -2; i <= 2; i++) 737 { 738 for (j = -2; j <= -1 - x; j++) 739 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 740 for (j = 0 - x; j <= 2; j++) 741 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 742 } 743 convSum += offset; 744 convSum = (int)rint((float)convSum / scale); 745 if (convSum < 0) 746 convSum = 0; 747 if (convSum > UCHAR_MAX) 748 convSum = UCHAR_MAX; 749 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 750 } 751 /* right band */ 752 for (x = w - 3; x < w; x++) 753 { 754 convSum = 0; 755 for (i = -2; i <= 2; i++) 756 { 757 for (j = -2; j <= -1 - (x - w); j++) 758 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 759 for (j = 0 - (x - w); j <= 2; j++) 760 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 761 } 762 convSum += offset; 763 convSum = (int)rint((float)convSum / scale); 764 if (convSum < 0) 765 convSum = 0; 766 if (convSum > UCHAR_MAX) 767 convSum = UCHAR_MAX; 768 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 769 } 770 } 771 for (y = h - 3; y < h; y++) 772 { 773 /* bottom left corner */ 774 for (x = 0; x < 0 + 2; x++) 775 { 776 convSum = 0; 777 for (i = -2; i <= -1 - (y - h); i++) 778 { 779 for (j = -2; j <= -1 - x; j++) 780 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 781 for (j = 0 - x; j <= 2; j++) 782 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 783 } 784 for (i = 0 - (y - h); i <= 2; i++) 785 { 786 for (j = -2; j <= -1 - x; j++) 787 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+(-j-1))*srcBytesPerPixel]; 788 for (j = 0 - x; j <= 2; j++) 789 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 790 } 791 convSum += offset; 792 convSum = (int)rint((float)convSum / scale); 793 if (convSum < 0) 794 convSum = 0; 795 if (convSum > UCHAR_MAX) 796 convSum = UCHAR_MAX; 797 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 798 } 799 /* bottom band */ 800 for (x = 0 + 2; x < w - 3; x++) 801 { 802 convSum = 0; 803 for (i = -2; i <= -1 - (y - h); i++) 804 for (j = -2; j <= 2; j++) 805 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 806 for (i = 0 - (y - h); i <= 2; i++) 807 for (j = -2; j <= 2; j++) 808 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 809 convSum += offset; 810 convSum = (int)rint((float)convSum / scale); 811 if (convSum < 0) 812 convSum = 0; 813 if (convSum > UCHAR_MAX) 814 convSum = UCHAR_MAX; 815 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 816 } 817 /* bottom right corner */ 818 for (x = w - 3; x < w; x++) 819 { 820 convSum = 0; 821 for (i = -2; i <= -1 - (y - h); i++) 822 { 823 for (j = -2; j <= -1 - (x - w); j++) 824 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 825 for (j = 0 - (x - w); j <= 2; j++) 826 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 827 } 828 for (i = 0 - (y - h); i <= 2; i++) 829 { 830 for (j = -2; j <= -1 - (x - w); j++) 831 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 832 for (j = 0 - (x - w); j <= 2; j++) 833 convSum += convMat[i+2][j+2] * (int)srcData[(y+(-i+1)) * srcBytesPerRow + (x+(-j+1))*srcBytesPerPixel]; 834 } 835 convSum += offset; 836 convSum = (int)rint((float)convSum / scale); 837 if (convSum < 0) 838 convSum = 0; 839 if (convSum > UCHAR_MAX) 840 convSum = UCHAR_MAX; 841 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 842 } 843 } 844 /* the core */ 845 for (y = 0 + 2; y < h - 3; y++) 846 for (x = 0 + 2; x < w - 3; x++) 847 { 848 convSum = 0; 849 for (i = -2; i <= 2; i++) 850 for (j = -2; j <= 2; j++) 851 convSum += convMat[i+2][j+2] * (int)srcData[(y+i) * srcBytesPerRow + (x+j)*srcBytesPerPixel]; 852 convSum += offset; 853 convSum = (int)rint((float)convSum / scale); 854 if (convSum < 0) 855 convSum = 0; 856 if (convSum > UCHAR_MAX) 857 convSum = UCHAR_MAX; 858 destData[destBytesPerRow * y + destBytesPerPixel * x] = (unsigned char)convSum; 859 } 860 } 861 862 /* preserve Alpha Channel if present */ 863 if (hasAlpha) 864 { 865 for (y = 0; y < h; y++) 866 for (x = 0; x < w; x++) 867 destData[destBytesPerRow * y + destBytesPerPixel * x + (destSamplesPerPixel-1)] = srcData[srcBytesPerRow * y + srcBytesPerPixel * x + (srcSamplesPerPixel-1)]; 868 } 869 870 if (progPanel != nil) 871 { 872 [self setActivity:@"Done"]; 873 [self showProgress]; 874 } 875 [destImage setBitmapRep:destImageRep]; 876 [destImageRep release]; 877 [destImage autorelease]; 878 return destImage; 879} 880 881 882@end 883