/*
 * Copyright (c) 1997-2004 Alexandros Eleftheriadis, Danny Hong and
 * Yuntai Kyong.
 * 
 * This file is part of Flavor, developed at Columbia University
 * (www.ee.columbia.edu/flavor).
 *
 * Flavor is free software; you can redistribute it and/or modify
 * it under the terms of the Flavor Artistic License as described in
 * the file COPYING.txt. 
 *
 */

/*
 * Authors:
 * Danny Hong <danny@ee.columbia.edu>
 *
 */

/*
 * Flavor description of the GIF87a bitstream specification.
 *
 */

// Set array size to 256 and also allow tracing
%pragma array=256, trace

// Color map entries
class ColorEntry {
    unsigned int(8) r;
    unsigned int(8) g;
    unsigned int(8) b;
}

// Color maps (argument is bits/pixel
class ColorMap(unsigned int bpp) {
    ColorEntry color[1<<bpp];
}

// Screen descriptor
class ScreenDescriptor {
    // GIF uses LSB ordering
    little unsigned int(16) width;
    little unsigned int(16) height;
    
    // This flag is set if a global color map follows the descriptor
    bit(1) M;
    
    // Color resolution minus 1
    unsigned int(3) cr;

    // Marker (always 0)
    bit(1) marker = 0;

    // Bits/pixel in image minus 1
    unsigned int(3) pixel;

    // Index of background color
    unsigned int(8) background;

    // If M is set, we have a global colormap; its size is 2**(pixel+1)
    if (M != 0)
        ColorMap globalColorMap(pixel+1);
}

// Extension block (signalled by '!')
class ExtensionBlock {
    unsigned int(8) function_code;

    do {
        unsigned int(8) byte_count;
        if (byte_count != 0) {
            unsigned int i;
            for (i=0; i<byte_count; i++) {
                unsigned int(8) data;
            }
        }
    } while (byte_count != 0);
}

// The image data 
class ImageData {
    // Code size
    unsigned int(8) code_size;

    // Series of data blocks
    do {
        unsigned int(8) byte_count;
        if (byte_count != 0) {
            unsigned int i;
            for (i=0; i<byte_count; i++) 
                unsigned int(8) data;
        }
    } while (byte_count != 0);
}

// Image descriptor (signalled by ',')
class ImageDescriptor {
    little unsigned int(16) left;
    little unsigned int(16) top;
    little unsigned int(16) width;
    little unsigned int(16) height;
    
    /* If set, use local color map, and use 'pixel' below;
     * otherwise ignore 'pixel' and use global colormap
     */
    bit(1) M;

    // Interlace flag
    bit(1) I;

    // Three reserved bits; must be 0
    bit(3) markers = 0;

    // Bits/pixel in this image minus 1 (valid only if M=1)
    unsigned int(3) pixel;

    // If M is set, we have a local colormap; its size is 2**(pixel+1)
    if (M != 0) 
        ColorMap localColorMap(pixel+1);

    // Image data
    ImageData data;
}

class GIF87a {
    // GIF signature
    char(8) GIFsignature[6] = "GIF87a";
    
    // Screen descriptor
    ScreenDescriptor sd;

    // One or more image descriptors
    do {
        unsigned int(8) end;
        
        if (end == ',') {   // We found an image descriptor
            ImageDescriptor id;
        }
        if (end == '!') {   // We found an extension block
            ExtensionBlock eb;
        }
        // Everything else is ignored
    } while (end != ';');   // ';' is the end-of-data marker
}