📄 gif.c
字号:
bytestream_put_le16(bytestream, width); bytestream_put_le16(bytestream, height); bytestream_put_byte(bytestream, 0xf7); /* flags: global clut, 256 entries */ bytestream_put_byte(bytestream, 0x1f); /* background color index */ bytestream_put_byte(bytestream, 0); /* aspect ratio */ /* the global palette */ if (!palette) { bytestream_put_buffer(bytestream, (const unsigned char *)gif_clut, 216*3); for(i=0;i<((256-216)*3);i++) bytestream_put_byte(bytestream, 0); } else { for(i=0;i<256;i++) { v = palette[i]; bytestream_put_be24(bytestream, v); } } /* update: this is the 'NETSCAPE EXTENSION' that allows for looped animated gif see http://members.aol.com/royalef/gifabout.htm#net-extension byte 1 : 33 (hex 0x21) GIF Extension code byte 2 : 255 (hex 0xFF) Application Extension Label byte 3 : 11 (hex (0x0B) Length of Application Block (eleven bytes of data to follow) bytes 4 to 11 : "NETSCAPE" bytes 12 to 14 : "2.0" byte 15 : 3 (hex 0x03) Length of Data Sub-Block (three bytes of data to follow) byte 16 : 1 (hex 0x01) bytes 17 to 18 : 0 to 65535, an unsigned integer in lo-hi byte format. This indicate the number of iterations the loop should be executed. bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator */ /* application extension header */#ifdef GIF_ADD_APP_HEADER if (loop_count >= 0 && loop_count <= 65535) { bytestream_put_byte(bytestream, 0x21); bytestream_put_byte(bytestream, 0xff); bytestream_put_byte(bytestream, 0x0b);#ifdef __CW32__ bytestream_put_buffer(bytestream, (const unsigned char*)"NETSCAPE2.0", 11); // bytes 4 to 14#else bytestream_put_buffer(bytestream, "NETSCAPE2.0", 11); // bytes 4 to 14#endif bytestream_put_byte(bytestream, 0x03); // byte 15 bytestream_put_byte(bytestream, 0x01); // byte 16 bytestream_put_le16(bytestream, (uint16_t)loop_count); bytestream_put_byte(bytestream, 0x00); // byte 19 }#endif return 0;}/* this is maybe slow, but allows for extensions */static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b){ return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));}static int gif_image_write_image(uint8_t **bytestream, int x1, int y1, int width, int height, const uint8_t *buf, int linesize, int pix_fmt){ PutBitContext p; uint8_t buffer[200]; /* 100 * 9 / 8 = 113 */ int i, left, w, v; const uint8_t *ptr; /* image block */ bytestream_put_byte(bytestream, 0x2c); bytestream_put_le16(bytestream, x1); bytestream_put_le16(bytestream, y1); bytestream_put_le16(bytestream, width); bytestream_put_le16(bytestream, height); bytestream_put_byte(bytestream, 0x00); /* flags */ /* no local clut */ bytestream_put_byte(bytestream, 0x08); left= width * height; init_put_bits(&p, buffer, 130);/* * the thing here is the bitstream is written as little packets, with a size byte before * but it's still the same bitstream between packets (no flush !) */ ptr = buf; w = width; while(left>0) { gif_put_bits_rev(&p, 9, 0x0100); /* clear code */ for(i=(left<GIF_CHUNKS)?left:GIF_CHUNKS;i;i--) { if (pix_fmt == PIX_FMT_RGB24) { v = gif_clut_index(ptr[0], ptr[1], ptr[2]); ptr+=3; } else { v = *ptr++; } gif_put_bits_rev(&p, 9, v); if (--w == 0) { w = width; buf += linesize; ptr = buf; } } if(left<=GIF_CHUNKS) { gif_put_bits_rev(&p, 9, 0x101); /* end of stream */ gif_flush_put_bits_rev(&p); } if(pbBufPtr(&p) - p.buf > 0) { bytestream_put_byte(bytestream, pbBufPtr(&p) - p.buf); /* byte count of the packet */ bytestream_put_buffer(bytestream, p.buf, pbBufPtr(&p) - p.buf); /* the actual buffer */ p.buf_ptr = p.buf; /* dequeue the bytes off the bitstream */ } left-=GIF_CHUNKS; } bytestream_put_byte(bytestream, 0x00); /* end of image block */ bytestream_put_byte(bytestream, 0x3b); return 0;}typedef struct { int64_t time, file_time; uint8_t buffer[100]; /* data chunks */ AVFrame picture;} GIFContext;static av_cold int gif_encode_init(AVCodecContext *avctx){ GIFContext *s = avctx->priv_data; avctx->coded_frame = &s->picture; return 0;}/* better than nothing gif encoder */static int gif_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){ GIFContext *s = avctx->priv_data; AVFrame *pict = data; AVFrame *const p = (AVFrame *)&s->picture; uint8_t *outbuf_ptr = outbuf; *p = *pict; p->pict_type = FF_I_TYPE; p->key_frame = 1; gif_image_write_header(&outbuf_ptr, avctx->width, avctx->height, -1, (uint32_t *)pict->data[1]); gif_image_write_image(&outbuf_ptr, 0, 0, avctx->width, avctx->height, pict->data[0], pict->linesize[0], PIX_FMT_PAL8); return outbuf_ptr - outbuf;}AVCodec gif_encoder = { "gif", CODEC_TYPE_VIDEO, CODEC_ID_GIF, sizeof(GIFContext), gif_encode_init, gif_encode_frame, NULL, //encode_end,#ifdef __CW32__ 0, 0, 0, 0, 0, (enum PixelFormat[]){PIX_FMT_PAL8, PIX_FMT_NONE}, NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"),#else .pix_fmts= (enum PixelFormat[]){PIX_FMT_PAL8, PIX_FMT_NONE}, .long_name= NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"),#endif};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -