Use number of components from ICC profile and alternate color space

BUG=406806

Review URL: https://codereview.chromium.org/493163003
diff --git a/core/include/fpdfapi/fpdf_parser.h b/core/include/fpdfapi/fpdf_parser.h
index 1007202..da22dc7 100644
--- a/core/include/fpdfapi/fpdf_parser.h
+++ b/core/include/fpdfapi/fpdf_parser.h
@@ -134,7 +134,7 @@
 
     CPDF_StreamAcc*			LoadFontFile(CPDF_Stream* pStream);
 
-    CPDF_IccProfile*		LoadIccProfile(CPDF_Stream* pStream, int nComponents);
+    CPDF_IccProfile*		LoadIccProfile(CPDF_Stream* pStream);
 
 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
 
diff --git a/core/include/fxcodec/fx_codec.h b/core/include/fxcodec/fx_codec.h
index ac3f71e..32d5c58 100644
--- a/core/include/fxcodec/fx_codec.h
+++ b/core/include/fxcodec/fx_codec.h
@@ -267,11 +267,11 @@
                                      ) = 0;
 
 
-    virtual FX_LPVOID	CreateTransform_sRGB(FX_LPCBYTE pProfileData, unsigned int dwProfileSize, int nComponents, int intent = 0,
+    virtual FX_LPVOID	CreateTransform_sRGB(FX_LPCBYTE pProfileData, FX_DWORD dwProfileSize, FX_INT32* nComponents, FX_INT32 intent = 0,
             FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT) = 0;
 
-    virtual FX_LPVOID	CreateTransform_CMYK(FX_LPCBYTE pSrcProfileData, unsigned int dwSrcProfileSize, int nSrcComponents,
-            FX_LPCBYTE pDstProfileData, unsigned int dwDstProfileSize, int intent = 0,
+    virtual FX_LPVOID	CreateTransform_CMYK(FX_LPCBYTE pSrcProfileData, FX_DWORD dwSrcProfileSize, FX_INT32* nSrcComponents,
+            FX_LPCBYTE pDstProfileData, FX_DWORD dwDstProfileSize, FX_INT32 intent = 0,
             FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT,
             FX_DWORD dwDstFormat = Icc_FORMAT_DEFAULT
                                           ) = 0;
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_colors.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_colors.cpp
index f1640ad..b5b4695 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_colors.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_colors.cpp
@@ -517,12 +517,16 @@
         pSrcBuf += 3;
     }
 }
-CPDF_IccProfile::CPDF_IccProfile(FX_LPCBYTE pData, FX_DWORD dwSize, int nComponents)
+CPDF_IccProfile::CPDF_IccProfile(FX_LPCBYTE pData, FX_DWORD dwSize)
 {
-    m_bsRGB = nComponents == 3 && dwSize == 3144 && FXSYS_memcmp32(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0;
-    m_pTransform = NULL;
-    if (!m_bsRGB && CPDF_ModuleMgr::Get()->GetIccModule()) {
-        m_pTransform = CPDF_ModuleMgr::Get()->GetIccModule()->CreateTransform_sRGB(pData, dwSize, nComponents);
+    if (dwSize == 3144 && FXSYS_memcmp32(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0) {
+        m_bsRGB = TRUE;
+        m_pTransform = NULL;
+        m_nSrcComponents = 3;
+    }
+    else if (CPDF_ModuleMgr::Get()->GetIccModule()) {
+        m_bsRGB = FALSE;
+        m_pTransform = CPDF_ModuleMgr::Get()->GetIccModule()->CreateTransform_sRGB(pData, dwSize, &m_nSrcComponents);
     }
 }
 CPDF_IccProfile::~CPDF_IccProfile()
@@ -583,11 +587,58 @@
     if (pStream == NULL) {
         return FALSE;
     }
-    CPDF_Dictionary* pDict = pStream->GetDict();
-    m_nComponents = pDict ? pDict->GetInteger(FX_BSTRC("N")) : 0;
-    if (m_nComponents != 1 && m_nComponents != 3 && m_nComponents != 4) {
+    m_pProfile = pDoc->LoadIccProfile(pStream);
+    if (!m_pProfile) {
         return FALSE;
     }
+    m_nComponents = m_pProfile->GetComponents(); //Try using the nComponents from ICC profile
+    CPDF_Dictionary* pDict = pStream->GetDict();
+    FX_INT32 Dict_nComponents = pDict ? pDict->GetInteger(FX_BSTRC("N")) : 0;
+    if (m_pProfile->m_pTransform == NULL) { // No valid ICC profile or using sRGB
+        CPDF_Object* pAlterCSObj = pDict ? pDict->GetElementValue(FX_BSTRC("Alternate")) : NULL;
+        if (pAlterCSObj) {
+            CPDF_ColorSpace* alter_cs = CPDF_ColorSpace::Load(pDoc, pAlterCSObj);
+            if (alter_cs) {
+                if (m_nComponents == 0) { // NO valid ICC profile
+                    if (alter_cs->CountComponents() > 0) { // Use Alternative colorspace
+                        m_nComponents = alter_cs->CountComponents();
+                        m_pAlterCS = alter_cs;
+                        m_bOwn = TRUE;
+                    }
+                    else { // No valid alternative colorspace
+                        alter_cs->ReleaseCS();
+                        if (Dict_nComponents == 1 || Dict_nComponents == 3 || Dict_nComponents == 4 ) {
+                            m_nComponents = Dict_nComponents;
+                        }
+                        else {
+                            return FALSE;
+                        }
+                    }
+
+                }
+                else { // Using sRGB
+                    if (alter_cs->CountComponents() != m_nComponents) {
+                        alter_cs->ReleaseCS();
+                    }
+                    else {
+                        m_pAlterCS = alter_cs;
+                        m_bOwn = TRUE;
+                    }
+                }
+            }
+        }
+        if (!m_pAlterCS) {
+            if (m_nComponents == 1) {
+                m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY);
+            }
+            if (m_nComponents == 3) {
+                m_pAlterCS = GetStockCS(PDFCS_DEVICERGB);
+            }
+            else if (m_nComponents == 4) {
+                m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK);
+            }
+        }
+    }
     CPDF_Array* pRanges = pDict->GetArray(FX_BSTRC("Range"));
     m_pRanges = FX_Alloc(FX_FLOAT, m_nComponents * 2);
     for (int i = 0; i < m_nComponents * 2; i ++) {
@@ -599,33 +650,6 @@
             m_pRanges[i] = 0;
         }
     }
-    m_pProfile = pDoc->LoadIccProfile(pStream, m_nComponents);
-    if (!m_pProfile) {
-        return FALSE;
-    }
-    if (m_pProfile->m_pTransform == NULL) {
-        CPDF_Object* pAlterCSObj = pDict ? pDict->GetElementValue(FX_BSTRC("Alternate")) : NULL;
-        if (pAlterCSObj) {
-            CPDF_ColorSpace* alter_cs = CPDF_ColorSpace::Load(pDoc, pAlterCSObj);
-            if (alter_cs) {
-                if (alter_cs->CountComponents() > m_nComponents) {
-                    alter_cs->ReleaseCS();
-                } else {
-                    m_pAlterCS = alter_cs;
-                    m_bOwn = TRUE;
-                }
-            }
-        }
-        if (!m_pAlterCS) {
-            if (m_nComponents == 3) {
-                m_pAlterCS = GetStockCS(PDFCS_DEVICERGB);
-            } else if (m_nComponents == 4) {
-                m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK);
-            } else {
-                m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY);
-            }
-        }
-    }
     return TRUE;
 }
 FX_BOOL CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_doc.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_doc.cpp
index 0b52800..16f0a9c 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_doc.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_doc.cpp
@@ -107,9 +107,9 @@
 {
     return GetValidatePageData()->GetPattern(pPatternObj, bShading, matrix);
 }
-CPDF_IccProfile* CPDF_Document::LoadIccProfile(CPDF_Stream* pStream, int nComponents)
+CPDF_IccProfile* CPDF_Document::LoadIccProfile(CPDF_Stream* pStream)
 {
-    return GetValidatePageData()->GetIccProfile(pStream, nComponents);
+    return GetValidatePageData()->GetIccProfile(pStream);
 }
 CPDF_Image* CPDF_Document::LoadImageF(CPDF_Object* pObj)
 {
@@ -543,7 +543,7 @@
     }
     PDF_DocPageData_Release<FX_DWORD, CPDF_Image*>(m_ImageMap, pImageStream->GetObjNum(), NULL);
 }
-CPDF_IccProfile* CPDF_DocPageData::GetIccProfile(CPDF_Stream* pIccProfileStream, FX_INT32 nComponents)
+CPDF_IccProfile* CPDF_DocPageData::GetIccProfile(CPDF_Stream* pIccProfileStream)
 {
     if (!pIccProfileStream) {
         return NULL;
@@ -563,7 +563,7 @@
         ipData->m_nCount++;
         return ipData->m_Obj;
     }
-    CPDF_IccProfile* pProfile = FX_NEW CPDF_IccProfile(stream.GetData(), stream.GetSize(), nComponents);
+    CPDF_IccProfile* pProfile = FX_NEW CPDF_IccProfile(stream.GetData(), stream.GetSize());
     if (!pProfile) {
         return NULL;
     }
diff --git a/core/src/fpdfapi/fpdf_page/pageint.h b/core/src/fpdfapi/fpdf_page/pageint.h
index 625e5df..24261ef 100644
--- a/core/src/fpdfapi/fpdf_page/pageint.h
+++ b/core/src/fpdfapi/fpdf_page/pageint.h
@@ -426,7 +426,7 @@
     void                        ReleasePattern(CPDF_Object* pPatternObj);
     CPDF_Image*                 GetImage(CPDF_Object* pImageStream);
     void                        ReleaseImage(CPDF_Object* pImageStream);
-    CPDF_IccProfile*            GetIccProfile(CPDF_Stream* pIccProfileStream, FX_INT32 nComponents);
+    CPDF_IccProfile*            GetIccProfile(CPDF_Stream* pIccProfileStream);
     void                        ReleaseIccProfile(CPDF_Stream* pIccProfileStream, CPDF_IccProfile* pIccProfile);
     CPDF_StreamAcc*             GetFontFileStreamAcc(CPDF_Stream* pFontStream);
     void                        ReleaseFontFileStreamAcc(CPDF_Stream* pFontStream, FX_BOOL bForce = FALSE);
@@ -468,9 +468,11 @@
 class CPDF_IccProfile : public CFX_Object
 {
 public:
-    CPDF_IccProfile(FX_LPCBYTE pData, FX_DWORD dwSize, int nComponents);
+    CPDF_IccProfile(FX_LPCBYTE pData, FX_DWORD dwSize);
     ~CPDF_IccProfile();
+    FX_INT32 GetComponents() { return m_nSrcComponents; }
     FX_BOOL					m_bsRGB;
+    FX_INT32                m_nSrcComponents;
     FX_LPVOID				m_pTransform;
 };
 class CPDF_DeviceCS : public CPDF_ColorSpace
diff --git a/core/src/fxcodec/codec/codec_int.h b/core/src/fxcodec/codec/codec_int.h
index 47f2c8e..1b97036 100644
--- a/core/src/fxcodec/codec/codec_int.h
+++ b/core/src/fxcodec/codec/codec_int.h
@@ -162,10 +162,10 @@
                                             FX_DWORD dwPrfIntent = Icc_INTENT_ABSOLUTE_COLORIMETRIC,
                                             FX_DWORD dwPrfFlag = Icc_FLAGS_SOFTPROOFING
                                       );
-    virtual FX_LPVOID		CreateTransform_sRGB(FX_LPCBYTE pProfileData, unsigned int dwProfileSize, int nComponents, int intent = 0,
+    virtual FX_LPVOID		CreateTransform_sRGB(FX_LPCBYTE pProfileData, FX_DWORD dwProfileSize, FX_INT32* nComponents, FX_INT32 intent = 0,
             FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT);
-    virtual FX_LPVOID		CreateTransform_CMYK(FX_LPCBYTE pSrcProfileData, unsigned int dwSrcProfileSize, int nSrcComponents,
-            FX_LPCBYTE pDstProfileData, unsigned int dwDstProfileSize, int intent = 0,
+    virtual FX_LPVOID		CreateTransform_CMYK(FX_LPCBYTE pSrcProfileData, FX_DWORD dwSrcProfileSize, FX_INT32* nSrcComponents,
+            FX_LPCBYTE pDstProfileData, FX_DWORD dwDstProfileSize, FX_INT32 intent = 0,
             FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT,
             FX_DWORD dwDstFormat = Icc_FORMAT_DEFAULT
                                            );
diff --git a/core/src/fxcodec/codec/fx_codec_icc.cpp b/core/src/fxcodec/codec/fx_codec_icc.cpp
index b10d9c4..f0ece07 100644
--- a/core/src/fxcodec/codec/fx_codec_icc.cpp
+++ b/core/src/fxcodec/codec/fx_codec_icc.cpp
@@ -7,6 +7,12 @@
 #include "../../../include/fxcodec/fx_codec.h"
 #include "codec_int.h"
 #include "../lcms2/include/fx_lcms2.h"
+#define N_COMPONENT_LAB 3
+#define N_COMPONENT_GRAY 1
+#define N_COMPONENT_RGB 3
+#define N_COMPONENT_CMYK 4
+#define N_COMPONENT_DEFAULT 3
+
 FX_BOOL MD5ComputeID( FX_LPCVOID buf, FX_DWORD dwSize, FX_BYTE ID[16] )
 {
     return cmsMD5computeIDExt(buf, dwSize, ID);
@@ -59,14 +65,35 @@
     }
     return TRUE;
 }
-void* IccLib_CreateTransform(const unsigned char* pSrcProfileData, unsigned int dwSrcProfileSize, int nSrcComponents,
-                             const unsigned char* pDstProfileData, unsigned int dwDstProfileSize, int nDstComponents,
+FX_INT32 GetCSComponents(cmsColorSpaceSignature cs)
+{
+    switch (cs) {
+        case cmsSigLabData:
+            return N_COMPONENT_LAB;
+            break;
+        case cmsSigGrayData:
+            return N_COMPONENT_GRAY;
+            break;
+        case cmsSigRgbData:
+            return N_COMPONENT_RGB;
+            break;
+        case cmsSigCmykData:
+            return N_COMPONENT_CMYK;
+            break;
+        default:
+            return N_COMPONENT_DEFAULT;
+            break;
+    }
+}
+void* IccLib_CreateTransform(const unsigned char* pSrcProfileData, FX_DWORD dwSrcProfileSize, FX_INT32* nSrcComponents,
+                             const unsigned char* pDstProfileData, FX_DWORD dwDstProfileSize, FX_INT32 nDstComponents,
                              int intent, FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT, FX_DWORD dwDstFormat = Icc_FORMAT_DEFAULT)
 {
     cmsHPROFILE srcProfile = NULL;
     cmsHPROFILE dstProfile = NULL;
     cmsHTRANSFORM hTransform = NULL;
     CLcmsCmm* pCmm = NULL;
+    *nSrcComponents = 0;
     srcProfile = cmsOpenProfileFromMem((void*)pSrcProfileData, dwSrcProfileSize);
     if (srcProfile == NULL) {
         return NULL;
@@ -83,16 +110,12 @@
     int srcFormat;
     FX_BOOL bLab = FALSE;
     cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile);
-    if (!CheckComponents(srcCS, nSrcComponents, FALSE)) {
-        cmsCloseProfile(srcProfile);
-        cmsCloseProfile(dstProfile);
-        return NULL;
-    }
+    *nSrcComponents = GetCSComponents(srcCS);
     if (srcCS == cmsSigLabData) {
-        srcFormat = COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0);
+        srcFormat = COLORSPACE_SH(PT_Lab) | CHANNELS_SH(*nSrcComponents) | BYTES_SH(0);
         bLab = TRUE;
     } else {
-        srcFormat = COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1);
+        srcFormat = COLORSPACE_SH(PT_ANY) | CHANNELS_SH(*nSrcComponents) | BYTES_SH(1);
         if (srcCS == cmsSigRgbData && T_DOSWAP(dwSrcFormat)) {
             srcFormat |= DOSWAP_SH(1);
         }
@@ -127,7 +150,7 @@
     if (pCmm == NULL) {
         return NULL;
     }
-    pCmm->m_nSrcComponents = nSrcComponents;
+    pCmm->m_nSrcComponents = *nSrcComponents;
     pCmm->m_nDstComponents = nDstComponents;
     pCmm->m_hTransform = hTransform;
     pCmm->m_bLab = bLab;
@@ -135,7 +158,7 @@
     cmsCloseProfile(dstProfile);
     return pCmm;
 }
-void* IccLib_CreateTransform_sRGB(const unsigned char* pProfileData, unsigned int dwProfileSize, int nComponents, int intent, FX_DWORD dwSrcFormat)
+void* IccLib_CreateTransform_sRGB(const unsigned char* pProfileData, FX_DWORD dwProfileSize, FX_INT32* nComponents, FX_INT32 intent, FX_DWORD dwSrcFormat)
 {
     return IccLib_CreateTransform(pProfileData, dwProfileSize, nComponents, NULL, 0, 3, intent, dwSrcFormat);
 }
@@ -192,7 +215,7 @@
             break;
     }
 }
-void IccLib_TranslateImage(void* pTransform, unsigned char* pDest, const unsigned char* pSrc, int pixels)
+void IccLib_TranslateImage(void* pTransform, unsigned char* pDest, const unsigned char* pSrc, FX_INT32 pixels)
 {
     cmsDoTransform(((CLcmsCmm*)pTransform)->m_hTransform, (void*)pSrc, pDest, pixels);
 }
@@ -242,7 +265,7 @@
             return ICodec_IccModule::IccCS_Unknown;
     }
 }
-ICodec_IccModule::IccCS CCodec_IccModule::GetProfileCS(FX_LPCBYTE pProfileData, unsigned int dwProfileSize)
+ICodec_IccModule::IccCS CCodec_IccModule::GetProfileCS(FX_LPCBYTE pProfileData, FX_DWORD dwProfileSize)
 {
     ICodec_IccModule::IccCS cs;
     cmsHPROFILE hProfile = cmsOpenProfileFromMem((void*)pProfileData, dwProfileSize);
@@ -517,12 +540,12 @@
         }
     }
 }
-void* CCodec_IccModule::CreateTransform_sRGB(FX_LPCBYTE pProfileData, unsigned int dwProfileSize, int nComponents, int intent, FX_DWORD dwSrcFormat)
+void* CCodec_IccModule::CreateTransform_sRGB(FX_LPCBYTE pProfileData, FX_DWORD dwProfileSize, FX_INT32* nComponents, FX_INT32 intent, FX_DWORD dwSrcFormat)
 {
     return IccLib_CreateTransform_sRGB(pProfileData, dwProfileSize, nComponents, intent, dwSrcFormat);
 }
-void* CCodec_IccModule::CreateTransform_CMYK(FX_LPCBYTE pSrcProfileData, unsigned int dwSrcProfileSize, int nSrcComponents,
-        FX_LPCBYTE pDstProfileData, unsigned int dwDstProfileSize, int intent,
+void* CCodec_IccModule::CreateTransform_CMYK(FX_LPCBYTE pSrcProfileData, FX_DWORD dwSrcProfileSize, FX_INT32* nSrcComponents,
+    FX_LPCBYTE pDstProfileData, FX_DWORD dwDstProfileSize, FX_INT32 intent,
         FX_DWORD dwSrcFormat , FX_DWORD dwDstFormat)
 {
     return IccLib_CreateTransform(pSrcProfileData, dwSrcProfileSize, nSrcComponents,
@@ -536,7 +559,7 @@
 {
     IccLib_Translate(pTransform, m_nComponents, pSrcValues, pDestValues);
 }
-void CCodec_IccModule::TranslateScanline(void* pTransform, FX_LPBYTE pDest, FX_LPCBYTE pSrc, int pixels)
+void CCodec_IccModule::TranslateScanline(void* pTransform, FX_LPBYTE pDest, FX_LPCBYTE pSrc, FX_INT32 pixels)
 {
     IccLib_TranslateImage(pTransform, pDest, pSrc, pixels);
 }