我一直在努力弄清楚microsoft WIC / WCS库在这里所做的事情,并且希望精通Windows颜色管理的任何人都可以提供帮助。该API的文档非常糟糕。
我正在使用OpenColourProfile阅读带有嵌入式ICC配置文件的JPEG,但是Windows对于某些图像似乎无法正确解析嵌入式ICC信息。对于其他人来说,也可以。但是,即使它无法使用Windows API解析标头信息,我也能够正确显示所有图像,但这只是对嵌入式ICC配置文件标头信息的解析是错误的。
不起作用
使用exif_tool工具显示无法通过我的代码运行的图像的ICC配置文件标题信息,exif_tool会正确返回:
Profile CMM Type : Adobe Systems Inc.
Profile Version : 2.1.0
Profile Class : Display Device Profile
Color Space Data : RGB
Profile Connection Space : XYZ
Profile Date Time : 2000:08:11 19:51:59
Profile File Signature : acsp
Primary Platform : Apple Computer Inc.
CMM flags : Not Embedded,Independent
Device Manufacturer : none
Device Model :
Device Attributes : Reflective,Glossy,Positive,Color
Rendering Intent : Perceptual
Connection Space Illuminant : 0.9642 1 0.82491
Profile Creator : Adobe Systems Inc.
Profile ID : 0
Profile Copyright : Copyright 2000 Adobe Systems Incorporated
Profile Description : Adobe RGB (1998)
Media White Point : 0.95045 1 1.08905
Media Black Point : 0 0 0
Red Tone Reproduction Curve : (Binary data 14 bytes,use -b option to extract)
Green Tone Reproduction Curve : (Binary data 14 bytes,use -b option to extract)
Blue Tone Reproduction Curve : (Binary data 14 bytes,use -b option to extract)
Red Matrix Column : 0.60974 0.31111 0.01947
Green Matrix Column : 0.20528 0.62567 0.06087
Blue Matrix Column : 0.14919 0.06322 0.74457
在我的代码中读取ICC配置文件标头后,Windows将CMM类型返回为0000(未定义)(请参见下文)。同样,版本标记的解析地址是v2.0(0x02000000),而不是上面的exif_tool输出中所示的v2.1。
此外,在此之后,一个查询(在我的代码中)返回ICC标签0x64657363(ProfileDescription)返回“ opRGB”而不是“ Adobe RGB(1998)”。
就此图像的EXIF数据而言,颜色空间被定义为“未校准”,并且指定了“互操作性索引”,其值为“ R03”,据我理解,该互操作性索引应解释为Adobe RGB。
工作
使用另一个带有嵌入式Adobe RGB(1998)配置文件的JPG,我通过exif_tool运行了它,并显示:
Profile CMM Type : Adobe Systems Inc.
Profile Version : 2.1.0
Profile Class : Display Device Profile
Color Space Data : RGB
Profile Connection Space : XYZ
Profile Date Time : 1999:06:03 00:00:00
Profile File Signature : acsp
Primary Platform : microsoft Corporation
CMM flags : Not Embedded,Color
Rendering Intent : Media-Relative Colorimetric
Connection Space Illuminant : 0.9642 1 0.82491
Profile Creator : Adobe Systems Inc.
Profile ID : 0
Profile Copyright : Copyright (c) 1999 Adobe Systems Incorporated. All Rights Reserved.
Profile Description : Adobe RGB (1998)
Media White Point : 0.95045 1 1.08905
Media Black Point : 0 0 0
Red Tone Reproduction Curve : (Binary data 14 bytes,use -b option to extract)
Red Matrix Column : 0.60974 0.31111 0.01947
Green Matrix Column : 0.20528 0.62567 0.06087
Blue Matrix Column : 0.14919 0.06322 0.74457
使用OpenColourProfile时,我的代码(使用Windows API)正确解析了标头信息:
在此之后,一个查询(在我的代码中)正确返回ICC标签0x64657363(ProfileDescription),将返回“ Adobe RGB(1998)”。
根据该图像的EXIF数据,颜色空间被定义为“未校准”,并且未指定“互操作性指数”。
代码
/* COLOUR PROFILE MANAGEMENT */
IWICColorContext* pContextsrc = NULL;
IWICColorContext* pContextDst = NULL;
hr = factory->CreateColorContext(&pContextsrc);
if (!SUCCEEDED(hr))
return nullptr;
UINT numColourContexts = 0;
hr = wic->mFrame->getcolorContexts(1,&pContextsrc,&numColourContexts);
if (numColourContexts > 0)
{
hr = factory->CreateColorContext(&pContextDst);
if (!SUCCEEDED(hr))
return nullptr;
WCHAR destColourContextFilename[_MAX_PATH + 1];
DWORD destColourContextFilenameSize = sizeof(destColourContextFilename);
if (getcolorDirectory(NULL,destColourContextFilename,&destColourContextFilenameSize))
{
hr = StringCchCatW(destColourContextFilename,sizeof(destColourContextFilename) / sizeof(destColourContextFilename[0]),L"\\sRGB Color Space Profile.icm");
}
else
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
hr = pContextDst->InitializeFromFilename(destColourContextFilename);
}
if (SUCCEEDED(hr))
{
hr = factory->CreateColorTransformer(&wic->pColorTransform);
}
if (SUCCEEDED(hr))
{
hr = wic->pColorTransform->Initialize(wic->mFrame.get(),pContextsrc,pContextDst,wic->mPixelFormat);
if (!SUCCEEDED(hr))
{
return nullptr;
}
}
// WICColorContextUninitialized = 0,// WICColorContextProfile = 0x1,// WICColorContextExifColorSpace = 0x2
WICColorContextType type;
pContextsrc->GetType(&type);
if (type == WICColorContextType::WICColorContextProfile)
{
UINT cbProfile = 0;
hr = pContextsrc->GetProfileBytes(0,NULL,&cbProfile);
if (!SUCCEEDED(hr))
return nullptr;
VOID* pvProfile = NULL;
if (SUCCEEDED(hr))
{
// allocate the block
pvProfile = HeapAlloc(
GetProcessHeap(),HEAP_ZERO_MEMORY,cbProfile);
hr = pvProfile ? S_OK : E_FAIL;
}
UINT cbSize = 0;
if (SUCCEEDED(hr))
{
// copy the profile into the block
hr = pContextsrc->GetProfileBytes(cbProfile,(BYTE*)pvProfile,&cbSize);
}
// ***Open the memory block as a HPROFILE***
HPROFILE hProfile = NULL;
// fill out a PROFILE structure
PROFILE prof =
{
PROFILE_MEMBUFFER,pvProfile,cbProfile
};
// create the HPROFILE
if (SUCCEEDED(hr))
{
/*hProfile = WcsOpenColorProfile(
&prof,PROFILE_READ,FILE_SHARE_READ,OPEN_EXISTING,0);*/
hProfile = OpenColorProfile(
&prof,OPEN_EXISTING);
hr = hProfile ? S_OK : E_FAIL;
HeapFree(GetProcessHeap(),pvProfile);
}
PROFILEHEADER ph;
getcolorProfileHeader(hProfile,&ph);
DWORD size = 100;
CHAR description[100];
for (int i = 0; i < 100; i++)
{
description[i] = '\0';
}
BOOL b;
BOOL s = getcolorProfileElement(hProfile,0x64657363,12,&size,&description,&b);
string profileDescription = std::string(description);
变量ph代表上面的蓝色图像屏幕截图,profileDescription代表ICC配置文件描述(仅对一个图像有效,而对另一幅图像无效)
ICC标头之间的差异
我已经总结了exif_tool报告的ICC标头信息中的差异,这导致Windows API无法正确解析嵌入的ICC标头信息:
工作
Profile Date Time : 2000:08:11 19:51:59
Primary Platform : Apple Computer Inc.
Rendering Intent : Perceptual
Profile Copyright : Copyright 2000 Adobe Systems Incorporated
不起作用
Profile Date Time : 1999:06:03 00:00:00
Primary Platform : microsoft Corporation
Rendering Intent : Media-Relative Colorimetric
Profile Copyright : Copyright (c) 1999 Adobe Systems Incorporated. All Rights Reserved.
其他图像编辑软件将两个图像正确报告为“ Adobe RGB(1998)”
当嵌入式ICC信息以microsoft平台为目标时,似乎Windows API不喜欢它(?)
可能是由于缺少“互操作性索引”(对于无效的映像指定为“ R03”,对于有效的映像指定为“ R03”),但是如果是这种情况,这似乎是Windows中的错误(?)
也许“ Adobe RGB”和“ Adobe RGB(1998)”是两个不同的配置文件,而所有其他将它们都报告为“ Adobe RGB(1998)”的软件根本无法区分它们吗? / p>
我的头很痛……有人知道这是怎么回事吗?
欢呼
编辑:
工作图像(使用Windows API读取时,配置文件说明= Adobe RGB(1998)):