• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/gif.c

Go to the documentation of this file.
00001 /*
00002  * GIF encoder.
00003  * Copyright (c) 2000 Fabrice Bellard
00004  * Copyright (c) 2002 Francois Revol
00005  * Copyright (c) 2006 Baptiste Coudurier
00006  *
00007  * This file is part of FFmpeg.
00008  *
00009  * FFmpeg is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * FFmpeg is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with FFmpeg; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00022  */
00023 
00024 /*
00025  * First version by Francois Revol revol@free.fr
00026  *
00027  * Features and limitations:
00028  * - currently no compression is performed,
00029  *   in fact the size of the data is 9/8 the size of the image in 8bpp
00030  * - uses only a global standard palette
00031  * - tested with IE 5.0, Opera for BeOS, NetPositive (BeOS), and Mozilla (BeOS).
00032  *
00033  * Reference documents:
00034  * http://www.goice.co.jp/member/mo/formats/gif.html
00035  * http://astronomy.swin.edu.au/pbourke/dataformats/gif/
00036  * http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/GIF89a.txt
00037  *
00038  * this url claims to have an LZW algorithm not covered by Unisys patent:
00039  * http://www.msg.net/utility/whirlgif/gifencod.html
00040  * could help reduce the size of the files _a lot_...
00041  * some sites mentions an RLE type compression also.
00042  */
00043 
00044 #include "avcodec.h"
00045 #include "bytestream.h"
00046 #include "lzw.h"
00047 
00048 /* The GIF format uses reversed order for bitstreams... */
00049 /* at least they don't use PDP_ENDIAN :) */
00050 #define BITSTREAM_WRITER_LE
00051 
00052 #include "put_bits.h"
00053 
00054 typedef struct {
00055     AVFrame picture;
00056     LZWState *lzw;
00057     uint8_t *buf;
00058 } GIFContext;
00059 
00060 /* GIF header */
00061 static int gif_image_write_header(AVCodecContext *avctx,
00062                                   uint8_t **bytestream, uint32_t *palette)
00063 {
00064     int i;
00065     unsigned int v;
00066 
00067     bytestream_put_buffer(bytestream, "GIF", 3);
00068     bytestream_put_buffer(bytestream, "89a", 3);
00069     bytestream_put_le16(bytestream, avctx->width);
00070     bytestream_put_le16(bytestream, avctx->height);
00071 
00072     bytestream_put_byte(bytestream, 0xf7); /* flags: global clut, 256 entries */
00073     bytestream_put_byte(bytestream, 0x1f); /* background color index */
00074     bytestream_put_byte(bytestream, 0); /* aspect ratio */
00075 
00076     /* the global palette */
00077     for(i=0;i<256;i++) {
00078         v = palette[i];
00079         bytestream_put_be24(bytestream, v);
00080     }
00081 
00082     return 0;
00083 }
00084 
00085 static int gif_image_write_image(AVCodecContext *avctx,
00086                                  uint8_t **bytestream, uint8_t *end,
00087                                  const uint8_t *buf, int linesize)
00088 {
00089     GIFContext *s = avctx->priv_data;
00090     int len, height;
00091     const uint8_t *ptr;
00092     /* image block */
00093 
00094     bytestream_put_byte(bytestream, 0x2c);
00095     bytestream_put_le16(bytestream, 0);
00096     bytestream_put_le16(bytestream, 0);
00097     bytestream_put_le16(bytestream, avctx->width);
00098     bytestream_put_le16(bytestream, avctx->height);
00099     bytestream_put_byte(bytestream, 0x00); /* flags */
00100     /* no local clut */
00101 
00102     bytestream_put_byte(bytestream, 0x08);
00103 
00104     ff_lzw_encode_init(s->lzw, s->buf, avctx->width*avctx->height,
00105                        12, FF_LZW_GIF, put_bits);
00106 
00107     ptr = buf;
00108     for (height = avctx->height; height--;) {
00109         len += ff_lzw_encode(s->lzw, ptr, avctx->width);
00110         ptr += linesize;
00111     }
00112     len += ff_lzw_encode_flush(s->lzw, flush_put_bits);
00113 
00114     ptr = s->buf;
00115     while (len > 0) {
00116         int size = FFMIN(255, len);
00117         bytestream_put_byte(bytestream, size);
00118         if (end - *bytestream < size)
00119             return -1;
00120         bytestream_put_buffer(bytestream, ptr, size);
00121         ptr += size;
00122         len -= size;
00123     }
00124     bytestream_put_byte(bytestream, 0x00); /* end of image block */
00125     bytestream_put_byte(bytestream, 0x3b);
00126     return 0;
00127 }
00128 
00129 static av_cold int gif_encode_init(AVCodecContext *avctx)
00130 {
00131     GIFContext *s = avctx->priv_data;
00132 
00133     avctx->coded_frame = &s->picture;
00134     s->lzw = av_mallocz(ff_lzw_encode_state_size);
00135     if (!s->lzw)
00136         return AVERROR(ENOMEM);
00137     s->buf = av_malloc(avctx->width*avctx->height*2);
00138     if (!s->buf)
00139          return AVERROR(ENOMEM);
00140     return 0;
00141 }
00142 
00143 /* better than nothing gif encoder */
00144 static int gif_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data)
00145 {
00146     GIFContext *s = avctx->priv_data;
00147     AVFrame *pict = data;
00148     AVFrame *const p = (AVFrame *)&s->picture;
00149     uint8_t *outbuf_ptr = outbuf;
00150     uint8_t *end = outbuf + buf_size;
00151 
00152     *p = *pict;
00153     p->pict_type = FF_I_TYPE;
00154     p->key_frame = 1;
00155     gif_image_write_header(avctx, &outbuf_ptr, (uint32_t *)pict->data[1]);
00156     gif_image_write_image(avctx, &outbuf_ptr, end, pict->data[0], pict->linesize[0]);
00157     return outbuf_ptr - outbuf;
00158 }
00159 
00160 static int gif_encode_close(AVCodecContext *avctx)
00161 {
00162     GIFContext *s = avctx->priv_data;
00163 
00164     av_freep(&s->lzw);
00165     av_freep(&s->buf);
00166     return 0;
00167 }
00168 
00169 AVCodec gif_encoder = {
00170     "gif",
00171     AVMEDIA_TYPE_VIDEO,
00172     CODEC_ID_GIF,
00173     sizeof(GIFContext),
00174     gif_encode_init,
00175     gif_encode_frame,
00176     gif_encode_close,
00177     .pix_fmts= (const enum PixelFormat[]){PIX_FMT_RGB8, PIX_FMT_BGR8, PIX_FMT_RGB4_BYTE, PIX_FMT_BGR4_BYTE, PIX_FMT_GRAY8, PIX_FMT_PAL8, PIX_FMT_NONE},
00178     .long_name= NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"),
00179 };

Generated on Fri Sep 16 2011 17:17:36 for FFmpeg by  doxygen 1.7.1