Added support for jpeg(stb) and webp(libwebp)
This commit is contained in:
@@ -14,15 +14,16 @@ find_package(DPP REQUIRED)
|
|||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(SQLITE3 REQUIRED sqlite3)
|
pkg_check_modules(SQLITE3 REQUIRED sqlite3)
|
||||||
pkg_check_modules(CAIRO REQUIRED cairo)
|
pkg_check_modules(CAIRO REQUIRED cairo)
|
||||||
|
pkg_check_modules(WEBP REQUIRED libwebpdecoder)
|
||||||
|
|
||||||
# Link the pre-installed DPP package.
|
# Link the pre-installed DPP package.
|
||||||
target_link_libraries(${PROJECT_NAME} ${DPP_LIBRARIES} ${SQLITE3_LIBRARIES}
|
target_link_libraries(${PROJECT_NAME} ${DPP_LIBRARIES} ${SQLITE3_LIBRARIES}
|
||||||
${CAIRO_LIBRARIES})
|
${CAIRO_LIBRARIES} ${WEBP_LIBRARIES})
|
||||||
|
|
||||||
# Include the DPP directories.
|
# Include the DPP directories.
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
${PROJECT_NAME} PRIVATE ${DPP_INCLUDE_DIR} ${SQLITE3_INCLUDE_DIR}
|
${PROJECT_NAME} PRIVATE ${DPP_INCLUDE_DIR} ${SQLITE3_INCLUDE_DIR}
|
||||||
${CAIRO_INCLUDE_DIR})
|
${CAIRO_INCLUDE_DIR} ${WEBP_INCLUDE_DIR})
|
||||||
|
|
||||||
# Set C++ version
|
# Set C++ version
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 20
|
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 20
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
#include "../Common.hpp"
|
#include "../Common.hpp"
|
||||||
#include "../Utility/CairoTools.hpp"
|
#include "../Utility/CairoTools.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
#include <dpp/dispatcher.h>
|
#include <dpp/dispatcher.h>
|
||||||
#include <dpp/dpp.h>
|
#include <dpp/dpp.h>
|
||||||
#include <dpp/guild.h>
|
#include <dpp/guild.h>
|
||||||
@@ -25,11 +27,22 @@ void commandGenerateReport(const dpp::slashcommand_t &event,
|
|||||||
bot.request(
|
bot.request(
|
||||||
file.url, dpp::http_method::m_get,
|
file.url, dpp::http_method::m_get,
|
||||||
[event, &bot, fileType](const dpp::http_request_completion_t &result) {
|
[event, &bot, fileType](const dpp::http_request_completion_t &result) {
|
||||||
std::string responseData = GenerateReportImage(
|
auto imageAsSurface = fileType->second(result.body);
|
||||||
fileType->second(
|
if (imageAsSurface == nullptr) {
|
||||||
result.body), // Image itself processed for cario to handle
|
event.edit_response("Failed to load the background image :(");
|
||||||
std::get<std::string>(event.get_parameter("headline")));
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't forget that its only funny if it is all in upper case
|
||||||
|
std::string headline =
|
||||||
|
std::get<std::string>(event.get_parameter("headline"));
|
||||||
|
|
||||||
|
// Never seen this method before but looks awesome
|
||||||
|
std::transform(headline.begin(), headline.end(), headline.data(),
|
||||||
|
::toupper);
|
||||||
|
|
||||||
|
std::string responseData =
|
||||||
|
GenerateReportImage(imageAsSurface, headline);
|
||||||
dpp::message response(event.command.channel_id, "");
|
dpp::message response(event.command.channel_id, "");
|
||||||
response.add_file("report.png", responseData);
|
response.add_file("report.png", responseData);
|
||||||
event.edit_response(response);
|
event.edit_response(response);
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "CairoTools.hpp"
|
#include "CairoTools.hpp"
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
std::string GenerateReportImage(cairo_surface_t *background,
|
std::string GenerateReportImage(cairo_surface_t *background,
|
||||||
std::string headline) {
|
std::string headline) {
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
#include "CairoTools.hpp"
|
#include "CairoTools.hpp"
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include <stb/stb_image.h>
|
||||||
|
|
||||||
|
#include <webp/decode.h>
|
||||||
|
#include <webp/types.h>
|
||||||
|
|
||||||
std::unordered_map<std::string,
|
std::unordered_map<std::string,
|
||||||
std::function<cairo_surface_t *(const std::string &)>>
|
std::function<cairo_surface_t *(const std::string &)>>
|
||||||
supportedImageFileTypes{{"image/png", pngToCairoSurface},
|
supportedImageFileTypes{{"image/png", pngToCairoSurface},
|
||||||
@@ -31,9 +37,63 @@ cairo_surface_t *pngToCairoSurface(const std::string &data) {
|
|||||||
return cairo_image_surface_create_from_png_stream(
|
return cairo_image_surface_create_from_png_stream(
|
||||||
cairoReadPNGdata, const_cast<std::string *>(&data));
|
cairoReadPNGdata, const_cast<std::string *>(&data));
|
||||||
}
|
}
|
||||||
cairo_surface_t *jpegToCairoSurface(std::string data) {
|
|
||||||
return cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 200);
|
///
|
||||||
|
/// JPEG and WEBP
|
||||||
|
///
|
||||||
|
|
||||||
|
inline cairo_surface_t *swizzleToBGRA(unsigned char *data, int width,
|
||||||
|
int height, bool isjpeg = true) {
|
||||||
|
// AI code start - Reviewed, looks solid
|
||||||
|
cairo_surface_t *surface =
|
||||||
|
cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
|
||||||
|
unsigned char *surface_data = cairo_image_surface_get_data(surface);
|
||||||
|
int stride = cairo_image_surface_get_stride(surface);
|
||||||
|
|
||||||
|
// Convert RGB to BGRA
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
unsigned char *src =
|
||||||
|
data + (y * width + x) * (isjpeg ? 3 : 4); // Swizzling
|
||||||
|
unsigned char *dst = surface_data + y * stride + x * 4; // Still swizzling
|
||||||
|
dst[0] = src[2]; // B
|
||||||
|
dst[1] = src[1]; // G
|
||||||
|
dst[2] = src[0]; // R
|
||||||
|
dst[3] = src[3]; // A
|
||||||
}
|
}
|
||||||
cairo_surface_t *webpToCairoSurface(std::string data) {
|
}
|
||||||
return cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 200);
|
cairo_surface_mark_dirty(surface);
|
||||||
|
// AI code end
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_surface_t *jpegToCairoSurface(const std::string &data) {
|
||||||
|
int width, height, channels;
|
||||||
|
unsigned char *imgData = stbi_load_from_memory(
|
||||||
|
reinterpret_cast<const unsigned char *>(data.data()), data.size(), &width,
|
||||||
|
&height, &channels, 3 // Channel count
|
||||||
|
);
|
||||||
|
|
||||||
|
if (imgData == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto image = swizzleToBGRA(imgData, width, height);
|
||||||
|
stbi_image_free(imgData);
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_surface_t *webpToCairoSurface(const std::string &data) {
|
||||||
|
int width, height;
|
||||||
|
unsigned char *imgData =
|
||||||
|
WebPDecodeRGBA(reinterpret_cast<const uint8_t *>(data.data()),
|
||||||
|
data.size(), &width, &height);
|
||||||
|
|
||||||
|
if (imgData == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto image = swizzleToBGRA(imgData, width, height, false);
|
||||||
|
WebPFree(imgData);
|
||||||
|
return image;
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
#define REPORT_HEIGHT 1200
|
#define REPORT_HEIGHT 1200
|
||||||
#define REPORT_HEIGHT_OFFSET 200
|
#define REPORT_HEIGHT_OFFSET 200
|
||||||
#define REPORT_TEXT_START_X 40
|
#define REPORT_TEXT_START_X 40
|
||||||
#define REPORT_TEXT_JUMP_Y 120
|
#define REPORT_TEXT_JUMP_Y 125
|
||||||
#define REPORT_TEXT_FONT_SIZE 120.0
|
#define REPORT_TEXT_FONT_SIZE 120.0
|
||||||
#define REPORT_TEXT_LENGTH 26
|
#define REPORT_TEXT_LENGTH 26
|
||||||
#define REPORT_RESOURCE_BUMPER_PATH "./assets/report_bumper.png"
|
#define REPORT_RESOURCE_BUMPER_PATH "./assets/report_bumper.png"
|
||||||
@@ -23,8 +23,8 @@ cairo_status_t cairoOutputAsPNGStream(void *closure, const unsigned char *data,
|
|||||||
unsigned int length);
|
unsigned int length);
|
||||||
|
|
||||||
cairo_surface_t *pngToCairoSurface(const std::string &data);
|
cairo_surface_t *pngToCairoSurface(const std::string &data);
|
||||||
cairo_surface_t *jpegToCairoSurface(std::string data);
|
cairo_surface_t *jpegToCairoSurface(const std::string &data);
|
||||||
cairo_surface_t *webpToCairoSurface(std::string data);
|
cairo_surface_t *webpToCairoSurface(const std::string &data);
|
||||||
|
|
||||||
extern std::unordered_map<std::string,
|
extern std::unordered_map<std::string,
|
||||||
std::function<cairo_surface_t *(const std::string &)>>
|
std::function<cairo_surface_t *(const std::string &)>>
|
||||||
|
Reference in New Issue
Block a user