OLD | NEW |
---|---|
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "core/fxcodec/codec/codec_int.h" | 7 #include "core/fxcodec/codec/codec_int.h" |
8 #include "core/fxcodec/include/fx_codec.h" | 8 #include "core/fxcodec/include/fx_codec.h" |
9 #include "third_party/lcms2-2.6/include/lcms2.h" | 9 #include "third_party/lcms2-2.6/include/lcms2.h" |
10 | 10 |
11 const uint32_t N_COMPONENT_LAB = 3; | 11 const uint32_t N_COMPONENT_LAB = 3; |
12 const uint32_t N_COMPONENT_GRAY = 1; | 12 const uint32_t N_COMPONENT_GRAY = 1; |
13 const uint32_t N_COMPONENT_RGB = 3; | 13 const uint32_t N_COMPONENT_RGB = 3; |
14 const uint32_t N_COMPONENT_CMYK = 4; | 14 const uint32_t N_COMPONENT_CMYK = 4; |
15 const uint32_t N_COMPONENT_DEFAULT = 3; | 15 const uint32_t N_COMPONENT_DEFAULT = 3; |
16 | 16 |
17 FX_BOOL MD5ComputeID(const void* buf, uint32_t dwSize, uint8_t ID[16]) { | |
18 return cmsMD5computeIDExt(buf, dwSize, ID); | |
19 } | |
20 struct CLcmsCmm { | 17 struct CLcmsCmm { |
Tom Sepez
2016/09/19 16:40:22
note: as a follow-up CL, you might want to put thi
| |
21 cmsHTRANSFORM m_hTransform; | 18 cmsHTRANSFORM m_hTransform; |
22 int m_nSrcComponents; | 19 int m_nSrcComponents; |
23 int m_nDstComponents; | 20 int m_nDstComponents; |
24 FX_BOOL m_bLab; | 21 FX_BOOL m_bLab; |
25 }; | 22 }; |
26 extern "C" { | |
27 int ourHandler(int ErrorCode, const char* ErrorText) { | |
28 return TRUE; | |
29 } | |
30 }; | |
31 FX_BOOL CheckComponents(cmsColorSpaceSignature cs, | 23 FX_BOOL CheckComponents(cmsColorSpaceSignature cs, |
32 int nComponents, | 24 int nComponents, |
33 FX_BOOL bDst) { | 25 FX_BOOL bDst) { |
34 if (nComponents <= 0 || nComponents > 15) { | 26 if (nComponents <= 0 || nComponents > 15) { |
35 return FALSE; | 27 return FALSE; |
36 } | 28 } |
37 switch (cs) { | 29 switch (cs) { |
38 case cmsSigLabData: | 30 case cmsSigLabData: |
39 if (nComponents < 3) { | 31 if (nComponents < 3) { |
40 return FALSE; | 32 return FALSE; |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
231 break; | 223 break; |
232 } | 224 } |
233 } | 225 } |
234 void IccLib_TranslateImage(void* pTransform, | 226 void IccLib_TranslateImage(void* pTransform, |
235 unsigned char* pDest, | 227 unsigned char* pDest, |
236 const unsigned char* pSrc, | 228 const unsigned char* pSrc, |
237 int32_t pixels) { | 229 int32_t pixels) { |
238 cmsDoTransform(((CLcmsCmm*)pTransform)->m_hTransform, (void*)pSrc, pDest, | 230 cmsDoTransform(((CLcmsCmm*)pTransform)->m_hTransform, (void*)pSrc, pDest, |
239 pixels); | 231 pixels); |
240 } | 232 } |
241 void* CreateProfile_Gray(double gamma) { | |
242 cmsCIExyY* D50 = (cmsCIExyY*)cmsD50_xyY(); | |
243 if (!cmsWhitePointFromTemp(D50, 6504)) { | |
244 return nullptr; | |
245 } | |
246 cmsToneCurve* curve = cmsBuildGamma(nullptr, gamma); | |
247 if (!curve) { | |
248 return nullptr; | |
249 } | |
250 void* profile = cmsCreateGrayProfile(D50, curve); | |
251 cmsFreeToneCurve(curve); | |
252 return profile; | |
253 } | |
254 CCodec_IccModule::IccCS GetProfileCSFromHandle(void* pProfile) { | |
255 if (!pProfile) { | |
256 return CCodec_IccModule::IccCS_Unknown; | |
257 } | |
258 switch (cmsGetColorSpace(pProfile)) { | |
259 case cmsSigXYZData: | |
260 return CCodec_IccModule::IccCS_XYZ; | |
261 case cmsSigLabData: | |
262 return CCodec_IccModule::IccCS_Lab; | |
263 case cmsSigLuvData: | |
264 return CCodec_IccModule::IccCS_Luv; | |
265 case cmsSigYCbCrData: | |
266 return CCodec_IccModule::IccCS_YCbCr; | |
267 case cmsSigYxyData: | |
268 return CCodec_IccModule::IccCS_Yxy; | |
269 case cmsSigRgbData: | |
270 return CCodec_IccModule::IccCS_Rgb; | |
271 case cmsSigGrayData: | |
272 return CCodec_IccModule::IccCS_Gray; | |
273 case cmsSigHsvData: | |
274 return CCodec_IccModule::IccCS_Hsv; | |
275 case cmsSigHlsData: | |
276 return CCodec_IccModule::IccCS_Hls; | |
277 case cmsSigCmykData: | |
278 return CCodec_IccModule::IccCS_Cmyk; | |
279 case cmsSigCmyData: | |
280 return CCodec_IccModule::IccCS_Cmy; | |
281 default: | |
282 return CCodec_IccModule::IccCS_Unknown; | |
283 } | |
284 } | |
285 CCodec_IccModule::IccCS CCodec_IccModule::GetProfileCS( | |
286 const uint8_t* pProfileData, | |
287 uint32_t dwProfileSize) { | |
288 CCodec_IccModule::IccCS cs; | |
289 cmsHPROFILE hProfile = | |
290 cmsOpenProfileFromMem((void*)pProfileData, dwProfileSize); | |
291 if (!hProfile) { | |
292 return IccCS_Unknown; | |
293 } | |
294 cs = GetProfileCSFromHandle(hProfile); | |
295 if (hProfile) { | |
296 cmsCloseProfile(hProfile); | |
297 } | |
298 return cs; | |
299 } | |
300 CCodec_IccModule::IccCS CCodec_IccModule::GetProfileCS(IFX_FileRead* pFile) { | |
301 if (!pFile) { | |
302 return IccCS_Unknown; | |
303 } | |
304 CCodec_IccModule::IccCS cs; | |
305 uint32_t dwSize = (uint32_t)pFile->GetSize(); | |
306 uint8_t* pBuf = FX_Alloc(uint8_t, dwSize); | |
307 pFile->ReadBlock(pBuf, 0, dwSize); | |
308 cs = GetProfileCS(pBuf, dwSize); | |
309 FX_Free(pBuf); | |
310 return cs; | |
311 } | |
312 uint32_t TransferProfileType(void* pProfile, uint32_t dwFormat) { | |
313 cmsColorSpaceSignature cs = cmsGetColorSpace(pProfile); | |
314 switch (cs) { | |
315 case cmsSigXYZData: | |
316 return TYPE_XYZ_16; | |
317 case cmsSigLabData: | |
318 return TYPE_Lab_DBL; | |
319 case cmsSigLuvData: | |
320 return TYPE_YUV_8; | |
321 case cmsSigYCbCrData: | |
322 return TYPE_YCbCr_8; | |
323 case cmsSigYxyData: | |
324 return TYPE_Yxy_16; | |
325 case cmsSigRgbData: | |
326 return T_DOSWAP(dwFormat) ? TYPE_RGB_8 : TYPE_BGR_8; | |
327 case cmsSigGrayData: | |
328 return TYPE_GRAY_8; | |
329 case cmsSigHsvData: | |
330 return TYPE_HSV_8; | |
331 case cmsSigHlsData: | |
332 return TYPE_HLS_8; | |
333 case cmsSigCmykData: | |
334 return T_DOSWAP(dwFormat) ? TYPE_KYMC_8 : TYPE_CMYK_8; | |
335 case cmsSigCmyData: | |
336 return TYPE_CMY_8; | |
337 case cmsSigMCH5Data: | |
338 return T_DOSWAP(dwFormat) ? TYPE_KYMC5_8 : TYPE_CMYK5_8; | |
339 case cmsSigMCH6Data: | |
340 return TYPE_CMYK6_8; | |
341 case cmsSigMCH7Data: | |
342 return T_DOSWAP(dwFormat) ? TYPE_KYMC7_8 : TYPE_CMYK7_8; | |
343 case cmsSigMCH8Data: | |
344 return T_DOSWAP(dwFormat) ? TYPE_KYMC8_8 : TYPE_CMYK8_8; | |
345 case cmsSigMCH9Data: | |
346 return T_DOSWAP(dwFormat) ? TYPE_KYMC9_8 : TYPE_CMYK9_8; | |
347 case cmsSigMCHAData: | |
348 return T_DOSWAP(dwFormat) ? TYPE_KYMC10_8 : TYPE_CMYK10_8; | |
349 case cmsSigMCHBData: | |
350 return T_DOSWAP(dwFormat) ? TYPE_KYMC11_8 : TYPE_CMYK11_8; | |
351 case cmsSigMCHCData: | |
352 return T_DOSWAP(dwFormat) ? TYPE_KYMC12_8 : TYPE_CMYK12_8; | |
353 default: | |
354 return 0; | |
355 } | |
356 } | |
357 class CFX_IccProfileCache { | |
358 public: | |
359 CFX_IccProfileCache(); | |
360 ~CFX_IccProfileCache(); | |
361 void* m_pProfile; | |
362 uint32_t m_dwRate; | |
363 | |
364 protected: | |
365 void Purge(); | |
366 }; | |
367 CFX_IccProfileCache::CFX_IccProfileCache() { | |
368 m_pProfile = nullptr; | |
369 m_dwRate = 1; | |
370 } | |
371 CFX_IccProfileCache::~CFX_IccProfileCache() { | |
372 if (m_pProfile) { | |
373 cmsCloseProfile(m_pProfile); | |
374 } | |
375 } | |
376 void CFX_IccProfileCache::Purge() {} | |
377 class CFX_IccTransformCache { | |
378 public: | |
379 CFX_IccTransformCache(CLcmsCmm* pCmm = nullptr); | |
380 ~CFX_IccTransformCache(); | |
381 void* m_pIccTransform; | |
382 uint32_t m_dwRate; | |
383 CLcmsCmm* m_pCmm; | |
384 | |
385 protected: | |
386 void Purge(); | |
387 }; | |
388 CFX_IccTransformCache::CFX_IccTransformCache(CLcmsCmm* pCmm) { | |
389 m_pIccTransform = nullptr; | |
390 m_dwRate = 1; | |
391 m_pCmm = pCmm; | |
392 } | |
393 CFX_IccTransformCache::~CFX_IccTransformCache() { | |
394 if (m_pIccTransform) { | |
395 cmsDeleteTransform(m_pIccTransform); | |
396 } | |
397 FX_Free(m_pCmm); | |
398 } | |
399 void CFX_IccTransformCache::Purge() {} | |
400 class CFX_ByteStringKey : public CFX_BinaryBuf { | |
401 public: | |
402 CFX_ByteStringKey() : CFX_BinaryBuf() {} | |
403 CFX_ByteStringKey& operator<<(uint32_t i); | |
404 }; | |
405 CFX_ByteStringKey& CFX_ByteStringKey::operator<<(uint32_t i) { | |
406 AppendBlock(&i, sizeof(uint32_t)); | |
407 return *this; | |
408 } | |
409 void* CCodec_IccModule::CreateProfile(CCodec_IccModule::IccParam* pIccParam, | |
410 Icc_CLASS ic, | |
411 CFX_BinaryBuf* pTransformKey) { | |
412 CFX_IccProfileCache* pCache = nullptr; | |
413 CFX_ByteStringKey key; | |
414 CFX_ByteString text; | |
415 key << pIccParam->ColorSpace << (pIccParam->dwProfileType | ic << 8); | |
416 uint8_t ID[16]; | |
417 switch (pIccParam->dwProfileType) { | |
418 case Icc_PARAMTYPE_NONE: | |
419 return nullptr; | |
420 case Icc_PARAMTYPE_BUFFER: | |
421 MD5ComputeID(pIccParam->pProfileData, pIccParam->dwProfileSize, ID); | |
422 break; | |
423 case Icc_PARAMTYPE_PARAM: | |
424 FXSYS_memset(ID, 0, 16); | |
425 switch (pIccParam->ColorSpace) { | |
426 case IccCS_Gray: | |
427 text.Format("%lf", pIccParam->Gamma); | |
428 break; | |
429 default: | |
430 break; | |
431 } | |
432 MD5ComputeID(text.GetBuffer(0), text.GetLength(), ID); | |
433 break; | |
434 default: | |
435 break; | |
436 } | |
437 key.AppendBlock(ID, 16); | |
438 CFX_ByteString ProfileKey(key.GetBuffer(), key.GetSize()); | |
439 ASSERT(pTransformKey); | |
440 pTransformKey->AppendBlock(ProfileKey.GetBuffer(0), ProfileKey.GetLength()); | |
441 auto it = m_MapProfile.find(ProfileKey); | |
442 if (it == m_MapProfile.end()) { | |
443 pCache = new CFX_IccProfileCache; | |
444 switch (pIccParam->dwProfileType) { | |
445 case Icc_PARAMTYPE_BUFFER: | |
446 pCache->m_pProfile = cmsOpenProfileFromMem(pIccParam->pProfileData, | |
447 pIccParam->dwProfileSize); | |
448 break; | |
449 case Icc_PARAMTYPE_PARAM: | |
450 switch (pIccParam->ColorSpace) { | |
451 case IccCS_Rgb: | |
452 pCache->m_pProfile = cmsCreate_sRGBProfile(); | |
453 break; | |
454 case IccCS_Gray: | |
455 pCache->m_pProfile = CreateProfile_Gray(pIccParam->Gamma); | |
456 break; | |
457 default: | |
458 break; | |
459 } | |
460 break; | |
461 default: | |
462 break; | |
463 } | |
464 m_MapProfile[ProfileKey] = pCache; | |
465 } else { | |
466 pCache = it->second; | |
467 pCache->m_dwRate++; | |
468 } | |
469 return pCache->m_pProfile; | |
470 } | |
471 void* CCodec_IccModule::CreateTransform( | |
472 CCodec_IccModule::IccParam* pInputParam, | |
473 CCodec_IccModule::IccParam* pOutputParam, | |
474 CCodec_IccModule::IccParam* pProofParam, | |
475 uint32_t dwIntent, | |
476 uint32_t dwFlag, | |
477 uint32_t dwPrfIntent, | |
478 uint32_t dwPrfFlag) { | |
479 CLcmsCmm* pCmm = nullptr; | |
480 ASSERT(pInputParam && pOutputParam); | |
481 CFX_ByteStringKey key; | |
482 void* pInputProfile = CreateProfile(pInputParam, Icc_CLASS_INPUT, &key); | |
483 if (!pInputProfile) { | |
484 return nullptr; | |
485 } | |
486 void* pOutputProfile = CreateProfile(pOutputParam, Icc_CLASS_OUTPUT, &key); | |
487 if (!pOutputProfile) { | |
488 return nullptr; | |
489 } | |
490 uint32_t dwInputProfileType = | |
491 TransferProfileType(pInputProfile, pInputParam->dwFormat); | |
492 uint32_t dwOutputProfileType = | |
493 TransferProfileType(pOutputProfile, pOutputParam->dwFormat); | |
494 if (dwInputProfileType == 0 || dwOutputProfileType == 0) { | |
495 return nullptr; | |
496 } | |
497 void* pProofProfile = nullptr; | |
498 if (pProofParam) { | |
499 pProofProfile = CreateProfile(pProofParam, Icc_CLASS_PROOF, &key); | |
500 } | |
501 key << dwInputProfileType << dwOutputProfileType << dwIntent << dwFlag | |
502 << !!pProofProfile << dwPrfIntent << dwPrfFlag; | |
503 CFX_ByteString TransformKey(key.GetBuffer(), key.GetSize()); | |
504 CFX_IccTransformCache* pTransformCache; | |
505 auto it = m_MapTranform.find(TransformKey); | |
506 if (it == m_MapTranform.end()) { | |
507 pCmm = FX_Alloc(CLcmsCmm, 1); | |
508 pCmm->m_nSrcComponents = T_CHANNELS(dwInputProfileType); | |
509 pCmm->m_nDstComponents = T_CHANNELS(dwOutputProfileType); | |
510 pCmm->m_bLab = T_COLORSPACE(pInputParam->dwFormat) == PT_Lab; | |
511 pTransformCache = new CFX_IccTransformCache(pCmm); | |
512 if (pProofProfile) { | |
513 pTransformCache->m_pIccTransform = cmsCreateProofingTransform( | |
514 pInputProfile, dwInputProfileType, pOutputProfile, | |
515 dwOutputProfileType, pProofProfile, dwIntent, dwPrfIntent, dwPrfFlag); | |
516 } else { | |
517 pTransformCache->m_pIccTransform = | |
518 cmsCreateTransform(pInputProfile, dwInputProfileType, pOutputProfile, | |
519 dwOutputProfileType, dwIntent, dwFlag); | |
520 } | |
521 pCmm->m_hTransform = pTransformCache->m_pIccTransform; | |
522 m_MapTranform[TransformKey] = pTransformCache; | |
523 } else { | |
524 pTransformCache = it->second; | |
525 pTransformCache->m_dwRate++; | |
526 } | |
527 return pTransformCache->m_pCmm; | |
528 } | |
529 | 233 |
530 CCodec_IccModule::CCodec_IccModule() : m_nComponents(0) {} | 234 CCodec_IccModule::CCodec_IccModule() : m_nComponents(0) {} |
531 | 235 |
532 CCodec_IccModule::~CCodec_IccModule() { | 236 CCodec_IccModule::~CCodec_IccModule() { |
533 for (const auto& pair : m_MapProfile) { | |
534 delete pair.second; | |
535 } | |
536 m_MapProfile.clear(); | |
537 for (const auto& pair : m_MapTranform) { | |
538 delete pair.second; | |
539 } | |
540 m_MapTranform.clear(); | |
541 } | 237 } |
542 void* CCodec_IccModule::CreateTransform_sRGB(const uint8_t* pProfileData, | 238 void* CCodec_IccModule::CreateTransform_sRGB(const uint8_t* pProfileData, |
543 uint32_t dwProfileSize, | 239 uint32_t dwProfileSize, |
544 uint32_t& nComponents, | 240 uint32_t& nComponents, |
545 int32_t intent, | 241 int32_t intent, |
546 uint32_t dwSrcFormat) { | 242 uint32_t dwSrcFormat) { |
547 return IccLib_CreateTransform_sRGB(pProfileData, dwProfileSize, nComponents, | 243 return IccLib_CreateTransform_sRGB(pProfileData, dwProfileSize, nComponents, |
548 intent, dwSrcFormat); | 244 intent, dwSrcFormat); |
549 } | 245 } |
550 | 246 |
551 void* CCodec_IccModule::CreateTransform_CMYK(const uint8_t* pSrcProfileData, | |
552 uint32_t dwSrcProfileSize, | |
553 uint32_t& nSrcComponents, | |
554 const uint8_t* pDstProfileData, | |
555 uint32_t dwDstProfileSize, | |
556 int32_t intent, | |
557 uint32_t dwSrcFormat, | |
558 uint32_t dwDstFormat) { | |
559 return IccLib_CreateTransform( | |
560 pSrcProfileData, dwSrcProfileSize, nSrcComponents, pDstProfileData, | |
561 dwDstProfileSize, 4, intent, dwSrcFormat, dwDstFormat); | |
562 } | |
563 | |
564 void CCodec_IccModule::DestroyTransform(void* pTransform) { | 247 void CCodec_IccModule::DestroyTransform(void* pTransform) { |
565 IccLib_DestroyTransform(pTransform); | 248 IccLib_DestroyTransform(pTransform); |
566 } | 249 } |
567 void CCodec_IccModule::Translate(void* pTransform, | 250 void CCodec_IccModule::Translate(void* pTransform, |
568 FX_FLOAT* pSrcValues, | 251 FX_FLOAT* pSrcValues, |
569 FX_FLOAT* pDestValues) { | 252 FX_FLOAT* pDestValues) { |
570 IccLib_Translate(pTransform, m_nComponents, pSrcValues, pDestValues); | 253 IccLib_Translate(pTransform, m_nComponents, pSrcValues, pDestValues); |
571 } | 254 } |
572 void CCodec_IccModule::TranslateScanline(void* pTransform, | 255 void CCodec_IccModule::TranslateScanline(void* pTransform, |
573 uint8_t* pDest, | 256 uint8_t* pDest, |
(...skipping 1424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1998 ASSERT(k1 == FXSYS_round(k * 255)); | 1681 ASSERT(k1 == FXSYS_round(k * 255)); |
1999 | 1682 |
2000 uint8_t r, g, b; | 1683 uint8_t r, g, b; |
2001 AdobeCMYK_to_sRGB1(c1, m1, y1, k1, r, g, b); | 1684 AdobeCMYK_to_sRGB1(c1, m1, y1, k1, r, g, b); |
2002 // Multiply by a constant rather than dividing because division is much | 1685 // Multiply by a constant rather than dividing because division is much |
2003 // more expensive. | 1686 // more expensive. |
2004 R = r * (1.0f / 255); | 1687 R = r * (1.0f / 255); |
2005 G = g * (1.0f / 255); | 1688 G = g * (1.0f / 255); |
2006 B = b * (1.0f / 255); | 1689 B = b * (1.0f / 255); |
2007 } | 1690 } |
OLD | NEW |