2014-03-25 87 views
2

我一直在爲這個問題苦苦掙扎多年,找不到任何解釋!從ProPhoto RGB到顯示器配置文件的色彩轉換

背景:

我創建一個色彩管理照片編輯應用程序在Windows上使用VC9 + MFC,並使用WCS(Windows顏色系統)的API轉換從照片嵌入的色彩配置像素到監視器的配置文件。

我的顯示器已經使用「Windows顯示器校準」進行了校準,並創建了一個名爲「CalibratedDisplayProfile-x.icc」的配置文件。

問題:

當我轉換從「ProPhoto RGB」像素監控的個人資料,在黑暗區域轉變的顏色,色調變爲綠色。如果目標配置文件爲sRGB,則不會在中間色調/高光中發生這種情況。這裏是屏幕截圖。

correct & error images

測試:

爲了簡化問題,我寫了一些測試代碼翻譯一個單一的顏色,但測試結果真的讓我很困惑。源顏色「c0」是RGB(0,0,65535),但輸出顏色「c1」是RGB(0,0,0) !!並且「CheckColor」功能失敗,出現「無效參數」錯誤...

這怎麼會發生?難道我做錯了什麼?

你可以在這裏下載這兩個配置文件:Color Profiles

非常感謝!

CString strProfilePath = _T("C:\\Windows\\System32\\spool\\drivers\\color\\"); 
CString strSrcProfile = strProfilePath + _T("ProPhoto.icm"); 
CString strDstProfile = strProfilePath + _T("CalibratedDisplayProfile-2.icc"); 
PROFILE pf = {0}; 
pf.dwType = PROFILE_FILENAME; 
pf.pProfileData = (PVOID)strSrcProfile.GetBuffer(); 
pf.cbDataSize = (strSrcProfile.GetLength() + 1) * sizeof(TCHAR); 
HPROFILE hSrcProfile = ::OpenColorProfile(&pf, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING); 
pf.pProfileData = (PVOID)strDstProfile.GetBuffer(); 
pf.cbDataSize = (strDstProfile.GetLength() + 1) * sizeof(TCHAR); 
HPROFILE hDstProfile = ::OpenColorProfile(&pf, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING); 

HPROFILE hProfiles[2]; 
hProfiles[0] = hSrcProfile; 
hProfiles[1] = hDstProfile; 
DWORD dwIndents[2] = { INTENT_RELATIVE_COLORIMETRIC, INTENT_RELATIVE_COLORIMETRIC }; 
HTRANSFORM hTransform = ::CreateMultiProfileTransform(hProfiles, 2, dwIndents, 2, BEST_MODE, INDEX_DONT_CARE); 

COLOR c0, c1; 
c0.rgb.red = 0; 
c0.rgb.green = 0; 
c0.rgb.blue = 0xffff; 
::TranslateColors(hTransform, &c0, 1, COLOR_RGB, &c1, COLOR_RGB); 

BYTE btResult = 0; 
::CheckColors(hTransform, &c0, 1, COLOR_RGB, &btResult); 

::DeleteColorTransform(hTransform); 
::CloseColorProfile(hSrcProfile); 
::CloseColorProfile(hDstProfile); 

回答

0

我在Windows 7 SP1 x64上遇到了與您的問題完全相同的問題。 看起來TranslateColors函數或者被設計破壞,或者不應該被這樣使用。我認爲這是微軟的錯,因爲他們可以在MSDN上編寫更多的WCS示例。

但我設法使用TranslateBitmapBits函數來解決問題。這裏是一個樣本:

bool translateColors(BYTE* srcRgbColors, BYTE* dstRgbColors, DWORD nBytes) 
{ 
    BOOL bResult = FALSE; 

    HPROFILE hSrcProfile  = nullptr; 
    HPROFILE hDstProfile  = nullptr; 
    HTRANSFORM hColorTransform = nullptr; 

    /* open source sRGB profile */ 
    wchar_t* srcProfilePath = L"sRGB Color Space Profile.icm"; 

    tagPROFILE targetProfile; 
    targetProfile.dwType = PROFILE_FILENAME; 
    targetProfile.pProfileData = srcProfilePath; 
    targetProfile.cbDataSize = sizeof(wchar_t) * (wcslen(srcProfilePath) + 1); 

    hSrcProfile = OpenColorProfile(&targetProfile, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING); 
    if (nullptr == hSrcProfile) goto EXIT; 

    /* open destination monitor profile */ 
    wchar_t* dstProfilePath = L"ActiveMonitorProfile.icm"; 

    tagPROFILE destinationProfile; 
    destinationProfile.dwType = PROFILE_FILENAME; 
    destinationProfile.pProfileData = dstProfilePath; 
    destinationProfile.cbDataSize = sizeof(wchar_t) * (wcslen(dstProfilePath) + 1); 

    hDstProfile = OpenColorProfile(&destinationProfile, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING); 
    if (nullptr == hDstProfile) goto EXIT; 

    /* create color transform */ 

    DWORD dwIntent = (DWORD)-1; 
    HPROFILE hProfileList[2] = { hSrcProfile, hDstProfile }; 

    hColorTransform = CreateMultiProfileTransform(
     hProfileList, 
     2, 
     &dwIntent, 
     1, 
     NORMAL_MODE, 
     INDEX_DONT_CARE 
    ); 

    if (nullptr == hColorTransform) goto EXIT; 

    /* transform colors */ 
    DWORD dwWidth = nBytes/3; // 3 channels per pixel, 8 bits per channel, RGB format 

    bResult = TranslateBitmapBits(
     hColorTransform, 
     srcRgbColors, 
     BM_RGBTRIPLETS, 
     dwWidth,  // bitmap width 
     1,    // bitmap height 
     0, 
     dstRgbColors, 
     BM_RGBTRIPLETS, 
     0, 
     nullptr, 
     0 
    ); 

EXIT: 
    /* free resources */ 
    if (nullptr != hColorTransform) { 
     DeleteColorTransform(hColorTransform); 
    } 

    if (nullptr != hSrcProfile) { 
     CloseColorProfile(hSrcProfile); 
    } 

    if (nullptr != hDstProfile) { 
     CloseColorProfile(hDstProfile); 
    } 

    return bResult == FALSE ? false : true; 
} 

/* example usage */ 
BYTE srcBitmapData[3]; 
srcBitmapData[0] = 0x1c; 
srcBitmapData[1] = 0x1a; 
srcBitmapData[2] = 0x1a; 

BYTE dstOutputBitmapData[3]; 
bool bResult = traslateColors(srcBitmapData, dstOutputBitmapData, 3); 

希望這會有所幫助。

+0

我現在在使用LittleCMS。它好多了。 –