⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gif.c

📁 lua脚本语言调用allegro游戏程序库的接口-跨平台
💻 C
字号:
#include "algif.h"#include "lzw.h"#include <stdlib.h>#include <string.h>//---------------------------------------------------------------------------------------------------------
GIF_ANIMATION* algif_create_raw_animation (int frames_count){    GIF_ANIMATION *gif = calloc (1, sizeof *gif);    /* Create frames. */    gif->frames_count = frames_count;    gif->frames = calloc (gif->frames_count, sizeof *gif->frames);    return gif;}
//---------------------------------------------------------------------------------------------------------
/* Destroy a complete gif, including all frames. */void algif_destroy_raw_animation (GIF_ANIMATION *gif){    int i;    for (i = 0; i < gif->frames_count; i++)    {        GIF_FRAME *frame = gif->frames + i;        if (frame->bitmap_8_bit)            destroy_bitmap (frame->bitmap_8_bit);    }    if (gif->store)        destroy_bitmap (gif->store);    free (gif->frames);    free (gif);}
//---------------------------------------------------------------------------------------------------------
static void write_palette (PACKFILE *file, GIF_PALETTE *palette, int bits){    int i;    for (i = 0; i < (1 << bits); i++)    {        pack_putc (palette->colors[i].r, file);        pack_putc (palette->colors[i].g, file);        pack_putc (palette->colors[i].b, file);    }}//---------------------------------------------------------------------------------------------------------
static void read_palette (PACKFILE * file, GIF_PALETTE *palette){    int i;    for (i = 0; i < palette->colors_count; i++)    {        palette->colors[i].r = pack_getc (file);        palette->colors[i].g = pack_getc (file);        palette->colors[i].b = pack_getc (file);    }}//---------------------------------------------------------------------------------------------------------
/* * Compresses all the frames in the animation and writes to a gif file. * Nothing else like extensions or comments is written. * * Returns 0 on success. * * Note: All bitmaps must have a color depth of 8. */int algif_save_raw_animation_pf (PACKFILE *file, GIF_ANIMATION *gif){    int frame;    int i, j;    
    //PACKFILE *file;    //file = pack_fopen (filename, "w");    
    if (!file) return -1;    pack_fwrite ("GIF89a", 6, file);    pack_iputw (gif->width, file);    pack_iputw (gif->height, file);    /* 7 global palette     * 456 color richness     * 3 sorted     * 012 palette bits     */    for (i = 1, j = 0; i < gif->palette.colors_count; i *= 2, j++);    pack_putc ((j ? 128 : 0) + 64 + 32 + 16 + (j ? j - 1 : 0), file);    pack_putc (gif->background_index, file);    pack_putc (0, file);        /* No aspect ratio. */    if (j)        write_palette (file, &gif->palette, j);    if (gif->loop != -1)    /* Loop count extension. */    {        pack_putc (0x21, file); /* Extension Introducer. */        pack_putc (0xff, file); /* Application Extension. */        pack_putc (11, file);    /* Size. */        pack_fwrite ("NETSCAPE2.0", 11, file);        pack_putc (3, file); /* Size. */        pack_putc (1, file);        pack_iputw (gif->loop, file);        pack_putc (0, file);    }    for (frame = 0; frame < gif->frames_count; frame++)    {        int w = gif->frames[frame].bitmap_8_bit->w;        int h = gif->frames[frame].bitmap_8_bit->h;        pack_putc (0x21, file); /* Extension Introducer. */        pack_putc (0xf9, file); /* Graphic Control Extension. */        pack_putc (4, file);    /* Size. */        /* Disposal method, and enable transparency. */        i = gif->frames[frame].disposal_method << 2;        if (gif->frames[frame].transparent_index != -1)            i |= 1;        pack_putc (i, file);        pack_iputw (gif->frames[frame].duration, file); /* In 1/100th seconds. */        if (gif->frames[frame].transparent_index != -1)            pack_putc (gif->frames[frame].transparent_index, file);       /* Transparent color index. */        else             pack_putc (0, file);        pack_putc (0x00, file); /* Terminator. */        pack_putc (0x2c, file); /* Image Descriptor. */        pack_iputw (gif->frames[frame].xoff, file);        pack_iputw (gif->frames[frame].yoff, file);        pack_iputw (w, file);        pack_iputw (h, file);         /* 7: local palette         * 6: interlaced         * 5: sorted         * 012: palette bits         */        for (i = 1, j = 0; i < gif->frames[frame].palette.colors_count; i *= 2, j++);        pack_putc ((j ? 128 : 0) + (j ? j - 1 : 0), file);        if (j)            write_palette (file, &gif->frames[frame].palette, j);        LZW_encode (file, gif->frames[frame].bitmap_8_bit);        pack_putc (0x00, file); /* Terminator. */    }    pack_putc (0x3b, file);     /* Trailer. */    /* never close the file pack_fclose (file);*/    return 0;}//---------------------------------------------------------------------------------------------------------
void deinterlace (BITMAP *bmp){    BITMAP *n = create_bitmap_ex (bitmap_color_depth (bmp), bmp->w, bmp->h);    int y, i = 0;    for (y = 0; y < n->h; y += 8)    {        blit (bmp, n, 0, i++, 0, y, n->w, 1);    }    for (y = 4; y < n->h; y += 8)    {        blit (bmp, n, 0, i++, 0, y, n->w, 1);    }    for (y = 2; y < n->h; y += 4)    {        blit (bmp, n, 0, i++, 0, y, n->w, 1);    }    for (y = 1; y < n->h; y += 2)    {        blit (bmp, n, 0, i++, 0, y, n->w, 1);    }    blit (n, bmp, 0, 0, 0, 0, n->w, n->h);    destroy_bitmap (n);}//---------------------------------------------------------------------------------------------------------
GIF_ANIMATION *load_gif_object_pf (PACKFILE * file, long size){    int version;    BITMAP *bmp = NULL;    int i, j;    GIF_ANIMATION *gif = calloc (1, sizeof *gif);    GIF_FRAME frame;    int have_global_palette = 0;    (void) size;    gif->frames_count = 0;    /* is it really a GIF? */    if (pack_getc (file) != 'G')        goto error;    if (pack_getc (file) != 'I')        goto error;    if (pack_getc (file) != 'F')        goto error;    if (pack_getc (file) != '8')        goto error;    /* '7' or '9', for 87a or 89a. */    version = pack_getc (file);    if (version != '7' && version != '9')        goto error;    if (pack_getc (file) != 'a')        goto error;    gif->width = pack_igetw (file);    gif->height = pack_igetw (file);    i = pack_getc (file);    /* Global color table? */    if (i & 128)        gif->palette.colors_count = 1 << ((i & 7) + 1);    else        gif->palette.colors_count = 0;    /* Background color is only valid with a global palette. */    gif->background_index = pack_getc (file);    /* Skip aspect ratio. */    pack_fseek (file, 1);    if (gif->palette.colors_count)    {        read_palette (file, &gif->palette);        have_global_palette = 1;    }    memset(&frame, 0, sizeof frame); /* For first frame. */    frame.transparent_index = -1;    do    {        i = pack_getc (file);        switch (i)        {            case 0x2c:         /* Image Descriptor */            {                int w, h;                int interlaced = 0;                frame.xoff = pack_igetw (file);                frame.yoff = pack_igetw (file);                w = pack_igetw (file);                h = pack_igetw (file);                bmp = create_bitmap_ex (8, w, h);                if (!bmp)                    goto error;                i = pack_getc (file);                /* Local palette. */                if (i & 128)                {                    frame.palette.colors_count = 1 << ((i & 7) + 1);                    read_palette (file, &frame.palette);                }                else                {                    frame.palette.colors_count = 0;                }                if (i & 64)                    interlaced = 1;                if (LZW_decode (file, bmp))                    goto error;                if (interlaced)                    deinterlace (bmp);                frame.bitmap_8_bit = bmp;                bmp = NULL;                gif->frames_count++;                gif->frames =                    realloc (gif->frames,                             gif->frames_count * sizeof *gif->frames);                gif->frames[gif->frames_count - 1] = frame;                memset(&frame, 0, sizeof frame); /* For next frame. */                frame.transparent_index = -1;                break;            }            case 0x21: /* Extension Introducer. */                j = pack_getc (file); /* Extension Type. */                i = pack_getc (file); /* Size. */                if (j == 0xf9) /* Graphic Control Extension. */                {                    /* size must be 4 */                    if (i != 4)                        goto error;                    i = pack_getc (file);                    frame.disposal_method = (i >> 2) & 7;                    frame.duration = pack_igetw (file);                    if (i & 1)  /* Transparency? */                    {                        frame.transparent_index = pack_getc (file);                    }                    else                    {                        pack_fseek (file, 1);                         frame.transparent_index = -1;                    }                    i = pack_getc (file); /* Size. */                }                /* Application Extension. */                else if (j == 0xff)                {                    if (i == 11)                    {                        char name[12];                        pack_fread (name, 11, file);                        i = pack_getc (file); /* Size. */                        name[11] = '\0';                        if (!strcmp (name, "NETSCAPE2.0"))                        {                            if (i == 3)                            {                                j = pack_getc (file);                                gif->loop = pack_igetw (file);                                if (j != 1)                                    gif->loop = 0;                                i = pack_getc (file); /* Size. */                            }                        }                    }                }                /* Possibly more blocks until terminator block (0). */                while (i)                {                    pack_fseek (file, i);                    i = pack_getc (file);                }                break;            case 0x3b:                /* GIF Trailer. */                /*pack_fclose (file);*/                return gif;        }    }    while (TRUE);  error:    /*if (file)        pack_fclose (file);*/    if (gif)        algif_destroy_raw_animation (gif);    if (bmp)        destroy_bitmap (bmp);    return NULL;}//---------------------------------------------------------------------------------------------------------
/* * Allocates and reads a GIF_ANIMATION structure, filling in all the * frames found in the file. On error, nothing is allocated, and NULL is * returned. No extensions or comments are read in. If the gif contains * a transparency index, and it is no 0, it is swapped with 0 - so index * 0 will be the transparent color. There is no way to know when a file * contained no transparency originally. Frame duration is specified in * 1/100th seconds. * * All bitmaps will have a color depth of 8. */GIF_ANIMATION *algif_load_raw_animation (const char *filename){   PACKFILE *file;   GIF_ANIMATION *gif = NULL;   file = pack_fopen (filename, "r");   if (file)   { 
      gif = load_gif_object_pf (file, 0);
      pack_fclose(file);
   }   return gif;}
//---------------------------------------------------------------------------------------------------------
static int get_rgbcolor (RGB *rgb){    return makecol (rgb->r, rgb->g, rgb->b);}//---------------------------------------------------------------------------------------------------------
/* Renders the next frame in a GIF animation to the specified bitmap and * the given position. You need to call this in order on the same * destination for frames [0..gif->frames_count - 1] to properly render all * the frames in the GIF. */void algif_render_frame (GIF_ANIMATION *gif, BITMAP *bitmap, int frame, int xpos,int ypos){    int x, y, w, h;    GIF_FRAME *f = &gif->frames[frame];    GIF_PALETTE *pal;    if (frame == 0)        rectfill (bitmap, xpos, ypos, xpos + gif->width - 1,              ypos + gif->height - 1, bitmap_mask_color (bitmap));    else    {        GIF_FRAME *p = &gif->frames[frame - 1];        if (p->disposal_method == 2)            rectfill (bitmap, xpos + p->xoff, ypos + p->yoff,                xpos + p->xoff + p->bitmap_8_bit->w - 1,                ypos + p->yoff + p->bitmap_8_bit->h - 1,                bitmap_mask_color (bitmap));        else if (p->disposal_method == 3 && gif->store)        {            blit (gif->store, bitmap, 0, 0, xpos + p->xoff, ypos + p->yoff,                gif->store->w, gif->store->h);            destroy_bitmap (gif->store);            gif->store = NULL;        }    }    w = f->bitmap_8_bit->w;    h = f->bitmap_8_bit->h;    if (f->disposal_method == 3)    {        if (gif->store)            destroy_bitmap (gif->store);        gif->store = create_bitmap_ex (bitmap_color_depth (bitmap), w, h);        blit (bitmap, gif->store, xpos + f->xoff, ypos + f->yoff, 0, 0, w, h);    }    pal = &gif->frames[frame].palette;    if (pal->colors_count == 0)        pal = &gif->palette;    //int i;    //for (i = 0; i < pal->colors_count; i++)    //    printf("%d: %d %d %d\n", i, pal->colors[i].r, pal->colors[i].g, pal->colors[i].b);    for (y = 0; y < h; y++)    {        for (x = 0; x < w; x++)        {            int c = getpixel (f->bitmap_8_bit, x, y);            if (c != f->transparent_index)            {                putpixel (bitmap, xpos + f->xoff + x, ypos + f->yoff + y,                          get_rgbcolor (&pal->colors[c]));            }        }    }}//---------------------------------------------------------------------------------------------------------
/* Registers gif as bitmap and datafile type. */void algif_init (void){    register_bitmap_file_type ("gif", load_gif, save_gif);    register_datafile_object (DAT_GIF,                              (void *(*)(PACKFILE *, long)) load_gif_object_pf,                              (void (*)(void *))                              algif_destroy_raw_animation);}
//---------------------------------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -