View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.imaging.formats.png.chunks;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.IOException;
21  import java.nio.charset.StandardCharsets;
22  import java.util.Arrays;
23  import java.util.logging.Level;
24  import java.util.logging.Logger;
25  import java.util.zip.InflaterInputStream;
26  
27  import org.apache.commons.imaging.ImagingException;
28  import org.apache.commons.imaging.common.Allocator;
29  import org.apache.commons.imaging.common.BinaryFunctions;
30  import org.apache.commons.io.IOUtils;
31  
32  /**
33   * The PNG iCCP chunk. If "present, the image samples conform to the color space represented by the embedded ICC profile as defined by the International Color
34   * Consortium".
35   *
36   * @see <a href="http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html">PNG Specification</a>
37   */
38  public class PngChunkIccp extends PngChunk {
39  
40      /*
41       * Logger.
42       */
43      private static final Logger LOGGER = Logger.getLogger(PngChunkIccp.class.getName());
44  
45      /**
46       * ICC profile name.
47       */
48      private final String profileName;
49  
50      /**
51       * Compression method.
52       */
53      private final int compressionMethod;
54  
55      /**
56       * Compressed profile data.
57       */
58      private final byte[] compressedProfile;
59  
60      /**
61       * Uncompressed profile data.
62       */
63      private final byte[] uncompressedProfile;
64  
65      /**
66       * Constructs a new instance.
67       *
68       * @param length    chunk length
69       * @param chunkType chunk type
70       * @param crc       CRC computed over the chunk type and chunk data (but not the length)
71       * @param bytes     chunk data bytes
72       * @throws ImagingException when no profile name is present
73       * @throws IOException      when an error happens while reading the profile data
74       */
75      public PngChunkIccp(final int length, final int chunkType, final int crc, final byte[] bytes) throws ImagingException, IOException {
76          super(length, chunkType, crc, bytes);
77  
78          final int index = BinaryFunctions.findNull(bytes, "PngChunkIccp: No Profile Name");
79          final byte[] nameBytes = Arrays.copyOf(bytes, index);
80          profileName = new String(nameBytes, StandardCharsets.ISO_8859_1);
81  
82          compressionMethod = bytes[index + 1];
83  
84          final int compressedProfileLength = bytes.length - (index + 1 + 1);
85          compressedProfile = Allocator.byteArray(compressedProfileLength);
86          System.arraycopy(bytes, index + 1 + 1, compressedProfile, 0, compressedProfileLength);
87  
88          if (LOGGER.isLoggable(Level.FINEST)) {
89              LOGGER.finest("ProfileName: " + profileName);
90              LOGGER.finest("ProfileName.length(): " + profileName.length());
91              LOGGER.finest("CompressionMethod: " + compressionMethod);
92              LOGGER.finest("CompressedProfileLength: " + compressedProfileLength);
93              LOGGER.finest("bytes.length: " + bytes.length);
94          }
95  
96          uncompressedProfile = IOUtils.toByteArray(new InflaterInputStream(new ByteArrayInputStream(compressedProfile)));
97  
98          if (LOGGER.isLoggable(Level.FINEST)) {
99              LOGGER.finest("UncompressedProfile: " + bytes.length);
100         }
101     }
102 
103     public byte[] getCompressedProfile() {
104         return compressedProfile.clone();
105     }
106 
107     public int getCompressionMethod() {
108         return compressionMethod;
109     }
110 
111     public String getProfileName() {
112         return profileName;
113     }
114 
115     /**
116      * Gets a copy of the uncompressed profile data.
117      *
118      * @return the uncompressed profile data
119      */
120     public byte[] getUncompressedProfile() {
121         return uncompressedProfile.clone();
122     }
123 
124 }