fix: replace FreeImage with stb_image and stb_image_write

fixes #204
This commit is contained in:
Alexis Maiquez 2024-10-12 20:01:06 +02:00
parent 5f58178cdc
commit 7278f2f817
15 changed files with 9804 additions and 162 deletions

View File

@ -24,7 +24,7 @@ jobs:
- uses: actions/checkout@v3
- name: Install dependencies
run: sudo apt-get update && sudo apt-get -y install libxrandr-dev libfreeimage-dev libxinerama-dev libxcursor-dev libxi-dev libgl-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libxxf86vm-dev libglm-dev libglfw3-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0
run: sudo apt-get update && sudo apt-get -y install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libgl-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libxxf86vm-dev libglm-dev libglfw3-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
@ -48,7 +48,7 @@ jobs:
- uses: actions/checkout@v3
- name: Install dependencies
run: sudo apt-get update && sudo apt-get -y install libxrandr-dev libfreeimage-dev libxinerama-dev libxcursor-dev libxi-dev libgl-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libxxf86vm-dev libglm-dev libglfw3-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0 wayland-scanner++ wayland-protocols libwayland-dev
run: sudo apt-get update && sudo apt-get -y install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libgl-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libxxf86vm-dev libglm-dev libglfw3-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0 wayland-scanner++ wayland-protocols libwayland-dev
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
@ -72,7 +72,7 @@ jobs:
- uses: actions/checkout@v3
- name: Install dependencies
run: sudo apt-get update && sudo apt-get -y install wayland-scanner++ wayland-protocols libwayland-dev libwayland-egl-backend-dev libfreeimage-dev libglfw3-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libglm-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0
run: sudo apt-get update && sudo apt-get -y install wayland-scanner++ wayland-protocols libwayland-dev libwayland-egl-backend-dev libglfw3-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libglm-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.

View File

@ -33,7 +33,6 @@ find_package(SDL2 REQUIRED)
find_package(MPV REQUIRED)
find_package(LZ4 REQUIRED)
find_package(FFMPEG REQUIRED)
find_package(FreeImage REQUIRED)
find_package(PulseAudio REQUIRED)
# Download CEF of specified version for current platform
@ -100,7 +99,6 @@ include_directories(
${LZ4_INCLUDE_DIR}
${SDL2_INCLUDE_DIRS}
${FFMPEG_INCLUDE_DIR}
${FREEIMAGE_INCLUDE_DIR}
${PULSEAUDIO_INCLUDE_DIR}
src
${CEF_INCLUDE_PATH}
@ -441,7 +439,6 @@ target_link_libraries (linux-wallpaperengine PUBLIC
${LZ4_LIBRARY}
${SDL2_LIBRARIES}
${FFMPEG_LIBRARIES}
${FREEIMAGE_LIBRARIES}
${MPV_LIBRARY}
${PULSEAUDIO_LIBRARY}
glfw

View File

@ -1,83 +0,0 @@
# Find the FreeImage library.
#
# This module defines
# FREEIMAGE_FOUND - True if FREEIMAGE was found.
# FREEIMAGE_INCLUDE_DIRS - Include directories for FREEIMAGE headers.
# FREEIMAGE_LIBRARIES - Libraries for FREEIMAGE.
#
# To specify an additional directory to search, set FREEIMAGE_ROOT.
#
# Copyright (c) 2010, Ewen Cheslack-Postava
# Based on FindSQLite3.cmake by:
# Copyright (c) 2006, Jaroslaw Staniek, <js@iidea.pl>
# Extended by Siddhartha Chaudhuri, 2008.
#
# Redistribution and use is allowed according to the terms of the BSD license.
#
SET(FREEIMAGE_FOUND FALSE)
SET(FREEIMAGE_INCLUDE_DIRS)
SET(FREEIMAGE_LIBRARIES)
SET(SEARCH_PATHS
$ENV{ProgramFiles}/freeimage/include
$ENV{SystemDrive}/freeimage/include
$ENV{ProgramFiles}/freeimage
$ENV{SystemDrive}/freeimage
)
IF(FREEIMAGE_ROOT)
SET(SEARCH_PATHS
${FREEIMAGE_ROOT}
${FREEIMAGE_ROOT}/include
${SEARCH_PATHS}
)
ENDIF()
FIND_PATH(FREEIMAGE_INCLUDE_DIRS
NAMES FreeImage.h
PATHS ${SEARCH_PATHS}
NO_DEFAULT_PATH)
IF(NOT FREEIMAGE_INCLUDE_DIRS) # now look in system locations
FIND_PATH(FREEIMAGE_INCLUDE_DIRS NAMES FreeImage.h)
ENDIF(NOT FREEIMAGE_INCLUDE_DIRS)
SET(FREEIMAGE_LIBRARY_DIRS)
IF(FREEIMAGE_ROOT)
SET(FREEIMAGE_LIBRARY_DIRS ${FREEIMAGE_ROOT})
IF(EXISTS "${FREEIMAGE_ROOT}/lib")
SET(FREEIMAGE_LIBRARY_DIRS ${FREEIMAGE_LIBRARY_DIRS} ${FREEIMAGE_ROOT}/lib)
ENDIF()
IF(EXISTS "${FREEIMAGE_ROOT}/lib/static")
SET(FREEIMAGE_LIBRARY_DIRS ${FREEIMAGE_LIBRARY_DIRS} ${FREEIMAGE_ROOT}/lib/static)
ENDIF()
ENDIF()
# FREEIMAGE
# Without system dirs
FIND_LIBRARY(FREEIMAGE_LIBRARY
NAMES freeimage
PATHS ${FREEIMAGE_LIBRARY_DIRS}
NO_DEFAULT_PATH
)
IF(NOT FREEIMAGE_LIBRARY) # now look in system locations
FIND_LIBRARY(FREEIMAGE_LIBRARY NAMES freeimage)
ENDIF(NOT FREEIMAGE_LIBRARY)
SET(FREEIMAGE_LIBRARIES)
IF(FREEIMAGE_LIBRARY)
SET(FREEIMAGE_LIBRARIES ${FREEIMAGE_LIBRARY})
ENDIF()
IF(FREEIMAGE_INCLUDE_DIRS AND FREEIMAGE_LIBRARIES)
SET(FREEIMAGE_FOUND TRUE)
IF(NOT FREEIMAGE_FIND_QUIETLY)
MESSAGE(STATUS "Found FreeImage: headers at ${FREEIMAGE_INCLUDE_DIRS}, libraries at ${FREEIMAGE_LIBRARY_DIRS} :: ${FREEIMAGE_LIBRARIES}")
ENDIF(NOT FREEIMAGE_FIND_QUIETLY)
ELSE(FREEIMAGE_INCLUDE_DIRS AND FREEIMAGE_LIBRARIES)
SET(FREEIMAGE_FOUND FALSE)
IF(FREEIMAGE_FIND_REQUIRED)
MESSAGE(STATUS "FreeImage not found")
ENDIF(FREEIMAGE_FIND_REQUIRED)
ENDIF(FREEIMAGE_INCLUDE_DIRS AND FREEIMAGE_LIBRARIES)
MARK_AS_ADVANCED(FREEIMAGE_INCLUDE_DIRS FREEIMAGE_LIBRARIES)

View File

@ -32,14 +32,13 @@ Wallpaper Engine is a software designed by [Kristjan Skutta](https://store.steam
- GLM
- GLEW
- GLUT
- FreeImage
- MPV
- PulseAudio
## Commands
```
sudo apt-get update
sudo apt-get install build-essential cmake libxrandr-dev libfreeimage-dev libxinerama-dev libxcursor-dev libxi-dev libgl-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libxxf86vm-dev libglm-dev libglfw3-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0
sudo apt-get install build-essential cmake libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libgl-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libxxf86vm-dev libglm-dev libglfw3-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0
```
# 5. How to use

7988
include/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

1724
include/stb_image_write.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ pkgdesc="use steam's wallpaperengine on linux"
arch=('x86_64')
url="https://github.com/Almamu/linux-wallpaperengine"
license=('GPL3')
depends=('lz4' 'ffmpeg' 'mpv' 'freeimage' 'glfw' 'glew' 'freeglut' 'libpulse')
depends=('lz4' 'ffmpeg' 'mpv' 'glfw' 'glew' 'freeglut' 'libpulse')
makedepends=('git' 'cmake' 'sdl2' 'glm')
provides=("linux-wallpaperengine")
source=("${pkgname}::git+https://github.com/Almamu/linux-wallpaperengine.git#branch=main")

View File

@ -87,7 +87,6 @@ CApplicationContext::CApplicationContext (int argc, char* argv []) {
{
.take = false,
.path = "",
.format = FIF_UNKNOWN,
},
};
@ -280,13 +279,7 @@ void CApplicationContext::validateScreenshot () {
const std::string extension = this->settings.screenshot.path.extension ();
if (extension == ".bmp")
this->settings.screenshot.format = FIF_BMP;
else if (extension == ".png")
this->settings.screenshot.format = FIF_PNG;
else if (extension == ".jpg" || extension == ".jpeg")
this->settings.screenshot.format = FIF_JPEG;
else
if (extension != ".bmp" && extension != ".png" && extension != ".jpeg" && extension != ".jpg")
sLog.exception ("Cannot determine screenshot format, unknown extension ", extension);
}

View File

@ -7,8 +7,6 @@
#include <glm/vec4.hpp>
#include <FreeImage.h>
#include "CApplicationState.h"
#include "WallpaperEngine/Assets/ITexture.h"
@ -101,8 +99,6 @@ class CApplicationContext {
bool take;
/** The path to where the screenshot must be saved */
std::filesystem::path path;
/** The image format */
FREE_IMAGE_FORMAT format;
} screenshot;
} settings;

View File

@ -16,6 +16,8 @@
#include "WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h"
#include <unistd.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
#define FULLSCREEN_CHECK_WAIT_TIME 250
@ -212,14 +214,13 @@ void CWallpaperApplication::setupProperties () {
this->setupPropertiesForProject (info);
}
void CWallpaperApplication::takeScreenshot (const std::filesystem::path& filename, FREE_IMAGE_FORMAT format) {
void CWallpaperApplication::takeScreenshot (const std::filesystem::path& filename) {
// this should be getting called at the end of the frame, so the right thing should be bound already
const int width = this->m_renderContext->getOutput ().getFullWidth ();
const int height = this->m_renderContext->getOutput ().getFullHeight ();
// build the output file with FreeImage
static FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
RGBQUAD color;
// build the output file with stbi_image_write
auto* bitmap = new uint8_t [width * height * sizeof (uint8_t) * 3] {0};
int xoffset = 0;
for (const auto& [screen, viewport] : this->m_renderContext->getOutput ().getViewports ()) {
@ -236,13 +237,12 @@ void CWallpaperApplication::takeScreenshot (const std::filesystem::path& filenam
// now get access to the pixels
for (int y = viewport->viewport.w; y > 0; y--) {
for (int x = 0; x < viewport->viewport.z; x++) {
color.rgbRed = *pixel++;
color.rgbGreen = *pixel++;
color.rgbBlue = *pixel++;
int finalx = x + xoffset;
int finaly = this->m_renderContext->getOutput ().renderVFlip () ? (viewport->viewport.w - y) : y;
// set the pixel in the destination
FreeImage_SetPixelColor (bitmap, x + xoffset,
this->m_renderContext->getOutput ().renderVFlip () ? (viewport->viewport.w - y) : y, &color);
bitmap[finaly * 3 + finalx] = *pixel++;
bitmap[finaly * 3 + finalx + 1] = *pixel++;
bitmap[finaly * 3 + finalx + 2] = *pixel++;
}
}
@ -253,10 +253,15 @@ void CWallpaperApplication::takeScreenshot (const std::filesystem::path& filenam
delete [] buffer;
}
// finally save the file
FreeImage_Save (format, bitmap, filename.c_str (), 0);
auto extension = filename.extension();
FreeImage_Unload (bitmap);
if (extension == ".bmp") {
stbi_write_bmp (filename.c_str(), width, height, 3, bitmap);
} else if (extension == ".png") {
stbi_write_png (filename.c_str(), width, height, 3, bitmap, width * 3);
} else if (extension == ".jpg" || extension == ".jpeg") {
stbi_write_jpg (filename.c_str(), width, height, 3, bitmap, 100);
}
}
void CWallpaperApplication::show () {
@ -398,8 +403,7 @@ void CWallpaperApplication::show () {
if (!this->m_context.settings.screenshot.take || m_videoDriver->getFrameCounter () < 5)
continue;
this->takeScreenshot (this->m_context.settings.screenshot.path,
this->m_context.settings.screenshot.format);
this->takeScreenshot (this->m_context.settings.screenshot.path);
this->m_context.settings.screenshot.take = false;
}

View File

@ -104,11 +104,9 @@ class CWallpaperApplication {
/**
* Takes an screenshot of the background and saves it to the specified path
*
* @param context
* @param filename
* @param format
*/
void takeScreenshot (const std::filesystem::path& filename, FREE_IMAGE_FORMAT format);
void takeScreenshot (const std::filesystem::path& filename);
/** The application context that contains the current app settings */
CApplicationContext& m_context;

View File

@ -5,6 +5,9 @@
#include <lz4.h>
#include <string>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
using namespace WallpaperEngine::Assets;
CTexture::CTexture (const void* fileData) : m_resolution () {
@ -17,7 +20,7 @@ CTexture::CTexture (const void* fileData) : m_resolution () {
this->m_resolution = {this->m_header->textureWidth, this->m_header->textureHeight, this->m_header->gifWidth,
this->m_header->gifHeight};
} else {
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) {
if (this->m_header->freeImageFormat != FreeImageFormat::FIF_UNKNOWN) {
// wpengine-texture format always has one mipmap
// get first image size
auto element = this->m_header->images.find (0)->second.begin ();
@ -31,7 +34,7 @@ CTexture::CTexture (const void* fileData) : m_resolution () {
}
}
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) {
if (this->m_header->freeImageFormat != FreeImageFormat::FIF_UNKNOWN) {
internalFormat = GL_RGBA8;
// set some extra information too as it's used for image sizing
// this ensures that a_TexCoord uses the full image instead of just part of it
@ -92,39 +95,32 @@ CTexture::CTexture (const void* fileData) : m_resolution () {
auto end = imgCur->second.end ();
for (int32_t level = 0; cur != end; ++cur, level++) {
FIBITMAP* bitmap = nullptr;
FIBITMAP* converted = nullptr;
FIMEMORY* memory = nullptr;
stbi_uc* handle = nullptr;
void* dataptr = (*cur)->uncompressedData;
uint32_t width = (*cur)->width;
uint32_t height = (*cur)->height;
int width = (*cur)->width;
int height = (*cur)->height;
uint32_t bufferSize = (*cur)->uncompressedSize;
GLenum textureFormat = GL_RGBA;
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) {
memory =
FreeImage_OpenMemory (reinterpret_cast<BYTE*> ((*cur)->uncompressedData), (*cur)->uncompressedSize);
if (this->m_header->freeImageFormat != FreeImageFormat::FIF_UNKNOWN) {
int fileChannels;
// load the image and setup pointers so they can be used
bitmap = FreeImage_LoadFromMemory (this->m_header->freeImageFormat, memory);
// flip the image vertically
FreeImage_FlipVertical (bitmap);
// convert to a 32bits bytearray
converted = FreeImage_ConvertTo32Bits (bitmap);
dataptr = FreeImage_GetBits (converted);
width = FreeImage_GetWidth (converted);
height = FreeImage_GetHeight (converted);
bufferSize = FreeImage_GetMemorySize (converted);
textureFormat = GL_BGRA;
dataptr = handle = stbi_load_from_memory (
reinterpret_cast <unsigned char*> ((*cur)->uncompressedData),
(*cur)->uncompressedSize,
&width,
&height,
&fileChannels,
4);
} else {
if (this->m_header->format == TextureFormat::R8) {
// red textures are 1-byte-per-pixel, so it's alignment has to be set manually
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
textureFormat = GL_RED;
} else if (this->m_header->format == TextureFormat::RG88)
} else if (this->m_header->format == TextureFormat::RG88) {
textureFormat = GL_RG;
}
}
switch (internalFormat) {
case GL_RGBA8:
@ -142,11 +138,9 @@ CTexture::CTexture (const void* fileData) : m_resolution () {
default: sLog.exception ("Cannot load texture, unknown format", this->m_header->format);
}
// freeimage buffer won't be used anymore, so free memory
if (this->m_header->freeImageFormat != FREE_IMAGE_FORMAT::FIF_UNKNOWN) {
FreeImage_Unload (bitmap);
FreeImage_Unload (converted);
FreeImage_CloseMemory (memory);
// stbi_image buffer won't be used anymore, so free memory
if (this->m_header->freeImageFormat != FreeImageFormat::FIF_UNKNOWN) {
stbi_image_free (handle);
}
}
}
@ -298,7 +292,7 @@ CTexture::TextureHeader* CTexture::parseHeader (const char* fileData) {
if (strncmp (fileData, "TEXB0003", 9) == 0) {
header->containerVersion = ContainerVersion::TEXB0003;
header->imageCount = *pointer++;
header->freeImageFormat = static_cast<FREE_IMAGE_FORMAT> (*pointer++);
header->freeImageFormat = static_cast<FreeImageFormat> (*pointer++);
} else if (strncmp (fileData, "TEXB0002", 9) == 0) {
header->containerVersion = ContainerVersion::TEXB0002;
header->imageCount = *pointer++;

View File

@ -2,7 +2,6 @@
#include "ITexture.h"
#include <FreeImage.h>
#include <GL/glew.h>
#include <glm/vec4.hpp>
#include <map>
@ -34,6 +33,48 @@ class CTexture final : public ITexture {
TEXS0003 = 1,
};
enum FreeImageFormat : int {
FIF_UNKNOWN = -1,
FIF_BMP = 0,
FIF_ICO = 1,
FIF_JPEG = 2,
FIF_JNG = 3,
FIF_KOALA = 4,
FIF_LBM = 5,
FIF_IFF = FIF_LBM,
FIF_MNG = 6,
FIF_PBM = 7,
FIF_PBMRAW = 8,
FIF_PCD = 9,
FIF_PCX = 10,
FIF_PGM = 11,
FIF_PGMRAW = 12,
FIF_PNG = 13,
FIF_PPM = 14,
FIF_PPMRAW = 15,
FIF_RAS = 16,
FIF_TARGA = 17,
FIF_TIFF = 18,
FIF_WBMP = 19,
FIF_PSD = 20,
FIF_CUT = 21,
FIF_XBM = 22,
FIF_XPM = 23,
FIF_DDS = 24,
FIF_GIF = 25,
FIF_HDR = 26,
FIF_FAXG3 = 27,
FIF_SGI = 28,
FIF_EXR = 29,
FIF_J2K = 30,
FIF_JP2 = 31,
FIF_PFM = 32,
FIF_PICT = 33,
FIF_RAW = 34,
FIF_WEBP = 35,
FIF_JXR = 36
};
/**
* Texture mipmap data
*/
@ -93,7 +134,7 @@ class CTexture final : public ITexture {
/** Texture data format */
TextureFormat format;
/** Free Image format */
FREE_IMAGE_FORMAT freeImageFormat = FREE_IMAGE_FORMAT::FIF_UNKNOWN;
FreeImageFormat freeImageFormat = FreeImageFormat::FIF_UNKNOWN;
/** The amount of images in the texture file */
uint32_t imageCount;
/** Number of mipmap levels on the texture */

View File

@ -1,7 +1,6 @@
#include "CGLFWOpenGLDriver.h"
#include "WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h"
#include "common.h"
#include <FreeImage.h>
#define GLFW_EXPOSE_NATIVE_X11
#include <GLFW/glfw3native.h>
@ -61,9 +60,6 @@ CGLFWOpenGLDriver::CGLFWOpenGLDriver (const char* windowTitle, CApplicationConte
if (result != GLEW_OK)
sLog.error ("Failed to initialize GLEW: ", glewGetErrorString (result));
// initialize free image
FreeImage_Initialise (TRUE);
// setup output
if (context.settings.render.mode == CApplicationContext::EXPLICIT_WINDOW ||
context.settings.render.mode == CApplicationContext::NORMAL_WINDOW) {
@ -82,7 +78,6 @@ CGLFWOpenGLDriver::CGLFWOpenGLDriver (const char* windowTitle, CApplicationConte
CGLFWOpenGLDriver::~CGLFWOpenGLDriver () {
glfwTerminate ();
FreeImage_DeInitialise ();
}
Output::COutput& CGLFWOpenGLDriver::getOutput () {

View File

@ -1,8 +1,6 @@
#include "CWaylandOpenGLDriver.h"
#include "WallpaperEngine/Application/CWallpaperApplication.h"
#include <FreeImage.h>
#include "common.h"
#define class _class
@ -255,8 +253,6 @@ CWaylandOpenGLDriver::CWaylandOpenGLDriver (CApplicationContext& context, CWallp
if (result != GLEW_OK)
sLog.error ("Failed to initialize GLEW: ", glewGetErrorString (result));
FreeImage_Initialise (TRUE);
}
CWaylandOpenGLDriver::~CWaylandOpenGLDriver () {