    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}