mirror of
https://github.com/hyprwm/hyprpaper.git
synced 2024-12-22 04:19:47 +01:00
Core: Move to hyprgraphics for image parsing (#216)
* move to hyprgraphics * Nix: add hyprgraphics --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
parent
11d91446f1
commit
b3ee62fe4a
15 changed files with 56 additions and 455 deletions
|
@ -64,7 +64,8 @@ pkg_check_modules(
|
||||||
libjxl_cms
|
libjxl_cms
|
||||||
libjxl_threads
|
libjxl_threads
|
||||||
hyprlang>=0.2.0
|
hyprlang>=0.2.0
|
||||||
hyprutils>=0.2.0)
|
hyprutils>=0.2.0
|
||||||
|
hyprgraphics)
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
||||||
|
|
||||||
|
|
27
flake.lock
27
flake.lock
|
@ -1,5 +1,31 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"hyprgraphics": {
|
||||||
|
"inputs": {
|
||||||
|
"hyprutils": [
|
||||||
|
"hyprutils"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1732808127,
|
||||||
|
"narHash": "sha256-jwqYmLVfvoLPu8UScEzZgdbbiNU3ioYcrsthjEEnGqI=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprgraphics",
|
||||||
|
"rev": "4d927a52be7e15e0846456f2aa1b0ad76b5bf059",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprgraphics",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"hyprlang": {
|
"hyprlang": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"hyprutils": [
|
"hyprutils": [
|
||||||
|
@ -90,6 +116,7 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"hyprgraphics": "hyprgraphics",
|
||||||
"hyprlang": "hyprlang",
|
"hyprlang": "hyprlang",
|
||||||
"hyprutils": "hyprutils",
|
"hyprutils": "hyprutils",
|
||||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||||
|
|
|
@ -5,6 +5,13 @@
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
systems.url = "github:nix-systems/default-linux";
|
systems.url = "github:nix-systems/default-linux";
|
||||||
|
|
||||||
|
hyprgraphics = {
|
||||||
|
url = "github:hyprwm/hyprgraphics";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.systems.follows = "systems";
|
||||||
|
inputs.hyprutils.follows = "hyprutils";
|
||||||
|
};
|
||||||
|
|
||||||
hyprutils = {
|
hyprutils = {
|
||||||
url = "github:hyprwm/hyprutils";
|
url = "github:hyprwm/hyprutils";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
@ -49,6 +56,7 @@
|
||||||
overlays = {
|
overlays = {
|
||||||
default = self.overlays.hyprpaper;
|
default = self.overlays.hyprpaper;
|
||||||
hyprpaper = lib.composeManyExtensions [
|
hyprpaper = lib.composeManyExtensions [
|
||||||
|
inputs.hyprgraphics.overlays.default
|
||||||
inputs.hyprlang.overlays.default
|
inputs.hyprlang.overlays.default
|
||||||
inputs.hyprutils.overlays.default
|
inputs.hyprutils.overlays.default
|
||||||
inputs.hyprwayland-scanner.overlays.default
|
inputs.hyprwayland-scanner.overlays.default
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
expat,
|
expat,
|
||||||
file,
|
file,
|
||||||
fribidi,
|
fribidi,
|
||||||
|
hyprgraphics,
|
||||||
hyprlang,
|
hyprlang,
|
||||||
hyprutils,
|
hyprutils,
|
||||||
hyprwayland-scanner,
|
hyprwayland-scanner,
|
||||||
|
@ -62,6 +63,7 @@ stdenv.mkDerivation {
|
||||||
expat
|
expat
|
||||||
file
|
file
|
||||||
fribidi
|
fribidi
|
||||||
|
hyprgraphics
|
||||||
hyprlang
|
hyprlang
|
||||||
hyprutils
|
hyprutils
|
||||||
libdatrie
|
libdatrie
|
||||||
|
|
|
@ -569,12 +569,12 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) {
|
||||||
origin.y, scale, (int)PWALLPAPERTARGET->m_vSize.x, (int)PWALLPAPERTARGET->m_vSize.y);
|
origin.y, scale, (int)PWALLPAPERTARGET->m_vSize.x, (int)PWALLPAPERTARGET->m_vSize.y);
|
||||||
|
|
||||||
if (TILE) {
|
if (TILE) {
|
||||||
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(PWALLPAPERTARGET->m_pCairoSurface);
|
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(PWALLPAPERTARGET->m_pCairoSurface->cairo());
|
||||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
|
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
|
||||||
cairo_set_source(PCAIRO, pattern);
|
cairo_set_source(PCAIRO, pattern);
|
||||||
} else {
|
} else {
|
||||||
cairo_scale(PCAIRO, scale, scale);
|
cairo_scale(PCAIRO, scale, scale);
|
||||||
cairo_set_source_surface(PCAIRO, PWALLPAPERTARGET->m_pCairoSurface, origin.x, origin.y);
|
cairo_set_source_surface(PCAIRO, PWALLPAPERTARGET->m_pCairoSurface->cairo(), origin.x, origin.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_paint(PCAIRO);
|
cairo_paint(PCAIRO);
|
||||||
|
@ -607,7 +607,7 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) {
|
||||||
|
|
||||||
cairo_show_text(PCAIRO, SPLASH.c_str());
|
cairo_show_text(PCAIRO, SPLASH.c_str());
|
||||||
|
|
||||||
cairo_surface_flush(PWALLPAPERTARGET->m_pCairoSurface);
|
cairo_surface_flush(PWALLPAPERTARGET->m_pCairoSurface->cairo());
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_restore(PCAIRO);
|
cairo_restore(PCAIRO);
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
#include "Bmp.hpp"
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
class BmpHeader {
|
|
||||||
public:
|
|
||||||
unsigned char format[2];
|
|
||||||
uint32_t sizeOfFile;
|
|
||||||
uint16_t reserved1;
|
|
||||||
uint16_t reserved2;
|
|
||||||
uint32_t dataOffset;
|
|
||||||
uint32_t sizeOfBitmapHeader;
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
uint16_t numberOfColors;
|
|
||||||
uint16_t numberOfBitPerPixel;
|
|
||||||
uint32_t compressionMethod;
|
|
||||||
uint32_t imageSize;
|
|
||||||
uint32_t horizontalResolutionPPM;
|
|
||||||
uint32_t verticalResolutionPPM;
|
|
||||||
uint32_t numberOfCollors;
|
|
||||||
uint32_t numberOfImportantCollors;
|
|
||||||
|
|
||||||
BmpHeader(std::ifstream& file) {
|
|
||||||
file.seekg(0, std::ios::end);
|
|
||||||
uint32_t streamLength = file.tellg();
|
|
||||||
file.seekg(0, std::ios::beg);
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&format), sizeof(format));
|
|
||||||
if (!(format[0] == 66 && format[1] == 77)) {
|
|
||||||
Debug::log(ERR, "Unable to parse bitmap header: wrong bmp file type");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&sizeOfFile), sizeof(sizeOfFile));
|
|
||||||
|
|
||||||
if (sizeOfFile != streamLength) {
|
|
||||||
Debug::log(ERR, "Unable to parse bitmap header: wrong value of file size header");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&reserved1), sizeof(reserved1));
|
|
||||||
file.read(reinterpret_cast<char*>(&reserved2), sizeof(reserved2));
|
|
||||||
file.read(reinterpret_cast<char*>(&dataOffset), sizeof(dataOffset));
|
|
||||||
file.read(reinterpret_cast<char*>(&sizeOfBitmapHeader), sizeof(sizeOfBitmapHeader));
|
|
||||||
file.read(reinterpret_cast<char*>(&width), sizeof(width));
|
|
||||||
file.read(reinterpret_cast<char*>(&height), sizeof(height));
|
|
||||||
file.read(reinterpret_cast<char*>(&numberOfColors), sizeof(numberOfColors));
|
|
||||||
file.read(reinterpret_cast<char*>(&numberOfBitPerPixel), sizeof(numberOfBitPerPixel));
|
|
||||||
file.read(reinterpret_cast<char*>(&compressionMethod), sizeof(compressionMethod));
|
|
||||||
file.read(reinterpret_cast<char*>(&imageSize), sizeof(imageSize));
|
|
||||||
file.read(reinterpret_cast<char*>(&horizontalResolutionPPM), sizeof(horizontalResolutionPPM));
|
|
||||||
file.read(reinterpret_cast<char*>(&verticalResolutionPPM), sizeof(verticalResolutionPPM));
|
|
||||||
file.read(reinterpret_cast<char*>(&numberOfCollors), sizeof(numberOfCollors));
|
|
||||||
file.read(reinterpret_cast<char*>(&numberOfImportantCollors), sizeof(numberOfImportantCollors));
|
|
||||||
|
|
||||||
if (!imageSize)
|
|
||||||
imageSize = sizeOfFile - dataOffset;
|
|
||||||
|
|
||||||
if (imageSize != (width * height * numberOfBitPerPixel / 8)) {
|
|
||||||
Debug::log(ERR, "Unable to parse bitmap header: wrong image size");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
file.seekg(dataOffset);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
void reflectImage(unsigned char* image, uint32_t numberOfRows, int stride) {
|
|
||||||
int rowStart = 0;
|
|
||||||
int rowEnd = numberOfRows - 1;
|
|
||||||
std::vector<unsigned char> temp;
|
|
||||||
temp.resize(stride);
|
|
||||||
while (rowStart < rowEnd) {
|
|
||||||
memcpy(&temp[0], &image[rowStart * stride], stride);
|
|
||||||
memcpy(&image[rowStart * stride], &image[rowEnd * stride], stride);
|
|
||||||
memcpy(&image[rowEnd * stride], &temp[0], stride);
|
|
||||||
rowStart++;
|
|
||||||
rowEnd--;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void convertRgbToArgb(std::ifstream& imageStream, unsigned char* outputImage, uint32_t newImageSize) {
|
|
||||||
uint8_t forthBitCounter = 0;
|
|
||||||
unsigned long imgCursor = 0;
|
|
||||||
while (imgCursor < newImageSize) {
|
|
||||||
imageStream.read(reinterpret_cast<char*>(&outputImage[imgCursor]), 1);
|
|
||||||
imgCursor++;
|
|
||||||
forthBitCounter++;
|
|
||||||
if (forthBitCounter == 3) {
|
|
||||||
outputImage[imgCursor] = 0;
|
|
||||||
imgCursor++;
|
|
||||||
forthBitCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
cairo_surface_t* BMP::createSurfaceFromBMP(const std::string& path) {
|
|
||||||
|
|
||||||
if (!std::filesystem::exists(path)) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromBMP: file doesn't exist??");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ifstream bitmapImageStream(path);
|
|
||||||
BmpHeader bitmapHeader(bitmapImageStream);
|
|
||||||
|
|
||||||
cairo_format_t format = CAIRO_FORMAT_ARGB32;
|
|
||||||
int stride = cairo_format_stride_for_width(format, bitmapHeader.width);
|
|
||||||
unsigned char* imageData = (unsigned char*)malloc(bitmapHeader.height * stride);
|
|
||||||
|
|
||||||
if (bitmapHeader.numberOfBitPerPixel == 24)
|
|
||||||
convertRgbToArgb(bitmapImageStream, imageData, bitmapHeader.height * stride);
|
|
||||||
else if (bitmapHeader.numberOfBitPerPixel == 32)
|
|
||||||
bitmapImageStream.read(reinterpret_cast<char*>(&imageData), bitmapHeader.imageSize);
|
|
||||||
else {
|
|
||||||
Debug::log(ERR, "createSurfaceFromBMP: unsupported bmp format");
|
|
||||||
bitmapImageStream.close();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
bitmapImageStream.close();
|
|
||||||
reflectImage(imageData, bitmapHeader.height, stride);
|
|
||||||
return cairo_image_surface_create_for_data(imageData, format, bitmapHeader.width, bitmapHeader.height, stride);
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../defines.hpp"
|
|
||||||
|
|
||||||
namespace BMP {
|
|
||||||
cairo_surface_t* createSurfaceFromBMP(const std::string&);
|
|
||||||
};
|
|
|
@ -1,66 +0,0 @@
|
||||||
#include "Jpeg.hpp"
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
cairo_surface_t* JPEG::createSurfaceFromJPEG(const std::string& path) {
|
|
||||||
|
|
||||||
if (!std::filesystem::exists(path)) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJPEG: file doesn't exist??");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__) {
|
|
||||||
Debug::log(CRIT, "tried to load a jpeg on a big endian system! ping vaxry he is lazy.");
|
|
||||||
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<uint8_t> bytes(file.tellg());
|
|
||||||
file.seekg(0);
|
|
||||||
file.read(reinterpret_cast<char*>(bytes.data()), bytes.size());
|
|
||||||
|
|
||||||
// now the JPEG is in the memory
|
|
||||||
|
|
||||||
jpeg_decompress_struct decompressStruct = {};
|
|
||||||
jpeg_error_mgr errorManager = {};
|
|
||||||
|
|
||||||
decompressStruct.err = jpeg_std_error(&errorManager);
|
|
||||||
jpeg_create_decompress(&decompressStruct);
|
|
||||||
jpeg_mem_src(&decompressStruct, bytes.data(), bytes.size());
|
|
||||||
jpeg_read_header(&decompressStruct, true);
|
|
||||||
|
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
||||||
decompressStruct.out_color_space = JCS_EXT_BGRA;
|
|
||||||
#else
|
|
||||||
decompressStruct.out_color_space = JCS_EXT_ARGB;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// decompress
|
|
||||||
jpeg_start_decompress(&decompressStruct);
|
|
||||||
|
|
||||||
auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, decompressStruct.output_width, decompressStruct.output_height);
|
|
||||||
|
|
||||||
if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJPEG: Cairo Failed (?)");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface);
|
|
||||||
const auto CAIROSTRIDE = cairo_image_surface_get_stride(cairoSurface);
|
|
||||||
JSAMPROW rowRead;
|
|
||||||
|
|
||||||
while (decompressStruct.output_scanline < decompressStruct.output_height) {
|
|
||||||
const auto PROW = CAIRODATA + (decompressStruct.output_scanline * CAIROSTRIDE);
|
|
||||||
rowRead = PROW;
|
|
||||||
jpeg_read_scanlines(&decompressStruct, &rowRead, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_surface_mark_dirty(cairoSurface);
|
|
||||||
cairo_surface_set_mime_data(cairoSurface, CAIRO_MIME_TYPE_JPEG, bytes.data(), bytes.size(), nullptr, nullptr);
|
|
||||||
jpeg_finish_decompress(&decompressStruct);
|
|
||||||
jpeg_destroy_decompress(&decompressStruct);
|
|
||||||
|
|
||||||
return cairoSurface;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../defines.hpp"
|
|
||||||
#include <jpeglib.h>
|
|
||||||
|
|
||||||
namespace JPEG {
|
|
||||||
cairo_surface_t* createSurfaceFromJPEG(const std::string&);
|
|
||||||
};
|
|
|
@ -1,107 +0,0 @@
|
||||||
#include "JpegXL.hpp"
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
|
||||||
#include <jxl/decode_cxx.h>
|
|
||||||
#include <jxl/resizable_parallel_runner_cxx.h>
|
|
||||||
|
|
||||||
cairo_surface_t* JXL::createSurfaceFromJXL(const std::string& path) {
|
|
||||||
|
|
||||||
if (!std::filesystem::exists(path)) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: 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<uint8_t> bytes(file.tellg());
|
|
||||||
file.seekg(0);
|
|
||||||
file.read(reinterpret_cast<char*>(bytes.data()), bytes.size());
|
|
||||||
|
|
||||||
JxlSignature signature = JxlSignatureCheck(bytes.data(), bytes.size());
|
|
||||||
if (signature != JXL_SIG_CODESTREAM && signature != JXL_SIG_CONTAINER) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: file is not JXL format");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dec = JxlDecoderMake(nullptr);
|
|
||||||
auto runner = JxlResizableParallelRunnerMake(nullptr);
|
|
||||||
if (JXL_DEC_SUCCESS != JxlDecoderSetParallelRunner(dec.get(), JxlResizableParallelRunner, runner.get())) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderSetParallelRunner failed");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JXL_DEC_SUCCESS != JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE)) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderSubscribeEvents failed");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
JxlDecoderSetInput(dec.get(), bytes.data(), bytes.size());
|
|
||||||
JxlDecoderCloseInput(dec.get());
|
|
||||||
if (JXL_DEC_BASIC_INFO != JxlDecoderProcessInput(dec.get())) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderProcessInput failed");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
JxlBasicInfo basicInfo;
|
|
||||||
if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(dec.get(), &basicInfo)) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderGetBasicInfo failed");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, basicInfo.xsize, basicInfo.ysize);
|
|
||||||
if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: Cairo Failed (?)");
|
|
||||||
cairo_surface_destroy(cairoSurface);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface);
|
|
||||||
|
|
||||||
JxlPixelFormat format = {
|
|
||||||
.num_channels = 4,
|
|
||||||
.data_type = JXL_TYPE_UINT8,
|
|
||||||
.endianness = JXL_LITTLE_ENDIAN,
|
|
||||||
.align = cairo_image_surface_get_stride(cairoSurface),
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto OUTPUTSIZE = basicInfo.xsize * basicInfo.ysize * format.num_channels;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
JxlDecoderStatus status = JxlDecoderProcessInput(dec.get());
|
|
||||||
if (status == JXL_DEC_ERROR) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderProcessInput failed");
|
|
||||||
cairo_surface_destroy(cairoSurface);
|
|
||||||
exit(1);
|
|
||||||
} else if (status == JXL_DEC_NEED_MORE_INPUT) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderProcessInput expected more input");
|
|
||||||
cairo_surface_destroy(cairoSurface);
|
|
||||||
exit(1);
|
|
||||||
} else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
|
|
||||||
JxlResizableParallelRunnerSetThreads(runner.get(), JxlResizableParallelRunnerSuggestThreads(basicInfo.xsize, basicInfo.ysize));
|
|
||||||
size_t bufferSize;
|
|
||||||
if (JXL_DEC_SUCCESS != JxlDecoderImageOutBufferSize(dec.get(), &format, &bufferSize)) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderImageOutBufferSize failed");
|
|
||||||
cairo_surface_destroy(cairoSurface);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (bufferSize != OUTPUTSIZE) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: invalid output buffer size");
|
|
||||||
cairo_surface_destroy(cairoSurface);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(dec.get(), &format, CAIRODATA, bufferSize)) {
|
|
||||||
Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderSetImageOutBuffer failed");
|
|
||||||
cairo_surface_destroy(cairoSurface);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else if (status == JXL_DEC_FULL_IMAGE) {
|
|
||||||
for (size_t i = 0; i < OUTPUTSIZE - 2; i += format.num_channels) {
|
|
||||||
std::swap(CAIRODATA[i + 0], CAIRODATA[i + 2]);
|
|
||||||
}
|
|
||||||
cairo_surface_mark_dirty(cairoSurface);
|
|
||||||
cairo_surface_set_mime_data(cairoSurface, "image/jxl", bytes.data(), bytes.size(), nullptr, nullptr);
|
|
||||||
return cairoSurface;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../defines.hpp"
|
|
||||||
|
|
||||||
namespace JXL {
|
|
||||||
cairo_surface_t* createSurfaceFromJXL(const std::string&);
|
|
||||||
};
|
|
|
@ -1,71 +0,0 @@
|
||||||
#include "Webp.hpp"
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
|
||||||
file.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit);
|
|
||||||
std::vector<uint8_t> bytes(file.tellg());
|
|
||||||
file.seekg(0);
|
|
||||||
file.read(reinterpret_cast<char*>(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;
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../defines.hpp"
|
|
||||||
|
|
||||||
namespace WEBP {
|
|
||||||
cairo_surface_t* createSurfaceFromWEBP(const std::string&);
|
|
||||||
};
|
|
|
@ -1,10 +1,11 @@
|
||||||
#include "WallpaperTarget.hpp"
|
#include "WallpaperTarget.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <magic.h>
|
#include <hyprgraphics/image/Image.hpp>
|
||||||
|
using namespace Hyprgraphics;
|
||||||
|
|
||||||
CWallpaperTarget::~CWallpaperTarget() {
|
CWallpaperTarget::~CWallpaperTarget() {
|
||||||
cairo_surface_destroy(m_pCairoSurface);
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWallpaperTarget::create(const std::string& path) {
|
void CWallpaperTarget::create(const std::string& path) {
|
||||||
|
@ -12,52 +13,17 @@ void CWallpaperTarget::create(const std::string& path) {
|
||||||
|
|
||||||
const auto BEGINLOAD = std::chrono::system_clock::now();
|
const auto BEGINLOAD = std::chrono::system_clock::now();
|
||||||
|
|
||||||
cairo_surface_t* CAIROSURFACE = nullptr;
|
auto loadedImage = CImage(path);
|
||||||
const auto len = path.length();
|
if (!loadedImage.success()) {
|
||||||
if (path.find(".png") == len - 4 || path.find(".PNG") == len - 4) {
|
Debug::log(CRIT, "Cannot load image %s: %s", path.c_str(), loadedImage.getError().c_str());
|
||||||
CAIROSURFACE = cairo_image_surface_create_from_png(path.c_str());
|
|
||||||
} 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(".bmp") == len - 4 || path.find(".BMP") == len - 4) {
|
|
||||||
CAIROSURFACE = BMP::createSurfaceFromBMP(path);
|
|
||||||
m_bHasAlpha = false;
|
|
||||||
} else if (path.find(".webp") == len - 5 || path.find(".WEBP") == len - 5) {
|
|
||||||
CAIROSURFACE = WEBP::createSurfaceFromWEBP(path);
|
|
||||||
} else if (path.find(".jxl") == len - 4 || path.find(".JXL") == len - 4) {
|
|
||||||
CAIROSURFACE = JXL::createSurfaceFromJXL(path);
|
|
||||||
} else {
|
|
||||||
// magic is slow, so only use it when no recognized extension is found
|
|
||||||
auto handle = magic_open(MAGIC_NONE | MAGIC_COMPRESS);
|
|
||||||
magic_load(handle, nullptr);
|
|
||||||
|
|
||||||
const auto type_str = std::string(magic_file(handle, path.c_str()));
|
|
||||||
const auto first_word = type_str.substr(0, type_str.find(" "));
|
|
||||||
|
|
||||||
if (first_word == "PNG") {
|
|
||||||
CAIROSURFACE = cairo_image_surface_create_from_png(path.c_str());
|
|
||||||
} else if (first_word == "JPEG") {
|
|
||||||
CAIROSURFACE = JPEG::createSurfaceFromJPEG(path);
|
|
||||||
m_bHasAlpha = false;
|
|
||||||
} else if (first_word == "BMP") {
|
|
||||||
CAIROSURFACE = BMP::createSurfaceFromBMP(path);
|
|
||||||
m_bHasAlpha = false;
|
|
||||||
} else {
|
|
||||||
Debug::log(CRIT, "unrecognized image %s", path.c_str());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cairo_surface_status(CAIROSURFACE) != CAIRO_STATUS_SUCCESS) {
|
|
||||||
Debug::log(CRIT, "Failed to read image %s because of:\n%s", path.c_str(), cairo_status_to_string(cairo_surface_status(CAIROSURFACE)));
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)};
|
m_vSize = loadedImage.cairoSurface()->size();
|
||||||
|
|
||||||
const auto MS = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - BEGINLOAD).count() / 1000.f;
|
const auto MS = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - BEGINLOAD).count() / 1000.f;
|
||||||
|
|
||||||
Debug::log(LOG, "Preloaded target %s in %.2fms -> Pixel size: [%i, %i]", path.c_str(), MS, (int)m_vSize.x, (int)m_vSize.y);
|
Debug::log(LOG, "Preloaded target %s in %.2fms -> Pixel size: [%i, %i]", path.c_str(), MS, (int)m_vSize.x, (int)m_vSize.y);
|
||||||
|
|
||||||
m_pCairoSurface = CAIROSURFACE;
|
m_pCairoSurface = loadedImage.cairoSurface();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../helpers/Jpeg.hpp"
|
#include <hyprgraphics/cairo/CairoSurface.hpp>
|
||||||
#include "../helpers/Bmp.hpp"
|
|
||||||
#include "../helpers/Webp.hpp"
|
|
||||||
#include "../helpers/JpegXL.hpp"
|
|
||||||
|
|
||||||
class CWallpaperTarget {
|
class CWallpaperTarget {
|
||||||
public:
|
public:
|
||||||
~CWallpaperTarget();
|
~CWallpaperTarget();
|
||||||
|
|
||||||
void create(const std::string& path);
|
void create(const std::string& path);
|
||||||
|
|
||||||
std::string m_szPath;
|
std::string m_szPath;
|
||||||
|
|
||||||
Vector2D m_vSize;
|
Vector2D m_vSize;
|
||||||
|
|
||||||
bool m_bHasAlpha = true;
|
bool m_bHasAlpha = true;
|
||||||
|
|
||||||
cairo_surface_t* m_pCairoSurface;
|
SP<Hyprgraphics::CCairoSurface> m_pCairoSurface;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue