public static StructType decode(ByteBuffer buffer, int id) {
   StructType struct = new StructType();
   struct.id = id;
   for (int opcode = buffer.get() & 0xff; opcode != 0; opcode = buffer.get() & 0xff) {
     if (opcode == 249) {
       int count = buffer.get() & 0xff;
       if (null == struct.values) {
         struct.values = new HashMap<Integer, Object>(count);
       }
       for (int i = 0; i < count; i++) {
         boolean stringParam = (buffer.get() & 0xff) == 1;
         int key = ByteBufferUtils.getTriByte(buffer);
         Object value;
         if (stringParam) {
           value = ByteBufferUtils.getString(buffer);
         } else {
           value = new Integer(buffer.getInt());
         }
         struct.values.put(key, value);
       }
     }
   }
   return struct;
 }
  /**
   * Decodes the {@link Sprite} from the specified {@link ByteBuffer}.
   *
   * @param buffer The buffer.
   * @return The sprite.
   */
  public static Sprite decode(ByteBuffer buffer) {
    /* find the size of this sprite set */
    buffer.position(buffer.limit() - 2);
    int size = buffer.getShort() & 0xFFFF;

    /* allocate arrays to store info */
    int[] offsetsX = new int[size];
    int[] offsetsY = new int[size];
    int[] subWidths = new int[size];
    int[] subHeights = new int[size];

    /* read the width, height and palette size */
    buffer.position(buffer.limit() - size * 8 - 7);
    int width = buffer.getShort() & 0xFFFF;
    int height = buffer.getShort() & 0xFFFF;
    int[] palette = new int[(buffer.get() & 0xFF) + 1];

    /* and allocate an object for this sprite set */
    Sprite set = new Sprite(width, height, size);

    /* read the offsets and dimensions of the individual sprites */
    for (int i = 0; i < size; i++) {
      offsetsX[i] = buffer.getShort() & 0xFFFF;
    }
    for (int i = 0; i < size; i++) {
      offsetsY[i] = buffer.getShort() & 0xFFFF;
    }
    for (int i = 0; i < size; i++) {
      subWidths[i] = buffer.getShort() & 0xFFFF;
    }
    for (int i = 0; i < size; i++) {
      subHeights[i] = buffer.getShort() & 0xFFFF;
    }

    /* read the palette */
    buffer.position(buffer.limit() - size * 8 - 7 - (palette.length - 1) * 3);
    palette[0] = 0; /* transparent colour (black) */
    for (int index = 1; index < palette.length; index++) {
      palette[index] = ByteBufferUtils.getTriByte(buffer);
      if (palette[index] == 0) palette[index] = 1;
    }

    /* read the pixels themselves */
    buffer.position(0);
    for (int id = 0; id < size; id++) {
      /* grab some frequently used values */
      int subWidth = subWidths[id], subHeight = subHeights[id];
      int offsetX = offsetsX[id], offsetY = offsetsY[id];

      /* create a BufferedImage to store the resulting image */
      BufferedImage image =
          set.frames[id] = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

      /* allocate an array for the palette indices */
      int[][] indices = new int[subWidth][subHeight];

      /* read the flags so we know whether to read horizontally or vertically */
      int flags = buffer.get() & 0xFF;

      /* now read the image */
      if (image != null) {
        /* read the palette indices */
        if ((flags & FLAG_VERTICAL) != 0) {
          for (int x = 0; x < subWidth; x++) {
            for (int y = 0; y < subHeight; y++) {
              indices[x][y] = buffer.get() & 0xFF;
            }
          }
        } else {
          for (int y = 0; y < subHeight; y++) {
            for (int x = 0; x < subWidth; x++) {
              indices[x][y] = buffer.get() & 0xFF;
            }
          }
        }

        /* read the alpha (if there is alpha) and convert values to ARGB */
        if ((flags & FLAG_ALPHA) != 0) {
          if ((flags & FLAG_VERTICAL) != 0) {
            for (int x = 0; x < subWidth; x++) {
              for (int y = 0; y < subHeight; y++) {
                int alpha = buffer.get() & 0xFF;
                image.setRGB(x + offsetX, y + offsetY, alpha << 24 | palette[indices[x][y]]);
              }
            }
          } else {
            for (int y = 0; y < subHeight; y++) {
              for (int x = 0; x < subWidth; x++) {
                int alpha = buffer.get() & 0xFF;
                image.setRGB(x + offsetX, y + offsetY, alpha << 24 | palette[indices[x][y]]);
              }
            }
          }
        } else {
          for (int x = 0; x < subWidth; x++) {
            for (int y = 0; y < subHeight; y++) {
              int index = indices[x][y];
              if (index == 0) {
                image.setRGB(x + offsetX, y + offsetY, 0);
              } else {
                image.setRGB(x + offsetX, y + offsetY, 0xFF000000 | palette[index]);
              }
            }
          }
        }
      }
    }
    return set;
  }