WebP图片的编码解码库libwebp

2022/10/30 program 共 4808 字,约 14 分钟

直接从releases下载列表里下载即可,里面有头文件和静态库,可以直接拿来使用。Windows版本的最近以来的都是64位的了,支持32位的较新的版本是:libwebp-1.0.3-windows-x86

如果是自己在Windows上编译,可以参考「Makefile、CMake、CMakeLists.txt、GCC、Clang、LLVM、MinGW、交叉编译」,及 编译 WebP - Google for Developers,在Windows搜索栏里搜索prompt找到VisualStudio的对应版本的控制台,进入到源码目录下,直接调用nmake命令即可编译,非常简单:

nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output

对于老版本的源码编译后的 libwebp.lib 里面的不会包含解密和保存文件的相关函数,需要重新修改下编译脚本。找到 Makefile.vc 中的:

LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
               $(UTILS_ENC_OBJS) $(DLL_OBJS) $(IMAGEIO_DEC_OBJS)

增加:$(IMAGEIO_ENC_OBJS) $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) ,修改为:

LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
               $(UTILS_ENC_OBJS) $(DLL_OBJS) $(IMAGEIO_ENC_OBJS) $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS)

例如想封装一个WebP图片转其他格式图片的函数,可以参考 libwebp 源码中的 examples/dwebp.c 文件。封装如下。

头文件 dwebp.h

// dwebp.h

#pragma once

// 判断是否是webp图片
bool IsWebpImage(const char* filename);

// webp图片转换为png图片
bool Webp2Image(const char* in_file, const char* out_file, const char* pixel_format = nullptr);

对应的 dwebp.cpp

// dwebp.cpp

#define HAVE_WINCODEC_H

#include "dwebp.h"
#include "./decode.h"
#include "./imageio/image_enc.h"
#include "./imageio/webpdec.h"
#include <locale>
#include <codecvt>
#include <string>
#include <iostream>
#include <fstream>


// 判断是否是webp图片
// 参考:https://cpp.hotexamples.com/zh/examples/-/-/WebPGetInfo/cpp-webpgetinfo-function-examples.html ImageFromData
bool IsWebpImage(const char* filename) {
    bool yes = false;

    std::ifstream in_file(filename, std::ios::binary);
    in_file.seekg(0, std::ios::end);
    int file_size = (int)in_file.tellg();
    if (file_size > 0) {
        uint8_t* buff = new uint8_t[file_size];
        if (buff) {
            in_file.seekg(0);
            in_file.read((char*)buff, file_size);
            int w = 0, h = 0;
            yes = WebPGetInfo((const uint8_t*)buff, file_size, &w, &h);
            delete[] buff;
        }
    }

    return yes;
}

// webp图片转换为图片
// 参考libwebp源码:examples/dwebp.c https://github.com/webmproject/libwebp/blob/1.0.3/examples/dwebp.c
#pragma comment(lib,"libwebp.lib")
#pragma comment(lib,"libwebpdemux.lib")
bool Webp2Image(const char* in_file, const char* out_file, const char* pixel_format/* = nullptr*/) {
	bool success = false;

    WebPDecoderConfig config;
    WebPDecBuffer* const output_buffer = &config.output;
    WebPBitstreamFeatures* const bitstream = &config.input;
    WebPOutputFileFormat format = PNG;
    const uint8_t* data = NULL;

    int incremental = 0;

    VP8StatusCode status = VP8_STATUS_OK;
    size_t data_size = 0;


    if (!WebPInitDecoderConfig(&config)) {
        return success;
    }

    if (pixel_format) {
        const char* const fmt = pixel_format;
        if (!strcmp(fmt, "RGB"))  format = RGB;
        else if (!strcmp(fmt, "RGBA")) format = RGBA;
        else if (!strcmp(fmt, "BGR"))  format = BGR;
        else if (!strcmp(fmt, "BGRA")) format = BGRA;
        else if (!strcmp(fmt, "ARGB")) format = ARGB;
        else if (!strcmp(fmt, "RGBA_4444")) format = RGBA_4444;
        else if (!strcmp(fmt, "RGB_565")) format = RGB_565;
        else if (!strcmp(fmt, "rgbA")) format = rgbA;
        else if (!strcmp(fmt, "bgrA")) format = bgrA;
        else if (!strcmp(fmt, "Argb")) format = Argb;
        else if (!strcmp(fmt, "rgbA_4444")) format = rgbA_4444;
        else if (!strcmp(fmt, "YUV"))  format = YUV;
        else if (!strcmp(fmt, "YUVA")) format = YUVA;
    }
    
    if (!LoadWebP(in_file, &data, &data_size, bitstream)) {
        goto Exit;
    }

    switch (format) {
    case PNG:
#ifdef HAVE_WINCODEC_H
        output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
#else
        output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB;
#endif
        break;
    case PAM:
        output_buffer->colorspace = MODE_RGBA;
        break;
    case PPM:
        output_buffer->colorspace = MODE_RGB;  // drops alpha for PPM
        break;
    case BMP:
        output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
        break;
    case TIFF:
        output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB;
        break;
    case PGM:
    case RAW_YUV:
        output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV;
        break;
    case ALPHA_PLANE_ONLY:
        output_buffer->colorspace = MODE_YUVA;
        break;
        // forced modes:
    case RGB: output_buffer->colorspace = MODE_RGB; break;
    case RGBA: output_buffer->colorspace = MODE_RGBA; break;
    case BGR: output_buffer->colorspace = MODE_BGR; break;
    case BGRA: output_buffer->colorspace = MODE_BGRA; break;
    case ARGB: output_buffer->colorspace = MODE_ARGB; break;
    case RGBA_4444: output_buffer->colorspace = MODE_RGBA_4444; break;
    case RGB_565: output_buffer->colorspace = MODE_RGB_565; break;
    case rgbA: output_buffer->colorspace = MODE_rgbA; break;
    case bgrA: output_buffer->colorspace = MODE_bgrA; break;
    case Argb: output_buffer->colorspace = MODE_Argb; break;
    case rgbA_4444: output_buffer->colorspace = MODE_rgbA_4444; break;
    case YUV: output_buffer->colorspace = MODE_YUV; break;
    case YUVA: output_buffer->colorspace = MODE_YUVA; break;
    default: goto Exit;
    }

    if (incremental) {
        status = DecodeWebPIncremental(data, data_size, &config);
    } else {
        status = DecodeWebP(data, data_size, &config);
    }

    if (status != VP8_STATUS_OK) {
        PrintWebPError(in_file, status);
        goto Exit;
    }

    if (out_file != NULL) {
       success = WebPSaveImage(output_buffer, format, out_file);
    }

Exit:
    WebPFreeDecBuffer(output_buffer);
    WebPFree((void*)data);

	return success;
}

文档信息

Search

    Table of Contents