// // PRScale.m // PRICE // // Created by Riccardo Mottola on Wed Jan 19 2005. // Copyright (c) 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 "PRScale.h" @implementation PRScale - (PRImage *)scaleImage :(PRImage *)srcImage :(int)sizeX :(int)sizeY :(int)method :(PRCProgress *)prPanel { NSBitmapImageRep *srcImageRep; PRImage *destImage; NSBitmapImageRep *destImageRep; int origW, origH; int x, y; int i; unsigned char *srcData; unsigned char *destData; int bytesPerPixel; BOOL isColored; float xRatio, yRatio; /* some trace */ NSLog(@"inside %@.%@", [self className], NSStringFromSelector(_cmd)); progressSteps = 0; totalProgressSteps = 2; progPanel = prPanel; /* get source image representation and associated information */ if (progPanel != nil) { [self setActivity:@"Get image size"]; [self advanceProgress]; } srcImageRep = [NSBitmapImageRep imageRepWithData:[srcImage TIFFRepresentation]]; origW = [srcImageRep pixelsWide]; origH = [srcImageRep pixelsHigh]; bytesPerPixel = [srcImageRep bitsPerPixel] /8; xRatio = (float)origW / (float)sizeX; yRatio = (float)origH / (float)sizeY; /* check bith depth and color/greyscale image */ if ([srcImageRep hasAlpha]) { if ([srcImageRep samplesPerPixel] == 2) return srcImage; else return srcImage; } else { destImage = [[PRImage alloc] initWithSize:NSMakeSize(sizeX, sizeY)]; if ([srcImageRep samplesPerPixel] == 1) { destImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:sizeX pixelsHigh:sizeY bitsPerSample:8 samplesPerPixel:1 hasAlpha:NO isPlanar:NO colorSpaceName:NSCalibratedWhiteColorSpace bytesPerRow:0 bitsPerPixel:0]; isColored = NO; } else { destImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:sizeX pixelsHigh:sizeY bitsPerSample:8 samplesPerPixel:3 hasAlpha:NO isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace bytesPerRow:0 bitsPerPixel:0]; isColored = YES; } } srcData = [srcImageRep bitmapData]; destData = [destImageRep bitmapData]; if (progPanel != nil) { [self setActivity:@"Scale"]; [self advanceProgress]; } if (method == NEAREST_NEIGHBOUR) { for (y = 0; y < sizeY; y++) for (x = 0; x < sizeX; x++) for (i = 0; i < bytesPerPixel; i++) destData[bytesPerPixel * (y * sizeX + x) + i] = srcData[bytesPerPixel * ((int)floor(y * yRatio) * origW + (int)floor(x * xRatio)) + i]; } else if (method == LINEAR_HV) { register int v1, v2, v3; register int realX, realY; register int nextX, nextY; for (y = 0; y < sizeY-1; y++) for (x = 0; x < sizeX-1; x++) for (i = 0; i < bytesPerPixel; i++) { realX = (int)floor(x * xRatio); nextX = (int)floor((x+1) * xRatio); realY = (int)floor(y * yRatio); nextY = (int)floor((y+1) * yRatio); v1 = srcData[bytesPerPixel * (realY * origW + realX) + i]; v2 = srcData[bytesPerPixel * (realY * origW + nextX) + i]; v3 = srcData[bytesPerPixel * (nextY * origW + realX) + i]; destData[bytesPerPixel * (y * sizeX + x) + i] = \ v1 + \ (int)((((float)(v2 - v1) / (float)(nextX - realX) * (x * xRatio - (float)realX)) + \ ((float)(v3 - v1) / (float)(nextY - realY) * (y * yRatio - (float)realY)))/2); } // we left out one pixel at the right and bottom border // bottom y = sizeY-1; for (x = 0; x < sizeX-1; x++) for (i = 0; i < bytesPerPixel; i++) { realX = (int)floor(x * xRatio); nextX = (int)floor((x+1) * xRatio); realY = (int)floor(y * yRatio); v1 = srcData[bytesPerPixel * (realY * origW + realX) + i]; v2 = srcData[bytesPerPixel * (realY * origW + nextX) + i]; destData[bytesPerPixel * (y * sizeX + x) + i] = \ v1 + \ (int)((float)(v2 - v1) / (float)(nextX - realX) * (x * xRatio - (float)realX)); } // right // x = sizeX-1 at loop exit already. for (y = 0; y < sizeY-1; y++) for (i = 0; i < bytesPerPixel; i++) { realX = (int)floor(x * xRatio); realY = (int)floor(y * yRatio); nextY = (int)floor((y+1) * yRatio); v1 = srcData[bytesPerPixel * (realY * origW + realX) + i]; v3 = srcData[bytesPerPixel * (nextY * origW + realX) + i]; destData[bytesPerPixel * (y * sizeX + x) + i] = \ v1 + \ (int)((float)(v3 - v1) / (float)(nextY - realY) * (y * yRatio - (float)realY)); } // the last pixel, x & y are correct already for (i = 0; i < bytesPerPixel; i++) destData[bytesPerPixel * (y * sizeX + x) + i] = srcData[bytesPerPixel * ((int)floor(y * yRatio) * origW + (int)floor(x * xRatio)) + i]; } else NSLog(@"Unknown scaling method"); if (progPanel != nil) { [self setActivity:@"Done"]; [self showProgress]; } [destImage addRepresentation:destImageRep]; [destImageRep release]; [destImage autorelease]; return destImage; } @end