mirror of
https://github.com/hyprwm/hyprpaper.git
synced 2024-11-16 22:25:59 +01:00
feat: Add webp support (#113)
* feat: add webp support * readme: add libwebp dependency * refactor: move including webp to source file * style: fix using tab * style: make const value upper-case * Nix: add libwebp --------- Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
This commit is contained in:
parent
a5e21e2d4a
commit
ae4f498fda
7 changed files with 105 additions and 8 deletions
|
@ -41,7 +41,7 @@ add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-m
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols cairo pango pangocairo libjpeg)
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols cairo pango pangocairo libjpeg libwebp)
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ The development files of these packages need to be installed on the system for `
|
||||||
- libglvnd
|
- libglvnd
|
||||||
- libglvnd-core
|
- libglvnd-core
|
||||||
- libjpeg-turbo
|
- libjpeg-turbo
|
||||||
|
- libwebp
|
||||||
|
|
||||||
Also `gcc-c++` and `ninja` needs to installed.
|
Also `gcc-c++` and `ninja` needs to installed.
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ wallpaper = monitor2,/path/to/next_image.png
|
||||||
# .. more monitors
|
# .. more monitors
|
||||||
```
|
```
|
||||||
|
|
||||||
Preload will tell Hyprland to load a particular image (supported formats: png, jpg, jpeg). Wallpaper will apply the wallpaper to the selected output (`monitor` is the monitor's name, easily can be retrieved with `hyprctl monitors`. You can leave it empty for a wildcard (aka fallback). You can also use `desc:` followed by the monitor's description without the (PORT) at the end)
|
Preload will tell Hyprland to load a particular image (supported formats: png, jpg, jpeg, webp). Wallpaper will apply the wallpaper to the selected output (`monitor` is the monitor's name, easily can be retrieved with `hyprctl monitors`. You can leave it empty for a wildcard (aka fallback). You can also use `desc:` followed by the monitor's description without the (PORT) at the end)
|
||||||
|
|
||||||
You may add `contain:` before the file path in `wallpaper=` to set the mode to contain instead of cover:
|
You may add `contain:` before the file path in `wallpaper=` to set the mode to contain instead of cover:
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
libselinux,
|
libselinux,
|
||||||
libsepol,
|
libsepol,
|
||||||
libthai,
|
libthai,
|
||||||
|
libwebp,
|
||||||
pango,
|
pango,
|
||||||
pcre,
|
pcre,
|
||||||
util-linux,
|
util-linux,
|
||||||
|
@ -44,6 +45,7 @@ stdenv.mkDerivation {
|
||||||
libselinux
|
libselinux
|
||||||
libsepol
|
libsepol
|
||||||
libthai
|
libthai
|
||||||
|
libwebp
|
||||||
pango
|
pango
|
||||||
pcre
|
pcre
|
||||||
wayland
|
wayland
|
||||||
|
|
84
src/helpers/Webp.cpp
Normal file
84
src/helpers/Webp.cpp
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include "Webp.hpp"
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* imageRawData;
|
||||||
|
|
||||||
|
struct stat fileInfo = {};
|
||||||
|
|
||||||
|
const auto FD = open(path.c_str(), O_RDONLY);
|
||||||
|
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
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((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;
|
||||||
|
|
||||||
|
}
|
7
src/helpers/Webp.hpp
Normal file
7
src/helpers/Webp.hpp
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
|
||||||
|
namespace WEBP {
|
||||||
|
cairo_surface_t* createSurfaceFromWEBP(const std::string&);
|
||||||
|
};
|
|
@ -18,6 +18,8 @@ void CWallpaperTarget::create(const std::string& path) {
|
||||||
} else if (path.find(".jpg") == len - 4 || path.find(".JPG") == len - 4 || path.find(".jpeg") == len - 5 || path.find(".JPEG") == len - 5) {
|
} else if (path.find(".jpg") == len - 4 || path.find(".JPG") == len - 4 || path.find(".jpeg") == len - 5 || path.find(".JPEG") == len - 5) {
|
||||||
CAIROSURFACE = JPEG::createSurfaceFromJPEG(path);
|
CAIROSURFACE = JPEG::createSurfaceFromJPEG(path);
|
||||||
m_bHasAlpha = false;
|
m_bHasAlpha = false;
|
||||||
|
} else if (path.find(".webp") == len - 5 || path.find(".WEBP") == len - 5) {
|
||||||
|
CAIROSURFACE = WEBP::createSurfaceFromWEBP(path);
|
||||||
} else {
|
} else {
|
||||||
// magic is slow, so only use it when no recognized extension is found
|
// magic is slow, so only use it when no recognized extension is found
|
||||||
auto handle = magic_open(MAGIC_NONE|MAGIC_COMPRESS);
|
auto handle = magic_open(MAGIC_NONE|MAGIC_COMPRESS);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/Jpeg.hpp"
|
#include "../helpers/Jpeg.hpp"
|
||||||
|
#include "../helpers/Webp.hpp"
|
||||||
|
|
||||||
class CWallpaperTarget {
|
class CWallpaperTarget {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue