1 /*
2  * imagesource_ncolour_preview.cpp
3  *
4  * Renders an RGB preview of a DeviceN Image
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/util.h"
19 
20 #include "imagesource_devicen_preview.h"
21 
22 using namespace std;
23 
24 
ISDeviceN_Colorant_Preview()25 ISDeviceN_Colorant_Preview::ISDeviceN_Colorant_Preview()
26 	: red(0), green(0), blue(0), longname(NULL), alias(0)
27 {
28 }
29 
30 
ISDeviceN_Colorant_Preview(const char * longname,int red,int green,int blue,char alias)31 ISDeviceN_Colorant_Preview::ISDeviceN_Colorant_Preview(const char *longname,int red, int green, int blue, char alias)
32 	: red(EIGHTTOIS(red)),green(EIGHTTOIS(green)),blue(EIGHTTOIS(blue)),longname(NULL),alias(alias)
33 {
34 	if(longname)
35 		this->longname=strdup(longname);
36 }
37 
38 
ISDeviceN_Colorant_Preview(const char * longname)39 ISDeviceN_Colorant_Preview::ISDeviceN_Colorant_Preview(const char *longname)
40 	: red(EIGHTTOIS(red)),green(EIGHTTOIS(green)),blue(EIGHTTOIS(blue)),longname(NULL),alias(alias)
41 {
42 	if(StrcasecmpIgnoreSpaces(longname,"Cyan")==0)
43 	{
44 		red=EIGHTTOIS(0); green=EIGHTTOIS(190); blue=EIGHTTOIS(255); alias='C';
45 	}
46 	else if(StrcasecmpIgnoreSpaces(longname,"Magenta")==0)
47 	{
48 		red=EIGHTTOIS(255); green=EIGHTTOIS(0); blue=EIGHTTOIS(190); alias='M';
49 	}
50 	else if(StrcasecmpIgnoreSpaces(longname,"Vivid Magenta")==0)
51 	{
52 		red=EIGHTTOIS(255); green=EIGHTTOIS(0); blue=EIGHTTOIS(190); alias='M';
53 	}
54 	else if(StrcasecmpIgnoreSpaces(longname,"Yellow")==0)
55 	{
56 		red=EIGHTTOIS(255); green=EIGHTTOIS(255); blue=EIGHTTOIS(0); alias='Y';
57 	}
58 	else if(StrcasecmpIgnoreSpaces(longname,"Black")==0)
59 	{
60 		red=EIGHTTOIS(0); green=EIGHTTOIS(0); blue=EIGHTTOIS(0); alias='K';
61 	}
62 	else if(StrcasecmpIgnoreSpaces(longname,"Photo Black")==0)
63 	{
64 		red=EIGHTTOIS(0); green=EIGHTTOIS(0); blue=EIGHTTOIS(0); alias='K';
65 	}
66 	else if(StrcasecmpIgnoreSpaces(longname,"Matte Black")==0)
67 	{
68 		red=EIGHTTOIS(0); green=EIGHTTOIS(0); blue=EIGHTTOIS(0); alias='T';
69 	}
70 	else if(StrcasecmpIgnoreSpaces(longname,"Light Cyan")==0)
71 	{
72 		red=EIGHTTOIS(127); green=EIGHTTOIS(220); blue=EIGHTTOIS(255); alias='c';
73 	}
74 	else if(StrcasecmpIgnoreSpaces(longname,"Light Magenta")==0)
75 	{
76 		red=EIGHTTOIS(255); green=EIGHTTOIS(127); blue=EIGHTTOIS(220); alias='m';
77 	}
78 	else if(StrcasecmpIgnoreSpaces(longname,"Vivid Light Magenta")==0)
79 	{
80 		red=EIGHTTOIS(255); green=EIGHTTOIS(127); blue=EIGHTTOIS(220); alias='m';
81 	}
82 	else if(StrcasecmpIgnoreSpaces(longname,"Light Black")==0)
83 	{
84 		red=EIGHTTOIS(127); green=EIGHTTOIS(127); blue=EIGHTTOIS(127); alias='k';
85 	}
86 	else if(StrcasecmpIgnoreSpaces(longname,"Red")==0)
87 	{
88 		red=EIGHTTOIS(255); green=EIGHTTOIS(0); blue=EIGHTTOIS(0); alias='R';
89 	}
90 	else if(StrcasecmpIgnoreSpaces(longname,"Blue")==0)
91 	{
92 		red=EIGHTTOIS(0); green=EIGHTTOIS(0); blue=EIGHTTOIS(255); alias='B';
93 	}
94 	else
95 		throw "Unknown colorant";
96 	if(longname)
97 		this->longname=strdup(longname);
98 }
99 
100 
ISDeviceN_Colorant_Preview(const ISDeviceN_Colorant_Preview & other)101 ISDeviceN_Colorant_Preview::ISDeviceN_Colorant_Preview(const ISDeviceN_Colorant_Preview &other)
102 	: red(other.red), green(other.green), blue(other.blue), longname(NULL), alias(other.alias)
103 {
104 	if(other.longname)
105 		longname=strdup(other.longname);
106 }
107 
108 
~ISDeviceN_Colorant_Preview()109 ISDeviceN_Colorant_Preview::~ISDeviceN_Colorant_Preview()
110 {
111 	if(longname)
112 		free(longname);
113 }
114 
115 
operator =(const ISDeviceN_Colorant_Preview & other)116 ISDeviceN_Colorant_Preview &ISDeviceN_Colorant_Preview::operator=(const ISDeviceN_Colorant_Preview &other)
117 {
118 	if(longname)
119 		free(longname);
120 	if(other.longname)
121 		longname=strdup(other.longname);
122 	red=other.red;
123 	green=other.green;
124 	blue=other.blue;
125 	alias=other.alias;
126 	return(*this);
127 }
128 
129 //////////////////////////////////////////////////////////////////////////////
130 
131 class ISDeviceNPreview_Colorant
132 {
133 	public:
134 	ISDataType red,green,blue;
135 };
136 
137 //////////////////////////////////////////////////////////////////////////////
138 
139 
~ImageSource_DeviceN_Preview()140 ImageSource_DeviceN_Preview::~ImageSource_DeviceN_Preview()
141 {
142 	if(source)
143 		delete source;
144 
145 	if(colorants)
146 		delete[] colorants;
147 }
148 
149 
GetRow(int row)150 ISDataType *ImageSource_DeviceN_Preview::GetRow(int row)
151 {
152 	if(row==currentrow)
153 		return(rowbuffer);
154 
155 	ISDataType *srcdata=source->GetRow(row);
156 
157 	switch(type)
158 	{
159 		case IS_TYPE_RGBA:
160 			for(int x=0;x<width;++x)
161 			{
162 				unsigned int red=IS_SAMPLEMAX,green=IS_SAMPLEMAX,blue=IS_SAMPLEMAX;
163 				for(int s=0;s<source->samplesperpixel-1;++s)
164 				{
165 					unsigned int t=srcdata[x*source->samplesperpixel+s];
166 					unsigned int tr=IS_SAMPLEMAX-((IS_SAMPLEMAX-colorants[s].red)*t)/IS_SAMPLEMAX;
167 					unsigned int tg=IS_SAMPLEMAX-((IS_SAMPLEMAX-colorants[s].green)*t)/IS_SAMPLEMAX;
168 					unsigned int tb=IS_SAMPLEMAX-((IS_SAMPLEMAX-colorants[s].blue)*t)/IS_SAMPLEMAX;
169 					if(tr<red) red=tr;
170 					if(tg<green) green=tg;
171 					if(tb<blue) blue=tb;
172 				}
173 				rowbuffer[x*samplesperpixel]=red;
174 				rowbuffer[x*samplesperpixel+1]=green;
175 				rowbuffer[x*samplesperpixel+2]=blue;
176 				rowbuffer[x*samplesperpixel+3]=srcdata[x*source->samplesperpixel+source->samplesperpixel-1];
177 			}
178 			break;
179 		case IS_TYPE_RGB:
180 			for(int x=0;x<width;++x)
181 			{
182 				unsigned int red=IS_SAMPLEMAX,green=IS_SAMPLEMAX,blue=IS_SAMPLEMAX;
183 				for(int s=0;s<source->samplesperpixel;++s)
184 				{
185 					unsigned int t=srcdata[x*source->samplesperpixel+s];
186 					unsigned int tr=IS_SAMPLEMAX-((IS_SAMPLEMAX-colorants[s].red)*t)/IS_SAMPLEMAX;
187 					unsigned int tg=IS_SAMPLEMAX-((IS_SAMPLEMAX-colorants[s].green)*t)/IS_SAMPLEMAX;
188 					unsigned int tb=IS_SAMPLEMAX-((IS_SAMPLEMAX-colorants[s].blue)*t)/IS_SAMPLEMAX;
189 					if(tr<red) red=tr;
190 					if(tg<green) green=tg;
191 					if(tb<blue) blue=tb;
192 				}
193 				rowbuffer[x*samplesperpixel]=red;
194 				rowbuffer[x*samplesperpixel+1]=green;
195 				rowbuffer[x*samplesperpixel+2]=blue;
196 			}
197 			break;
198 		default:
199 			throw "DeviceN Preview currently only supports RGB output";
200 			break;
201 	}
202 
203 	currentrow=row;
204 
205 	return(rowbuffer);
206 }
207 
208 
ImageSource_DeviceN_Preview(struct ImageSource * source,DeviceNColorantList * cols,int firstcolorant)209 ImageSource_DeviceN_Preview::ImageSource_DeviceN_Preview(struct ImageSource *source,DeviceNColorantList *cols,int firstcolorant)
210 	: ImageSource(source), source(source), colorants(NULL)
211 {
212 	int sourcespp=source->samplesperpixel;
213 	if(HAS_ALPHA(type))
214 	{
215 		type=IS_TYPE_RGBA;
216 		samplesperpixel=4;
217 		--sourcespp;
218 	}
219 	else
220 	{
221 		type=IS_TYPE_RGB;
222 		samplesperpixel=3;
223 	}
224 	int c=cols->GetColorantCount();
225 	if((c-firstcolorant)<sourcespp)
226 		throw "ISDeviceN: Not enough colorants provided!";
227 	colorants=new ISDeviceNPreview_Colorant[c];
228 	for(int i=0;i<(c-firstcolorant);++i)
229 	{
230 		DeviceNColorant *col=(*cols)[i+firstcolorant];
231 		colorants[i].red=EIGHTTOIS(col->red);
232 		colorants[i].green=EIGHTTOIS(col->green);
233 		colorants[i].blue=EIGHTTOIS(col->blue);
234 	}
235 	MakeRowBuffer();
236 }
237 
238