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.util.Objects;
21
22 import org.apache.commons.imaging.common.BinaryFileParser;
23
24 /**
25 * A PNG image is composed of several chunks. This is the base class for the chunks, used by the parser.
26 *
27 * @see <a href="https://en.wikipedia.org/wiki/Portable_Network_Graphics#%22Chunks%22_within_the_file">Portable_Network_Graphics</a>
28 */
29 public class PngChunk extends BinaryFileParser {
30
31 private final int length;
32 private final int chunkType;
33 private final int crc;
34 private final byte[] bytes;
35
36 private final boolean[] propertyBits;
37 private final boolean ancillary;
38 private final boolean isPrivate;
39 private final boolean reserved;
40 private final boolean safeToCopy;
41
42 /**
43 * Constructs a new instance.
44 *
45 * @param length chunk length
46 * @param chunkType chunk type
47 * @param crc CRC computed over the chunk type and chunk data (but not the length)
48 * @param bytes chunk data bytes
49 * @throws NullPointerException if bytes is null.
50 */
51 public PngChunk(final int length, final int chunkType, final int crc, final byte[] bytes) {
52 this.length = length;
53 this.chunkType = chunkType;
54 this.crc = crc;
55 this.bytes = Objects.requireNonNull(bytes, "bytes").clone();
56
57 propertyBits = new boolean[4];
58 int shift = 24;
59 final int theMask = 1 << 5;
60 for (int i = 0; i < propertyBits.length; i++) {
61 final int theByte = 0xff & chunkType >> shift;
62 shift -= 8;
63 propertyBits[i] = (theByte & theMask) > 0;
64 }
65
66 ancillary = propertyBits[0];
67 isPrivate = propertyBits[1];
68 reserved = propertyBits[2];
69 safeToCopy = propertyBits[3];
70 }
71
72 /**
73 * Gets a copy of the chunk bytes.
74 *
75 * @return the chunk bytes
76 */
77 public byte[] getBytes() {
78 return bytes.clone();
79 }
80
81 public int getChunkType() {
82 return chunkType;
83 }
84
85 public int getCrc() {
86 return crc;
87 }
88
89 /**
90 * Gets a new {@link ByteArrayInputStream} for the chunk bytes.
91 *
92 * <p>
93 * The caller is responsible for closing the resource.
94 * </p>
95 *
96 * @return a ByteArrayInputStream for the chunk bytes
97 */
98 protected ByteArrayInputStream getDataStream() {
99 return new ByteArrayInputStream(bytes);
100 }
101
102 public int getLength() {
103 return length;
104 }
105
106 /**
107 * Gets a copy of the chunk property bits.
108 *
109 * @return the chunk property bits
110 */
111 public boolean[] getPropertyBits() {
112 return propertyBits.clone();
113 }
114
115 public boolean isAncillary() {
116 return ancillary;
117 }
118
119 public boolean isPrivate() {
120 return isPrivate;
121 }
122
123 public boolean isReserved() {
124 return reserved;
125 }
126
127 public boolean isSafeToCopy() {
128 return safeToCopy;
129 }
130
131 }