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