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}