糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 动态图(三) 动态WebP解码与播放

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

时间:2024-07-31 14:09:33

相关推荐

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

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

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

概述

WebP是谷歌定义的,如顾名思义(web picture),就是专门优化用于web显示的图片,大概就这样。

定义:

友(you)情(qiang)链接:/speed/webp/

无(wu)情(qiang)链接:/speed/webp?hl=zh-cn

GitHub Mirror: /webmproject/libwebp

环境

解码:libwebp

显示:GDI+ + Win32

开发环境: VS

搭建工程

libwebp
Clone libwebp用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){//借用了 /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;}

借用 /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

/conn-public/vs-proj/tree/master/project/WebPDemo

如果觉得《动态图(三) 动态WebP解码与播放》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。