/********************************************************************** * GDump - JSTOR/Harvard Object Validation Environment * Copyright 2004 by the President and Fellows of Harvard College * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA **********************************************************************/ import edu.harvard.hul.ois.jhove.*; import java.io.*; //import java.util.*; /** * Dump contents of GIF file in human-readable format. */ public class GDump extends Dump { /****************************************************************** * MAIN ENTRY POINT. ******************************************************************/ /** * Main entry point. * @param args Command line arguments */ public static void main (String [] args) { if (args.length < 1) { System.err.println ("usage: java GDump file"); System.exit (-1); } try { FileInputStream file = new FileInputStream (args[0]); BufferedInputStream buffer = new BufferedInputStream (file); DataInputStream stream = new DataInputStream (buffer); boolean bigEndian = false; String signature = readChars (stream, 3); String version = readChars (stream, 3); System.out.println ("00000000: \"" + signature + version + "\""); int width = ModuleBase.readUnsignedShort(stream, bigEndian, null); int height = ModuleBase.readUnsignedShort(stream, bigEndian, null); int packedFields = stream.readUnsignedByte (); int backgroundColor = stream.readUnsignedByte (); int aspectRatio = stream.readUnsignedByte (); System.out.println ("00000006: LogicalScreenDescriptor: " + width + "x" + height + " 0x" + leading (packedFields, 2) + Integer.toHexString (packedFields) + " " + backgroundColor + " " + aspectRatio); long os = 13; boolean globalColorTable = (packedFields & 0x80) != 0; int globalColorTableSize = packedFields & 0x07; if (globalColorTable) { System.out.println (leading (os, 8) + os + ": GlobalColorTable:"); os = colorTable (stream, os, globalColorTableSize); } for (int op = 0; (op = stream.readUnsignedByte ()) != -1;) { if (op == 0x00) { System.out.println (leading (os, 8) + os + ": BlockTerminator"); os++; } else if (op == 0x2c) { int imageLeft = ModuleBase.readUnsignedShort (stream, bigEndian, null); int imageTop = ModuleBase.readUnsignedShort (stream, bigEndian, null); int imageWidth = ModuleBase.readUnsignedShort (stream, bigEndian, null); int imageHeight = ModuleBase.readUnsignedShort (stream, bigEndian, null); packedFields = stream.readUnsignedByte (); System.out.println (leading (os, 8) + os + ": ImageDescriptor: " + imageLeft + "," + imageTop + " " + imageWidth + "x" + imageHeight + " 0x" + leading (packedFields, 2) + Integer.toHexString (packedFields)); os += 10; boolean localColorTable = (packedFields & 0x80) != 0; int localColorTableSize = packedFields & 0x07; if (localColorTable) { System.out.println (leading (os, 8) + os + ": LocalColorTable:"); os = colorTable (stream, os, localColorTableSize); } int size = stream.readUnsignedByte (); System.out.println (leading (os, 8) + os + ": ImageData: " + size); os = subBlocks (stream, ++os); } else if (op == 0x21) { int label = stream.readUnsignedByte (); if (label == 0x01) { int blockSize = stream.readUnsignedByte (); int gridLeft = ModuleBase.readUnsignedShort(stream, bigEndian, null); int gridTop = ModuleBase.readUnsignedShort(stream, bigEndian, null); int gridWidth = ModuleBase.readUnsignedShort(stream, bigEndian, null); int gridHeight= ModuleBase.readUnsignedShort(stream, bigEndian, null); int cellWidth = stream.readUnsignedByte (); int cellHeight = stream.readUnsignedByte (); int foreground = stream.readUnsignedByte (); int background = stream.readUnsignedByte (); System.out.println (leading (os, 8) + os + ": PlainTextExtension: " + blockSize + " " + gridLeft + "," + gridTop + " " + gridWidth + "x" + gridHeight + " " + cellWidth + "x" + cellHeight + " " + foreground + "," + background); os += 15; os = subBlocks (stream, os); } else if (label == 0xf9) { int blockSize = stream.readUnsignedByte (); packedFields = stream.readUnsignedByte (); int delayTime = ModuleBase.readUnsignedShort(stream, bigEndian, null); int colorIndex= stream.readUnsignedByte (); System.out.println (leading (os, 8) + os + ": GraphicControlExtension: " + blockSize + " 0x" + leading (packedFields, 2) + packedFields + " " + delayTime + " " + colorIndex); os += 7; } else if (label == 0xfe) { System.out.println (leading (os, 8) + os + ": CommentExtension: \"" + "\""); os += 2; os = subBlocks (stream, os); } else if (label == 0xff) { int blockSize = stream.readUnsignedByte (); String appId = readChars (stream, 8); int [] authCode = new int [3]; authCode[0] = stream.readUnsignedByte (); authCode[1] = stream.readUnsignedByte (); authCode[2] = stream.readUnsignedByte (); System.out.println (leading (os, 8) + os + ": ApplicationExtension: " + blockSize + " \"" + appId + "\" " + authCode[0] + "," + authCode[1] + "," + authCode[2]); os += 14; os = subBlocks (stream, os); } else { String hex = Integer.toHexString (label); System.out.println (leading (os-1, 8) + (os-1) + ": Unknown extension block: 0x" + leading (hex, 2) + hex); os += 2; } } else if (op == 0x3b) { System.out.println (leading (os, 8) + os + ": Trailer: 0x3b"); os++; break; } else { String hex = Integer.toHexString (op); System.out.println (leading (os, 8) + os + ": Unknown block: 0x" + leading (hex, 2) + hex); os++; } } stream.close (); } catch (Exception e) { e.printStackTrace (System.err); System.exit (-2); } } /** * Read and display a color table. * @param stream Data input stream * @param os Current byte offset * @param size Color table size * @return Updated byte offset */ private static long colorTable (DataInputStream stream, long os, int size) throws IOException { int n = 2<