예제 #1
0
static void GIFReadImageData(struct GIFImage *image, FILE *stream)
{
    int           minCodeSize;
    unsigned char **rows;
    unsigned int  width, height, interlaced;
    unsigned char *colors;
    unsigned int  numColors;
    unsigned int  xpos, ypos;
    int           pass, val;

    GIF_TRACE(("Reading Image Data\n"));

    /* Initialize the compression routines. */
    GIF_FGETC(minCodeSize, stream);
    if (minCodeSize >= LZW_BITS_MAX)  /* this should be in fact <= 8 */
        GIFError("GIF/LZW error: invalid LZW code size");

    if (LZWReadByte(LZW_TRUE, minCodeSize, stream) < 0)
        GIFError("Error reading GIF image");

    /* Ignore the picture if it is "uninteresting". */
    rows = image->Rows;
    if (rows == NULL)
    {
#if 0
        while (LZWReadByte(LZW_FALSE, minCodeSize, stream) >= 0)
        {
        }
#else
        /* This is faster, but possible LZW errors may go undetected. */
        GIFSkipDataBlocks(stream);
#endif
        return;
    }

    width      = image->Width;
    height     = image->Height;
    interlaced = image->InterlaceFlag;
    GIFGetColorTable(&colors, &numColors, image);
    xpos = ypos = 0;
    pass = 0;
    while ((val = LZWReadByte(LZW_FALSE, minCodeSize, stream)) >= 0)
    {
        if ((unsigned int)val >= numColors)
        {
            GIFWarning("Pixel value out of range");
            val = numColors - 1;
        }
        rows[ypos][xpos] = (unsigned char)val;
        if (++xpos == width)
        {
            xpos = 0;
            if (interlaced)
            {
                switch (pass)
                {
                case 0:
                case 1:
                    ypos += 8;
                    break;
                case 2:
                    ypos += 4;
                    break;
                case 3:
                    ypos += 2;
                    break;
                }
                if (ypos >= height)
                {
                    switch (++pass)
                    {
                    case 1:
                        ypos = 4;
                        break;
                    case 2:
                        ypos = 2;
                        break;
                    case 3:
                        ypos = 1;
                        break;
                    default:
                        goto fini;
                    }
                }
            }
            else
                ++ypos;
        }
        if (ypos >= height)
            break;
    }
fini:
    /* Ignore the trailing garbage. */
    while (LZWReadByte(LZW_FALSE, minCodeSize, stream) >= 0)
    {
    }
}
예제 #2
0
int /* PRIVATE */
pngx_read_gif(png_structp png_ptr, png_infop info_ptr, FILE *stream)
{
   /* GIF-specific data */
   struct GIFScreen screen;
   struct GIFImage image;
   struct GIFExtension ext;
   struct GIFGraphicCtlExt graphicExt;
   int code;
   unsigned char *colorTable;
   unsigned int numColors;
   unsigned int transparent;
   unsigned int numImages;
   /* PNG-specific data */
   png_uint_32 width, height;
   png_bytepp row_pointers;

   /* Set up the custom error handling. */
   pngx_err_ptr = png_ptr;
   GIFError     = pngx_gif_error;
   GIFWarning   = pngx_gif_warning;

   /* Read the GIF screen. */
   GIFReadScreen(&screen, stream);
   width  = screen.Width;
   height = screen.Height;

   /* Set the PNG image type. */
   png_set_IHDR(png_ptr, info_ptr,
      width, height, 8, PNG_COLOR_TYPE_PALETTE,
      PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

   /* Allocate memory. */
   row_pointers = pngx_malloc_rows(png_ptr, info_ptr, (int)screen.Background);

   /* Complete the initialization of the GIF reader. */
   GIFInitImage(&image, &screen, row_pointers);
   GIFInitExtension(&ext, &screen, NULL, 0);
   transparent = (unsigned int)(-1);
   numImages = 0;

   /* Iterate over the GIF file. */
   for ( ; ; )
   {
      code = GIFReadNextBlock(&image, &ext, stream);
      if (code == GIF_IMAGE)  /* ',' */
      {
         if (image.Rows != NULL)
         {
            /* Complete the PNG info. */
            if (image.InterlaceFlag)
               pngx_set_interlace_type(png_ptr, info_ptr,
                  PNG_INTERLACE_ADAM7);
            colorTable = GIFGetColorTable(&image, &numColors);
            pngx_set_GIF_palette(png_ptr, info_ptr, colorTable, numColors);
            if (transparent < 256)
               pngx_set_GIF_transparent(png_ptr, info_ptr, transparent);

            /* Inform the GIF routines not to read the upcoming images. */
            image.Rows = NULL;
         }
         ++numImages;
      }
      else if (code == GIF_EXTENSION && ext.Label == GIF_GRAPHICCTL)  /* '!' */
      {
         GIFGetGraphicCtl(&ext, &graphicExt);
         if (image.Rows != NULL && graphicExt.TransparentFlag)
            if (transparent >= 256)
               transparent = graphicExt.Transparent;
      }
      else if (code == GIF_TERMINATOR)  /* ';' */
         break;
   }

   /* Deallocate the GIF reader's extension buffer.
    * Use free() in conjunction with the reader's realloc().
    */
   if (ext.Buffer != NULL)
      free(ext.Buffer);
   /* FIXME:
    * Deallocate ext.Buffer on error, to prevent memory leaks.
    */

   if (image.Rows != NULL)
      png_error(png_ptr, "No image in GIF file");

   return numImages;
}