1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 
8 #include <iostream>
9 #include <string>
10 #include <QDir>
11 #include <QFile>
12 
13 #include "sclcmscolormgmtengineimpl.h"
14 #include "sclcmscolorprofileimpl.h"
15 #include "sclcmscolortransformimpl.h"
16 
17 #ifndef cmsFLAGS_PRESERVEBLACK
18 #define cmsFLAGS_PRESERVEBLACK 0x8000
19 #endif
20 
21 QSharedPointer<ScColorProfileCache>  ScLcmsColorMgmtEngineImpl::m_profileCache;
22 QSharedPointer<ScColorTransformPool> ScLcmsColorMgmtEngineImpl::m_transformPool;
23 
ScLcmsColorMgmtEngineImpl()24 ScLcmsColorMgmtEngineImpl::ScLcmsColorMgmtEngineImpl()
25                          : ScColorMgmtEngineData("Littlecms v1", 0)
26 {
27 	if (!m_profileCache)
28 		m_profileCache = QSharedPointer<ScColorProfileCache>(new ScColorProfileCache());
29 	if (!m_transformPool)
30 		m_transformPool = QSharedPointer<ScColorTransformPool>(new ScColorTransformPool(0));
31 	cmsSetAlarmCodes(0, 255, 0);
32 }
33 
setStrategy(const ScColorMgmtStrategy & strategy)34 void ScLcmsColorMgmtEngineImpl::setStrategy(const ScColorMgmtStrategy& strategy)
35 {
36 	m_strategy = strategy;
37 }
38 
getAvailableProfileInfo(const QString & directory,bool recursive)39 QList<ScColorProfileInfo> ScLcmsColorMgmtEngineImpl::getAvailableProfileInfo(const QString& directory, bool recursive)
40 {
41 	QList<ScColorProfileInfo> profileInfos;
42 
43 	QDir d(directory, "*", QDir::Name, QDir::Files | QDir::Readable | QDir::Dirs | QDir::NoSymLinks);
44 	if ((!d.exists()) || (d.count() == 0))
45 		return profileInfos;
46 
47 	QString nam = "";
48 	cmsHPROFILE hIn = nullptr;
49 
50 	for (uint dc = 0; dc < d.count(); ++dc)
51 	{
52 		QString file = d[dc];
53 		if (file == "." ||  file == "..")
54 			continue;
55 		QFileInfo fi(directory + "/" + file);
56 		if (fi.isDir() && !recursive)
57 			continue;
58 		else if (fi.isDir() && !file.startsWith('.'))
59 		{
60 			QList<ScColorProfileInfo> profileInfos2 = getAvailableProfileInfo(fi.filePath()+"/", true);
61 			profileInfos.append(profileInfos2);
62 			continue;
63 		}
64 
65 		ScColorProfileInfo profileInfo;
66 		profileInfo.file = fi.filePath();
67 
68 		QFile f(fi.filePath());
69 		QByteArray bb(40, ' ');
70 		if (!f.open(QIODevice::ReadOnly)) {
71 			profileInfo.debug = QString("couldn't open %1 as color profile").arg(fi.filePath());
72 			profileInfos.append(profileInfo);
73 			continue;
74 		}
75 		int len = f.read(bb.data(), 40);
76 		f.close();
77 		if (len == 40 && bb[36] == 'a' && bb[37] == 'c' && bb[38] == 's' && bb[39] == 'p')
78 		{
79 			const QByteArray profilePath( QString(directory + "/" + file).toLocal8Bit() );
80 			cmsSetErrorHandler(&cmsErrorHandler);
81 			try
82 			{
83 				hIn = cmsOpenProfileFromFile(profilePath.data(), "r");
84 				if (hIn == nullptr)
85 					continue;
86 				const char* profileDescriptor = cmsTakeProductDesc(hIn);
87 				profileInfo.description = QString(profileDescriptor);
88 				if (profileInfo.description.isEmpty())
89 				{
90 					cmsCloseProfile(hIn);
91 					profileInfo.debug = QString("Color profile %1 is broken : no valid description").arg(fi.filePath());
92 					profileInfos.append(profileInfo);
93 					continue;
94 				}
95 				profileInfo.colorSpace  = translateLcmsColorSpaceType( cmsGetColorSpace(hIn) );
96 				profileInfo.deviceClass = translateLcmsProfileClass( cmsGetDeviceClass(hIn) );
97 				profileInfos.append(profileInfo);
98 				cmsCloseProfile(hIn);
99 				hIn = nullptr;
100 			}
101 			catch (lcmsException&)
102 			{
103 				// Profile is broken
104 				if (hIn)
105 				{
106 					cmsCloseProfile(hIn);
107 					hIn = nullptr;
108 				}
109 				profileInfo.debug = QString("Color profile %1 is broken").arg(fi.filePath());
110 				profileInfos.append(profileInfo);
111 			}
112 			cmsSetErrorHandler(nullptr);
113 		}
114 	}
115 	cmsSetErrorHandler(nullptr);
116 
117 	return profileInfos;
118 }
119 
openProfileFromFile(ScColorMgmtEngine & engine,const QString & filePath)120 ScColorProfile ScLcmsColorMgmtEngineImpl::openProfileFromFile(ScColorMgmtEngine& engine, const QString& filePath)
121 {
122 	// Search profile in profile cache first
123 	ScColorProfile profile = m_profileCache->profile(filePath);
124 	if (!profile.isNull())
125 		return profile;
126 	cmsHPROFILE lcmsProf = nullptr;
127 	cmsSetErrorHandler(&cmsErrorHandler);
128 	try
129 	{
130 		QFile file(filePath);
131 		if (file.open(QFile::ReadOnly))
132 		{
133 			// We do not use lcms cmsOpenProfileFromFile() to avoid limitations
134 			// of I/O on 8bit filenames on Windows
135 			QByteArray data = file.readAll();
136 			if (!data.isEmpty())
137 			{
138 				lcmsProf = cmsOpenProfileFromMem(data.data(), data.size());
139 				if (lcmsProf)
140 				{
141 					ScLcmsColorProfileImpl* profData = new ScLcmsColorProfileImpl(engine, lcmsProf);
142 					profData->m_profileData = data;
143 					profData->m_profilePath = filePath;
144 					profile = ScColorProfile(dynamic_cast<ScColorProfileData*>(profData));
145 					m_profileCache->addProfile(profile);
146 				}
147 				if (profile.isNull() && lcmsProf)
148 				{
149 					cmsCloseProfile(lcmsProf);
150 					lcmsProf = nullptr;
151 				}
152 			}
153 			file.close();
154 		}
155 	}
156 	catch (lcmsException& e)
157 	{
158 		std::cerr << e.what() << std::endl;
159 		if (profile.isNull() && lcmsProf)
160 			cmsCloseProfile(lcmsProf);
161 		profile = ScColorProfile();
162 	}
163 	cmsSetErrorHandler(nullptr);
164 	return profile;
165 }
166 
openProfileFromMem(ScColorMgmtEngine & engine,const QByteArray & data)167 ScColorProfile ScLcmsColorMgmtEngineImpl::openProfileFromMem(ScColorMgmtEngine& engine, const QByteArray& data)
168 {
169 	ScColorProfile profile;
170 	cmsHPROFILE lcmsProf = nullptr;
171 	cmsSetErrorHandler(&cmsErrorHandler);
172 	try
173 	{
174 		lcmsProf = cmsOpenProfileFromMem((LPVOID) data.data(), data.size());
175 		if (lcmsProf)
176 		{
177 			ScLcmsColorProfileImpl* profData = new ScLcmsColorProfileImpl(engine, lcmsProf);
178 			QString desc = profData->productDescription();
179 			if (!desc.isEmpty())
180 				profData->m_profilePath = QString("memprofile://%1").arg(desc);
181 			profData->m_profileData = data;
182 			profile = ScColorProfile(dynamic_cast<ScColorProfileData*>(profData));
183 		}
184 		if (profile.isNull() && lcmsProf)
185 		{
186 			cmsCloseProfile(lcmsProf);
187 			lcmsProf = nullptr;
188 		}
189 	}
190 	catch (lcmsException& e)
191 	{
192 		std::cerr << e.what() << std::endl;
193 		if (profile.isNull() && lcmsProf)
194 			cmsCloseProfile(lcmsProf);
195 		profile = ScColorProfile();
196 	}
197 	cmsSetErrorHandler(nullptr);
198 	return profile;
199 }
200 
createProfile_sRGB(ScColorMgmtEngine & engine)201 ScColorProfile ScLcmsColorMgmtEngineImpl::createProfile_sRGB(ScColorMgmtEngine& engine)
202 {
203 	QString internalProfilePath("memprofile://Internal sRGB profile");
204 	ScColorProfile profile = m_profileCache->profile(internalProfilePath);
205 	if (!profile.isNull())
206 		return profile;
207 
208 	cmsHPROFILE lcmsProf = nullptr;
209 	cmsSetErrorHandler(&cmsErrorHandler);
210 	try
211 	{
212 		lcmsProf = cmsCreate_sRGBProfile();
213 		if (lcmsProf)
214 		{
215 			ScLcmsColorProfileImpl* profData = new ScLcmsColorProfileImpl(engine, lcmsProf);
216 			profData->m_profilePath = internalProfilePath;
217 			profile = ScColorProfile(dynamic_cast<ScColorProfileData*>(profData));
218 			m_profileCache->addProfile(profile);
219 		}
220 		if (profile.isNull() && lcmsProf)
221 		{
222 			cmsCloseProfile(lcmsProf);
223 			lcmsProf = nullptr;
224 		}
225 	}
226 	catch (lcmsException& e)
227 	{
228 		std::cerr << e.what() << std::endl;
229 		if (profile.isNull() && lcmsProf)
230 			cmsCloseProfile(lcmsProf);
231 		profile = ScColorProfile();
232 	}
233 	cmsSetErrorHandler(nullptr);
234 	return profile;
235 }
236 
createProfile_Lab(ScColorMgmtEngine & engine)237 ScColorProfile ScLcmsColorMgmtEngineImpl::createProfile_Lab(ScColorMgmtEngine& engine)
238 {
239 	QString internalProfilePath("memprofile://Internal Lab profile");
240 	ScColorProfile profile = m_profileCache->profile(internalProfilePath);
241 	if (!profile.isNull())
242 		return profile;
243 
244 	cmsHPROFILE lcmsProf = nullptr;
245 	cmsSetErrorHandler(&cmsErrorHandler);
246 	try
247 	{
248 		lcmsProf = cmsCreateLabProfile(nullptr);
249 		if (lcmsProf)
250 		{
251 			ScLcmsColorProfileImpl* profData = new ScLcmsColorProfileImpl(engine, lcmsProf);
252 			profData->m_profilePath = internalProfilePath;
253 			profile = ScColorProfile(dynamic_cast<ScColorProfileData*>(profData));
254 			m_profileCache->addProfile(profile);
255 		}
256 		if (profile.isNull() && lcmsProf)
257 		{
258 			cmsCloseProfile(lcmsProf);
259 			lcmsProf = nullptr;
260 		}
261 	}
262 	catch (lcmsException& e)
263 	{
264 		std::cerr << e.what() << std::endl;
265 		if (profile.isNull() && lcmsProf)
266 			cmsCloseProfile(lcmsProf);
267 		profile = ScColorProfile();
268 	}
269 	cmsSetErrorHandler(nullptr);
270 	return profile;
271 }
272 
createTransform(ScColorMgmtEngine & engine,const ScColorProfile & inputProfile,eColorFormat inputFormat,const ScColorProfile & outputProfile,eColorFormat outputFormat,eRenderIntent renderIntent,long transformFlags)273 ScColorTransform ScLcmsColorMgmtEngineImpl::createTransform(ScColorMgmtEngine& engine,
274                                  const ScColorProfile& inputProfile , eColorFormat inputFormat,
275 	                             const ScColorProfile& outputProfile, eColorFormat outputFormat,
276                                  eRenderIntent renderIntent, long transformFlags)
277 {
278 	ScColorTransform transform(nullptr);
279 	if (inputProfile.isNull() || outputProfile.isNull())
280 		return transform;
281 	int inputProfEngineID  = inputProfile.engine().engineID();
282 	int outputProfEngineID = outputProfile.engine().engineID();
283 	if ((engine.engineID() != m_engineID) || (inputProfEngineID != m_engineID) || (outputProfEngineID != m_engineID))
284 		return transform;
285 	const ScLcmsColorProfileImpl* lcmsInputProf  = dynamic_cast<const ScLcmsColorProfileImpl*>(inputProfile.data());
286 	const ScLcmsColorProfileImpl* lcmsOutputProf = dynamic_cast<const ScLcmsColorProfileImpl*>(outputProfile.data());
287 	if (!lcmsInputProf || !lcmsOutputProf)
288 		return transform;
289 
290 	transformFlags &= (~Ctf_Softproofing);
291 	transformFlags &= (~Ctf_GamutCheck);
292 	long strategyFlags = 0;
293 	if (m_strategy.useBlackPointCompensation)
294 		strategyFlags |= Ctf_BlackPointCompensation;
295 	if (m_strategy.useBlackPreservation)
296 		strategyFlags |= Ctf_BlackPreservation;
297 
298 	ScColorTransformInfo transInfo;
299 	transInfo.inputProfile  = inputProfile.productDescription();
300 	transInfo.outputProfile = outputProfile.productDescription();
301 	transInfo.proofingProfile.clear();
302 	transInfo.inputFormat   = inputFormat;
303 	transInfo.outputFormat  = outputFormat;
304 	transInfo.renderIntent  = renderIntent;
305 	transInfo.proofingIntent = (eRenderIntent) 0;
306 	transInfo.flags = transformFlags | strategyFlags;
307 
308 	bool nullTransform = false;
309 	if (transInfo.inputProfile == transInfo.outputProfile)
310 	{
311 		// This is a null transform
312 		transInfo.inputProfile.clear();
313 		transInfo.outputProfile.clear();
314 		transInfo.proofingProfile.clear();
315 		transInfo.renderIntent    = (eRenderIntent) 0;
316 		transInfo.proofingIntent  = (eRenderIntent) 0;
317 		transInfo.flags = 0;
318 		nullTransform = true;
319 	}
320 
321 	transform = m_transformPool->findTransform(transInfo);
322 	if (transform.isNull())
323 	{
324 		DWORD lcmsFlags     = translateFlagsToLcmsFlags(transformFlags | strategyFlags);
325 		DWORD lcmsInputFmt  = translateFormatToLcmsFormat(inputFormat);
326 		DWORD lcmsOutputFmt = translateFormatToLcmsFormat(outputFormat);
327 		int   lcmsIntent    = translateIntentToLcmsIntent(renderIntent);
328 		if (nullTransform)
329 			lcmsFlags |= cmsFLAGS_NULLTRANSFORM;
330 		cmsHTRANSFORM hTransform = nullptr;
331 		cmsSetErrorHandler(&cmsErrorHandler);
332 		try
333 		{
334 			hTransform = cmsCreateTransform(lcmsInputProf->m_profileHandle , lcmsInputFmt,
335 											lcmsOutputProf->m_profileHandle, lcmsOutputFmt,
336 											lcmsIntent, lcmsFlags | cmsFLAGS_LOWRESPRECALC);
337 			if (hTransform)
338 			{
339 				ScLcmsColorTransformImpl* newTrans = new ScLcmsColorTransformImpl(engine, hTransform);
340 				newTrans->setTransformInfo(transInfo);
341 				transform = ScColorTransform(dynamic_cast<ScColorTransformData*>(newTrans));
342 				m_transformPool->addTransform(transform, true);
343 			}
344 		}
345 		catch (lcmsException& e)
346 		{
347 			std::cerr << e.what() << std::endl;
348 			// #9922 : no idea why that crash in release mode
349 			/*if (transform.isNull() && hTransform)
350 				cmsDeleteTransform(hTransform);*/
351 			transform = ScColorTransform();
352 		}
353 		cmsSetErrorHandler(nullptr);
354 	}
355 	return transform;
356 }
357 
createProofingTransform(ScColorMgmtEngine & engine,const ScColorProfile & inputProfile,eColorFormat inputFormat,const ScColorProfile & outputProfile,eColorFormat outputFormat,const ScColorProfile & proofProfile,eRenderIntent renderIntent,eRenderIntent proofingIntent,long transformFlags)358 ScColorTransform ScLcmsColorMgmtEngineImpl::createProofingTransform(ScColorMgmtEngine& engine,
359                                              const ScColorProfile& inputProfile , eColorFormat inputFormat,
360 	                                         const ScColorProfile& outputProfile, eColorFormat outputFormat,
361                                              const ScColorProfile& proofProfile , eRenderIntent renderIntent,
362                                              eRenderIntent proofingIntent, long transformFlags)
363 {
364 	ScColorTransform transform(nullptr);
365 	if (inputProfile.isNull() || outputProfile.isNull())
366 		return transform;
367 	int inputProfEngineID  = inputProfile.engine().engineID();
368 	int outputProfEngineID = outputProfile.engine().engineID();
369 	int proofProfEngineID  = proofProfile.engine().engineID();
370 	if ((engine.engineID()  != m_engineID) || (inputProfEngineID != m_engineID) ||
371 		(outputProfEngineID != m_engineID) || (proofProfEngineID != m_engineID))
372 		return transform;
373 	const ScLcmsColorProfileImpl* lcmsInputProf    = dynamic_cast<const ScLcmsColorProfileImpl*>(inputProfile.data());
374 	const ScLcmsColorProfileImpl* lcmsOutputProf   = dynamic_cast<const ScLcmsColorProfileImpl*>(outputProfile.data());
375 	const ScLcmsColorProfileImpl* lcmsProofingProf = dynamic_cast<const ScLcmsColorProfileImpl*>(proofProfile.data());
376 	if (!lcmsInputProf || !lcmsOutputProf || !lcmsProofingProf)
377 		return transform;
378 
379 	long strategyFlags = 0;
380 	if (m_strategy.useBlackPointCompensation)
381 		strategyFlags |= Ctf_BlackPointCompensation;
382 	if (m_strategy.useBlackPreservation)
383 		strategyFlags |= Ctf_BlackPreservation;
384 
385 	ScColorTransformInfo transInfo;
386 	transInfo.inputProfile    = inputProfile.productDescription();
387 	transInfo.outputProfile   = outputProfile.productDescription();
388 	transInfo.proofingProfile = proofProfile.productDescription();
389 	transInfo.inputFormat     = inputFormat;
390 	transInfo.outputFormat    = outputFormat;
391 	transInfo.renderIntent    = renderIntent;
392 	transInfo.proofingIntent  = proofingIntent;
393 	transInfo.flags = transformFlags | strategyFlags;
394 
395 	DWORD lcmsFlags     = translateFlagsToLcmsFlags(transformFlags | strategyFlags);
396 	DWORD lcmsInputFmt  = translateFormatToLcmsFormat(inputFormat);
397 	DWORD lcmsOutputFmt = translateFormatToLcmsFormat(outputFormat);
398 	int   lcmsIntent    = translateIntentToLcmsIntent(renderIntent);
399 	int   lcmsPrfIntent = translateIntentToLcmsIntent(proofingIntent);
400 
401 	if (transInfo.inputProfile != transInfo.proofingProfile)
402 	{
403 		if (transInfo.proofingProfile == transInfo.outputProfile)
404 		{
405 			transInfo.proofingIntent = Intent_Relative_Colorimetric;
406 			lcmsPrfIntent = translateIntentToLcmsIntent(Intent_Relative_Colorimetric);
407 		}
408 		transform = m_transformPool->findTransform(transInfo);
409 		if (transform.isNull())
410 		{
411 			cmsSetErrorHandler(&cmsErrorHandler);
412 			cmsHTRANSFORM hTransform = nullptr;
413 			try
414 			{
415 				hTransform = cmsCreateProofingTransform(lcmsInputProf->m_profileHandle , lcmsInputFmt,
416 														lcmsOutputProf->m_profileHandle, lcmsOutputFmt,
417 														lcmsProofingProf->m_profileHandle, lcmsIntent,
418 														lcmsPrfIntent, lcmsFlags | cmsFLAGS_SOFTPROOFING);
419 				if (hTransform)
420 				{
421 					ScLcmsColorTransformImpl* newTrans = new ScLcmsColorTransformImpl(engine, hTransform);
422 					newTrans->setTransformInfo(transInfo);
423 					transform = ScColorTransform(dynamic_cast<ScColorTransformData*>(newTrans));
424 					m_transformPool->addTransform(transform, true);
425 				}
426 			}
427 			catch (lcmsException& e)
428 			{
429 				std::cerr << e.what() << std::endl;
430 				// #9922 : no idea why that crash in release mode
431 				/*if (transform.isNull() && hTransform)
432 					cmsDeleteTransform(hTransform);*/
433 				transform = ScColorTransform();
434 			}
435 			cmsSetErrorHandler(nullptr);
436 		}
437 	}
438 	else
439 	{
440 		transformFlags  &= (~Ctf_Softproofing);
441 		transformFlags  &= (~Ctf_GamutCheck);
442 		lcmsFlags        = translateFlagsToLcmsFlags(transformFlags | strategyFlags);
443 		transInfo.flags  = transformFlags | strategyFlags;
444 		transInfo.renderIntent   = proofingIntent;
445 		transInfo.proofingIntent = (eRenderIntent) 0;
446 		if (transInfo.inputProfile == transInfo.outputProfile)
447 		{
448 			lcmsFlags |= cmsFLAGS_NULLTRANSFORM;
449 			transInfo.inputProfile.clear();
450 			transInfo.outputProfile.clear();
451 			transInfo.proofingProfile.clear();
452 			transInfo.renderIntent    = (eRenderIntent) 0;
453 			transInfo.proofingIntent  = (eRenderIntent) 0;
454 			transInfo.flags = 0;
455 		}
456 		transform = m_transformPool->findTransform(transInfo);
457 		if (transform.isNull())
458 		{
459 			cmsSetErrorHandler(&cmsErrorHandler);
460 			cmsHTRANSFORM hTransform = nullptr;
461 			try
462 			{
463 				hTransform  = cmsCreateTransform(lcmsInputProf->m_profileHandle , lcmsInputFmt,
464 											     lcmsOutputProf->m_profileHandle, lcmsOutputFmt,
465 												 lcmsPrfIntent, lcmsFlags | cmsFLAGS_LOWRESPRECALC);
466 				if (hTransform)
467 				{
468 					ScLcmsColorTransformImpl* newTrans = new ScLcmsColorTransformImpl(engine, hTransform);
469 					newTrans->setTransformInfo(transInfo);
470 					transform = ScColorTransform(dynamic_cast<ScColorTransformData*>(newTrans));
471 					m_transformPool->addTransform(transform, true);
472 				}
473 			}
474 			catch (lcmsException& e)
475 			{
476 				std::cerr << e.what() << std::endl;
477 				// #9922 : no idea why that crash in release mode
478 				/*if (transform.isNull() && hTransform)
479 					cmsDeleteTransform(hTransform);*/
480 				transform = ScColorTransform();
481 			}
482 			cmsSetErrorHandler(nullptr);
483 		}
484 	}
485 	return transform;
486 }
487 
translateFlagsToLcmsFlags(long flags)488 DWORD ScLcmsColorMgmtEngineImpl::translateFlagsToLcmsFlags(long flags)
489 {
490 	DWORD lFlags = 0;
491 	if (flags & Ctf_BlackPointCompensation)
492 		lFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
493 	if (flags & Ctf_BlackPreservation)
494 		lFlags |= cmsFLAGS_PRESERVEBLACK;
495 	if (flags & Ctf_Softproofing)
496 		lFlags |= cmsFLAGS_SOFTPROOFING;
497 	if (flags & Ctf_GamutCheck)
498 		lFlags |= cmsFLAGS_GAMUTCHECK;
499 	return lFlags;
500 }
501 
translateFormatToLcmsFormat(eColorFormat format)502 DWORD ScLcmsColorMgmtEngineImpl::translateFormatToLcmsFormat(eColorFormat format)
503 {
504 	DWORD lFormat = 0;
505 	if (format == Format_RGB_8)
506 		lFormat = TYPE_RGB_8;
507 	if (format == Format_RGB_16)
508 		lFormat = TYPE_RGB_16;
509 	if (format == Format_RGBA_8)
510 		lFormat = TYPE_RGBA_8;
511 	if (format == Format_RGBA_16)
512 		lFormat = TYPE_RGBA_16;
513 	if (format == Format_ARGB_8)
514 		lFormat = TYPE_ARGB_8;
515 	if (format == Format_ARGB_16)
516 		lFormat = TYPE_ARGB_16;
517 	if (format == Format_BGRA_8)
518 		lFormat = TYPE_BGRA_8;
519 	if (format == Format_BGRA_16)
520 		lFormat = TYPE_BGRA_16;
521 	if (format == Format_CMYK_8)
522 		lFormat = TYPE_CMYK_8;
523 	if (format == Format_CMYK_16)
524 		lFormat = TYPE_CMYK_16;
525 	if (format == Format_CMYKA_8)
526 		lFormat = (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(1));
527 	if (format == Format_CMYKA_16)
528 		lFormat = (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(2));
529 	if (format == Format_YMCK_8)
530 		lFormat = (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1));
531 	if (format == Format_YMCK_16)
532 		lFormat = (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1));
533 	if (format == Format_GRAY_8)
534 		lFormat = TYPE_GRAY_8;
535 	if (format == Format_GRAY_16)
536 		lFormat = TYPE_GRAY_16;
537 	if (format == Format_LabA_8)
538 		lFormat = COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1);
539 	return lFormat;
540 }
541 
translateIntentToLcmsIntent(eRenderIntent intent,eRenderIntent defIntent)542 int ScLcmsColorMgmtEngineImpl::translateIntentToLcmsIntent(eRenderIntent intent, eRenderIntent defIntent)
543 {
544 	int lIntent = defIntent;
545 	if (intent == Intent_Perceptual)
546 		lIntent = INTENT_PERCEPTUAL;
547 	if (intent == Intent_Relative_Colorimetric)
548 		lIntent = INTENT_RELATIVE_COLORIMETRIC;
549 	if (intent == Intent_Saturation)
550 		lIntent = INTENT_SATURATION;
551 	if (intent == Intent_Absolute_Colorimetric)
552 		lIntent = INTENT_ABSOLUTE_COLORIMETRIC;
553 	return lIntent;
554 }
555 
translateLcmsColorSpaceType(icColorSpaceSignature signature)556 eColorSpaceType ScLcmsColorMgmtEngineImpl::translateLcmsColorSpaceType(icColorSpaceSignature signature)
557 {
558 	eColorSpaceType colorSpaceType = ColorSpace_Unknown;
559 	if (signature == icSigXYZData)
560 		colorSpaceType = ColorSpace_XYZ;
561 	if (signature == icSigLabData)
562 		colorSpaceType = ColorSpace_Lab;
563 	if (signature == icSigLuvData)
564 		colorSpaceType = ColorSpace_Luv;
565 	if (signature == icSigYCbCrData)
566 		colorSpaceType = ColorSpace_YCbCr;
567 	if (signature == icSigYxyData)
568 		colorSpaceType = ColorSpace_Yxy;
569 	if (signature == icSigRgbData)
570 		colorSpaceType = ColorSpace_Rgb;
571 	if (signature == icSigGrayData)
572 		colorSpaceType = ColorSpace_Gray;
573 	if (signature == icSigHsvData)
574 		colorSpaceType = ColorSpace_Hsv;
575 	if (signature == icSigHlsData)
576 		colorSpaceType = ColorSpace_Hls;
577 	if (signature == icSigCmykData)
578 		colorSpaceType = ColorSpace_Cmyk;
579 	if (signature == icSigCmyData)
580 		colorSpaceType = ColorSpace_Cmy;
581 	return colorSpaceType;
582 }
583 
translateLcmsProfileClass(icProfileClassSignature signature)584 eProfileClass ScLcmsColorMgmtEngineImpl::translateLcmsProfileClass(icProfileClassSignature signature)
585 {
586 	eProfileClass profileClass = Class_Unknown;
587 	if (signature == icSigInputClass)
588 		profileClass = Class_Input;
589 	if (signature == icSigDisplayClass)
590 		profileClass = Class_Display;
591 	if (signature == icSigOutputClass)
592 		profileClass = Class_Output;
593 	if (signature == icSigLinkClass)
594 		profileClass = Class_Link;
595 	if (signature == icSigAbstractClass)
596 		profileClass = Class_Abstract;
597 	if (signature == icSigColorSpaceClass)
598 		profileClass = Class_ColorSpace;
599 	if (signature == icSigNamedColorClass)
600 		profileClass = Class_NamedColor;
601 	return profileClass;
602 }
603 
cmsErrorHandler(int,const char * ErrorText)604 int ScLcmsColorMgmtEngineImpl::cmsErrorHandler(int /*ErrorCode*/, const char *ErrorText)
605 {
606 	std::string msg = std::string("Littlecms : ") + ErrorText;
607 	throw lcmsException(msg.c_str());
608 	return 1;
609 }
610