return "image/gif";
}
public void adapt(File oFile, ParserContext ctx) throws IOException {
// Add the MetaData to the tree!
DataSource ftk = new FileDataSource(oFile);
// Header and default information
ctx.fireStartParseEvent("GIF");
writeFileInfo(oFile, ctx);
try {
gifHeaderElement.read(ftk, ctx);
String version = ((String) ctx.getAttribute("GIF.version"))
.toLowerCase();
// this is where the standards file formats diverge
if (version.equals("87a")) {
gifScreenElement87a.read(ftk, ctx);
} else if (version.equals("89a")) {
gifScreenElement89a.read(ftk, ctx);
} else {
throw new RuntimeException("Unknown GIF Version :" + version);
}
// now jump over the global colour map.
boolean hasGlobalMap = ctx
.getBooleanAttribute("GIF.PACKED.global-map");
// System.out.println(hasGlobalMap);
if (hasGlobalMap) {
int bitsPerPixel = (int) ctx
.getIntAttribute("GIF.PACKED.bits-per-pixel");
readColorTable(ftk, ctx, bitsPerPixel);
}
// start reading all the blocks...
int imgC = 1;
boolean clean = false;
while (true) {
long b = FXUtil.getNumericalValue(ftk.getData(1), false);
// System.out.println("Block head "+b+"
// ("+Integer.toHexString((int)b)+")");
if (b == 0x21) {
/* Control Block */
// there are different kinds of control block...
long sb = FXUtil.getNumericalValue(ftk.getData(1), false);
if (sb == 0xf9) {
ctx.fireStartParseEvent("control-block");
ctx.fireParseEvent("sequence", imgC);
gifControlElement89a.read(ftk, ctx);
ctx.fireEndParseEvent("control-block");
} else if (sb == 0x01) {
// plain text
ctx.fireStartParseEvent("text");
gifPlainTextElement89a.read(ftk, ctx);
int blocks = readSubBlocks(ftk, ctx, false);
ctx.fireEndParseEvent("text");
} else if (sb == 0xfe) {
// plain text
ctx.fireStartParseEvent("comment");
int blocks = readSubBlocks(ftk, ctx, false);
ctx.fireEndParseEvent("comment");
} else if (sb == 0xff) {
ctx.fireStartParseEvent("application");
gifApplicationElement.read(ftk, ctx);
int blocks = readSubBlocks(ftk, ctx, true);
ctx.fireParseEvent("data-blocks", blocks);
ctx.fireEndParseEvent("application");
} else {
// System.out.println("unknown extension block "+sb+" at
// "+(ftk.getPosition()-1));
// can we recover and move on... No!
throw new RuntimeException("unknown extension block "
+ sb + " at " + (ftk.getPosition()));
}
} else if (b == 0x3b) {
/* Terminator */
clean = true;
break;
} else if (b == 0x2c) {
/* The Image... */
ctx.fireStartParseEvent("image-info");
ctx.fireParseEvent("sequence", imgC);
gifImageElement.read(ftk, ctx);
// move the pointer along to the next block (skip local
// color table and image data)
boolean hasLocalMap = ctx
.getBooleanAttribute("GIF.image-info.PACKED.has-local-map");
if (hasLocalMap) {
int bitsPerPixel = (int) ctx
.getIntAttribute("GIF.PACKED.image-bits-per-pixel");
readColorTable(ftk, ctx, bitsPerPixel);
}
// ...and the image data itself...
byte lzwMinCodeSize = ftk.getData(1)[0];
int blocks = readSubBlocks(ftk, ctx, true);
ctx.fireParseEvent("data-blocks", blocks);
// done!
ctx.fireEndParseEvent("image-info");
imgC++;
} else {
/* Unknown */
clean = false;
break;
}
}
ctx.fireParseEvent("frames", imgC - 1);
ctx.fireParseEvent("clean-termination", clean);
ctx.fireParseEvent("animated", imgC > 2 ? "true" : "false");
} catch (Exception ex) {
ex.printStackTrace();
ex.fillInStackTrace();
throw new RuntimeException(ex);
} finally {
ctx.fireEndParseEvent("GIF");
ftk.close();
}
}