1//
2//  PRScale.m
3//  PRICE
4//
5//  Created by Riccardo Mottola on Wed Jan 19 2005.
6//  Copyright (c) 2005-2017 Riccardo Mottola. 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#if !defined (GNUSTEP) &&  (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4)
15#ifndef NSInteger
16#define NSInteger int
17#endif
18#endif
19
20@implementation PRScale
21
22- (NSImage *)filterImage:(NSImage *)image with:(NSArray *)parameters progressPanel:(PRCProgress *)progressPanel
23{
24    int pixelsX;
25    int pixelsY;
26    int method;
27
28    /* interpret the parameters */
29    pixelsX = [[parameters objectAtIndex:0] intValue];
30    pixelsY = [[parameters objectAtIndex:1] intValue];
31    method = [[parameters objectAtIndex:2] intValue];
32
33    return [self scaleImage:image :pixelsX :pixelsY :method :progressPanel];
34}
35
36- (NSString *)actionName
37{
38    return @"Scale";
39}
40
41- (NSImage *)scaleImage :(NSImage *)srcImage :(int)sizeX :(int)sizeY :(int)method :(PRCProgress *)prPanel
42{
43  NSBitmapImageRep *srcImageRep;
44  NSImage *destImage;
45  NSBitmapImageRep *destImageRep;
46  NSInteger origW, origH;
47  NSInteger x, y;
48  NSInteger i;
49  NSSize newSize;
50  unsigned char *srcData;
51  unsigned char *destData;
52  NSInteger srcSamplesPerPixel;
53  NSInteger destSamplesPerPixel;
54  register NSInteger srcBytesPerPixel;
55  register NSInteger destBytesPerPixel;
56  register NSInteger srcBytesPerRow;
57  register NSInteger destBytesPerRow;
58  float xRatio, yRatio;
59
60    /* get source image representation and associated information */
61    srcImageRep = [[srcImage representations] objectAtIndex:0];
62    srcBytesPerRow = [srcImageRep bytesPerRow];
63    srcSamplesPerPixel = [srcImageRep samplesPerPixel];
64    srcBytesPerPixel = [srcImageRep bitsPerPixel] / 8;
65
66    origW = [srcImageRep pixelsWide];
67    origH = [srcImageRep pixelsHigh];
68
69
70    xRatio = (float)origW / (float)sizeX;
71    yRatio = (float)origH / (float)sizeY;
72
73
74    destImage = [[NSImage alloc] initWithSize:NSMakeSize(sizeX, sizeY)];
75    destSamplesPerPixel = [srcImageRep samplesPerPixel];
76    destImageRep = [[NSBitmapImageRep alloc]
77                     initWithBitmapDataPlanes:NULL
78                     pixelsWide:sizeX
79                     pixelsHigh:sizeY
80                     bitsPerSample:8
81                     samplesPerPixel:destSamplesPerPixel
82                     hasAlpha:[srcImageRep hasAlpha]
83                     isPlanar:NO
84                     colorSpaceName:[srcImageRep colorSpaceName]
85                     bytesPerRow:0
86                     bitsPerPixel:0];
87
88    srcData = [srcImageRep bitmapData];
89    destData = [destImageRep bitmapData];
90    destBytesPerRow = [destImageRep bytesPerRow];
91    destBytesPerPixel = [destImageRep bitsPerPixel] / 8;
92    newSize = NSMakeSize([srcImageRep size].width / xRatio, [srcImageRep size].height / yRatio);
93    [destImageRep setSize:newSize];
94
95    if (method == NEAREST_NEIGHBOUR)
96      {
97        for (y = 0; y < sizeY; y++)
98            for (x = 0; x < sizeX; x++)
99                for (i = 0; i < srcSamplesPerPixel; i++)
100                    destData[destBytesPerRow * y + destBytesPerPixel * x + i] = srcData[srcBytesPerRow * (int)(y * yRatio)  + srcBytesPerPixel * (int)(x * xRatio) + i];
101      }
102    else if (method == BILINEAR)
103      {
104	/*
105	  w,h : original width and height
106	  v1, v2, v3, 4: four original corner values
107	  v' : new computed value
108
109	  v' = v1(1-w)(1-h) + v2(w)(1-h) + v3(h)(1-w) + v3(w)(h)
110	*/
111        int v1, v2, v3, v4;
112        register int x0, y0;
113
114        for (y = 0; y < sizeY; y++)
115	  for (x = 0; x < sizeX; x++)
116	    {
117	      register float xDiff, yDiff;
118	      float xFloat, yFloat;
119
120	      xFloat = (float)x * xRatio;
121	      yFloat = (float)y * yRatio;
122	      x0 = (int)(xFloat);
123	      y0 = (int)(yFloat);
124	      xDiff = (xFloat - x0);
125	      yDiff = (yFloat - y0);
126	      for (i = 0; i < srcSamplesPerPixel; i++)
127		{
128                  v1 = 0;
129                  v2 = 0;
130                  v3 = 0;
131                  v4 = 0;
132		  v1 = srcData[srcBytesPerRow * y0 + srcBytesPerPixel * x0 + i];
133                  if (x < sizeX-1 )
134                    v2 = srcData[srcBytesPerRow * y0 + srcBytesPerPixel * (x0+1) + i];
135                  if (y < sizeY-1 )
136                    v3 = srcData[srcBytesPerRow * (y0+1) + srcBytesPerPixel * x0 + i];
137                  if ((x < sizeX-1) && (y < sizeY-1))
138                    v4 = srcData[srcBytesPerRow * (y0+1) + srcBytesPerPixel * (x0+1) + i];
139
140		  destData[destBytesPerRow * y + destBytesPerPixel * 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      }
148    else
149      NSLog(@"Unknown scaling method");
150
151    [destImage addRepresentation:destImageRep];
152    [destImageRep release];
153    [destImage autorelease];
154    return destImage;
155}
156
157@end
158