2023-12-22 05:15:05 +08:00
|
|
|
#include "Webp.hpp"
|
|
|
|
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
2024-07-17 16:25:07 +02:00
|
|
|
#include <filesystem>
|
2023-12-22 05:15:05 +08:00
|
|
|
#include <webp/decode.h>
|
|
|
|
|
|
|
|
|
|
cairo_surface_t* WEBP::createSurfaceFromWEBP(const std::string& path) {
|
|
|
|
|
|
|
|
|
|
if (!std::filesystem::exists(path)) {
|
|
|
|
|
Debug::log(ERR, "createSurfaceFromWEBP: file doesn't exist??");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-17 16:25:07 +02:00
|
|
|
void* imageRawData;
|
2023-12-22 05:15:05 +08:00
|
|
|
|
|
|
|
|
struct stat fileInfo = {};
|
|
|
|
|
|
2024-07-17 16:25:07 +02:00
|
|
|
const auto FD = open(path.c_str(), O_RDONLY);
|
2023-12-22 05:15:05 +08:00
|
|
|
|
|
|
|
|
fstat(FD, &fileInfo);
|
|
|
|
|
|
|
|
|
|
imageRawData = malloc(fileInfo.st_size);
|
|
|
|
|
|
|
|
|
|
read(FD, imageRawData, fileInfo.st_size);
|
|
|
|
|
|
|
|
|
|
close(FD);
|
|
|
|
|
|
|
|
|
|
// now the WebP is in the memory
|
|
|
|
|
|
|
|
|
|
WebPDecoderConfig config;
|
|
|
|
|
if (!WebPInitDecoderConfig(&config)) {
|
|
|
|
|
Debug::log(CRIT, "WebPInitDecoderConfig Failed");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (WebPGetFeatures((const unsigned char*)imageRawData, fileInfo.st_size, &config.input) != VP8_STATUS_OK) {
|
|
|
|
|
Debug::log(ERR, "createSurfaceFromWEBP: file is not webp format");
|
|
|
|
|
free(imageRawData);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto HEIGHT = config.input.height;
|
2024-07-17 16:25:07 +02:00
|
|
|
const auto WIDTH = config.input.width;
|
2023-12-22 05:15:05 +08:00
|
|
|
|
2024-07-17 16:25:07 +02:00
|
|
|
auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT);
|
2023-12-22 05:15:05 +08:00
|
|
|
if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) {
|
|
|
|
|
Debug::log(CRIT, "createSurfaceFromWEBP: Cairo Failed (?)");
|
|
|
|
|
cairo_surface_destroy(cairoSurface);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-26 01:08:13 +08:00
|
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
|
|
|
config.output.colorspace = MODE_bgrA;
|
|
|
|
|
#else
|
|
|
|
|
config.output.colorspace = MODE_Argb;
|
|
|
|
|
#endif
|
2023-12-22 05:15:05 +08:00
|
|
|
|
2024-07-17 16:25:07 +02:00
|
|
|
const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface);
|
2023-12-22 05:15:05 +08:00
|
|
|
const auto CAIROSTRIDE = cairo_image_surface_get_stride(cairoSurface);
|
|
|
|
|
|
|
|
|
|
config.options.no_fancy_upsampling = 1;
|
2024-07-17 16:25:07 +02:00
|
|
|
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;
|
2023-12-22 05:15:05 +08:00
|
|
|
|
|
|
|
|
if (WebPDecode((const unsigned char*)imageRawData, fileInfo.st_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, CAIRO_MIME_TYPE_PNG, (const unsigned char*)imageRawData, fileInfo.st_size, free, imageRawData);
|
|
|
|
|
|
|
|
|
|
WebPFreeDecBuffer(&config.output);
|
|
|
|
|
|
|
|
|
|
return cairoSurface;
|
|
|
|
|
}
|