mirror of
https://github.com/hyprwm/hyprgraphics.git
synced 2026-05-04 15:18:04 +02:00
implement loading
This commit is contained in:
parent
3b545552ec
commit
ec51fd4267
3 changed files with 100 additions and 0 deletions
|
|
@ -66,12 +66,25 @@ Hyprgraphics::CImage::CImage(const std::string& path) : filepath(path) {
|
|||
return;
|
||||
#endif
|
||||
|
||||
} else if (path.find(".avif") == len-5 || path.find(".AVIF") == len-5) {
|
||||
|
||||
#ifdef HEIF_FOUND
|
||||
CAIROSURFACE = AVIF::createSurfaceFromAvif(path);
|
||||
mime = "image/avif";
|
||||
#else
|
||||
lastError = "hyprgraphics compiled without HEIF support";
|
||||
return;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
// magic is slow, so only use it when no recognized extension is found
|
||||
auto handle = magic_open(MAGIC_NONE | MAGIC_COMPRESS | MAGIC_SYMLINK);
|
||||
magic_load(handle, nullptr);
|
||||
|
||||
const auto type_str = std::string(magic_file(handle, path.c_str()));
|
||||
|
||||
magic_close(handle);
|
||||
|
||||
const auto first_word = type_str.substr(0, type_str.find(' '));
|
||||
|
||||
if (first_word == "PNG") {
|
||||
|
|
@ -88,6 +101,14 @@ Hyprgraphics::CImage::CImage(const std::string& path) : filepath(path) {
|
|||
#else
|
||||
lastError = "hyprgraphics compiled without JXL support";
|
||||
return;
|
||||
#endif
|
||||
} else if (type_str.contains("AVIF")) { // libmagic can identify AVIF images as "ISO Media, AVIF Image"
|
||||
#ifdef HEIF_FOUND
|
||||
CAIROSURFACE = AVIF::createSurfaceFromAvif(path);
|
||||
mime = "image/avif";
|
||||
#else
|
||||
lastError = "hyprgraphics compiled without AVIF support";
|
||||
return;
|
||||
#endif
|
||||
} else if (first_word == "BMP") {
|
||||
CAIROSURFACE = BMP::createSurfaceFromBMP(path);
|
||||
|
|
|
|||
75
src/image/formats/Avif.cpp
Normal file
75
src/image/formats/Avif.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#include "Avif.hpp"
|
||||
#include <cairo.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <expected>
|
||||
#include <filesystem>
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
#include <libheif/heif.h>
|
||||
using namespace Hyprutils::Utils;
|
||||
|
||||
static std::expected<cairo_surface_t*, std::string> loadFromContext(heif_context* ctx) {
|
||||
heif_image_handle* handle;
|
||||
heif_context_get_primary_image_handle(ctx, &handle);
|
||||
|
||||
heif_image* img;
|
||||
heif_decode_image(handle, &img, heif_colorspace_RGB, heif_chroma_interleaved_RGBA, nullptr);
|
||||
|
||||
size_t width = heif_image_get_width(img, heif_channel_interleaved);
|
||||
size_t height = heif_image_get_height(img, heif_channel_interleaved);
|
||||
int stride;
|
||||
const uint8_t* data = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride);
|
||||
|
||||
std::vector<uint8_t> rawData;
|
||||
rawData.resize(width * height * 4);
|
||||
|
||||
for (size_t y = 0; y < height; y++) {
|
||||
const uint8_t* src = data + (y * stride);
|
||||
uint32_t* dst = (uint32_t*)(rawData.data() + (y * width * 4));
|
||||
for (size_t x = 0; x < width; x++) {
|
||||
uint8_t r = src[(4 * x) + 0];
|
||||
uint8_t g = src[(4 * x) + 1];
|
||||
uint8_t b = src[(4 * x) + 2];
|
||||
uint8_t a = src[(4 * x) + 3];
|
||||
|
||||
r = (r * a) / 255.F;
|
||||
g = (g * a) / 255.F;
|
||||
b = (b * a) / 255.F;
|
||||
|
||||
dst[x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
|
||||
auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
if (!CAIROSURFACE)
|
||||
return std::unexpected("loading avif: cairo failed");
|
||||
|
||||
memcpy(cairo_image_surface_get_data(CAIROSURFACE), rawData.data(), rawData.size());
|
||||
cairo_surface_mark_dirty(CAIROSURFACE);
|
||||
|
||||
heif_image_release(img);
|
||||
heif_image_handle_release(handle);
|
||||
return CAIROSURFACE;
|
||||
}
|
||||
|
||||
std::expected<cairo_surface_t*, std::string> AVIF::createSurfaceFromAvif(const std::string& path) {
|
||||
if (!std::filesystem::exists(path))
|
||||
return std::unexpected("loading avif: file doesn't exist");
|
||||
|
||||
heif_context* ctx = heif_context_alloc();
|
||||
heif_context_read_from_file(ctx, path.c_str(), nullptr);
|
||||
|
||||
auto result = loadFromContext(ctx);
|
||||
heif_context_free(ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
std::expected<cairo_surface_t*, std::string> AVIF::createSurfaceFromAvif(const std::span<uint8_t>& buf) {
|
||||
heif_context* ctx = heif_context_alloc();
|
||||
heif_context_read_from_memory(ctx, buf.data(), buf.size(), nullptr);
|
||||
|
||||
auto result = loadFromContext(ctx);
|
||||
heif_context_free(ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -79,6 +79,10 @@ int main(int argc, char** argv, char** envp) {
|
|||
#ifndef JXL_FOUND
|
||||
if (file.path().filename() == "hyprland.jxl")
|
||||
expectation = false;
|
||||
#endif
|
||||
#ifndef HEIF_FOUND
|
||||
if (file.path().filename() == "hyprland.avif")
|
||||
expectation = false;
|
||||
#endif
|
||||
EXPECT(tryLoadImageFromFile(file.path()), expectation);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue