1// 2// PRScale.m 3// PRICE 4// 5// Created by Riccardo Mottola on Wed Jan 19 2005. 6// Copyright (c) 2005-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#include <math.h> 12#import "PRScale.h" 13 14 15@implementation PRScale 16 17- (PRImage *)filterImage:(PRImage *)image with:(NSArray *)parameters progressPanel:(PRCProgress *)progressPanel 18{ 19 int pixelsX; 20 int pixelsY; 21 int method; 22 23 /* interpret the parameters */ 24 pixelsX = [[parameters objectAtIndex:0] intValue]; 25 pixelsY = [[parameters objectAtIndex:1] intValue]; 26 method = [[parameters objectAtIndex:2] intValue]; 27 28 return [self scaleImage:image :pixelsX :pixelsY :method :progressPanel]; 29} 30 31- (NSString *)actionName 32{ 33 return @"Scale"; 34} 35 36- (PRImage *)scaleImage :(PRImage *)srcImage :(int)sizeX :(int)sizeY :(int)method :(PRCProgress *)prPanel 37{ 38 NSBitmapImageRep *srcImageRep; 39 PRImage *destImage; 40 NSBitmapImageRep *destImageRep; 41 NSInteger origW, origH; 42 NSInteger x, y; 43 NSInteger i; 44 unsigned char *srcData; 45 unsigned char *destData; 46 NSInteger srcSamplesPerPixel; 47 NSInteger destSamplesPerPixel; 48 register NSInteger srcBytesPerPixel; 49 register NSInteger destBytesPerPixel; 50 register NSInteger srcBytesPerRow; 51 register NSInteger destBytesPerRow; 52 float xRatio, yRatio; 53 54 progressSteps = 0; 55 totalProgressSteps = 2; 56 progPanel = prPanel; 57 58 /* get source image representation and associated information */ 59 if (progPanel != nil) 60 { 61 [self setActivity:@"Get image size"]; 62 [self advanceProgress]; 63 } 64 srcImageRep = [srcImage bitmapRep]; 65 srcBytesPerRow = [srcImageRep bytesPerRow]; 66 srcSamplesPerPixel = [srcImageRep samplesPerPixel]; 67 srcBytesPerPixel = [srcImageRep bitsPerPixel] / 8; 68 69 origW = [srcImageRep pixelsWide]; 70 origH = [srcImageRep pixelsHigh]; 71 72 73 xRatio = (float)origW / (float)sizeX; 74 yRatio = (float)origH / (float)sizeY; 75 76 77 destImage = [[PRImage alloc] initWithSize:NSMakeSize(sizeX, sizeY)]; 78 destSamplesPerPixel = [srcImageRep samplesPerPixel]; 79 destImageRep = [[NSBitmapImageRep alloc] 80 initWithBitmapDataPlanes:NULL 81 pixelsWide:sizeX 82 pixelsHigh:sizeY 83 bitsPerSample:8 84 samplesPerPixel:destSamplesPerPixel 85 hasAlpha:[srcImageRep hasAlpha] 86 isPlanar:NO 87 colorSpaceName:[srcImageRep colorSpaceName] 88 bytesPerRow:destSamplesPerPixel*sizeX 89 bitsPerPixel:0]; 90 91 srcData = [srcImageRep bitmapData]; 92 destData = [destImageRep bitmapData]; 93 destBytesPerRow = [destImageRep bytesPerRow]; 94 destBytesPerPixel = [destImageRep bitsPerPixel] / 8; 95 96 if (progPanel != nil) 97 { 98 [self setActivity:@"Scale"]; 99 [self advanceProgress]; 100 } 101 102 if (method == NEAREST_NEIGHBOUR) 103 { 104 for (y = 0; y < sizeY; y++) 105 for (x = 0; x < sizeX; x++) 106 for (i = 0; i < srcSamplesPerPixel; i++) 107 destData[destBytesPerRow * y + destBytesPerPixel * (sizeX + x) + i] = srcData[srcBytesPerRow * (int)(y * yRatio) + srcBytesPerPixel * (int)(x * xRatio) + i]; 108 } 109 else if (method == BILINEAR) 110 { 111 /* 112 w,h : original width and height 113 v1, v2, v3, 4: four original corner values 114 v' : new computed value 115 116 v' = v1(1-w)(1-h) + v2(w)(1-h) + v3(h)(1-w) + v3(w)(h) 117 */ 118 int v1, v2, v3, v4; 119 register int x0, y0; 120 121 for (y = 0; y < sizeY-1; y++) 122 for (x = 0; x < sizeX-1; x++) 123 { 124 register float xDiff, yDiff; 125 float xFloat, yFloat; 126 127 xFloat = (float)x * xRatio; 128 yFloat = (float)y * yRatio; 129 x0 = (int)(xFloat); 130 y0 = (int)(yFloat); 131 xDiff = (xFloat - x0); 132 yDiff = (yFloat - y0); 133 for (i = 0; i < srcSamplesPerPixel; i++) 134 { 135 v1 = srcData[srcBytesPerRow * y0 + srcBytesPerPixel * x0 + i]; 136 v2 = srcData[srcBytesPerRow * y0 + srcBytesPerPixel * (x0+1) + i]; 137 v3 = srcData[srcBytesPerRow * (y0+1) + srcBytesPerPixel * x0 + i]; 138 v4 = srcData[srcBytesPerRow * (y0+1) + srcBytesPerPixel * (x0+1) + i]; 139 140 destData[destBytesPerPixel * (y * sizeX + x) + i] = \ 141 (int)(v1*(1-xDiff)*(1-yDiff) + \ 142 v2*xDiff*(1-yDiff) + \ 143 v3*yDiff*(1-xDiff) + \ 144 v4*xDiff*yDiff); 145 } 146 } 147 /* we left out one pixel at the right and bottom border */ 148 y = sizeY-1; 149 for (x = 0; x < sizeX-1; x++) 150 { 151 register float xDiff, yDiff; 152 float xFloat, yFloat; 153 154 xFloat = (float)x * xRatio; 155 yFloat = (float)y * yRatio; 156 x0 = (int)(xFloat); 157 y0 = (int)(yFloat); 158 xDiff = (xFloat - x0); 159 yDiff = (yFloat - y0); 160 161 for (i = 0; i < srcSamplesPerPixel; i++) 162 { 163 v1 = srcData[srcBytesPerRow * y0 + srcBytesPerPixel * x0 + i]; 164 v2 = srcData[srcBytesPerRow * y0 + srcBytesPerPixel * (x0+1) + i]; 165 166 destData[destSamplesPerPixel * (y * sizeX + x) + i] = \ 167 (int)(v1*(1-xDiff)*(1-yDiff) + \ 168 v2*xDiff*(1-yDiff)); 169 } 170 } 171 172 x = sizeX-1; 173 for (y = 0; y < sizeY-1; y++) 174 { 175 register float xDiff, yDiff; 176 float xFloat, yFloat; 177 178 xFloat = (float)x * xRatio; 179 yFloat = (float)y * yRatio; 180 x0 = (int)(xFloat); 181 y0 = (int)(yFloat); 182 xDiff = (xFloat - x0); 183 yDiff = (yFloat - y0); 184 for (i = 0; i < srcSamplesPerPixel; i++) 185 { 186 v1 = srcData[srcBytesPerRow * y0 + srcBytesPerPixel * x0 + i]; 187 v3 = srcData[srcBytesPerRow * (y0+1) + srcBytesPerPixel * x0 + i]; 188 189 destData[destBytesPerPixel * (y * sizeX + x) + i] = \ 190 (int)(v1*(1-xDiff)*(1-yDiff) + \ 191 v3*yDiff*(1-xDiff)); 192 } 193 } 194 /* the bottom right corner */ 195 { 196 register float xDiff, yDiff; 197 float xFloat, yFloat; 198 199 xFloat = (float)x * xRatio; 200 yFloat = (float)y * yRatio; 201 x0 = (int)(xFloat); 202 y0 = (int)(yFloat); 203 xDiff = (xFloat - x0); 204 yDiff = (yFloat - y0); 205 for (i = 0; i < srcBytesPerPixel; i++) 206 { 207 v1 = srcData[srcBytesPerRow * y0 + srcBytesPerPixel * x0 + i]; 208 209 destData[destBytesPerPixel * (y * sizeX + x) + i] = \ 210 (int)(v1*(1-xDiff)*(1-yDiff)); 211 } 212 } 213 } else 214 NSLog(@"Unknown scaling method"); 215 if (progPanel != nil) 216 { 217 [self setActivity:@"Done"]; 218 [self showProgress]; 219 } 220 221 [destImage setBitmapRep:destImageRep]; 222 [destImageRep release]; 223 [destImage autorelease]; 224 return destImage; 225} 226 227@end 228