1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49:
50: public class PNGFile
51: {
52:
55: private static final byte[] signature = new byte[]
56: { (byte)137, 80, 78, 71, 13, 10, 26, 10 };
57:
58:
62: private static final byte[] endChunk = new byte[]
63: { 0, 0, 0, 0, (byte)0x49, (byte)0x45, (byte)0x4E, (byte)0x44,
64: (byte)0xAE, (byte)0x42, (byte)0x60, (byte)0x82 };
65:
66:
69: private Vector chunks;
70:
71:
74: private PNGHeader header;
75:
76:
79: private boolean hasPalette;
80:
81:
84: private int width, height;
85:
86:
89: private PNGDecoder decoder;
90:
91:
94: private PNGEncoder encoder;
95:
96:
99: private BufferedImage sourceImage;
100:
101:
104: public PNGFile(InputStream in) throws IOException, PNGException
105: {
106: PNGChunk chunk;
107: byte[] fileHdr = new byte[8];
108: chunks = new Vector();
109: hasPalette = false;
110:
111: if( in.read( fileHdr ) != 8 )
112: throw new IOException("Could not read file header.");
113: if( !validateHeader( fileHdr ) )
114: throw new PNGException("Invalid file header. Not a PNG file.");
115:
116: chunk = PNGChunk.readChunk( in, false );
117: if( !(chunk instanceof PNGHeader) )
118: throw new PNGException("First chunk not a header chunk.");
119: header = (PNGHeader)chunk;
120: if( !header.isValidChunk() )
121: throw new PNGException("First chunk not a valid header.");
122: System.out.println(header);
123:
124: decoder = new PNGDecoder( header );
125:
126: do
127: {
128: chunk = PNGChunk.readChunk( in, false );
129:
133: if( chunk.isValidChunk() )
134: {
135: if( chunk instanceof PNGData )
136: decoder.addData( (PNGData)chunk );
137: else
138: if( chunk.getType() != PNGChunk.TYPE_END )
139: {
140: chunks.add( chunk );
141: hasPalette |= ( chunk instanceof PNGPalette );
142: }
143: }
144: else
145: System.out.println("WARNING: Invalid chunk!");
146: }
147: while( chunk.getType() != PNGChunk.TYPE_END );
148:
149: if( header.isIndexed() && !hasPalette )
150: throw new PNGException("File is indexed color and has no palette.");
151:
152: width = header.getWidth();
153: height = header.getHeight();
154: }
155:
156:
159: public PNGFile(BufferedImage bi) throws PNGException
160: {
161: sourceImage = bi;
162: width = bi.getWidth();
163: height = bi.getHeight();
164: chunks = new Vector();
165: encoder = new PNGEncoder( bi );
166: header = encoder.getHeader();
167: if( header.isIndexed() )
168: chunks.add( encoder.getPalette() );
169:
170:
171: chunks.addAll( encoder.encodeImage() );
172: }
173:
174:
177: public void writePNG(OutputStream out) throws IOException
178: {
179: out.write( signature );
180: header.writeChunk( out );
181: for( int i = 0; i < chunks.size(); i++ )
182: {
183: PNGChunk chunk = ((PNGChunk)chunks.elementAt(i));
184: chunk.writeChunk( out );
185: }
186: out.write( endChunk );
187: }
188:
189:
192: private boolean validateHeader( byte[] hdr )
193: {
194: if( hdr.length != 8 )
195: return false;
196: for( int i = 0; i < 8; i++ )
197: if( signature[i] != hdr[i] )
198: return false;
199: return true;
200: }
201:
202:
205: public BufferedImage getBufferedImage()
206: {
207: if( decoder == null )
208: return sourceImage;
209:
210: WritableRaster r = decoder.getRaster( header );
211: ColorModel cm;
212: if( header.isIndexed() )
213: {
214: PNGPalette pngp = getPalette();
215: cm = pngp.getPalette( getColorSpace() );
216: }
217: else
218: cm = decoder.getColorModel( getColorSpace(),
219: header.getColorType(),
220: header.getDepth() );
221:
222: return new BufferedImage(cm, r, false, null);
223: }
224:
225:
228: private PNGPalette getPalette()
229: {
230: for(int i = 0; i < chunks.size(); i++ )
231: if( chunks.elementAt(i) instanceof PNGPalette )
232: return ((PNGPalette)chunks.elementAt(i));
233: return null;
234: }
235:
236:
240: private ColorSpace getColorSpace()
241: {
242: PNGICCProfile icc = null;
243: PNGGamma gamma = null;
244: for(int i = 0; i < chunks.size(); i++ )
245: {
246: if( chunks.elementAt(i) instanceof PNGICCProfile )
247: icc = ((PNGICCProfile)chunks.elementAt(i));
248: else if(chunks.elementAt(i) instanceof PNGGamma )
249: gamma = ((PNGGamma)chunks.elementAt(i));
250: }
251:
252: if( icc != null )
253: return icc.getColorSpace();
254:
255:
256: return null;
257: }
258: }