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