1 /*
2 * imagesource_ncolour_remap.cpp
3 *
4 * Supports DeviceN
5 * Supports random access
6 *
7 * Copyright (c) 2008 by Alastair M. Robinson
8 * Distributed under the terms of the GNU General Public License -
9 * see the file named "COPYING" for more details.
10 *
11 */
12
13 #include <iostream>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <math.h>
17
18 #include "../support/debug.h"
19
20 #include "imagesource_devicen_remap.h"
21
22 using namespace std;
23
~ImageSource_DeviceN_Remap()24 ImageSource_DeviceN_Remap::~ImageSource_DeviceN_Remap()
25 {
26 if(source)
27 delete source;
28 if(table)
29 free(table);
30 }
31
32
GetRow(int row)33 ISDataType *ImageSource_DeviceN_Remap::GetRow(int row)
34 {
35 if(row==currentrow)
36 return(rowbuffer);
37
38 // Clear the rowbuffer here, since if the channels are mismatched there may be channels we don't set.
39 for(int x=0;x<width*samplesperpixel;++x)
40 rowbuffer[x]=0;
41
42 ISDataType *srcdata=source->GetRow(row);
43
44 // For each pixel we remap each source channel to a channel in the rowbuffer, using the translation table.
45 if(HAS_ALPHA(type))
46 {
47 for(int x=0;x<width;++x)
48 {
49 for(int s=0;s<source->samplesperpixel-1;++s)
50 {
51 if(table[s]>-1)
52 rowbuffer[x*samplesperpixel+table[s]]=srcdata[x*source->samplesperpixel+s];
53 }
54 rowbuffer[x*samplesperpixel+source->samplesperpixel-1]=srcdata[x*samplesperpixel+source->samplesperpixel-1];
55 }
56 }
57 else
58 {
59 for(int x=0;x<width;++x)
60 {
61 for(int s=0;s<source->samplesperpixel;++s)
62 {
63 if(table[s]>-1)
64 rowbuffer[x*samplesperpixel+table[s]]=srcdata[x*source->samplesperpixel+s];
65 }
66 }
67 }
68 currentrow=row;
69
70 return(rowbuffer);
71 }
72
73
ImageSource_DeviceN_Remap(struct ImageSource * source,const int * maptable,int outchannels)74 ImageSource_DeviceN_Remap::ImageSource_DeviceN_Remap(struct ImageSource *source,const int *maptable,int outchannels)
75 : ImageSource(source), source(source)
76 {
77 table=(int *)malloc(sizeof(int)*source->samplesperpixel);
78
79 if(outchannels)
80 samplesperpixel=outchannels;
81 type=IS_TYPE_DEVICEN;
82 for(int i=0;i<source->samplesperpixel;++i)
83 {
84 table[i]=maptable[i];
85 if(table[i]>=samplesperpixel)
86 throw "Error: not enough output channels for remapping table";
87 }
88 MakeRowBuffer();
89 }
90
91
92 // ImageSource_ToDeviceN - "promotes" data from Greyscale, RGB or CMYK to DeviceN
93 // RGB data is inverted.
94
ImageSource_ToDeviceN(ImageSource * source)95 ImageSource_ToDeviceN::ImageSource_ToDeviceN(ImageSource *source) : ImageSource(source), source(source)
96 {
97 if(STRIP_ALPHA(source->type)==IS_TYPE_RGB)
98 {
99 Debug[COMMENT] << "Original image is RGB - inverting as well as re-interpreting..." << endl;
100 MakeRowBuffer();
101 }
102 type=IS_TYPE_DEVICEN;
103 }
104
~ImageSource_ToDeviceN()105 ImageSource_ToDeviceN::~ImageSource_ToDeviceN()
106 {
107 if(source)
108 delete source;
109 }
110
GetRow(int row)111 ISDataType *ImageSource_ToDeviceN::GetRow(int row)
112 {
113 ISDataType *src=source->GetRow(row);
114 switch(source->type)
115 {
116 case IS_TYPE_RGB:
117 if(row==currentrow)
118 return(rowbuffer);
119
120 for(int x=0;x<width*samplesperpixel;++x)
121 {
122 rowbuffer[x]=IS_SAMPLEMAX-src[x];
123 }
124 currentrow=row;
125 return(rowbuffer);
126 break;
127 case IS_TYPE_RGBA:
128 if(row==currentrow)
129 return(rowbuffer);
130
131 for(int x=0;x<width;++x)
132 {
133 for(int s=0;s<samplesperpixel-1;++s)
134 rowbuffer[x*samplesperpixel+s]=IS_SAMPLEMAX-src[x*samplesperpixel+s];
135 rowbuffer[x*samplesperpixel+samplesperpixel-1]=src[x*samplesperpixel+samplesperpixel-1];
136 }
137 currentrow=row;
138 return(rowbuffer);
139 break;
140 default:
141 return(src);
142 break;
143 }
144 }
145
146
147 // Forces an ImageSource from DeviceN to RGB, inverting the data as it goes.
148 // NOTE this *doesn't* remap the channels or downrender to RGB - it merely
149 // re-interprets the data as RGB.
150 // Alpha channel, if present, is not inverted.
151
ImageSource_DeviceNToRGB(ImageSource * source)152 ImageSource_DeviceNToRGB::ImageSource_DeviceNToRGB(ImageSource *source) : ImageSource(source), source(source)
153 {
154 switch(samplesperpixel)
155 {
156 case 3:
157 type=IS_TYPE_RGB;
158 break;
159 case 4:
160 type=IS_TYPE_RGBA;
161 break;
162 default:
163 throw "Can't reinterpret DeviceN image as RGB - wrong number of channels!";
164 }
165 MakeRowBuffer();
166 }
167
168
~ImageSource_DeviceNToRGB()169 ImageSource_DeviceNToRGB::~ImageSource_DeviceNToRGB()
170 {
171 if(source)
172 delete(source);
173 }
174
175
GetRow(int row)176 ISDataType *ImageSource_DeviceNToRGB::GetRow(int row)
177 {
178 if(row==currentrow)
179 return(rowbuffer);
180
181 ISDataType *src=source->GetRow(row);
182
183 switch(source->type)
184 {
185 case IS_TYPE_RGB:
186 for(int x=0;x<width*samplesperpixel;++x)
187 {
188 rowbuffer[x]=IS_SAMPLEMAX-src[x];
189 }
190 break;
191 case IS_TYPE_RGBA:
192 for(int x=0;x<width;++x)
193 {
194 for(int s=0;s<samplesperpixel-1;++s)
195 rowbuffer[x*samplesperpixel+s]=IS_SAMPLEMAX-src[x*samplesperpixel+s];
196 rowbuffer[x*samplesperpixel+samplesperpixel-1]=src[x*samplesperpixel+samplesperpixel-1];
197 }
198 break;
199 default:
200 break;
201 }
202 currentrow=row;
203 return(rowbuffer);
204 }
205
206
207 // Forces an ImageSource from DeviceN to CMYK
208 // NOTE this *doesn't* remap the channels or downrender to CMYK - it merely
209 // re-interprets the data as CMYK.
210
ImageSource_DeviceNToCMYK(ImageSource * source)211 ImageSource_DeviceNToCMYK::ImageSource_DeviceNToCMYK(ImageSource *source) : ImageSource(source), source(source)
212 {
213 switch(samplesperpixel)
214 {
215 case 4:
216 type=IS_TYPE_CMYK;
217 break;
218 case 5:
219 type=IS_TYPE_CMYKA;
220 break;
221 default:
222 throw "Can't reinterpret DeviceN image as RGB - wrong number of channels!";
223 }
224 MakeRowBuffer();
225 }
226
227
~ImageSource_DeviceNToCMYK()228 ImageSource_DeviceNToCMYK::~ImageSource_DeviceNToCMYK()
229 {
230 if(source)
231 delete(source);
232 }
233
234
GetRow(int row)235 ISDataType *ImageSource_DeviceNToCMYK::GetRow(int row)
236 {
237 return(source->GetRow(row));
238 }
239
240