formats: fix format selection and some safeguards (#28)
Some checks are pending
Build & Test (Arch) / Arch: Build and Test (gcc) (push) Waiting to run
Build & Test (Arch) / Arch: Build and Test (clang) (push) Waiting to run
Build & Test / nix (hyprgraphics) (push) Waiting to run
Build & Test / nix (hyprgraphics-with-tests) (push) Waiting to run

* formats: differentiate between JPEG and JXL when using magic

* formats: check magic bytes for jpeg and webp

* jpeg: error handling bs for libjpeg
This commit is contained in:
Maximilian Seidler 2025-07-10 10:17:08 +02:00 committed by GitHub
parent b841473a0b
commit 83885a6edf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 1 deletions

View file

@ -74,10 +74,18 @@ Hyprgraphics::CImage::CImage(const std::string& path) : filepath(path) {
if (first_word == "PNG") {
CAIROSURFACE = PNG::createSurfaceFromPNG(path);
mime = "image/png";
} else if (first_word == "JPEG") {
} else if (first_word == "JPEG" && !type_str.contains("XL") && !type_str.contains("2000")) {
CAIROSURFACE = JPEG::createSurfaceFromJPEG(path);
imageHasAlpha = false;
mime = "image/jpeg";
} else if (first_word == "JPEG" && type_str.contains("XL")) {
#ifdef JXL_FOUND
CAIROSURFACE = JXL::createSurfaceFromJXL(path);
mime = "image/jxl";
#else
lastError = "hyprgraphics compiled without JXL support";
return;
#endif
} else if (first_word == "BMP") {
CAIROSURFACE = BMP::createSurfaceFromBMP(path);
imageHasAlpha = false;

View file

@ -4,6 +4,13 @@
#include <filesystem>
#include <fstream>
#include <vector>
#include <csetjmp>
// TODO: TurboJPEG C API and get rid of this
jmp_buf bailoutBuf = {};
static void bailout(j_common_ptr _) {
longjmp(bailoutBuf, 1);
}
std::expected<cairo_surface_t*, std::string> JPEG::createSurfaceFromJPEG(const std::string& path) {
@ -19,12 +26,20 @@ std::expected<cairo_surface_t*, std::string> JPEG::createSurfaceFromJPEG(const s
file.seekg(0);
file.read(reinterpret_cast<char*>(bytes.data()), bytes.size());
if (bytes[0] != 0xFF || bytes[1] != 0xD8)
return std::unexpected("loading jpeg: invalid magic bytes");
// now the JPEG is in the memory
jpeg_decompress_struct decompressStruct = {};
jpeg_error_mgr errorManager = {};
decompressStruct.err = jpeg_std_error(&errorManager);
errorManager.error_exit = bailout;
if (setjmp(bailoutBuf))
return std::unexpected("loading jpeg: libjpeg encountered a fatal error");
jpeg_create_decompress(&decompressStruct);
jpeg_mem_src(&decompressStruct, bytes.data(), bytes.size());
jpeg_read_header(&decompressStruct, true);

View file

@ -17,6 +17,9 @@ std::expected<cairo_surface_t*, std::string> WEBP::createSurfaceFromWEBP(const s
file.seekg(0);
file.read(reinterpret_cast<char*>(bytes.data()), bytes.size());
if (bytes[0] != 'R' || bytes[1] != 'I' || bytes[2] != 'F' || bytes[3] != 'F')
return std::unexpected("loading webp: invalid magic bytes");
// now the WebP is in the memory
WebPDecoderConfig config;