Logo Search packages:      
Sourcecode: fbi version File versions  Download package

read-gif.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gif_lib.h>

#include "readers.h"

struct gif_state {
    FILE         *infile;
    GifFileType  *gif;
    GifPixelType *row;
    GifPixelType *il;
    int w,h;
};

static GifRecordType
gif_fileread(struct gif_state *h)
{
    GifRecordType RecordType;
    GifByteType *Extension;
    int ExtCode, rc;
    char *type;

    for (;;) {
      if (GIF_ERROR == DGifGetRecordType(h->gif,&RecordType)) {
          if (debug)
            fprintf(stderr,"gif: DGifGetRecordType failed\n");
          PrintGifError();
          return -1;
      }
      switch (RecordType) {
      case IMAGE_DESC_RECORD_TYPE:
          if (debug)
            fprintf(stderr,"gif: IMAGE_DESC_RECORD_TYPE found\n");
          return RecordType;
      case EXTENSION_RECORD_TYPE:
          if (debug)
            fprintf(stderr,"gif: EXTENSION_RECORD_TYPE found\n");
          for (rc = DGifGetExtension(h->gif,&ExtCode,&Extension);
             NULL != Extension;
             rc = DGifGetExtensionNext(h->gif,&Extension)) {
            if (rc == GIF_ERROR) {
                if (debug)
                  fprintf(stderr,"gif: DGifGetExtension failed\n");
                PrintGifError();
                return -1;
            }
            if (debug) {
                switch (ExtCode) {
                case COMMENT_EXT_FUNC_CODE:     type="comment";   break;
                case GRAPHICS_EXT_FUNC_CODE:    type="graphics";  break;
                case PLAINTEXT_EXT_FUNC_CODE:   type="plaintext"; break;
                case APPLICATION_EXT_FUNC_CODE: type="appl";      break;
                default:                        type="???";       break;
                }
                fprintf(stderr,"gif: extcode=0x%x [%s]\n",ExtCode,type);
            }
          }
          break;
      case TERMINATE_RECORD_TYPE:
          if (debug)
            fprintf(stderr,"gif: TERMINATE_RECORD_TYPE found\n");
          return RecordType;
      default:
          if (debug)
            fprintf(stderr,"gif: unknown record type [%d]\n",RecordType);
          return -1;
      }
    }
}

#if 0
static void
gif_skipimage(struct gif_state *h)
{
    unsigned char *line;
    int i;

    if (debug)
      fprintf(stderr,"gif: skipping image record ...\n");
    DGifGetImageDesc(h->gif);
    line = malloc(h->gif->SWidth);
    for (i = 0; i < h->gif->SHeight; i++)
      DGifGetLine(h->gif, line, h->gif->SWidth);
    free(line);
}
#endif

static void*
gif_init(FILE *fp, char *filename, unsigned int page,
       struct ida_image_info *info, int thumbnail)
{
    struct gif_state *h;
    GifRecordType RecordType;
    int i, image = 0;
    
    h = malloc(sizeof(*h));
    memset(h,0,sizeof(*h));

    h->infile = fp;
    h->gif = DGifOpenFileHandle(fileno(fp));
    h->row = malloc(h->gif->SWidth * sizeof(GifPixelType));

    while (0 == image) {
      RecordType = gif_fileread(h);
      switch (RecordType) {
      case IMAGE_DESC_RECORD_TYPE:
          if (GIF_ERROR == DGifGetImageDesc(h->gif)) {
            if (debug)
                fprintf(stderr,"gif: DGifGetImageDesc failed\n");
            PrintGifError();
          }
          if (NULL == h->gif->SColorMap &&
            NULL == h->gif->Image.ColorMap) {
            if (debug)
                fprintf(stderr,"gif: oops: no colormap found\n");
            goto oops;
          }
#if 0
          info->width  = h->w = h->gif->SWidth;
          info->height = h->h = h->gif->SHeight;
#else
          info->width  = h->w = h->gif->Image.Width;
          info->height = h->h = h->gif->Image.Height;
#endif
            info->npages = 1;
          image = 1;
          if (debug)
            fprintf(stderr,"gif: reading image record ...\n");
          if (h->gif->Image.Interlace) {
            if (debug)
                fprintf(stderr,"gif: interlaced\n");
            h->il = malloc(h->w * h->h * sizeof(GifPixelType));
            for (i = 0; i < h->h; i += 8)
                DGifGetLine(h->gif, h->il + h->w*i,h->w);
            for (i = 4; i < h->gif->SHeight; i += 8)
                DGifGetLine(h->gif, h->il + h->w*i,h->w);
            for (i = 2; i < h->gif->SHeight; i += 4)
                DGifGetLine(h->gif, h->il + h->w*i,h->w);
          }
          break;
      case TERMINATE_RECORD_TYPE:
      default:
          goto oops;
      }
    }
    if (0 == info->width || 0 == info->height)
      goto oops;

    if (debug)
      fprintf(stderr,"gif: s=%dx%d i=%dx%d\n",
            h->gif->SWidth,h->gif->SHeight,
            h->gif->Image.Width,h->gif->Image.Height);
    return h;

 oops:
    if (debug)
      fprintf(stderr,"gif: fatal error, aborting\n");
    DGifCloseFile(h->gif);
    fclose(h->infile);
    free(h->row);
    free(h);
    return NULL;
}

static void
gif_read(unsigned char *dst, unsigned int line, void *data)
{
    struct gif_state *h = data;
    GifColorType *cmap;
    int x;
    
    if (h->gif->Image.Interlace) {
      if (line % 2) {
          DGifGetLine(h->gif, h->row, h->w);
      } else {
          memcpy(h->row, h->il + h->w * line, h->w);
      }
    } else {
      DGifGetLine(h->gif, h->row, h->w);
    }
    cmap = h->gif->Image.ColorMap ?
      h->gif->Image.ColorMap->Colors : h->gif->SColorMap->Colors;
    for (x = 0; x < h->w; x++) {
        dst[0] = cmap[h->row[x]].Red;
      dst[1] = cmap[h->row[x]].Green;
      dst[2] = cmap[h->row[x]].Blue;
      dst += 3;
    }
}

static void
gif_done(void *data)
{
    struct gif_state *h = data;

    if (debug)
      fprintf(stderr,"gif: done, cleaning up\n");
    DGifCloseFile(h->gif);
    fclose(h->infile);
    if (h->il)
      free(h->il);
    free(h->row);
    free(h);
}

static struct ida_loader gif_loader = {
    magic: "GIF",
    moff:  0,
    mlen:  3,
    name:  "libungif",
    init:  gif_init,
    read:  gif_read,
    done:  gif_done,
};

static void __init init_rd(void)
{
    load_register(&gif_loader);
}

Generated by  Doxygen 1.6.0   Back to index