265 lines
8.3 KiB
Java
265 lines
8.3 KiB
Java
/**********************************************************************
|
|
* 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<<size;
|
|
for (int i=0; i<n; i++) {
|
|
long r = stream.readUnsignedByte ();
|
|
long g = stream.readUnsignedByte ();
|
|
long b = stream.readUnsignedByte ();
|
|
System.out.println (leading (os, 8) + os + ": " +
|
|
leading (i, 3, ' ') + i + ": " +
|
|
leading (r, 3, ' ') + r + "," +
|
|
leading (g, 3, ' ') + g + "," +
|
|
leading (b, 3, ' ') + b);
|
|
os += 3;
|
|
}
|
|
return os;
|
|
}
|
|
|
|
/**
|
|
* Read and display a sequence of sub-blocks.
|
|
* @param stream Data input stream
|
|
* @param os Current byte offset
|
|
* @return Updated byte offset
|
|
*/
|
|
private static long subBlocks (DataInputStream stream, long os)
|
|
throws IOException
|
|
{
|
|
int size;
|
|
|
|
while ((size = stream.readUnsignedByte ()) != 0) {
|
|
System.out.println (leading (os, 8) + os + ": SubBlock: " + size);
|
|
os += 1;
|
|
for (int i=0; i<size; i++) {
|
|
stream.readUnsignedByte ();
|
|
os += 1;
|
|
}
|
|
}
|
|
System.out.println (leading (os, 8) + os + ": BlockTerminator");
|
|
return os + 1;
|
|
}
|
|
}
|