• 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, smallest_alpha = 0xFF, alpha_component = 0;
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         if (v >> 24 < smallest_alpha) {
00081             smallest_alpha = v >> 24;
00082             alpha_component = i;
00083         }
00084     }
00085 
00086     if (smallest_alpha < 128) {
00087         bytestream_put_byte(bytestream, 0x21); /* Extension Introducer */
00088         bytestream_put_byte(bytestream, 0xf9); /* Graphic Control Label */
00089         bytestream_put_byte(bytestream, 0x04); /* block length */
00090         bytestream_put_byte(bytestream, 0x01); /* Transparent Color Flag */
00091         bytestream_put_le16(bytestream, 0x00); /* no delay */
00092         bytestream_put_byte(bytestream, alpha_component);
00093         bytestream_put_byte(bytestream, 0x00);
00094     }
00095 
00096     return 0;
00097 }
00098 
00099 static int gif_image_write_image(AVCodecContext *avctx,
00100                                  uint8_t **bytestream, uint8_t *end,
00101                                  const uint8_t *buf, int linesize)
00102 {
00103     GIFContext *s = avctx->priv_data;
00104     int len = 0, height;
00105     const uint8_t *ptr;
00106     /* image block */
00107 
00108     bytestream_put_byte(bytestream, 0x2c);
00109     bytestream_put_le16(bytestream, 0);
00110     bytestream_put_le16(bytestream, 0);
00111     bytestream_put_le16(bytestream, avctx->width);
00112     bytestream_put_le16(bytestream, avctx->height);
00113     bytestream_put_byte(bytestream, 0x00); /* flags */
00114     /* no local clut */
00115 
00116     bytestream_put_byte(bytestream, 0x08);
00117 
00118     ff_lzw_encode_init(s->lzw, s->buf, avctx->width*avctx->height,
00119                        12, FF_LZW_GIF, put_bits);
00120 
00121     ptr = buf;
00122     for (height = avctx->height; height--;) {
00123         len += ff_lzw_encode(s->lzw, ptr, avctx->width);
00124         ptr += linesize;
00125     }
00126     len += ff_lzw_encode_flush(s->lzw, flush_put_bits);
00127 
00128     ptr = s->buf;
00129     while (len > 0) {
00130         int size = FFMIN(255, len);
00131         bytestream_put_byte(bytestream, size);
00132         if (end - *bytestream < size)
00133             return -1;
00134         bytestream_put_buffer(bytestream, ptr, size);
00135         ptr += size;
00136         len -= size;
00137     }
00138     bytestream_put_byte(bytestream, 0x00); /* end of image block */
00139     bytestream_put_byte(bytestream, 0x3b);
00140     return 0;
00141 }
00142 
00143 static av_cold int gif_encode_init(AVCodecContext *avctx)
00144 {
00145     GIFContext *s = avctx->priv_data;
00146 
00147     avctx->coded_frame = &s->picture;
00148     s->lzw = av_mallocz(ff_lzw_encode_state_size);
00149     if (!s->lzw)
00150         return AVERROR(ENOMEM);
00151     s->buf = av_malloc(avctx->width*avctx->height*2);
00152     if (!s->buf)
00153          return AVERROR(ENOMEM);
00154     return 0;
00155 }
00156 
00157 /* better than nothing gif encoder */
00158 static int gif_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data)
00159 {
00160     GIFContext *s = avctx->priv_data;
00161     AVFrame *pict = data;
00162     AVFrame *const p = (AVFrame *)&s->picture;
00163     uint8_t *outbuf_ptr = outbuf;
00164     uint8_t *end = outbuf + buf_size;
00165 
00166     *p = *pict;
00167     p->pict_type = AV_PICTURE_TYPE_I;
00168     p->key_frame = 1;
00169     gif_image_write_header(avctx, &outbuf_ptr, (uint32_t *)pict->data[1]);
00170     gif_image_write_image(avctx, &outbuf_ptr, end, pict->data[0], pict->linesize[0]);
00171     return outbuf_ptr - outbuf;
00172 }
00173 
00174 static int gif_encode_close(AVCodecContext *avctx)
00175 {
00176     GIFContext *s = avctx->priv_data;
00177 
00178     av_freep(&s->lzw);
00179     av_freep(&s->buf);
00180     return 0;
00181 }
00182 
00183 AVCodec ff_gif_encoder = {
00184     .name           = "gif",
00185     .type           = AVMEDIA_TYPE_VIDEO,
00186     .id             = CODEC_ID_GIF,
00187     .priv_data_size = sizeof(GIFContext),
00188     .init           = gif_encode_init,
00189     .encode         = gif_encode_frame,
00190     .close          = gif_encode_close,
00191     .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},
00192     .long_name= NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"),
00193 };
Generated on Fri Feb 1 2013 14:34:35 for FFmpeg by doxygen 1.7.1