Image 确定JPEG的颜色空间

Image 确定JPEG的颜色空间,image,jpeg,color-space,Image,Jpeg,Color Space,我正在写一个确定JPEG图像颜色空间的代码。我找到了两个参考资料,可以帮助我实现这一点。一个是上,另一个是C源代码,其中“负责原始JPEG标准的参考实现” 然而,它们确实不同。例如,在IJG中,当没有Adobe标记且有4个通道时,假定为CMYK,但在oracle中为YCCA。此外,IJG的实现不考虑子采样,而对于4通道子采样,在oracle规范中是YCCK,等等 在ColorSpace类中也有很多遗漏,当我实现oracle的逻辑时,我需要指定3个额外的颜色空间,比如YCCK、YCCA、RGBA

我正在写一个确定JPEG图像颜色空间的代码。我找到了两个参考资料,可以帮助我实现这一点。一个是上,另一个是C源代码,其中“负责原始JPEG标准的参考实现”

然而,它们确实不同。例如,在IJG中,当没有Adobe标记且有4个通道时,假定为CMYK,但在oracle中为YCCA。此外,IJG的实现不考虑子采样,而对于4通道子采样,在oracle规范中是YCCK,等等

在ColorSpace类中也有很多遗漏,当我实现oracle的逻辑时,我需要指定3个额外的颜色空间,比如YCCK、YCCA、RGBA

另一点是,我发现JPEG在alpha通道中不支持透明度,为什么oracle会在JPEG metadat规范的上下文中谈论YCCA和RGBA


结果,当用IJG的逻辑检查图像时,它告诉我它是CMYK(在ubuntu上用ImageMagick检查图像,它还说它是CMYK),用oracle的逻辑它是YCCA。相信谁?为什么oracle不依赖原始JPEG规范?或者还有什么我不知道的?

我也很难理解您提到的Oracle文档

根据我的经验,从编写一个程序开始,正确的做法是遵循IJG的实现。这是大多数软件所做的,因此它将在用户中造成最少的混淆(即“为什么我的图像在您的软件和软件X中看起来不同?”)。Sun/Oracle算法在许多情况下与“世界其他地区”不一致

我最终实现了一个稍微不同的算法,该算法考虑了“额外”的Java颜色空间,但在其他方面与IJG实现非常接近:

//改编自libjpeg jdapimin.c:
//猜测输入颜色空间
//(希望JPEG委员会能提供一种真正的方式来说明这一点……)
开关(startOfFrame.componentsInFrame()){
案例1:
返回JPEG颜色空间。灰色;
案例2:
返回jpegolorspace.GrayA;//Java特殊情况:灰色+Alpha
案例3:
如果(jfif!=null){
返回jpegolorspace.YCbCr;//JFIF表示YCbCr
}
else if(adobeDCT!=null){
开关(adobeDCT.transform){
病例报告。未知:
返回jpegolorspace.RGB;
案例AdobeDCT.YCC:
返回jpegolorspace.YCbCr;
违约:
//TODO:警告!
返回jpegolorspace.YCbCr;//假设它是YCbCr
}
}
否则{
//没有看到特殊标记,请尝试从组件ID猜测
int cid0=startOfFrame.components[0].id;
int cid1=startOfFrame.components[1].id;
int cid2=startOfFrame.components[2].id;
如果(cid0==1&&cid1==2&&cid2==3){
返回jpegolorspace.YCbCr;//假设JFIF带有/out标记
}
else if(cid0='R'&&cid1='G'&&cid2='B'){
返回jpegolorspace.RGB;//ASCII'R','G','B'
}
else if(cid0='Y'&&cid1='C'&&cid2='C'){
return jpegolorspace.PhotoYCC;//Java特殊情况:YCc
}
否则{
//TODO:警告!
返回jpegolorspace.YCbCr;//假设它是YCbCr
}
}
案例4:
if(adobeDCT!=null){
开关(adobeDCT.transform){
病例报告。未知:
返回jpegolorspace.CMYK;
案例AdobeDCT.YCCK:
返回jpegolorspace.YCCK;
违约:
//TODO:警告!
返回jpegolorspace.YCCK;//假设它是YCCK
}
}
否则{
//没有看到特殊标记,请尝试从组件ID猜测
int cid0=startOfFrame.components[0].id;
int cid1=startOfFrame.components[1].id;
int cid2=startOfFrame.components[2].id;
int cid3=startOfFrame.components[3].id;
如果(cid0==1&&cid1==2&&cid2==3&&cid3==4){
返回jpegolorspace.YCbCrA;//Java特殊情况:YCbCrA
}
else if(cid0='R'&&cid1='G'&&cid2='B'&&cid3='A'){
返回jpegolorspace.RGBA;//Java特殊情况:RGBA
}
else if(cid0='Y'&&cid1='C'&&cid2='C'&&cid3='A'){
return jpegolorspace.PhotoYCCA;//Java特殊情况:YCcA
}
否则{
//TODO:警告!
//无特殊标记,假设为直CMYK。
返回jpegolorspace.CMYK;
}
}
违约:
抛出新的IIOException(“无法确定源颜色空间”);
}

在我对旧JPEG标准的评论之后,我终于找到了答案

关于第6.1节:

  • 仅使用一个分量编码的图像被假定为灰度数据,其中0为黑色,255为白色

  • 假设使用三个分量编码的图像是编码为YCbCr的RGB数据,除非图像 包含6.5.3中规定的APP14标记段,在这种情况下,考虑颜色编码 根据APP14标记段的应用数据选择RGB或YCbCr。关系 RGB和YCbCr之间的定义见记录ITU-T T.871 | ISO/IEC 10918-5

  • 假设使用四个分量编码的图像为CMYK,其中(0,0,0,0)表示白色 图像包含6.5.3中规定的APP14标记段,在这种情况下,颜色编码为 根据应用数据考虑CMYKYCCK