FFMPEG之图片系列 --- png格式
来源:互联网 发布:java书籍推荐 知乎 编辑:程序博客网 时间:2024/05/16 19:43
在ffmpeg中,即支持png格式文件,也支持apng格式文件,下面就这两种区别做一描述:
PNG(Portable Network Graphics)是一种无损压缩的位图图形格式。其设计目的是试图替代GIF和过于复杂的TIFF文件格式,同时增加一些GIF文件不具备的特性。
MNG图形文件格式用来表现动画。以下是PNG、MNG、APNG的历史:
在libavcodec/allcodecs.c中 定义了png和apng的encoder和decoder.
REGISTER_ENCDEC (PNG, png); # ff_png_encoder in libavcodec/pngenc.c ff_png_decoder in libavcodec/pngdec.c REGISTER_ENCDEC (APNG, apng); # ff_apng_encoder in libavcodec/pngenc.c ff_png_decoder in libavcodec/pngdec.c REGISTER_PARSER(PNG, png); # ff_png_parser in libavcodec/png_parser.c
PNG文件结构:
PNG文件由一个8字节的PNG文件署名(PNG File Signature)和按照特定结构组织的3个以上的数据块(chunk)组成。
文件署名部分:
数据块部分:PNG中有两种类型的数据块,一是关键数据块,是一种必须的数据块,另一种是辅助数据块,是可选的。
不管是什么样的数据块,都有如下所示的4个字段域:
字段域名称字节数说明length 长度4-byte指定数据块中数据域的长度,长度不超过2^31 - 1 字节Chunk Type Code 数据块类型码4-byte数据块类型码有ASCII字母组成,区分大小写Chunk Data 数据块数据长度可变存储Chunk Type Code域制定的数据CRC 循环冗余检测4-byte存储用来检测是否有错误的循环冗余码关键数据块定义如下表所示的4中类型:
数据块标识符号数据块名称是否为多数据块是否为可选数据块块位置的限制IHDR文件头数据块否,只有一个否,必须有作为第一块PLTE调色板数据块否,只有一个是,可以没有在IDAT之前IDAT图像数据块是,可以有多个否,必须有与其它IDAT数据块相连IEND图像结束数据否,只有一个否,必须有最后一个数据块IHDR 文件头数据块IHDR: 包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG文件数据流中,而且一个PNG文件有且仅有一个IHDR.
PLTE调色板数据块,含有与索引彩色图像(indexed-color image)相关的彩色变换数据,它仅与索引彩色图像相关,而且要放在图像数据块之前。
PLTE数据块是定义图像的调色板信息,PLTE可以包含1~256个调色板信息,每个调色板信息由3个字节组成R,G,B.
IDAT图像数据块IDAT(image data chunk):它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。
不难明白,由于数据块结构的定义,IEND数据块的长度总是0(00 00 00 00,除非人为加入信息),数据标识总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82。
在libavcodec/png.h中定义如下的颜色类型,用来表示上面表格中提到的ColorType:
#define PNG_COLOR_MASK_PALETTE 1 //定义调色板#define PNG_COLOR_MASK_COLOR 2 //真彩色#define PNG_COLOR_MASK_ALPHA 4 //a通道#define PNG_COLOR_TYPE_GRAY 0 // 表示灰度图像#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) // 索引彩色图像#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) // 彩色图像#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) // 带a通道的彩色图像#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) // 带a通道的灰度图像
在libavcodec/png.c中定义如下的函数来获取不同颜色类型对应的通道数:
## 1通道: 灰度图像
## 2通道: 带a通道的灰度图像
## 3通道: 彩色图像或索引彩色图像
## 4通道: 带a通道的彩色图像
int ff_png_get_nb_channels(int color_type){ int channels; channels = 1; if ((color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) == PNG_COLOR_MASK_COLOR) channels = 3; if (color_type & PNG_COLOR_MASK_ALPHA) channels++; return channels;}
定义如下的函数用来计算在隔行扫描算法为Adam7时调用:
/* compute the row size of an interleaved pass */int ff_png_pass_row_size(int pass, int bits_per_pixel, int width){ int shift, xmin, pass_width; xmin = ff_png_pass_xmin[pass]; if (width <= xmin) return 0; shift = ff_png_pass_xshift[pass]; pass_width = (width - xmin + (1 << shift) - 1) >> shift; return (pass_width * bits_per_pixel + 7) >> 3;}
在libavcodec/png_parser.c中定义png文件解析函数:
static int png_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size){ PNGParseContext *ppc = s->priv_data; int next = END_NOT_FOUND; int i = 0; s->pict_type = AV_PICTURE_TYPE_NONE; *poutbuf_size = 0; if (!ppc->pc.frame_start_found) { uint64_t state64 = ppc->pc.state64; for (; i < buf_size; i++) { state64 = (state64 << 8) | buf[i]; if (state64 == PNGSIG || state64 == MNGSIG) { i++; ppc->pc.frame_start_found = 1; break; } } ppc->pc.state64 = state64; } else if (ppc->remaining_size) { i = FFMIN(ppc->remaining_size, buf_size); ppc->remaining_size -= i; if (ppc->remaining_size) goto flush; if (ppc->chunk_pos == -1) { next = i; goto flush; } } for (; ppc->pc.frame_start_found && i < buf_size; i++) { ppc->pc.state = (ppc->pc.state << 8) | buf[i]; if (ppc->chunk_pos == 3) { ppc->chunk_length = ppc->pc.state; if (ppc->chunk_length > 0x7fffffff) { ppc->chunk_pos = ppc->pc.frame_start_found = 0; goto flush; } ppc->chunk_length += 4; } else if (ppc->chunk_pos == 7) { if (ppc->chunk_length >= buf_size - i) ppc->remaining_size = ppc->chunk_length - buf_size + i + 1; if (ppc->pc.state == MKBETAG('I', 'E', 'N', 'D')) { if (ppc->remaining_size) ppc->chunk_pos = -1; else next = ppc->chunk_length + i + 1; break; } else { ppc->chunk_pos = 0; if (ppc->remaining_size) break; else i += ppc->chunk_length; continue; } } ppc->chunk_pos++;
- FFMPEG之图片系列 --- png格式
- FFMPEG之图片系列 --- tif 格式
- png格式图片详解
- png格式的图片
- PNG格式图片原理
- PNG格式图片原理
- png格式图片
- ffmpeg分析系列之三(输入输出格式)
- ffmpeg分析系列之三(输入输出格式)
- ffmpeg分析系列之三(输入输出格式)
- ffmpeg 编码 png apng图片
- ffmpeg 解码 png apng 图片
- Qt之生成png/jpg/bmp格式图片
- 图像文件格式之PNG
- Symbian png格式图片显示
- IE6支持PNG格式图片
- PNG格式图片优化技巧
- MFC 绘制 PNG 格式图片
- MFC_事件对象_打印字符串_2线程_同步
- EventBus的详细使用攻略
- [破除迷信]java.util.ArrayList在foreach循环遍历时可以删除元素
- Java设计模式-策略模式
- 葵花宝典 十九 jsp动作标签和EL表达式
- FFMPEG之图片系列 --- png格式
- 使用node作为多个项目的服务器
- mysql sqlmode几个模式
- Ubuntu优盘启动盘制作教程
- POI的基本使用
- 如何解决Windows Server 2008 服务启动不能调用Office Word的问题
- cin.good()的值
- Redis使用
- 查看每个应用程序最高可用内存