1//
2//  PRInvert.m
3//  PRICE
4//
5//  Created by Riccardo Mottola on Fri Dec 07 2007.
6//  Copyright (c) 2007-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 <limits.h>
12#import "PRInvert.h"
13
14
15@implementation PRInvert
16
17- (PRImage *)filterImage:(PRImage *)image with:(NSArray *)parameters progressPanel:(PRCProgress *)progressPanel
18{
19    /* interpret the parameters */
20
21    return [self filterImage:image];
22}
23
24- (NSString *)actionName
25{
26    return @"Invert";
27}
28
29- (PRImage *)filterImage:(PRImage *)srcImage
30{
31  NSBitmapImageRep    *srcImageRep;
32  PRImage             *destImage;
33  NSBitmapImageRep    *destImageRep;
34  NSInteger           w, h;
35  NSInteger           x, y;
36  BOOL                hasAlpha;
37  NSInteger           srcBytesPerRow;
38  NSInteger           destBytesPerRow;
39  NSInteger           bitsPerPixel;
40  NSInteger           srcBytesPerPixel;
41  NSInteger           destBytesPerPixel;
42  register NSInteger  maxPerChannel;
43
44
45  /* get source image representation and associated information */
46  srcImageRep = [srcImage bitmapRep];
47  w = [srcImageRep pixelsWide];
48  h = [srcImageRep pixelsHigh];
49  srcBytesPerRow = [srcImageRep bytesPerRow];
50  hasAlpha = [srcImageRep hasAlpha];
51  bitsPerPixel = [srcImageRep bitsPerPixel];
52  srcBytesPerPixel = bitsPerPixel / 8;
53  maxPerChannel = pow(2, [srcImageRep bitsPerSample])-1;
54
55  /* allocate destination image and its representation */
56  destImage = [[PRImage alloc] initWithSize:[srcImage size]];
57  destImageRep = [[NSBitmapImageRep alloc]
58                    initWithBitmapDataPlanes:NULL
59                                  pixelsWide:w
60                                  pixelsHigh:h
61                               bitsPerSample:[srcImageRep bitsPerSample]
62                             samplesPerPixel:[srcImageRep samplesPerPixel]
63                                    hasAlpha:hasAlpha
64                                    isPlanar:NO
65                              colorSpaceName:[srcImageRep colorSpaceName]
66                                 bytesPerRow:0
67                                bitsPerPixel:0];
68
69  destBytesPerRow = [destImageRep bytesPerRow];
70  destBytesPerPixel = [destImageRep bitsPerPixel] / 8;
71
72  /* execute the actual filtering  */
73  /* take in account if image has alpha and if it is has one or 3 samples */
74  /* alpha shall be preserved and not inverted */
75  if ([srcImageRep bitsPerSample] == 8)
76    {
77      unsigned char    *srcData;
78      unsigned char    *destData;
79      unsigned char    *p1;
80      unsigned char    *p2;
81
82      srcData = [srcImageRep bitmapData];
83      destData = [destImageRep bitmapData];
84      if (![srcImage hasColor])
85        for (y = 0; y < h; y++)
86          for (x = 0; x < w; x++)
87            {
88              p1 = srcData + srcBytesPerRow * y + srcBytesPerPixel * x;
89              p2 = destData + destBytesPerRow * y + destBytesPerPixel * x;
90              p2[0] = maxPerChannel - p1[0];
91              if (hasAlpha)
92                p2[1] = p1[1];
93            }
94      else
95        for (y = 0; y < h; y++)
96          for (x = 0; x < w; x++)
97            {
98              p1 = srcData + srcBytesPerRow * y + srcBytesPerPixel * x;
99              p2 = destData + destBytesPerRow * y + destBytesPerPixel * x;
100              p2[0] = maxPerChannel - p1[0];
101              p2[1] = maxPerChannel - p1[1];
102              p2[2] = maxPerChannel - p1[2];
103              if(hasAlpha)
104                p2[3] = p1[3];
105            }
106    }
107  else if ([srcImageRep bitsPerSample] == 16)
108    {
109      unsigned short    *srcData;
110      unsigned short    *destData;
111      unsigned short    *p1;
112      unsigned short    *p2;
113
114      srcData = (unsigned short*)[srcImageRep bitmapData];
115      destData = (unsigned short*)[destImageRep bitmapData];
116      if (![srcImage hasColor])
117        for (y = 0; y < h; y++)
118          for (x = 0; x < w; x++)
119            {
120              p1 = (unsigned short*)((unsigned char*)srcData + srcBytesPerRow * y + srcBytesPerPixel * x);
121              p2 = (unsigned short*)((unsigned char*)destData + destBytesPerRow * y + destBytesPerPixel * x);
122              p2[0] = maxPerChannel - p1[0];
123              if (hasAlpha)
124                p2[1] = p1[1];
125            }
126      else
127        for (y = 0; y < h; y++)
128          for (x = 0; x < w; x++)
129            {
130              p1 = (unsigned short*)((unsigned char*)srcData + srcBytesPerRow * y + srcBytesPerPixel * x);
131              p2 = (unsigned short*)((unsigned char*)destData + destBytesPerRow * y + destBytesPerPixel * x);
132              p2[0] = maxPerChannel - p1[0];
133              p2[1] = maxPerChannel - p1[1];
134              p2[2] = maxPerChannel - p1[2];
135              if(hasAlpha)
136                p2[3] = p1[3];
137            }
138    }
139  else
140    {
141      NSLog(@"Unhandled bits per sample: %ld", (long int)[srcImageRep bitsPerSample]);
142    }
143  [destImage setBitmapRep:destImageRep];
144  [destImageRep release];
145  [destImage autorelease];
146  return destImage;
147}
148
149- (BOOL)displayProgress
150{
151    return NO;
152}
153
154
155@end
156