mirror of
https://github.com/hyprwm/hyprpaper.git
synced 2024-12-22 12:19:49 +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
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.4)
|
||||
project(hyprpaper
|
||||
project(hyprpaper
|
||||
DESCRIPTION "A blazing fast wayland wallpaper utility"
|
||||
)
|
||||
|
||||
|
@ -41,7 +41,7 @@ add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-m
|
|||
find_package(Threads 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")
|
||||
|
||||
|
|
11
README.md
11
README.md
|
@ -26,6 +26,7 @@ The development files of these packages need to be installed on the system for `
|
|||
- libglvnd
|
||||
- libglvnd-core
|
||||
- libjpeg-turbo
|
||||
- libwebp
|
||||
|
||||
Also `gcc-c++` and `ninja` needs to installed.
|
||||
|
||||
|
@ -67,7 +68,7 @@ wallpaper = monitor2,/path/to/next_image.png
|
|||
# .. 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:
|
||||
|
||||
|
@ -106,9 +107,9 @@ In the actual configuration for Hyprland, *hyprland.conf*, variables can be set
|
|||
|
||||
*~/.config/hypr/hyprland.conf*
|
||||
```
|
||||
$w1 = hyprctl hyprpaper wallpaper "DP-1,~/Pictures/myepicpng.png"
|
||||
$w2 = hyprctl hyprpaper wallpaper "DP-1,~/Pictures/myepicpngToo.png"
|
||||
$w3 = hyprctl hyprpaper wallpaper "DP-1,~/Pictures/myepicpngAlso.png"
|
||||
$w1 = hyprctl hyprpaper wallpaper "DP-1,~/Pictures/myepicpng.png"
|
||||
$w2 = hyprctl hyprpaper wallpaper "DP-1,~/Pictures/myepicpngToo.png"
|
||||
$w3 = hyprctl hyprpaper wallpaper "DP-1,~/Pictures/myepicpngAlso.png"
|
||||
#yes use quotes around desired monitor and wallpaper
|
||||
#... continued with desired amount
|
||||
```
|
||||
|
@ -127,7 +128,7 @@ bind=SUPER,2,exec,$w2 #SuperKey + 2 switches to wallpaper $w2 on DP-1 as def
|
|||
bind=SUPER,3,workspace,3 #Superkey + 3 switches to workspace 3
|
||||
bind=SUPER,3,exec,$w3 #SuperKey + 3 switches to wallpaper $w3 on DP-1 as defined in the variable
|
||||
|
||||
#... and so on
|
||||
#... and so on
|
||||
```
|
||||
Because the default behavior in Hyprland is to also switch the workspace whenever movetoworkspace is used to move a window to another workspace you may want to include the following:
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
libselinux,
|
||||
libsepol,
|
||||
libthai,
|
||||
libwebp,
|
||||
pango,
|
||||
pcre,
|
||||
util-linux,
|
||||
|
@ -44,6 +45,7 @@ stdenv.mkDerivation {
|
|||
libselinux
|
||||
libsepol
|
||||
libthai
|
||||
libwebp
|
||||
pango
|
||||
pcre
|
||||
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) {
|
||||
CAIROSURFACE = JPEG::createSurfaceFromJPEG(path);
|
||||
m_bHasAlpha = false;
|
||||
} else if (path.find(".webp") == len - 5 || path.find(".WEBP") == len - 5) {
|
||||
CAIROSURFACE = WEBP::createSurfaceFromWEBP(path);
|
||||
} else {
|
||||
// magic is slow, so only use it when no recognized extension is found
|
||||
auto handle = magic_open(MAGIC_NONE|MAGIC_COMPRESS);
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/Jpeg.hpp"
|
||||
#include "../helpers/Webp.hpp"
|
||||
|
||||
class CWallpaperTarget {
|
||||
public:
|
||||
|
||||
~CWallpaperTarget();
|
||||
|
||||
|
||||
void create(const std::string& path);
|
||||
|
||||
std::string m_szPath;
|
||||
|
|
Loading…
Reference in a new issue