动态图(三) 动态WebP解码与播放

  • 概述
    • 环境
      • 搭建工程
        • libwebp
    • 解码
    • 播放
    • GitHub

概述

WebP是谷歌定义的,如顾名思义(web picture),就是专门优化用于web显示的图片,大概就这样。
定义:
友(you)情(qiang)链接:https://developers.google.com/speed/webp/
无(wu)情(qiang)链接:https://developers.google.cn/speed/webp?hl=zh-cn

GitHub Mirror: https://github.com/webmproject/libwebp

环境

解码:libwebp
显示:GDI+ + Win32
开发环境: VS2015

搭建工程

libwebp
  1. Clone libwebp
  2. 用vs新建一个lib工程,名为 libwebp.vcxproj,把llibwebp\src\目录整个拷到工程目录,加入src*.*到工程去

解码

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

//WebP解码
#include "stdafx.h"
#include "WebPLoader.h"
#include "StringUtil.hpp"BOOL CWebPLoader::LoadImage(const wstring& strImg)
{//借用了 https://github.com/webmproject/libwebp/blob/master/examples/anim_util.hreturn ReadAnimatedImage(CStringUtil::ToStringA(strImg).c_str(), &image);
}Bitmap* CWebPLoader::GetFrameAt(UINT32 nIndex, UINT32& nDelayMS)
{if (nIndex >= image.num_frames)return m_pBmp;DecodedFrame* pFrame = &image.frames[nIndex];if (!pFrame->rgba)return m_pBmp;Bitmap* pBmp = m_pBmp ? m_pBmp : new Bitmap(image.canvas_width, image.canvas_height);BitmapData bmd;Rect rc(0, 0, image.canvas_width, image.canvas_height);pBmp->LockBits(&rc, ImageLockModeRead | ImageLockModeWrite, PixelFormat32bppARGB, &bmd);LPBYTE pDst = (LPBYTE)bmd.Scan0;LPBYTE pSrc = pFrame->rgba;int rowsize = rc.Width * 4;for (int h = 0; h < rc.Height; ++h){memcpy(pDst, pSrc, rowsize);pSrc += rowsize;pDst += bmd.Stride;}pBmp->UnlockBits(&bmd);m_nCurFrame = nIndex;m_pBmp = pBmp;nDelayMS = pFrame->duration;return pBmp;
}

借用 https://github.com/webmproject/libwebp/blob/master/examples/anim_util.*,并作相应修改,部分代码:

// Read animated WebP bitstream 'webp_data' into 'AnimatedImage' struct.
static int ReadAnimatedWebP(const char filename[],const WebPData* const webp_data,AnimatedImage* const image) {int ok = 0;int dump_ok = 1;uint32_t frame_index = 0;int prev_frame_timestamp = 0;WebPAnimDecoder* dec;WebPAnimInfo anim_info;memset(image, 0, sizeof(*image));////We need BGRA, so we can build gdi+ bitmap directly.WebPAnimDecoderOptions opt;memset(&opt, 0, sizeof(opt));opt.color_mode = MODE_BGRA;opt.use_threads = 0;dec = WebPAnimDecoderNew(webp_data, &opt);if (dec == NULL) {//WFPRINTF(stderr, "Error parsing image: %s\n", (const W_CHAR*)filename);goto End;}// Main object storing the configuration for advanced decodingWebPDecoderConfig decoder_config;// Initialize the configuration as empty// This function must always be called first, unless WebPGetFeatures() is to be calledif (!WebPInitDecoderConfig(&decoder_config)) {goto End;}// Retrieve features from the bitstream// The bitstream structure is filled with information gathered from the bitstreamint webp_status = WebPGetFeatures(webp_data->bytes, webp_data->size, &decoder_config.input);if (webp_status != VP8_STATUS_OK) {goto End;}if (!WebPAnimDecoderGetInfo(dec, &anim_info)) {fprintf(stderr, "Error getting global info about the animation\n");goto End;}// Animation properties.image->canvas_width = anim_info.canvas_width;image->canvas_height = anim_info.canvas_height;image->loop_count = anim_info.loop_count;image->bgcolor = anim_info.bgcolor;// Allocate frames.if (!AllocateFrames(image, anim_info.frame_count)) return 0;// Decode frames.while (WebPAnimDecoderHasMoreFrames(dec)) {DecodedFrame* curr_frame;uint8_t* curr_rgba;uint8_t* frame_rgba;int timestamp;if (!WebPAnimDecoderGetNext(dec, &frame_rgba, &timestamp)) {fprintf(stderr, "Error decoding frame #%u\n", frame_index);goto End;}assert(frame_index < anim_info.frame_count);curr_frame = &image->frames[frame_index];curr_rgba = curr_frame->rgba;curr_frame->duration = timestamp - prev_frame_timestamp;curr_frame->is_key_frame = 0;  // Unused.memcpy(curr_rgba, frame_rgba,image->canvas_width * kNumChannels * image->canvas_height);++frame_index;prev_frame_timestamp = timestamp;}ok = dump_ok;if (ok) image->format = ANIM_WEBP;End:WebPAnimDecoderDelete(dec);return ok;
}

播放

使用标准Win32工程模板,加个定时器驱动,so easy,部分代码:

#include "stdafx.h"
#include "WebPDemo.h"
#include "GdiplusAutoStartup.hpp"
#include "WebPLoader.h"// 全局变量:
CWebPLoader g_webpLoader;
UINT32 g_nCurrentFrameID = 0;int APIENTRY wWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPWSTR    lpCmdLine,_In_ int       nCmdShow)
{UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);// 解码GDIPLUS_AUTO_STARTUP;WCHAR szPath[MAX_PATH + 1];GetModuleFileName(NULL, szPath, _countof(szPath));PathRemoveFileSpec(szPath);PathAppend(szPath, L"\\..\\..\\..\\test\\rainbow_cat.webp");if (!g_webpLoader.LoadImage(szPath)){MessageBoxA(NULL, "Error decoding file! Aborting.\n", "Error", MB_ICONERROR|MB_OK);return 1;}//return 0;
}//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message){case WM_CREATE://first frameSetTimer(hWnd, 1234, 500, NULL);break;case WM_PAINT:{PAINTSTRUCT ps;HDC hdc = BeginPaint(hWnd, &ps);// 绘图代码RECT rcWin;GetClientRect(hWnd, &rcWin);Rect rcBg(0, 0, rcWin.right - rcWin.left, rcWin.bottom - rcWin.top);// 双缓冲HDC hMemDC = ::CreateCompatibleDC(hdc);HBITMAP hBmpOffscreen = ::CreateCompatibleBitmap(hdc, rcBg.Width, rcBg.Height);HBITMAP hBmpOld = (HBITMAP)::SelectObject(hMemDC, hBmpOffscreen);Graphics gr(hMemDC);gr.Clear(0xFFFFFFFFu);UINT32 nDelayMS = 0;Bitmap* pBmp = g_webpLoader.GetFrameAt(g_nCurrentFrameID, nDelayMS);if (pBmp){Rect rc(0, 0, rcWin.right - rcWin.left, rcWin.bottom - rcWin.top);rc.Offset((rc.Width - (INT)pBmp->GetWidth()) / 2, (rc.Height - (INT)pBmp->GetHeight()) / 2);rc.Width = pBmp->GetWidth();rc.Height = pBmp->GetHeight();gr.DrawImage(pBmp, rc);}BitBlt(hdc, 0, 0, rcBg.Width, rcBg.Height, hMemDC, 0, 0, SRCCOPY);::SelectObject(hMemDC, hBmpOld);DeleteObject(hBmpOffscreen);DeleteDC(hMemDC);EndPaint(hWnd, &ps);//next frameSetTimer(hWnd, 1234, nDelayMS, NULL);}break;case WM_DESTROY:PostQuitMessage(0);break;case WM_ERASEBKGND:return 1;case WM_TIMER:if (wParam == 1234){g_nCurrentFrameID++;g_nCurrentFrameID %= g_webpLoader.GetFrameCount();RECT rc;GetClientRect(hWnd, &rc);InvalidateRect(hWnd, &rc, TRUE);}break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;
}

GitHub

https://github.com/conn-public/vs-proj/tree/master/project/WebPDemo

动态图(三) 动态WebP解码与播放相关推荐

  1. python简单动态图_python动态图的绘制和保存

    前言 这段时间要做一个涉及排队论的数学建模,需要动态绘图.建好了模,却没想到在原以为简单的绘图上耗费了我大量时间.原因在于用python作动态绘图的参考资料过于琐碎.因此在我费了九牛二虎之力终于实现动 ...

  2. 动态图GIF动态图怎么做?上传动态效果图到你的csdn?

    动态图GIF动态图怎么做?上传动态效果图到你的csdn? 微信订阅号.CSND.博客等等很多地方都会用到GIF图,如何自己制作.这里直接提供工具. GIF工具下载:http://download.cs ...

  3. Excel绘制动态图三种方式

    目录 一.项目背景 二.实现过程 一.项目背景 Excel是一款强大的数据分析统计工具,当数据量不太大或者需要快捷处理数据时, 我们经常要用到它,在面试时也会被经常问到一些函数功能和绘制图形等问题.本 ...

  4. php换脸,gif动态图换脸 动态图如何换脸 怎样更换gif动态图的人脸头像

    在网上我们经常能看到一些非常滑稽的图片,比如说:图片中的人物是电影主角,但是脸却是其他人的,关键是换脸之后还非常的有意思,让人忍不住捧腹大笑.很多动态的恶搞图片也是这样,明明是个很正常的gif动态图片 ...

  5. 怎么制作gif动态图 QQ动态表情包怎么制作

    在平时的聊天中经常会使用到GIF动图,不仅仅可以缓解气氛,还很有趣,那这些动态图是如何制作的呢?没有想象的那么难,今天来看看怎么制作的吧! 1.先准备好素材,要制作什么样的动图,可以是图片也可以是视频 ...

  6. python和java打架动态图_Python动态图实例与实践,PYTHON

    今天(3.8)是个特殊节日哈,针对妇女朋友.众所周知,世界上最早的程序员是女性哦,刚好有GITHUB一个超火的动态图项目:barrace(https://gist.githubusercontent. ...

  7. css如何插入动态图,css动态图(作业)

    loading动画 .box{ width: 300px; height: 135px; border: 2px solid #000; margin: 200px auto 0; } .box p{ ...

  8. php 股票动态图,股票动态图,看懂了秒变高手!

    技术面炒股的方法有很多种,主要包括K线技术.均线技术.趋势线技术和MACD.KDJ等各种指标技术. 但话说回来,技术面炒股主要是用于做短线和波段操作,要长线投资必须结合基本面.政策面等其他因素才能显示 ...

  9. python动态图的绘制和保存

    前言 这段时间要做一个涉及排队论的数学建模,需要动态绘图.建好了模,却没想到在原以为简单的绘图上耗费了我大量时间.原因在于用python作动态绘图的参考资料过于琐碎.因此在我费了九牛二虎之力终于实现动 ...

最新文章

  1. 关于AxWebBrowser关闭网页时的关闭提示
  2. 让浏览器非阻塞加载javascript的几种方式
  3. 1.计算机的组成(冯诺依曼体系)
  4. 网络推广外包——网络推广外包专员浅析网站流量应该如何提升?
  5. 华为 鸿蒙只是物联网,“鸿蒙”不只是手机系统,任正非:是为物联网所打造的系统...
  6. 基本数据类型与String之间的转换
  7. Spring框架----Confinguration和Component-Scan注解
  8. 2019.7.19刷题统计
  9. 主成分分析(PCA)算法实现iris数据集降维
  10. Windows快速更改IP脚本
  11. C#学习笔记之线程安全
  12. win10安装ePLAN P8 2.7无法通过驱动精灵更新MultiUSB Key驱动问题的解决办法
  13. 服务器空间对SEO的影响有多大
  14. TensorFlow - 正弦曲线
  15. 神舟微型计算机系统重装步骤,电脑重装系统步骤,最简单安全的操作!
  16. 2021中国工业软件上市企业公司排行2021中国智能制造企业排名
  17. 月薪不过万郑州程序员的真实生活
  18. 导航星历的钟差,TGD问题
  19. 关系型数据库是什么?
  20. 老板无偿征用你的朋友圈,你愿意吗?

热门文章

  1. 漫画 | 我用了10年 从深圳流水线厂妹做到纽约高薪程序员!
  2. 『读书』可复制的领导力(内含思维导图)
  3. 翻回头看自己走过的路
  4. 海博科技助力各地深化“智慧车驾管”模式,一站式利警便民超体验
  5. python整数表示精确到什么位_保留整数表示精确到什么位?
  6. hosts文件位置?hosts文件是什么?hosts文件修复方法的详细介绍
  7. 智能网联(车联网)示范区发展现状分析—西南篇
  8. Sentinel详解
  9. Python:from aip import AipOcr报错
  10. 语义分割MIoU代码解析