Java从ICC_配置文件中提取颜色空间和PC,以验证图像的完整性

Java从ICC_配置文件中提取颜色空间和PC,以验证图像的完整性,java,image,colors,metadata,exif,Java,Image,Colors,Metadata,Exif,首先(我忘了说我是java新手,这是我在这里的第一篇帖子,所以如果我犯了一些错误,请纠正我;) 我有个问题,我有很多照片。在这些图像之间是一些相互关联的图像(例如,具有ICC配置文件CMYK和Lab的图像具有像素方案RGB或其他示例ICC:RGB和XYZ以及像素方案CMYK)。我需要编写一个Java应用程序来测试这些特定类别的文件 文件类型有:JPG、TIFF、GIF、PNG和BMP 我已经从twelvemonkeys安装了ImageIO和ImageIO以接受CMYK文件。我试图读出Meta/e

首先(我忘了说我是java新手,这是我在这里的第一篇帖子,所以如果我犯了一些错误,请纠正我;) 我有个问题,我有很多照片。在这些图像之间是一些相互关联的图像(例如,具有ICC配置文件CMYK和Lab的图像具有像素方案RGB或其他示例ICC:RGB和XYZ以及像素方案CMYK)。我需要编写一个Java应用程序来测试这些特定类别的文件

文件类型有:JPG、TIFF、GIF、PNG和BMP

我已经从twelvemonkeys安装了ImageIO和ImageIO以接受CMYK文件。我试图读出Meta/exif数据和ICC数据,但没有显示我需要的信息

我试图用PhotoMe读出数据,但因此我不得不一个接一个地查找所有文件,并手动进行比较。所以我知道数据在文件中,不是空的

因此,我们的目标是读取元数据和ICC Profil,并比较具体的值

谢谢 佐良

编辑:我想我设法得到了像素方案,但我无法获得其他信息。下面是访问像素方案(或颜色空间)的代码。那么你有没有想过买其他东西

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 = ");
            }   
    }
public void ICC(文件)引发IOException
{
//错误指出了文件的原因(但我不知道其他导入图像的方法(尝试将其转换为某些类型的数组,但无法工作))
Map metadataMap=Metadata.readMetadata(文件));
ICCProfile icc_profile=(ICCProfile)metadataMap.get(MetadataType.icc_profile);
如果(icc_配置文件!=null){
icc_profile.showmatadata();
log.append(“PCS=”);
log.append(“Color Space=”);
}   
}
但现在我的问题是: 是否有可能只获取这两条数据 [颜色空间:CMYK+ PCS:Lab]从标头中取出并将其写入变量?(括号中的两个) 我需要它,因为我必须显示颜色空间和PC的结果,并将其与像素方案进行比较


更新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");
                  }   
}
public void ICC(文件)引发IOException
{          
Map metadataMap=Metadata.readMetadata(文件);
ICCProfile icc_profile=(ICCProfile)metadataMap.get(MetadataType.icc_profile);
如果(icc_配置文件!=null)
{
icc_profile.showmatadata();
字符串iccs=icc_profile.getReader().getColorSpace();
字符串icpcs=icc_profile.getReader().getPCS();
log.append(“Color Space=“+iccs+”\n”);
log.append(“PCS=“+icpcs+”\n”);
}   
}

更新3: 发现错误;)太多了

非常感谢这本书

您可能想试试。它支持从TIFF、JPEG、PNG中提取ICC_配置文件。以下是特定运行的一些信息:

*** 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);
                 }          
            }
        }   
    }
更新2:

如果需要从特定标记读取更多数据,可以先获取标记表,然后获取感兴趣的标记条目。以下是一个片段:

    public void readTag(ProfileTag tag) {
        ProfileTagTable tagTable = reader.getTagTable();
        TagEntry tag = tagTable.getTagEntry(tag);
        // Do your stuff with tag entry
    }
下面是嵌套的标记项类:

    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;
        }       
    }
公共静态类标记项实现可比较{
私有int-profileTag;
私有int数据偏移;
私有int数据长度;
专用字节[]数据;
公共标记项(int-profileTag、int-dataOffset、int-dataLength、byte[]数据){
this.profileTag=profileTag;
this.dataOffset=dataOffset;
this.dataLength=数据长度;
这个数据=数据;
}
@凌驾
公共整数比较(Tago条目){
返回(int)((this.profileTag&0xffffffffffl)-(o.profileTag&0x0ffffffffL));
}
public int getProfileTag(){
返回profileTag;
}
public int getDataOffset(){
返回数据偏移量;
}
public int getDataLength(){
返回数据长度;
}
公共字节[]getData(){
返回数据;
}       
}

首先:感谢icafe.jar,我尝试了一下,但因为我还在学习java,所以很难进入它;)我一收到一些信息就发布我的结果。我更新了我的第一篇文章,我希望你能给我一个提示。我发现了--“严重错误1”)太多了。。。。是的,我也找到了个人电脑和色彩空间,在我深入搜索你的库->我希望我能给你投票,但我没有声誉;)感谢您的帮助,祝您愉快。我不认为ICC_配置文件颜色空间与来自PixelSchema的颜色空间之间存在一对一的映射,而且在图像读取过程中可能会进行一些颜色空间转换。因此,当涉及到BuffereImage时,颜色空间可能已经发生了变化。我测试是否存在任何逐个映射,因为我编写了该工具,并使用整个图像的一些选取(用于PhotoMe和其他程序)来测试我的结果,以验证它
    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;
        }       
    }