001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.imaging.formats.png.chunks;
018
019import java.io.ByteArrayInputStream;
020import java.util.Objects;
021
022import org.apache.commons.imaging.common.BinaryFileParser;
023
024/**
025 * A PNG image is composed of several chunks. This is the base class for the chunks, used by the parser.
026 *
027 * @see <a href="https://en.wikipedia.org/wiki/Portable_Network_Graphics#%22Chunks%22_within_the_file">Portable_Network_Graphics</a>
028 */
029public class PngChunk extends BinaryFileParser {
030
031    private final int length;
032    private final int chunkType;
033    private final int crc;
034    private final byte[] bytes;
035
036    private final boolean[] propertyBits;
037    private final boolean ancillary;
038    private final boolean isPrivate;
039    private final boolean reserved;
040    private final boolean safeToCopy;
041
042    /**
043     * Constructs a new instance.
044     *
045     * @param length    chunk length.
046     * @param chunkType chunk type.
047     * @param crc       CRC computed over the chunk type and chunk data (but not the length).
048     * @param bytes     chunk data bytes.
049     * @throws NullPointerException if {@code bytes} is null.
050     */
051    public PngChunk(final int length, final int chunkType, final int crc, final byte[] bytes) {
052        this.bytes = Objects.requireNonNull(bytes, "bytes").clone();
053        this.length = length;
054        this.chunkType = chunkType;
055        this.crc = crc;
056
057        propertyBits = new boolean[4];
058        int shift = 24;
059        final int theMask = 1 << 5;
060        for (int i = 0; i < propertyBits.length; i++) {
061            final int theByte = 0xff & chunkType >> shift;
062            shift -= 8;
063            propertyBits[i] = (theByte & theMask) > 0;
064        }
065
066        ancillary = propertyBits[0];
067        isPrivate = propertyBits[1];
068        reserved = propertyBits[2];
069        safeToCopy = propertyBits[3];
070    }
071
072    /**
073     * Gets a copy of the chunk bytes.
074     *
075     * @return the chunk bytes
076     */
077    public byte[] getBytes() {
078        return bytes.clone();
079    }
080
081    public int getChunkType() {
082        return chunkType;
083    }
084
085    public int getCrc() {
086        return crc;
087    }
088
089    /**
090     * Gets a new {@link ByteArrayInputStream} for the chunk bytes.
091     *
092     * <p>
093     * The caller is responsible for closing the resource.
094     * </p>
095     *
096     * @return a ByteArrayInputStream for the chunk bytes
097     */
098    protected ByteArrayInputStream getDataStream() {
099        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}