Java 从 ICC_Profile 中提取颜色空间和 PCS 以验证图像的完整性
Java extract colorSpace and PCS from ICC_Profile to verify the integrety of an image
首先(我忘了说我是 java 的新手,这是我第一次 post 在这里,所以如果我犯了一些错误,请纠正我 ;) )
我遇到了问题,我得到了很多图像。在这些图像之间有一些被损坏了(例如,带有 ICC-Profile CMYK 和 Lab 的图片具有 pixel-scheme RGB 或其他示例 ICC:RGB 和 XYZ 以及 pixel-scheme CMYK)。我需要编写一个 Java 应用程序来针对该特定类别测试这些文件。
文件类型为:JPG、TIFF、GIF、PNG 和 BMP。
我已经从 twelvemonkeys 安装了 ImageIO 和 ImageIO 以接受 CMYK-Files。我试图读出 Meta/exif-data 和 ICC-data 但它没有显示我需要的信息。
我试图用 PhotoMe 读出数据,但因此我必须一个一个地查找所有文件并手工比较。所以我知道数据在文件中而不是空的。
所以目标是读出元数据和ICC-Profil并比较具体值。
谢谢
佐里安
编辑:我想我设法获得了 Pixel-Scheme,但我无法访问其他信息。下面是访问 Pixel-Scheme(或 ColorSpace)的代码。那么你有没有想过得到其他东西?
int cst = 0;
ColorSpace cs= image.getColorModel().getColorSpace();
System.out.println("--> "+cs.getType());
cst = cs.getType();
PixelScheme pisc = new PixelScheme();
pisc.showPixelSchema(cst);
log.append("Pixel-Scheme = " + pisc.showPixelScheme(cst) + "\n");
//Class Pixel-Scheme
//the Case values taken from a table from java.awt.color.ColorSpace;
package components;
import java.awt.color.ColorSpace;
public class PixelSchema {
public String showPixelSchema (int cst)
{
switch (cst)
{
case 0: ptype = "XYZ";
break;
case 1: ptype = "Lab";
break;
case 2: ptype = "Luv";
break;
case 3: ptype = "YCbCr";
break;
case 4: ptype = "Yxy";
break;
case 5: ptype = "RGB";
break;
case 6: ptype = "GRAY";
break;
case 7: ptype = "HSV";
break;
case 8: ptype = "HLS";
break;
case 9: ptype = "CMYK";
break;
case 11: ptype = "CMY";
break;
case 12: ptype = "2CLR";
break;
case 13: ptype = "3CLR";
break;
case 14: ptype = "4CLR";
break;
case 15: ptype = "5CLR";
break;
case 16: ptype = "6CLR";
break;
case 17: ptype = "7CLR";
break;
case 18: ptype = "8CLR";
break;
case 19: ptype = "9CLR";
break;
case 20: ptype = "ACLR";
break;
case 21: ptype = "BCLR";
break;
case 22: ptype = "CCLR";
break;
case 23: ptype = "DCLR";
break;
case 24: ptype = "ECLR";
break;
case 25: ptype = "FCLR";
break;
case 1000: ptype = "sRGB";
break;
case 1001: ptype = "CIEXYZ";
break;
case 1002: ptype = "PYCC";
break;
case 1003: ptype = "GRAY";
break;
case 1004: ptype = "LINEAR_RGB";
break;
default: ptype = "ERROR!";
break;
}
return ptype;
}
}
更新:
我实现了代码片段,但在 Netbeans 中仍然出现错误,但它以某种方式工作并向我显示了所需的数据。
public void ICC(File file) throws IOException
{
//Error indicated cause of file (but I don't know an other way to import my image (tried to convert it to some kinds of arrays but it won't work))
Map<MetadataType, Metadata> metadataMap = Metadata.readMetadata(file));
ICCProfile icc_profile = (ICCProfile)metadataMap.get(MetadataType.ICC_PROFILE);
if(icc_profile != null) {
icc_profile.showMetadata();
log.append("PCS = ");
log.append("Color Space = ");
}
}
但现在我的问题是:
有没有可能只得到这两条数据
[颜色Space:CMYK +
PCS: Lab] 从 header 中取出并将它们写入变量? (括号内的两个)
我需要它,因为我必须显示 Color Space 和 PCS 的结果并将其与 PixelScheme 进行比较。
更新 2:
我终于得到了我需要的所有数据,但仍然遇到更新 1 的问题!
这是我针对此错误的代码片段!
public void ICC(File file) throws IOException
{
Map<MetadataType, Metadata> metadataMap = Metadata.readMetadata(file);
ICCProfile icc_profile = (ICCProfile)metadataMap.get(MetadataType.ICC_PROFILE);
if(icc_profile != null)
{
icc_profile.showMetadata();
String iccs = icc_profile.getReader().getColorSpace();
String icpcs = icc_profile.getReader().getPCS();
log.append("Color Space = " + iccs + "\n");
log.append("PCS = " + icpcs + "\n");
}
}
更新 3:
发现错误 ;) 1 ) 太多
非常感谢这个库!
您可能想试试 icafe。它支持从 TIFF、JPEG、PNG 中提取 ICC_Profile。以下是来自特定运行的一些信息:
*** Start of ICC_Profile Header ***
Profile Size: 3144
CMM Type: Lino
Version: 2.10
Profile/Device Class: 'mntr': display devices - CRTs and LCDs
Color Space: RGB
PCS: XYZ
Date Created: 1998/2/9, 6:49:0
Profile File Signature: acsp
Primary Platform Signature: MSFT
Flags: not embedded, used independently
Device Manufacturer: IEC
Device Model: sRGB
Device Attributes: reflective, glossy, positive, color
Rendering Intent: media-relative colorimetric
PCS Illuminant: X = 0.9642029, Y = 1.0, Z = 0.8249054
Profile Creator: HP
Profile ID: [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
*** End of ICC_Profile Header ***
*** Start of ICC_Profile Tag Table ***
Tag Count: 17
Tag# 0, Tag Name: bTRC (blueTRCTag), Data Offset: 1084, Data Length: 2060
Tag# 1, Tag Name: bXYZ (blueMatrixColumnTag), Data Offset: 576, Data Length: 20
Tag# 2, Tag Name: BKPT (mediaBlackPointTag), Data Offset: 516, Data Length: 20
Tag# 3, Tag Name: cprt (copyrightTag), Data Offset: 336, Data Length: 51
Tag# 4, Tag Name: desc (profileDescriptionTag), Data Offset: 388, Data Length: 108
Tag# 5, Tag Name: dmdd (deviceModelDescTag), Data Offset: 708, Data Length: 136
Tag# 6, Tag Name: dmnd (deviceMfgDescTag), Data Offset: 596, Data Length: 112
Tag# 7, Tag Name: gTRC (greenTRCTag), Data Offset: 1084, Data Length: 2060
Tag# 8, Tag Name: gXYZ (greenMatrixColumnTag), Data Offset: 556, Data Length: 20
Tag# 9, Tag Name: lumi (luminanceTag), Data Offset: 1016, Data Length: 20
Tag# 10, Tag Name: meas (measurementTag), Data Offset: 1036, Data Length: 36
Tag# 11, Tag Name: rTRC (redTRCTag), Data Offset: 1084, Data Length: 2060
Tag# 12, Tag Name: rXYZ (redMatrixColumnTag), Data Offset: 536, Data Length: 20
Tag# 13, Tag Name: tech (technologyTag), Data Offset: 1072, Data Length: 12
Tag# 14, Tag Name: view (viewingConditionsTag), Data Offset: 980, Data Length: 36
Tag# 15, Tag Name: vued (viewingCondDescTag), Data Offset: 844, Data Length: 134
Tag# 16, Tag Name: wtpt (mediaWhitePointTag), Data Offset: 496, Data Length: 20
*** End of ICC_Profile Tag Table ***
这里是一个代码示例:
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import com.icafe4j.image.meta.Metadata;
import com.icafe4j.image.meta.MetadataEntry;
import com.icafe4j.image.meta.MetadataType;
import com.icafe4j.image.meta.icc.ICCProfile;
public class ExtractICCProfile {
public static void main(String[] args) throws IOException {
Map<MetadataType, Metadata> metadataMap = Metadata.readMetadata(args[0]);
ICCProfile icc_profile = (ICCProfile)metadataMap.get(MetadataType.ICC_PROFILE);
if(icc_profile != null) {
Iterator<MetadataEntry> iterator = icc_profile.iterator();
while(iterator.hasNext()) {
MetadataEntry item = iterator.next();
printMetadata(item, "", " ");
}
}
}
private void printMetadata(MetadataEntry entry, String indent, String increment) {
logger.info(indent + entry.getKey() (StringUtils.isNullOrEmpty(entry.getValue())? "" : ": " + entry.getValue()));
if(entry.isMetadataEntryGroup()) {
indent += increment;
Collection<MetadataEntry> entries = entry.getMetadataEntries();
for(MetadataEntry e : entries) {
printMetadata(e, indent, increment);
}
}
}
}
从上述 link 的 "lib" 目录中获取“icafe.jar”,您可以使用代码示例进行测试.
更新: 你只能像这样显示 colorSpace 和 PCS:
if(icc_profile != null)
{
String colorSpace = icc_profile.getColorSpace();
String pcs = icc_profile.getPCS();
}
更新二:
如果您需要从特定标签中读取更多数据,您可以先抓取标签 table,然后获取您感兴趣的标签条目。这是一个片段:
public void readTag(ProfileTag tag) {
ProfileTagTable tagTable = reader.getTagTable();
TagEntry tag = tagTable.getTagEntry(tag);
// Do your stuff with tag entry
}
这里是嵌套的 TagEntry class:
public static class TagEntry implements Comparable<TagEntry> {
private int profileTag;
private int dataOffset;
private int dataLength;
private byte[] data;
public TagEntry(int profileTag, int dataOffset, int dataLength, byte[] data) {
this.profileTag = profileTag;
this.dataOffset = dataOffset;
this.dataLength = dataLength;
this.data = data;
}
@Override
public int compareTo(TagEntry o) {
return (int)((this.profileTag&0xffffffffL) - (o.profileTag&0x0ffffffffL));
}
public int getProfileTag() {
return profileTag;
}
public int getDataOffset() {
return dataOffset;
}
public int getDataLength() {
return dataLength;
}
public byte[] getData() {
return data;
}
}
首先(我忘了说我是 java 的新手,这是我第一次 post 在这里,所以如果我犯了一些错误,请纠正我 ;) ) 我遇到了问题,我得到了很多图像。在这些图像之间有一些被损坏了(例如,带有 ICC-Profile CMYK 和 Lab 的图片具有 pixel-scheme RGB 或其他示例 ICC:RGB 和 XYZ 以及 pixel-scheme CMYK)。我需要编写一个 Java 应用程序来针对该特定类别测试这些文件。
文件类型为:JPG、TIFF、GIF、PNG 和 BMP。
我已经从 twelvemonkeys 安装了 ImageIO 和 ImageIO 以接受 CMYK-Files。我试图读出 Meta/exif-data 和 ICC-data 但它没有显示我需要的信息。
我试图用 PhotoMe 读出数据,但因此我必须一个一个地查找所有文件并手工比较。所以我知道数据在文件中而不是空的。
所以目标是读出元数据和ICC-Profil并比较具体值。
谢谢 佐里安
编辑:我想我设法获得了 Pixel-Scheme,但我无法访问其他信息。下面是访问 Pixel-Scheme(或 ColorSpace)的代码。那么你有没有想过得到其他东西?
int cst = 0;
ColorSpace cs= image.getColorModel().getColorSpace();
System.out.println("--> "+cs.getType());
cst = cs.getType();
PixelScheme pisc = new PixelScheme();
pisc.showPixelSchema(cst);
log.append("Pixel-Scheme = " + pisc.showPixelScheme(cst) + "\n");
//Class Pixel-Scheme
//the Case values taken from a table from java.awt.color.ColorSpace;
package components;
import java.awt.color.ColorSpace;
public class PixelSchema {
public String showPixelSchema (int cst)
{
switch (cst)
{
case 0: ptype = "XYZ";
break;
case 1: ptype = "Lab";
break;
case 2: ptype = "Luv";
break;
case 3: ptype = "YCbCr";
break;
case 4: ptype = "Yxy";
break;
case 5: ptype = "RGB";
break;
case 6: ptype = "GRAY";
break;
case 7: ptype = "HSV";
break;
case 8: ptype = "HLS";
break;
case 9: ptype = "CMYK";
break;
case 11: ptype = "CMY";
break;
case 12: ptype = "2CLR";
break;
case 13: ptype = "3CLR";
break;
case 14: ptype = "4CLR";
break;
case 15: ptype = "5CLR";
break;
case 16: ptype = "6CLR";
break;
case 17: ptype = "7CLR";
break;
case 18: ptype = "8CLR";
break;
case 19: ptype = "9CLR";
break;
case 20: ptype = "ACLR";
break;
case 21: ptype = "BCLR";
break;
case 22: ptype = "CCLR";
break;
case 23: ptype = "DCLR";
break;
case 24: ptype = "ECLR";
break;
case 25: ptype = "FCLR";
break;
case 1000: ptype = "sRGB";
break;
case 1001: ptype = "CIEXYZ";
break;
case 1002: ptype = "PYCC";
break;
case 1003: ptype = "GRAY";
break;
case 1004: ptype = "LINEAR_RGB";
break;
default: ptype = "ERROR!";
break;
}
return ptype;
}
}
更新: 我实现了代码片段,但在 Netbeans 中仍然出现错误,但它以某种方式工作并向我显示了所需的数据。
public void ICC(File file) throws IOException
{
//Error indicated cause of file (but I don't know an other way to import my image (tried to convert it to some kinds of arrays but it won't work))
Map<MetadataType, Metadata> metadataMap = Metadata.readMetadata(file));
ICCProfile icc_profile = (ICCProfile)metadataMap.get(MetadataType.ICC_PROFILE);
if(icc_profile != null) {
icc_profile.showMetadata();
log.append("PCS = ");
log.append("Color Space = ");
}
}
但现在我的问题是: 有没有可能只得到这两条数据 [颜色Space:CMYK + PCS: Lab] 从 header 中取出并将它们写入变量? (括号内的两个) 我需要它,因为我必须显示 Color Space 和 PCS 的结果并将其与 PixelScheme 进行比较。
更新 2: 我终于得到了我需要的所有数据,但仍然遇到更新 1 的问题! 这是我针对此错误的代码片段!
public void ICC(File file) throws IOException
{
Map<MetadataType, Metadata> metadataMap = Metadata.readMetadata(file);
ICCProfile icc_profile = (ICCProfile)metadataMap.get(MetadataType.ICC_PROFILE);
if(icc_profile != null)
{
icc_profile.showMetadata();
String iccs = icc_profile.getReader().getColorSpace();
String icpcs = icc_profile.getReader().getPCS();
log.append("Color Space = " + iccs + "\n");
log.append("PCS = " + icpcs + "\n");
}
}
更新 3: 发现错误 ;) 1 ) 太多
非常感谢这个库!
您可能想试试 icafe。它支持从 TIFF、JPEG、PNG 中提取 ICC_Profile。以下是来自特定运行的一些信息:
*** Start of ICC_Profile Header ***
Profile Size: 3144
CMM Type: Lino
Version: 2.10
Profile/Device Class: 'mntr': display devices - CRTs and LCDs
Color Space: RGB
PCS: XYZ
Date Created: 1998/2/9, 6:49:0
Profile File Signature: acsp
Primary Platform Signature: MSFT
Flags: not embedded, used independently
Device Manufacturer: IEC
Device Model: sRGB
Device Attributes: reflective, glossy, positive, color
Rendering Intent: media-relative colorimetric
PCS Illuminant: X = 0.9642029, Y = 1.0, Z = 0.8249054
Profile Creator: HP
Profile ID: [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
*** End of ICC_Profile Header ***
*** Start of ICC_Profile Tag Table ***
Tag Count: 17
Tag# 0, Tag Name: bTRC (blueTRCTag), Data Offset: 1084, Data Length: 2060
Tag# 1, Tag Name: bXYZ (blueMatrixColumnTag), Data Offset: 576, Data Length: 20
Tag# 2, Tag Name: BKPT (mediaBlackPointTag), Data Offset: 516, Data Length: 20
Tag# 3, Tag Name: cprt (copyrightTag), Data Offset: 336, Data Length: 51
Tag# 4, Tag Name: desc (profileDescriptionTag), Data Offset: 388, Data Length: 108
Tag# 5, Tag Name: dmdd (deviceModelDescTag), Data Offset: 708, Data Length: 136
Tag# 6, Tag Name: dmnd (deviceMfgDescTag), Data Offset: 596, Data Length: 112
Tag# 7, Tag Name: gTRC (greenTRCTag), Data Offset: 1084, Data Length: 2060
Tag# 8, Tag Name: gXYZ (greenMatrixColumnTag), Data Offset: 556, Data Length: 20
Tag# 9, Tag Name: lumi (luminanceTag), Data Offset: 1016, Data Length: 20
Tag# 10, Tag Name: meas (measurementTag), Data Offset: 1036, Data Length: 36
Tag# 11, Tag Name: rTRC (redTRCTag), Data Offset: 1084, Data Length: 2060
Tag# 12, Tag Name: rXYZ (redMatrixColumnTag), Data Offset: 536, Data Length: 20
Tag# 13, Tag Name: tech (technologyTag), Data Offset: 1072, Data Length: 12
Tag# 14, Tag Name: view (viewingConditionsTag), Data Offset: 980, Data Length: 36
Tag# 15, Tag Name: vued (viewingCondDescTag), Data Offset: 844, Data Length: 134
Tag# 16, Tag Name: wtpt (mediaWhitePointTag), Data Offset: 496, Data Length: 20
*** End of ICC_Profile Tag Table ***
这里是一个代码示例:
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import com.icafe4j.image.meta.Metadata;
import com.icafe4j.image.meta.MetadataEntry;
import com.icafe4j.image.meta.MetadataType;
import com.icafe4j.image.meta.icc.ICCProfile;
public class ExtractICCProfile {
public static void main(String[] args) throws IOException {
Map<MetadataType, Metadata> metadataMap = Metadata.readMetadata(args[0]);
ICCProfile icc_profile = (ICCProfile)metadataMap.get(MetadataType.ICC_PROFILE);
if(icc_profile != null) {
Iterator<MetadataEntry> iterator = icc_profile.iterator();
while(iterator.hasNext()) {
MetadataEntry item = iterator.next();
printMetadata(item, "", " ");
}
}
}
private void printMetadata(MetadataEntry entry, String indent, String increment) {
logger.info(indent + entry.getKey() (StringUtils.isNullOrEmpty(entry.getValue())? "" : ": " + entry.getValue()));
if(entry.isMetadataEntryGroup()) {
indent += increment;
Collection<MetadataEntry> entries = entry.getMetadataEntries();
for(MetadataEntry e : entries) {
printMetadata(e, indent, increment);
}
}
}
}
从上述 link 的 "lib" 目录中获取“icafe.jar”,您可以使用代码示例进行测试.
更新: 你只能像这样显示 colorSpace 和 PCS:
if(icc_profile != null)
{
String colorSpace = icc_profile.getColorSpace();
String pcs = icc_profile.getPCS();
}
更新二:
如果您需要从特定标签中读取更多数据,您可以先抓取标签 table,然后获取您感兴趣的标签条目。这是一个片段:
public void readTag(ProfileTag tag) {
ProfileTagTable tagTable = reader.getTagTable();
TagEntry tag = tagTable.getTagEntry(tag);
// Do your stuff with tag entry
}
这里是嵌套的 TagEntry class:
public static class TagEntry implements Comparable<TagEntry> {
private int profileTag;
private int dataOffset;
private int dataLength;
private byte[] data;
public TagEntry(int profileTag, int dataOffset, int dataLength, byte[] data) {
this.profileTag = profileTag;
this.dataOffset = dataOffset;
this.dataLength = dataLength;
this.data = data;
}
@Override
public int compareTo(TagEntry o) {
return (int)((this.profileTag&0xffffffffL) - (o.profileTag&0x0ffffffffL));
}
public int getProfileTag() {
return profileTag;
}
public int getDataOffset() {
return dataOffset;
}
public int getDataLength() {
return dataLength;
}
public byte[] getData() {
return data;
}
}