#include "Webp.hpp" #include #include #include cairo_surface_t* WEBP::createSurfaceFromWEBP(const std::string& path) { if (!std::filesystem::exists(path)) { Debug::log(ERR, "createSurfaceFromWEBP: file doesn't exist??"); exit(1); } std::ifstream file(path, std::ios::binary | std::ios::ate); file.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); std::vector bytes(file.tellg()); file.seekg(0); file.read(reinterpret_cast(bytes.data()), bytes.size()); // now the WebP is in the memory WebPDecoderConfig config; if (!WebPInitDecoderConfig(&config)) { Debug::log(CRIT, "WebPInitDecoderConfig Failed"); exit(1); } if (WebPGetFeatures(bytes.data(), bytes.size(), &config.input) != VP8_STATUS_OK) { Debug::log(ERR, "createSurfaceFromWEBP: file is not webp format"); exit(1); } const auto HEIGHT = config.input.height; const auto WIDTH = config.input.width; auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT); if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) { Debug::log(CRIT, "createSurfaceFromWEBP: Cairo Failed (?)"); cairo_surface_destroy(cairoSurface); exit(1); } #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ config.output.colorspace = MODE_bgrA; #else config.output.colorspace = MODE_Argb; #endif const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface); const auto CAIROSTRIDE = cairo_image_surface_get_stride(cairoSurface); config.options.no_fancy_upsampling = 1; config.output.u.RGBA.rgba = CAIRODATA; config.output.u.RGBA.stride = CAIROSTRIDE; config.output.u.RGBA.size = CAIROSTRIDE * HEIGHT; config.output.is_external_memory = 1; config.output.width = WIDTH; config.output.height = HEIGHT; if (WebPDecode(bytes.data(), bytes.size(), &config) != VP8_STATUS_OK) { Debug::log(CRIT, "createSurfaceFromWEBP: WebP Decode Failed (?)"); exit(1); } cairo_surface_mark_dirty(cairoSurface); cairo_surface_set_mime_data(cairoSurface, "image/webp", bytes.data(), bytes.size(), nullptr, nullptr); WebPFreeDecBuffer(&config.output); return cairoSurface; }