动态图二 APNG解码与播放

动态图(二) APNG解码与播放

概述

APNG是PNG一个小分支,但还没有正式加入libpng这个库,而是以一个patch的形式存在。
libpng 这里下载:https://sourceforge.net/projects/libpng/files/
APNG的patch则在这儿: https://sourceforge.net/projects/libpng-apng/
而libpng还依赖zlib,还需要这个:http://zlib.net/

APNG格式定义:
see https://wiki.mozilla.org/APNG_Specification#mw-head

环境

解码:libpng + libpng-apng.patch + zlib
显示:GDI+ + Win32
开发环境: VS2015

搭建工程
libpng
  1. Clone libpng, apng.patch最新版,所有源文件放到同一个目录,如: e:\apng\libpng\
  2. 打patch需要用到patch命令,我用的是: git for windows 的 git bash:
	patch -p0 < libpng-1.6.37-apng.patch

用vs新建一个lib工程,名为 libpng.vcxproj,加入libpng*.c, libpng*.h

zlib
  1. Clone zlib最新版,所有源文件放在 e:\apng\zlib\
  2. 用vs新建一个lib工程,名为 zlib.vcxproj,加入zlib*.c, zlib*.h

可以用cmake搭建工程,但可能有error,且小工程还没我手动来得快~

解码

解码目标是使用libpng把所有APNG帧解析成BGRA流,用来构建后续用来显示的GDI+ Bitmap,部分代码:

//APNG解码
#include "stdafx.h"
#include "ApngLoader.h"

BOOL CApngLoader::LoadAPNG(const wstring& strImg)
{
   
    FILE* f1 = NULL;
    _wfopen_s(&f1, strImg.c_str(), L"rb");
    if (f1 == NULL)
    {
   
        OutputDebugString(L"Cannot open file!\r\n");
        return FALSE;
    }

    UINT32 i, j;
    png_bytepp rows_image;
    png_bytepp rows_frame;
    BYTE* p_image;
    BYTE* p_frame;
    BYTE* p_temp;
    BYTE sig[8];

    fread(sig, 1, 8, f1);
    if (png_sig_cmp(sig, 0, 8) != 0)
    {
   
        OutputDebugString(L"Not a png image!\r\n");
        fclose(f1);
        return FALSE;
    }

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (png_ptr && info_ptr)
    {
   
        if (setjmp(png_jmpbuf(png_ptr)))
        {
   
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(f1);
            return FALSE;
        }
        png_init_io(png_ptr, f1);
        png_set_sig_bytes(png_ptr, 8);
        png_read_info(png_ptr, info_ptr);

        if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL))
        {
   
            OutputDebugString(L"Not a apng image!\r\n");
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(f1);
            return FALSE;
        }

        UINT32 nFrameCount = 1;
        m_nPlays = 0;
        png_get_acTL(png_ptr, info_ptr, &nFrameCount, &m_nPlays);
        if (nFrameCount <= 1)
        {
   
            OutputDebugString(L"Not a apng Image!\r\n");
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(f1);
            return FALSE;
        }
		//设置解码的格式,统统转成BGRA格式
        png_set_expand(png_ptr);
        png_set_strip_16(png_ptr);
        png_set_gray_to_rgb(png_ptr);
        png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
        png_set_bgr(png_ptr);
        png_set_interlace_handling(png_ptr)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值