Package gif

Source Code of gif.GifInfo

/**
* Copyright: t3am_C9 (Alexander Schäffer, Johannes Ebersold, Sebastian Geib, Thomas Kisiel)
*
* This file is part of GifToApngConverter
*
* GifToApngConverter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GifToApngConverter 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GifToApngConverter. If not, see <a href="http://www.gnu.org/licenses/">here</a>
*/

package gif;


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
* Reads information from the Gif-file which can't be accessed with
* the integrated image reader. It's a bit complex... but whatever.
* It could evolve to a real gifreader xD
*/
public class GifInfo
{
  // a few needed constants to identifiy blocks
  private final int IMAGEDESCRIPTOR = 0x2c;
  private final int TRAILER = 0x3b;
 
  private final int EXTENSIONBLOCK = 0x21;
  private final int APPLICATIONEXTENSIONLABEL = 0xFF;
  private final int COMMENTEXTENSIONBLOCK = 0xFE;
  private final int PLAINTEXTEXTENSION = 0x01;
  private final int GRAPHICCONTROLEXTENSION = 0xF9;
 
  private final int MARKLIMIT = 1024;
 
 
  // member
  protected int mLoops = 1;    // 0 = forever
  private StringBuilder mComment;  // holds a Comment String
 
  /**
   * Reads information from a file. Right now, it will only read the
   * netscape extension information, because there is no other way to get it.
   * @param file File
   * @throws IOException
   */
  public GifInfo(File file) throws IOException
  {
    // create a buffered stream. Error handling will be done outside)
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
   
    // load the string builder
    mComment = new StringBuilder();
   
    // make sure that we have the mark/reset feature because I need it
    if (!bis.markSupported())
    {
      throw new IOException("Error: Mark/Read not supported.");
    }
   
    readHeader(bis);
    readBlocks(bis);
   
    bis.close();
  }
 
  /**
   * Moves through all blocks in the gif file and reads the needed information
   * @param bis BufferedInputStream
   */
  private void readBlocks(BufferedInputStream bis) throws IOException
  {
    int id = 0;
   
    do
    {
      // get block id and leave fpointer where it is
      bis.mark(MARKLIMIT);
      id = bis.read();
      bis.reset();
     
      if (id <= 0) throw new IOException("GifInfo: Something went wrong or I reached EOF.")// quit loop
     
      // decide what to do with the blocks
      if (id != EXTENSIONBLOCK)
      {
        // handle gif blocks here. They MUST be processed
        switch (id)
        {
        case IMAGEDESCRIPTOR:
          readImage(bis);
          break;
        case TRAILER:
          return;
        default:
          throw new IOException("Error: GifInfo encountered an unknown block type: "+ id);
        }
      }
      else
      {
        // handle extension blocks here
        int label = 0;
        bis.mark(MARKLIMIT);
        safeSkip(bis,1);
        label = bis.read();
        bis.reset();
       
        switch (label)
        {
        case APPLICATIONEXTENSIONLABEL:
          readNetscapeExtensionBlock(bis);
          break;
        case COMMENTEXTENSIONBLOCK:
          readComment(bis);
          break;
        case PLAINTEXTEXTENSION:
          //TODO is this even implementable in the apng???
          skipExtensionBlock(bis);
          break;
        case GRAPHICCONTROLEXTENSION:
          skipExtensionBlock(bis);
          break;
        default:
          skipExtensionBlock(bis);
        }
      }
    } while (true);
   
  }
 
  /**
   * Moves the filepointer over a filetable. Function needs the packed fields value and
   * it has to be called after the end of the preceding block
   * @param bis BufferedStreamReader
   * @param packedFieldsValue int
   * @throws IOException
   */
  private void skipColorTable(BufferedInputStream bis, int packedFieldsValue) throws IOException
  {
    if ((packedFieldsValue & 128) > 0)    // checks flag 8
    {
      int tableSize = packedFieldsValue & 7// get 3 bit value
      tableSize = 3 * ((int) Math.pow(2, (tableSize +1 )));
      safeSkip(bis,tableSize);
    }
  }
 
  /**
   * Right now just skip over the header. We just need the palette information to
   * know how far we have to skip. This method moves the filepointer.
   * @param bis BufferedInputStream
   * @throws IOException
   */
  private void readHeader(BufferedInputStream bis) throws IOException
  {
    int value = 0;
   
    // skipp header information. Check for global table and it's size if available
    safeSkip(bis,6)// jump over header
    // try to read the header information
    safeSkip(bis,4);
    value = bis.read();    // packed fields
    safeSkip(bis,2);
    // handle a possible global color table
    skipColorTable(bis, value);
  }
 
  /**
   * Will skip over the imageblock. This method moves the filepointer.
   * @param bis BufferedInputStream
   * @throws IOException
   */
  private void readImage(BufferedInputStream bis) throws IOException
  {
    // skip some data
    safeSkip(bis,9);
    int value = bis.read();
   
    // skip local table if available
    skipColorTable(bis, value);
   
    // skip the lzw info
    safeSkip(bis,1);
   
    skipSubBlocks(bis);
   
    // pointer is now at the beginning of the next block
  }
 
  private void readComment(BufferedInputStream bis) throws IOException
  {
    // skip first two bytes because I am sue that i am correct
    safeSkip(bis,2);
   
    // now read in the data
    int length;
    int value;
    do
    {
      length = bis.read();
      if(length>0 && mComment.length()>0){
        mComment.append(' '); //space between comment-blocks
      }
      for (int i = 0; i < length;i++)
      {
        value = bis.read();
        mComment.append((char)value);
      }     
    } while (length > 0);
    // pointer will be at the beginning of the next block
  }
 
  /**
   * Moves the filepointer over an extensionblock
   * This method moves the filepointer!
   * @param bis BufferedInputStream
   */
  private void skipExtensionBlock(BufferedInputStream bis) throws IOException
  {
    safeSkip(bis,2)// skip ident and label
    int length = bis.read();
    // skip data
    safeSkip(bis,length);
   
    // skip data block with subblocks
    skipSubBlocks(bis);
  }
 
  /**
   * Skips over subblocks which appear in a Datablock
   * @param bis
   * @throws IOException
   */
  private void skipSubBlocks(BufferedInputStream bis) throws IOException
  {
    // skip all subblocks
    int value = 0;
    do
    {
      value = bis.read();
      safeSkip(bis, value);     
     
    } while (value != 0);
  }
 
  /**
   * Reads the Netscape extension. If this isn't the netscape extension, we skip it.
   * @param bis BufferedInputStream
   * @throws IOException
   */
  private void readNetscapeExtensionBlock(BufferedInputStream bis) throws IOException
  {
    bis.mark(MARKLIMIT)// safe position in case we need to skip this blo
    safeSkip(bis,3); // skip identification and blocksize
   
    // we just check 1 letter for now
   
    if (bis.read() == 'N')
    {
      safeSkip(bis,12); // skip useless data for now
      // now read the looping count... finally =)
      int value = 0;
      value = bis.read();
      value += 256 * bis.read();
      if (value > 0) value++;
      mLoops = value;  // yay :D
      safeSkip(bis,1);
    }
    else
    {
      bis.reset();
      skipExtensionBlock(bis);
    }
    // we should be now at the beginning of the next block
  }
 
  /**
   * Returns the number of iterations for the gif
   * @return int
   */
  public int getLoops()
  {
    return mLoops;
  }
 
  /**
   * Returns a comment in a String
   * @return String
   */
  public String getComment()
  {
    return mComment.toString();
  }
 
  /**
   * Will skip for 100%.
   * @param bis
   * @param count
   * @throws IOException
   */
  private void safeSkip(BufferedInputStream bis, long count) throws IOException
  {
    do
    {
      count = count - bis.skip(count);
      // if count > 0 check for EOF
      if (count >= bis.available())
        throw new IOException("Error: End of File reached (file might be corrupt)");
    } while (count > 0);
  }
}
TOP

Related Classes of gif.GifInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.