diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ba8cd521..41d504d2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,4 +49,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: ${{matrix.platform.key}} - path: build/Release/image.node + path: build/Release/esmbmedia.node diff --git a/CMakeLists.txt b/CMakeLists.txt index ad28fa8f..c05b1757 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ -cmake_minimum_required(VERSION 3.15...3.31) -project(image) +cmake_minimum_required(VERSION 3.19...3.31) +project(esmbmedia) include(FindPkgConfig) include(FetchContent) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(SOURCE_FILES natives/blur.cc +set(IMAGE_SOURCE_FILES natives/blur.cc natives/bounce.cc natives/caption.cc natives/caption2.cc @@ -60,20 +60,22 @@ option(WITH_ZXING "Build with zxing-cpp, enables the qr command" ${WITH_ZXING_DE option(WITH_BACKWARD "Build with backward-cpp, prints a backtrace on crash/abort" ON) if (WITH_MAGICK) - list(APPEND SOURCE_FILES natives/magik.cc) + list(APPEND IMAGE_SOURCE_FILES natives/magik.cc) endif() if (WITH_ZXING) - list(APPEND SOURCE_FILES natives/qr.cc) + list(APPEND IMAGE_SOURCE_FILES natives/qr.cc) endif() +set(SOURCE_FILES "${IMAGE_SOURCE_FILES}") + if (CMAKE_JS_VERSION) - add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC} natives/node/image.cc natives/node/worker.cc) + add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC} natives/node/media.cc natives/node/worker.cc) set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node") target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC}) target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_JS_LIB}) else() - add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} natives/generic/image.cc) + add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} natives/generic/media.cc) endif() target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) @@ -125,15 +127,12 @@ include_directories(${VIPS_INCLUDE_DIRS}) link_directories(${VIPS_LIBRARY_DIRS}) target_link_libraries(${PROJECT_NAME} ${VIPS_LDFLAGS}) +file(READ "${CMAKE_CURRENT_SOURCE_DIR}/package.json" PACKAGE_JSON) +string(JSON ESMB_VERSION GET "${PACKAGE_JSON}" "version") +add_definitions("-DESMB_VERSION=\"${ESMB_VERSION}\"") + if (NOT CMAKE_JS_VERSION) set(CMAKE_POSITION_INDEPENDENT_CODE ON) - FetchContent_Declare( - simdjson - GIT_REPOSITORY https://github.com/simdjson/simdjson.git - GIT_TAG tags/v3.13.0 - GIT_SHALLOW TRUE) - FetchContent_MakeAvailable(simdjson) - target_link_libraries(${PROJECT_NAME} simdjson) endif() if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET AND CMAKE_JS_VERSION) diff --git a/commands/general/raw.js b/commands/general/raw.js index e2068b7d..be6c761b 100644 --- a/commands/general/raw.js +++ b/commands/general/raw.js @@ -1,6 +1,6 @@ import { Constants } from "oceanic.js"; import Command from "#cmd-classes/command.js"; -import imageDetect from "#utils/imagedetect.js"; +import imageDetect from "#utils/mediadetect.js"; class RawCommand extends Command { async run() { diff --git a/commands/general/sticker.js b/commands/general/sticker.js index d6e6d329..e5a456d4 100644 --- a/commands/general/sticker.js +++ b/commands/general/sticker.js @@ -1,5 +1,5 @@ import Command from "#cmd-classes/command.js"; -import { stickerDetect } from "#utils/imagedetect.js"; +import { stickerDetect } from "#utils/mediadetect.js"; class StickerCommand extends Command { async run() { diff --git a/commands/message/select-image.js b/commands/message/select-image.js index e35324a2..6ea08788 100644 --- a/commands/message/select-image.js +++ b/commands/message/select-image.js @@ -1,7 +1,7 @@ import { Message } from "oceanic.js"; import Command from "#cmd-classes/command.js"; import { selectedImages } from "#utils/collections.js"; -import imageDetect from "#utils/imagedetect.js"; +import imageDetect from "#utils/mediadetect.js"; class SelectImageCommand extends Command { async run() { diff --git a/docs/setup.md b/docs/setup.md index b450871a..0a0dcab9 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -253,9 +253,9 @@ pm2 start ecosystem.config.cjs ## Troubleshooting -??? faq "Error: Cannot find module './build/Release/image.node'" +??? faq "Error: Cannot find module './build/Release/esmbmedia.node'" - The native image functions haven't been built. Run `pnpm build` to build them. + The native media functions haven't been built. Run `pnpm build` to build them. ??? faq "`pnpm install` or `pnpm build` fails with error 'ELIFECYCLE  Command failed.'" diff --git a/natives/blur.cc b/natives/blur.cc index 628e2f8c..6e167a12 100644 --- a/natives/blur.cc +++ b/natives/blur.cc @@ -1,15 +1,19 @@ -#include #include #include #include "common.h" +#include "common/argmap.h" using namespace std; using namespace vips; -ArgumentMap Blur(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { - bool sharp = GetArgument(arguments, "sharp"); +FunctionArgs BlurArgs = { + {"sharp", {typeid(bool), false}} +}; + +CmdOutput Blur(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { + bool sharp = GetArgumentWithFallback(arguments, "sharp", false); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)); @@ -20,8 +24,5 @@ ArgumentMap Blur(const string &type, string &outType, const char *bufferdata, si char *buf; size_t dataSize = 0; out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - return output; + return {buf, dataSize}; } diff --git a/natives/bounce.cc b/natives/bounce.cc index c2ddec61..462a2376 100644 --- a/natives/bounce.cc +++ b/natives/bounce.cc @@ -1,5 +1,4 @@ #include - #include #include "common.h" @@ -7,8 +6,8 @@ using namespace std; using namespace vips; -ArgumentMap Bounce(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Bounce(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, true)) .colourspace(VIPS_INTERPRETATION_sRGB); if (!in.has_alpha()) in = in.bandjoin(255); @@ -22,10 +21,8 @@ ArgumentMap Bounce(const string &type, string &outType, const char *bufferdata, in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -59,9 +56,5 @@ ArgumentMap Bounce(const string &type, string &outType, const char *bufferdata, if (outType != "webp") outType = "gif"; - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/caption.cc b/natives/caption.cc index c0f8e81a..5800d505 100644 --- a/natives/caption.cc +++ b/natives/caption.cc @@ -1,4 +1,3 @@ -#include #include #include "common.h" @@ -6,10 +5,16 @@ using namespace std; using namespace vips; -ArgumentMap Caption(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs CaptionArgs = { + {"caption", {typeid(string), true} }, + {"font", {typeid(string), false}}, + {"basePath", {typeid(string), true} } +}; + +CmdOutput Caption(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string caption = GetArgument(arguments, "caption"); - string font = GetArgument(arguments, "font"); + string font = GetArgumentWithFallback(arguments, "font", "futura"); string basePath = GetArgument(arguments, "basePath"); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)) @@ -60,9 +65,5 @@ ArgumentMap Caption(const string &type, string &outType, const char *bufferdata, final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/caption2.cc b/natives/caption2.cc index 7728a82c..d7adffc0 100644 --- a/natives/caption2.cc +++ b/natives/caption2.cc @@ -1,4 +1,3 @@ -#include #include #include @@ -7,11 +6,18 @@ using namespace std; using namespace vips; -ArgumentMap CaptionTwo(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { - bool top = GetArgument(arguments, "top"); +FunctionArgs CaptionTwoArgs = { + {"top", {typeid(bool), false} }, + {"caption", {typeid(string), true} }, + {"font", {typeid(string), false}}, + {"basePath", {typeid(string), true} } +}; + +CmdOutput CaptionTwo(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { + bool top = GetArgumentWithFallback(arguments, "top", false); string caption = GetArgument(arguments, "caption"); - string font = GetArgument(arguments, "font"); + string font = GetArgumentWithFallback(arguments, "font", "helvetica"); string basePath = GetArgument(arguments, "basePath"); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)) @@ -62,9 +68,5 @@ ArgumentMap CaptionTwo(const string &type, string &outType, const char *bufferda final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/circle.cc b/natives/circle.cc index 0c88eedb..8d386c2a 100644 --- a/natives/circle.cc +++ b/natives/circle.cc @@ -29,8 +29,8 @@ VImage rectangularMap(int width, int height) { return index; } -ArgumentMap Circle(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Circle(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, false, false)); @@ -42,10 +42,8 @@ ArgumentMap Circle(const string &type, string &outType, const char *bufferdata, in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -72,8 +70,6 @@ ArgumentMap Circle(const string &type, string &outType, const char *bufferdata, size_t dataSize = 0; out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - return output; + + return {buf, dataSize}; } diff --git a/natives/colors.cc b/natives/colors.cc index 7bcd3e2f..f47edf1c 100644 --- a/natives/colors.cc +++ b/natives/colors.cc @@ -1,4 +1,3 @@ -#include #include #include @@ -7,10 +6,15 @@ using namespace std; using namespace vips; +FunctionArgs ColorsArgs = { + {"color", {typeid(string), true}}, + {"shift", {typeid(int), false} } +}; + VImage sepia = VImage::new_matrixv(3, 3, 0.3588, 0.7044, 0.1368, 0.2990, 0.5870, 0.1140, 0.2392, 0.4696, 0.0912); -ArgumentMap Colors(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +CmdOutput Colors(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string color = GetArgument(arguments, "color"); int shift = GetArgumentWithFallback(arguments, "shift", 0); @@ -35,9 +39,5 @@ ArgumentMap Colors(const string &type, string &outType, const char *bufferdata, size_t dataSize = 0; out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/commands.h b/natives/commands.h index fa3c79d6..896613d9 100644 --- a/natives/commands.h +++ b/natives/commands.h @@ -1,12 +1,27 @@ #pragma once +#include "common/argmap.h" +#include + +struct CmdOutput { + char *buf; + size_t length; +}; + +struct FunctionArg { + std::type_index type; + bool required; +}; + +typedef const std::map FunctionArgs; + // Vultu: These are both bad, but I wanted to clean up code at least a little -using std::string; #define declare_input_func(NAME) \ - ArgumentMap NAME(const string &type, string &outType, const char *bufferData, size_t bufferLength, \ - ArgumentMap arguments, bool *shouldKill) + CmdOutput NAME(const std::string &type, std::string &outType, const char *bufferData, size_t bufferLength, \ + esmb::ArgumentMap arguments, bool *shouldKill) #define declare_noinput_func(NAME) \ - ArgumentMap NAME(const string &type, string &outType, ArgumentMap arguments, bool *shouldKill) + CmdOutput NAME(const std::string &type, std::string &outType, esmb::ArgumentMap arguments, bool *shouldKill) +#define declare_input_args(NAME) extern FunctionArgs NAME; // Declare our Input Functions declare_input_func(Blur); @@ -61,3 +76,37 @@ declare_noinput_func(Homebrew); declare_noinput_func(QrCreate); #endif declare_noinput_func(Sonic); + +// Declare our Input Args +declare_input_args(BlurArgs); +declare_input_args(CaptionArgs); +declare_input_args(CaptionTwoArgs); +declare_input_args(ColorsArgs); +declare_input_args(DistortArgs); +declare_input_args(FadeArgs); +declare_input_args(FlagArgs); +declare_input_args(FlipArgs); +declare_input_args(FreezeArgs); +declare_input_args(GamexplainArgs); +declare_input_args(GlobeArgs); +declare_input_args(HomebrewArgs); +declare_input_args(JpegArgs); +declare_input_args(MemeArgs); +declare_input_args(MirrorArgs); +declare_input_args(MotivateArgs); +#if ZXING_ENABLED +declare_input_args(QrCreateArgs); +#endif +declare_input_args(RedditArgs); +declare_input_args(ResizeArgs); +declare_input_args(ReverseArgs); +declare_input_args(ScottArgs); +declare_input_args(SlideArgs); +declare_input_args(SnapchatArgs); +declare_input_args(SonicArgs); +declare_input_args(SpeedArgs); +declare_input_args(SpotifyArgs); +declare_input_args(UncannyArgs); +declare_input_args(UncaptionArgs); +declare_input_args(WatermarkArgs); +declare_input_args(WhisperArgs); diff --git a/natives/common.h b/natives/common.h index 3a0f37ef..f0045dd6 100644 --- a/natives/common.h +++ b/natives/common.h @@ -15,9 +15,6 @@ using std::map; using std::string; using std::variant; -typedef variant ArgumentVariant; -typedef map ArgumentMap; - void SetupTimeoutCallback(vips::VImage image, bool *shouldKill); typedef struct { time_t expiration; @@ -32,17 +29,6 @@ uint32_t readUint32LE(unsigned char *buffer); void LoadFonts(string basePath); vips::VImage NormalizeVips(vips::VImage in, int *width, int *pageHeight, int nPages); vips::VOption *GetInputOptions(string type, bool sequential, bool sequentialIfAnim); -#define MapContainsKey(MAP, KEY) (MAP.find(KEY) != MAP.end()) - -template T GetArgument(ArgumentMap map, string key) { - if (!MapContainsKey(map, key)) throw "Invalid requested type from variant."; - return std::get(map.at(key)); -} - -template T GetArgumentWithFallback(ArgumentMap map, string key, T fallback) { - if (!MapContainsKey(map, key)) return fallback; - return std::get(map.at(key)); -} const std::vector zeroVec = {0, 0, 0, 0}; const std::vector zeroVecOneAlpha = {0, 0, 0, 1}; @@ -53,62 +39,3 @@ const std::unordered_map fontPaths{ {"roboto", "assets/fonts/reddit.ttf" }, {"ubuntu", "assets/fonts/Ubuntu.ttf" } }; - -const std::map - FunctionMap = { - {"blur", &Blur }, - {"bounce", &Bounce }, - {"caption", &Caption }, - {"captionTwo", &CaptionTwo}, - {"circle", &Circle }, - {"colors", &Colors }, - {"crop", &Crop }, - {"deepfry", &Deepfry }, - {"distort", &Distort }, - {"fade", &Fade }, - {"flag", &Flag }, - {"flip", &Flip }, - {"freeze", &Freeze }, - {"gamexplain", &Gamexplain}, - {"globe", &Globe }, - {"invert", &Invert }, - {"jpeg", &Jpeg }, -#ifdef MAGICK_ENABLED - {"magik", &Magik }, -#endif - {"meme", &Meme }, - {"mirror", &Mirror }, - {"motivate", &Motivate }, -#ifdef ZXING_ENABLED - {"qrread", &QrRead }, -#endif - {"reddit", &Reddit }, - {"resize", &Resize }, - {"reverse", &Reverse }, - {"scott", &Scott }, - {"slide", &Slide }, - {"snapchat", &Snapchat }, - {"speed", &Speed }, - {"spin", &Spin }, - {"spotify", &Spotify }, - {"squish", &Squish }, - {"swirl", &Swirl }, - {"tile", &Tile }, - {"togif", &ToGif }, - {"uncanny", &Uncanny }, - {"uncaption", &Uncaption }, - {"wall", &Wall }, - {"watermark", &Watermark }, - {"whisper", &Whisper } -}; - -const std::map - NoInputFunctionMap = { - {"homebrew", &Homebrew}, -#if ZXING_ENABLED - {"qrcreate", &QrCreate}, -#endif - {"sonic", &Sonic } -}; diff --git a/natives/common/argmap.h b/natives/common/argmap.h new file mode 100644 index 00000000..a010fba9 --- /dev/null +++ b/natives/common/argmap.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +namespace esmb { + typedef std::variant ArgumentVariant; + typedef std::map ArgumentMap; +} // namespace esmb + +#define MapContainsKey(MAP, KEY) (MAP.find(KEY) != MAP.end()) + +template T GetArgument(esmb::ArgumentMap map, std::string key) { + if (!MapContainsKey(map, key)) throw "Invalid requested type from variant."; + return std::get(map.at(key)); +} + +template T GetArgumentWithFallback(esmb::ArgumentMap map, std::string key, T fallback) { + if (!MapContainsKey(map, key)) return fallback; + return std::get(map.at(key)); +} diff --git a/natives/common/maps.h b/natives/common/maps.h new file mode 100644 index 00000000..a1fc9fc9 --- /dev/null +++ b/natives/common/maps.h @@ -0,0 +1,98 @@ +#include "../commands.h" +#include "argmap.h" + +namespace esmb { + const std::map + FunctionMap = { + {"blur", &Blur }, + {"bounce", &Bounce }, + {"caption", &Caption }, + {"captionTwo", &CaptionTwo}, + {"circle", &Circle }, + {"colors", &Colors }, + {"crop", &Crop }, + {"deepfry", &Deepfry }, + {"distort", &Distort }, + {"fade", &Fade }, + {"flag", &Flag }, + {"flip", &Flip }, + {"freeze", &Freeze }, + {"gamexplain", &Gamexplain}, + {"globe", &Globe }, + {"invert", &Invert }, + {"jpeg", &Jpeg }, +#ifdef MAGICK_ENABLED + {"magik", &Magik }, +#endif + {"meme", &Meme }, + {"mirror", &Mirror }, + {"motivate", &Motivate }, +#ifdef ZXING_ENABLED + {"qrread", &QrRead }, +#endif + {"reddit", &Reddit }, + {"resize", &Resize }, + {"reverse", &Reverse }, + {"scott", &Scott }, + {"slide", &Slide }, + {"snapchat", &Snapchat }, + {"speed", &Speed }, + {"spin", &Spin }, + {"spotify", &Spotify }, + {"squish", &Squish }, + {"swirl", &Swirl }, + {"tile", &Tile }, + {"togif", &ToGif }, + {"uncanny", &Uncanny }, + {"uncaption", &Uncaption }, + {"wall", &Wall }, + {"watermark", &Watermark }, + {"whisper", &Whisper } + }; + + const std::map + NoInputFunctionMap = { + {"homebrew", &Homebrew}, +#if ZXING_ENABLED + {"qrcreate", &QrCreate}, +#endif + {"sonic", &Sonic } + }; + + const std::map FunctionArgsMap = { + {"blur", &BlurArgs }, + {"caption", &CaptionArgs }, + {"captionTwo", &CaptionTwoArgs}, + {"colors", &ColorsArgs }, + {"distort", &DistortArgs }, + {"fade", &FadeArgs }, + {"flag", &FlagArgs }, + {"flip", &FlipArgs }, + {"freeze", &FreezeArgs }, + {"gamexplain", &GamexplainArgs}, + {"globe", &GlobeArgs }, + {"homebrew", &HomebrewArgs }, + {"jpeg", &JpegArgs }, + {"meme", &MemeArgs }, + {"mirror", &MirrorArgs }, + {"motivate", &MotivateArgs }, +#if ZXING_ENABLED + {"qrcreate", &QrCreateArgs }, +#endif + {"reddit", &RedditArgs }, + {"resize", &ResizeArgs }, + {"reverse", &ReverseArgs }, + {"scott", &ScottArgs }, + {"slide", &SlideArgs }, + {"snapchat", &SnapchatArgs }, + {"sonic", &SonicArgs }, + {"speed", &SpeedArgs }, + {"spotify", &SpotifyArgs }, + {"uncanny", &UncannyArgs }, + {"uncaption", &UncaptionArgs }, + {"watermark", &WatermarkArgs }, + {"whisper", &WhisperArgs } + }; +} // namespace esmb diff --git a/natives/crop.cc b/natives/crop.cc index 88fec82a..2c202212 100644 --- a/natives/crop.cc +++ b/natives/crop.cc @@ -1,4 +1,3 @@ -#include #include #include @@ -7,8 +6,8 @@ using namespace std; using namespace vips; -ArgumentMap Crop(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Crop(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)); int width = in.width(); @@ -39,9 +38,5 @@ ArgumentMap Crop(const string &type, string &outType, const char *bufferdata, si final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/deepfry.cc b/natives/deepfry.cc index 131d8def..3735e3d0 100644 --- a/natives/deepfry.cc +++ b/natives/deepfry.cc @@ -1,4 +1,3 @@ -#include #include #include "common.h" @@ -6,8 +5,8 @@ using namespace std; using namespace vips; -ArgumentMap Deepfry(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Deepfry(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)); int width = in.width(); @@ -48,9 +47,5 @@ ArgumentMap Deepfry(const string &type, string &outType, const char *bufferdata, final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/distort.cc b/natives/distort.cc index f9d3c980..54ab5a6f 100644 --- a/natives/distort.cc +++ b/natives/distort.cc @@ -5,8 +5,13 @@ using namespace std; using namespace vips; -ArgumentMap Distort(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs DistortArgs = { + {"mapName", {typeid(string), true}}, + {"basePath", {typeid(string), true}} +}; + +CmdOutput Distort(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string mapName = GetArgument(arguments, "mapName"); string basePath = GetArgument(arguments, "basePath"); @@ -39,9 +44,5 @@ ArgumentMap Distort(const string &type, string &outType, const char *bufferdata, size_t dataSize = 0; final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/fade.cc b/natives/fade.cc index c5cbe737..2af11332 100644 --- a/natives/fade.cc +++ b/natives/fade.cc @@ -7,8 +7,12 @@ using namespace std; using namespace vips; -ArgumentMap Fade(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs FadeArgs = { + {"alpha", {typeid(bool), false}} +}; + +CmdOutput Fade(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { bool alpha = GetArgumentWithFallback(arguments, "alpha", false); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, true)) @@ -24,10 +28,8 @@ ArgumentMap Fade(const string &type, string &outType, const char *bufferdata, si in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -65,9 +67,5 @@ ArgumentMap Fade(const string &type, string &outType, const char *bufferdata, si size_t dataSize = 0; final.write_to_buffer(outType == "webp" ? ".webp" : ".gif", reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/flag.cc b/natives/flag.cc index 553c1c45..de9024c9 100644 --- a/natives/flag.cc +++ b/natives/flag.cc @@ -5,8 +5,13 @@ using namespace std; using namespace vips; -ArgumentMap Flag(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs FlagArgs = { + {"overlay", {typeid(string), true}}, + {"basePath", {typeid(string), true}} +}; + +CmdOutput Flag(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string overlay = GetArgument(arguments, "overlay"); string basePath = GetArgument(arguments, "basePath"); @@ -40,9 +45,5 @@ ArgumentMap Flag(const string &type, string &outType, const char *bufferdata, si final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/flip.cc b/natives/flip.cc index 3e2bad46..998fe9de 100644 --- a/natives/flip.cc +++ b/natives/flip.cc @@ -1,4 +1,3 @@ -#include #include #include "common.h" @@ -6,8 +5,12 @@ using namespace std; using namespace vips; -ArgumentMap Flip(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs FlipArgs = { + {"flop", {typeid(bool), false}} +}; + +CmdOutput Flip(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { bool flop = GetArgumentWithFallback(arguments, "flop", false); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, true)); @@ -39,9 +42,5 @@ ArgumentMap Flip(const string &type, string &outType, const char *bufferdata, si out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/freeze.cc b/natives/freeze.cc index f4c6336f..c5cfe55b 100644 --- a/natives/freeze.cc +++ b/natives/freeze.cc @@ -1,5 +1,4 @@ #include -#include #include #include "common.h" @@ -7,6 +6,11 @@ using namespace std; using namespace vips; +FunctionArgs FreezeArgs = { + {"loop", {typeid(bool), false}}, + {"frame", {typeid(int), false} } +}; + char *vipsTrim(const char *data, size_t length, size_t &dataSize, int frame, string suffix, string outType, bool *shouldKill) { VImage in = VImage::new_from_buffer(data, length, "", GetInputOptions(suffix, true, false)); @@ -26,12 +30,12 @@ char *vipsTrim(const char *data, size_t length, size_t &dataSize, int frame, str return buf; } -ArgumentMap Freeze(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +CmdOutput Freeze(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { bool loop = GetArgumentWithFallback(arguments, "loop", false); int frame = GetArgumentWithFallback(arguments, "frame", -1); - ArgumentMap output; + CmdOutput output; size_t dataSize = 0; if (type == "gif") { @@ -64,10 +68,10 @@ ArgumentMap Freeze(const string &type, string &outType, const char *bufferdata, } if (none) dataSize = bufferLength; - output["buf"] = newData; + output.buf = newData; } else if (frame >= 0 && !loop) { char *buf = vipsTrim(bufferdata, bufferLength, dataSize, frame, type, outType, shouldKill); - output["buf"] = buf; + output.buf = buf; } else { lastPos = reinterpret_cast(memchr(fileData, '\x21', bufferLength)); while (lastPos != NULL) { @@ -82,14 +86,14 @@ ArgumentMap Freeze(const string &type, string &outType, const char *bufferdata, } if (none) dataSize = bufferLength; - output["buf"] = fileData; + output.buf = fileData; } - output["size"] = dataSize; + output.length = dataSize; } else if (type == "webp") { if (frame >= 0 && !loop) { char *buf = vipsTrim(bufferdata, bufferLength, dataSize, frame, type, outType, shouldKill); - output["buf"] = buf; - output["size"] = dataSize; + output.buf = buf; + output.length = dataSize; } else { char *fileData = reinterpret_cast(malloc(bufferLength)); memcpy(fileData, bufferdata, bufferLength); @@ -110,14 +114,14 @@ ArgumentMap Freeze(const string &type, string &outType, const char *bufferdata, position += 8 + chunkSize + (chunkSize % 2); } - output["buf"] = fileData; - output["size"] = bufferLength; + output.buf = fileData; + output.length = bufferLength; } } else { char *data = reinterpret_cast(malloc(bufferLength)); memcpy(data, bufferdata, bufferLength); - output["buf"] = data; - output["size"] = bufferLength; + output.buf = data; + output.length = bufferLength; } return output; diff --git a/natives/gamexplain.cc b/natives/gamexplain.cc index 75f26f10..d4c3898b 100644 --- a/natives/gamexplain.cc +++ b/natives/gamexplain.cc @@ -5,8 +5,12 @@ using namespace std; using namespace vips; -ArgumentMap Gamexplain(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs GamexplainArgs = { + {"basePath", {typeid(string), true}} +}; + +CmdOutput Gamexplain(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string basePath = GetArgument(arguments, "basePath"); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)) @@ -39,9 +43,5 @@ ArgumentMap Gamexplain(const string &type, string &outType, const char *bufferda final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/generic/image.cc b/natives/generic/image.cc deleted file mode 100644 index 35f4de92..00000000 --- a/natives/generic/image.cc +++ /dev/null @@ -1,100 +0,0 @@ -#include "../common.h" -#include "image.h" - -#if defined(WIN32) && defined(MAGICK_ENABLED) -#include -#endif -#include -#include - -using namespace simdjson; - -#ifdef __cplusplus -extern "C" { -#endif - -void esmb_image_init() { -#if defined(WIN32) && defined(MAGICK_ENABLED) - Magick::InitializeMagick(""); -#endif - if (VIPS_INIT("")) vips_error_exit(NULL); - vips_cache_set_max(0); -#if VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 13 - vips_block_untrusted_set(true); - vips_operation_block_set("VipsForeignLoad", true); - vips_operation_block_set("VipsForeignLoadJpeg", false); - vips_operation_block_set("VipsForeignLoadPng", false); - vips_operation_block_set("VipsForeignLoadNsgif", false); - vips_operation_block_set("VipsForeignLoadWebp", false); - vips_operation_block_set("VipsForeignLoadHeif", false); -#endif - return; -} - -image_result *esmb_image_process(const char *command, const char *args, size_t args_length, const char *type, const char *data, size_t length) { - ondemand::parser parser; - padded_string padded(args, args_length); - ondemand::document parsedArgs = parser.iterate(padded); - ondemand::object obj(parsedArgs); - ArgumentMap Arguments; - - for (auto pair : obj) { - std::string key(pair.escaped_key().value()); - auto val = pair.value(); - switch (val.type()) { - case ondemand::json_type::boolean: - Arguments[key] = val.get_bool(); - break; - case ondemand::json_type::string: - Arguments[key] = std::string(val.get_string().value()); - break; - case ondemand::json_type::number: - if (val.is_integer()) { - Arguments[key] = static_cast(val.get_int64()); - } else { - Arguments[key] = static_cast(val.get_double()); - } - break; - default: - throw "Unimplemented value type passed to image native."; - } - } - - string outType = GetArgumentWithFallback(Arguments, "togif", false) ? "gif" : type; - - ArgumentMap outMap; - if (length != 0) { - if (MapContainsKey(FunctionMap, command)) { - outMap = FunctionMap.at(command)(type, outType, data, length, Arguments, NULL); - } else { // Vultu: I don't think we will ever be here, but just in case we need a descriptive error - string cmd(command); - throw "Error: \"FunctionMap\" does not contain \"" + cmd + - "\", which was requested because \"length\" parameter was not 0."; - } - } else { - if (MapContainsKey(NoInputFunctionMap, command)) { - outMap = NoInputFunctionMap.at(command)(type, outType, Arguments, NULL); - } else { - string cmd(command); - throw "Error: \"NoInputFunctionMap\" does not contain \"" + cmd + - "\", which was requested because \"length\" parameter was 0."; - } - } - - vips_error_clear(); - vips_thread_shutdown(); - - char *buf = GetArgument(outMap, "buf"); - - image_result *out = (image_result *)malloc(sizeof(image_result)); - out->buf = buf; - out->type = outType.c_str(); - out->length = GetArgument(outMap, "size"); - return out; -} - -void esmb_image_free(void *ptr, [[maybe_unused]] void *ctx) { g_free(ptr); } - -#ifdef __cplusplus -} -#endif diff --git a/natives/generic/image.h b/natives/generic/image.h deleted file mode 100644 index bade55fc..00000000 --- a/natives/generic/image.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct image_result { - const char *type; - size_t length; - void *buf; -}; - -void esmb_image_init(); -image_result *esmb_image_process(const char *command, const char *args, size_t args_length, const char *type, const char *data, size_t length); -void esmb_image_free(void *ptr, [[maybe_unused]] void *ctx); - -inline const char *esmb_image_get_type(image_result *result) { return result->type; } -inline void *esmb_image_get_data(image_result *result) { return result->buf; } -inline size_t esmb_image_get_size(image_result *result) { return result->length; } - -#ifdef __cplusplus -} -#endif diff --git a/natives/generic/media.cc b/natives/generic/media.cc new file mode 100644 index 00000000..fc28f562 --- /dev/null +++ b/natives/generic/media.cc @@ -0,0 +1,108 @@ +#include "media.h" +#include "../common/maps.h" + +#if defined(WIN32) && defined(MAGICK_ENABLED) +#include +#endif +#include + +const char *esmb_media_version() { +#ifdef ESMB_VERSION + return ESMB_VERSION; +#else + return "unknown"; +#endif +} + +esmb_media_result *esmb_media_process(const char *command, esmb::ArgumentMap args, const char *type, + const char *out_type, const char *data, size_t length) { + // std::string outType = GetArgumentWithFallback(args, "togif", false) ? "gif" : type; + std::string outType = out_type; + + CmdOutput outData; + if (length != 0) { + if (MapContainsKey(esmb::FunctionMap, command)) { + outData = esmb::FunctionMap.at(command)(type, outType, data, length, args, NULL); + } else { // Vultu: I don't think we will ever be here, but just in case we need a descriptive error + std::string cmd(command); + throw "Error: \"FunctionMap\" does not contain \"" + cmd + + "\", which was requested because \"length\" parameter was not 0."; + } + } else { + if (MapContainsKey(esmb::NoInputFunctionMap, command)) { + outData = esmb::NoInputFunctionMap.at(command)(type, outType, args, NULL); + } else { + std::string cmd(command); + throw "Error: \"NoInputFunctionMap\" does not contain \"" + cmd + + "\", which was requested because \"length\" parameter was 0."; + } + } + + vips_error_clear(); + vips_thread_shutdown(); + + esmb_media_result *out = (esmb_media_result *)malloc(sizeof(esmb_media_result)); + out->buf = outData.buf; + out->type = outType.c_str(); + out->length = outData.length; + return out; +} + +#ifdef __cplusplus +extern "C" { +#endif + +void esmb_media_init() { +#if defined(WIN32) && defined(MAGICK_ENABLED) + Magick::InitializeMagick(""); +#endif + if (VIPS_INIT("")) vips_error_exit(NULL); + vips_cache_set_max(0); +#if VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 13 + vips_block_untrusted_set(true); + vips_operation_block_set("VipsForeignLoad", true); + vips_operation_block_set("VipsForeignLoadJpeg", false); + vips_operation_block_set("VipsForeignLoadPng", false); + vips_operation_block_set("VipsForeignLoadNsgif", false); + vips_operation_block_set("VipsForeignLoadWebp", false); + vips_operation_block_set("VipsForeignLoadHeif", false); +#endif + return; +} + +esmb_media_args *esmb_media_create_args() { return reinterpret_cast(new esmb::ArgumentMap); } + +// todo: find a way to combine these +void esmb_media_add_string_arg(esmb_media_args *args, char *key, char *value) { + reinterpret_cast(args)->insert(std::make_pair(key, value)); +} + +void esmb_media_add_float_arg(esmb_media_args *args, char *key, float value) { + reinterpret_cast(args)->insert(std::make_pair(key, value)); +} + +void esmb_media_add_int_arg(esmb_media_args *args, char *key, int value) { + reinterpret_cast(args)->insert(std::make_pair(key, value)); +} + +void esmb_media_add_bool_arg(esmb_media_args *args, char *key, bool value) { + reinterpret_cast(args)->insert(std::make_pair(key, value)); +} + +esmb_media_result *esmb_media_process(const char *command, void *args, const char *type, const char *out_type, + const char *data, size_t length) { + esmb::ArgumentMap arguments = *reinterpret_cast(args); + + return esmb_media_process(command, arguments, type, out_type, data, length); +} + +void esmb_media_free_result(esmb_media_result *obj) { + // free(obj->type); + // delete obj->type; + free(obj->buf); + free(obj); +} + +#ifdef __cplusplus +} +#endif diff --git a/natives/generic/media.h b/natives/generic/media.h new file mode 100644 index 00000000..36e797b5 --- /dev/null +++ b/natives/generic/media.h @@ -0,0 +1,39 @@ +#pragma once +#include +#ifdef __cplusplus +#include "../common/argmap.h" +#endif + +struct esmb_media_result { + const char *type; + size_t length; + void *buf; +}; + +#ifdef __cplusplus + +esmb_media_result *esmb_media_process(const char *command, esmb::ArgumentMap args, const char *type, + const char *out_ype, const char *data, size_t length); + +extern "C" { +#endif + +void esmb_media_init(); +const char *esmb_media_version(); + +// wrappers for the esmb::ArgumentMap class +typedef void esmb_media_args; + +esmb_media_args *esmb_media_create_args(); +void esmb_media_add_string_arg(esmb_media_args *args, char *key, char *value); +void esmb_media_add_float_arg(esmb_media_args *args, char *key, float value); +void esmb_media_add_int_arg(esmb_media_args *args, char *key, int value); +void esmb_media_add_bool_arg(esmb_media_args *args, char *key, bool value); + +esmb_media_result *esmb_media_process(const char *command, void *args, const char *type, const char *out_ype, + const char *data, size_t length); +void esmb_media_free_result(esmb_media_result *obj); + +#ifdef __cplusplus +} +#endif diff --git a/natives/globe.cc b/natives/globe.cc index 5ad6de60..bc6a36a3 100644 --- a/natives/globe.cc +++ b/natives/globe.cc @@ -5,8 +5,12 @@ using namespace std; using namespace vips; -ArgumentMap Globe(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs GlobeArgs = { + {"basePath", {typeid(string), true}} +}; + +CmdOutput Globe(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string basePath = GetArgument(arguments, "basePath"); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, true)) @@ -22,10 +26,8 @@ ArgumentMap Globe(const string &type, string &outType, const char *bufferdata, s in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -72,9 +74,5 @@ ArgumentMap Globe(const string &type, string &outType, const char *bufferdata, s if (outType != "webp") outType = "gif"; - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/homebrew.cc b/natives/homebrew.cc index f0c84c60..edf5c011 100644 --- a/natives/homebrew.cc +++ b/natives/homebrew.cc @@ -5,7 +5,13 @@ using namespace std; using namespace vips; -ArgumentMap Homebrew([[maybe_unused]] const string &type, string &outType, ArgumentMap arguments, bool *shouldKill) { +FunctionArgs HomebrewArgs = { + {"caption", {typeid(string), true}}, + {"basePath", {typeid(string), true}} +}; + +CmdOutput Homebrew([[maybe_unused]] const string &type, string &outType, esmb::ArgumentMap arguments, + bool *shouldKill) { string caption = GetArgument(arguments, "caption"); string basePath = GetArgument(arguments, "basePath"); @@ -30,9 +36,5 @@ ArgumentMap Homebrew([[maybe_unused]] const string &type, string &outType, Argum size_t dataSize = 0; out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/invert.cc b/natives/invert.cc index fe6ef463..3a65c244 100644 --- a/natives/invert.cc +++ b/natives/invert.cc @@ -5,8 +5,8 @@ using namespace std; using namespace vips; -ArgumentMap Invert(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Invert(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)); bool hasAlpha = in.has_alpha(); @@ -21,9 +21,5 @@ ArgumentMap Invert(const string &type, string &outType, const char *bufferdata, size_t dataSize = 0; out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/jpeg.cc b/natives/jpeg.cc index 34c430ad..1817e305 100644 --- a/natives/jpeg.cc +++ b/natives/jpeg.cc @@ -5,8 +5,12 @@ using namespace std; using namespace vips; -ArgumentMap Jpeg(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs JpegArgs = { + {"quality", {typeid(int), false}} +}; + +CmdOutput Jpeg(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { int quality = GetArgumentWithFallback(arguments, "quality", 1); char *buf; @@ -60,9 +64,5 @@ ArgumentMap Jpeg(const string &type, string &outType, const char *bufferdata, si } } - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/magik.cc b/natives/magik.cc index 0fe0630f..472dfd78 100644 --- a/natives/magik.cc +++ b/natives/magik.cc @@ -10,8 +10,8 @@ using namespace std; using namespace Magick; -ArgumentMap Magik([[maybe_unused]] const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, [[maybe_unused]] bool *shouldKill) { +CmdOutput Magik([[maybe_unused]] const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, [[maybe_unused]] bool *shouldKill) { Blob blob; list frames; @@ -50,10 +50,6 @@ ArgumentMap Magik([[maybe_unused]] const string &type, string &outType, const ch char *data = reinterpret_cast(malloc(dataSize)); memcpy(data, blob.data(), dataSize); - ArgumentMap output; - output["buf"] = data; - output["size"] = dataSize; - - return output; + return {data, dataSize}; } #endif diff --git a/natives/meme.cc b/natives/meme.cc index efc2880d..50a5b956 100644 --- a/natives/meme.cc +++ b/natives/meme.cc @@ -5,6 +5,13 @@ using namespace std; using namespace vips; +FunctionArgs MemeArgs = { + {"topText", {typeid(string), false}}, + {"bottomText", {typeid(string), false}}, + {"font", {typeid(string), false}}, + {"basePath", {typeid(string), true} } +}; + VImage genText(string text, string font, const char *fontfile, int width, VImage mask, int radius) { VOption *options = VImage::option() ->set("rgba", true) @@ -21,11 +28,11 @@ VImage genText(string text, string font, const char *fontfile, int width, VImage return outline.composite2(in, VIPS_BLEND_MODE_OVER); } -ArgumentMap Meme(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { - string top = GetArgument(arguments, "topText"); - string bottom = GetArgument(arguments, "bottomText"); - string font = GetArgument(arguments, "font"); +CmdOutput Meme(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { + string top = GetArgumentWithFallback(arguments, "topText", ""); + string bottom = GetArgumentWithFallback(arguments, "bottomText", ""); + string font = GetArgumentWithFallback(arguments, "font", "impact"); string basePath = GetArgument(arguments, "basePath"); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)) @@ -74,9 +81,5 @@ ArgumentMap Meme(const string &type, string &outType, const char *bufferdata, si final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/mirror.cc b/natives/mirror.cc index 4067443c..64824f6a 100644 --- a/natives/mirror.cc +++ b/natives/mirror.cc @@ -5,8 +5,13 @@ using namespace std; using namespace vips; -ArgumentMap Mirror(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs MirrorArgs = { + {"vertical", {typeid(bool), false}}, + {"first", {typeid(bool), false}}, +}; + +CmdOutput Mirror(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { bool vertical = GetArgumentWithFallback(arguments, "vertical", false); bool first = GetArgumentWithFallback(arguments, "first", false); @@ -63,9 +68,5 @@ ArgumentMap Mirror(const string &type, string &outType, const char *bufferdata, size_t dataSize = 0; out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/motivate.cc b/natives/motivate.cc index f8d65747..d2e97bdd 100644 --- a/natives/motivate.cc +++ b/natives/motivate.cc @@ -5,11 +5,18 @@ using namespace std; using namespace vips; -ArgumentMap Motivate(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { - string top_text = GetArgument(arguments, "topText"); - string bottom_text = GetArgument(arguments, "bottomText"); - string font = GetArgument(arguments, "font"); +FunctionArgs MotivateArgs = { + {"topText", {typeid(string), false}}, + {"bottomText", {typeid(string), false}}, + {"font", {typeid(string), false}}, + {"basePath", {typeid(string), true} } +}; + +CmdOutput Motivate(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { + string top_text = GetArgumentWithFallback(arguments, "topText", ""); + string bottom_text = GetArgumentWithFallback(arguments, "bottomText", ""); + string font = GetArgumentWithFallback(arguments, "font", "times"); string basePath = GetArgument(arguments, "basePath"); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)) @@ -102,9 +109,5 @@ ArgumentMap Motivate(const string &type, string &outType, const char *bufferdata final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/node/image.cc b/natives/node/media.cc similarity index 73% rename from natives/node/image.cc rename to natives/node/media.cc index 7daa431a..76855bc1 100644 --- a/natives/node/image.cc +++ b/natives/node/media.cc @@ -1,6 +1,4 @@ #include - -#include #include #ifdef __GLIBC__ @@ -25,11 +23,7 @@ namespace backward { using namespace std; -bool isNapiValueInt(Napi::Env &env, Napi::Value &num) { - return env.Global().Get("Number").ToObject().Get("isInteger").As().Call({num}).ToBoolean().Value(); -} - -Napi::Value ProcessImage(const Napi::CallbackInfo &info) { +Napi::Value ProcessMedia(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); string command = info[0].As().Utf8Value(); @@ -38,29 +32,33 @@ Napi::Value ProcessImage(const Napi::CallbackInfo &info) { string type = input.Has("type") ? input.Get("type").As().Utf8Value() : "png"; Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env); - Napi::Array properties = obj.GetPropertyNames(); + esmb::ArgumentMap Arguments; - ArgumentMap Arguments; - - for (unsigned int i = 0; i < properties.Length(); i++) { - string property = properties.Get(uint32_t(i)).As().Utf8Value(); + // We only have a single possible global arg at the moment, + // let's define it here + auto val = obj.Get("togif"); + if (!val.IsEmpty() && !val.IsUndefined() && !val.IsNull()) { + Arguments["togif"] = val.ToBoolean().Value(); + } - auto val = obj.Get(property); - if (val.IsBoolean()) { - Arguments[property] = val.ToBoolean().Value(); - } else if (val.IsString()) { - Arguments[property] = val.ToString().As().Utf8Value(); - } else if (val.IsNumber()) { - auto num = val.ToNumber(); - if (isNapiValueInt(env, num) && property != "yscale" && property != "tolerance" && - property != "pos") { // dumb hack - Arguments[property] = num.Int32Value(); + if (MapContainsKey(esmb::FunctionArgsMap, command)) { + FunctionArgs *argTypes = esmb::FunctionArgsMap.at(command); + for (auto arg : *argTypes) { + val = obj.Get(arg.first); + if (val.IsEmpty() || val.IsUndefined() || val.IsNull()) continue; + + if (arg.second.type == typeid(bool)) { + Arguments[arg.first] = val.ToBoolean().Value(); + } else if (arg.second.type == typeid(string)) { + Arguments[arg.first] = val.ToString().As().Utf8Value(); + } else if (arg.second.type == typeid(int)) { + Arguments[arg.first] = val.ToNumber().Int32Value(); + } else if (arg.second.type == typeid(float)) { + Arguments[arg.first] = val.ToNumber().FloatValue(); } else { - Arguments[property] = num.FloatValue(); + deferred.Reject(Napi::Error::New(env, "Type of property \"" + arg.first + "\" is unknown").Value()); + return deferred.Promise(); } - } else { - deferred.Reject(Napi::Error::New(env, "Type of property \"" + property + "\" is unknown").Value()); - return deferred.Promise(); } } @@ -109,7 +107,7 @@ void *checkTypes(GType type, Napi::Object *formats) { return NULL; } -Napi::Value ImgInit(const Napi::CallbackInfo &info) { +Napi::Value MediaInit(const Napi::CallbackInfo &info) { #if __GLIBC__ /* Set mmap threshold to 128kb to work around a similar glibc bug to the one above. @@ -141,18 +139,18 @@ Napi::Value ImgInit(const Napi::CallbackInfo &info) { } Napi::Object Init(Napi::Env env, Napi::Object exports) { - exports.Set(Napi::String::New(env, "image"), Napi::Function::New(env, ProcessImage)); - exports.Set(Napi::String::New(env, "imageInit"), Napi::Function::New(env, ImgInit)); + exports.Set(Napi::String::New(env, "media"), Napi::Function::New(env, ProcessMedia)); + exports.Set(Napi::String::New(env, "init"), Napi::Function::New(env, MediaInit)); exports.Set(Napi::String::New(env, "trim"), Napi::Function::New(env, Trim)); Napi::Array arr = Napi::Array::New(env); size_t i = 0; - for (auto const &imap : FunctionMap) { + for (auto const &imap : esmb::FunctionMap) { Napi::HandleScope scope(env); arr[i] = Napi::String::New(env, imap.first); i++; } - for (auto const &imap : NoInputFunctionMap) { + for (auto const &imap : esmb::NoInputFunctionMap) { Napi::HandleScope scope(env); arr[i] = Napi::String::New(env, imap.first); i++; diff --git a/natives/node/worker.cc b/natives/node/worker.cc index b32aa38b..c35a6970 100644 --- a/natives/node/worker.cc +++ b/natives/node/worker.cc @@ -3,7 +3,7 @@ using namespace std; -ImageAsyncWorker::ImageAsyncWorker(Napi::Env &env, Promise::Deferred deferred, string command, ArgumentMap inArgs, +ImageAsyncWorker::ImageAsyncWorker(Napi::Env &env, Promise::Deferred deferred, string command, esmb::ArgumentMap inArgs, string type, const char *bufData, size_t bufSize) : AsyncWorker(env), deferred(deferred), command(command), inArgs(inArgs), type(type), bufData(bufData), bufSize(bufSize) {} @@ -13,9 +13,9 @@ void ImageAsyncWorker::Execute() { shouldKill = false; if (bufSize != 0) { - outArgs = FunctionMap.at(command)(type, outType, bufData, bufSize, inArgs, &shouldKill); + outData = esmb::FunctionMap.at(command)(type, outType, bufData, bufSize, inArgs, &shouldKill); } else { - outArgs = NoInputFunctionMap.at(command)(type, outType, inArgs, &shouldKill); + outData = esmb::NoInputFunctionMap.at(command)(type, outType, inArgs, &shouldKill); } } @@ -32,12 +32,8 @@ void ImageAsyncWorker::OnError(const Error &e) { void ImageAsyncWorker::OnOK() { vips_error_clear(); vips_thread_shutdown(); - Buffer nodeBuf = Buffer::New(Env(), 0); - size_t outSize = GetArgumentWithFallback(outArgs, "size", 0); - if (outSize > 0) { - char *buf = GetArgument(outArgs, "buf"); - nodeBuf = Buffer::New(Env(), buf, outSize, []([[maybe_unused]] Napi::Env env, char *data) { g_free(data); }); - } + Buffer nodeBuf = Buffer::New(Env(), outData.buf, outData.length, + []([[maybe_unused]] Napi::Env env, char *data) { free(data); }); Napi::Object returned = Napi::Object::New(Env()); returned.Set("data", nodeBuf); diff --git a/natives/node/worker.h b/natives/node/worker.h index 04a0f8d4..06ecbaf9 100644 --- a/natives/node/worker.h +++ b/natives/node/worker.h @@ -1,13 +1,14 @@ #pragma once -#include "../common.h" +#include "../common/maps.h" #include +#include using namespace Napi; class ImageAsyncWorker : public AsyncWorker { public: - ImageAsyncWorker(Napi::Env &env, Promise::Deferred deferred, string command, ArgumentMap inArgs, string type, - const char *bufData, size_t bufSize); + ImageAsyncWorker(Napi::Env &env, Promise::Deferred deferred, std::string command, esmb::ArgumentMap inArgs, + std::string type, const char *bufData, size_t bufSize); virtual ~ImageAsyncWorker() {}; void Execute(); @@ -19,15 +20,15 @@ public: private: Promise::Deferred deferred; - string command; - ArgumentMap inArgs; - string type; + std::string command; + esmb::ArgumentMap inArgs; + std::string type; const char *bufData; size_t bufSize; - ArgumentMap outArgs; - string outType; + CmdOutput outData; + std::string outType; bool shouldKill; }; diff --git a/natives/qr.cc b/natives/qr.cc index 0fede497..02e354eb 100644 --- a/natives/qr.cc +++ b/natives/qr.cc @@ -10,8 +10,12 @@ #include "common.h" -ArgumentMap QrCreate([[maybe_unused]] const string &type, string &outType, ArgumentMap arguments, - [[maybe_unused]] bool *shouldKill) { +FunctionArgs QrCreateArgs = { + {"text", {typeid(string), true}} +}; + +CmdOutput QrCreate([[maybe_unused]] const string &type, string &outType, esmb::ArgumentMap arguments, + [[maybe_unused]] bool *shouldKill) { string text = GetArgument(arguments, "text"); auto writer = @@ -32,15 +36,11 @@ ArgumentMap QrCreate([[maybe_unused]] const string &type, string &outType, Argum size_t dataSize = 0; img.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } -ArgumentMap QrRead([[maybe_unused]] const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, [[maybe_unused]] bool *shouldKill) { +CmdOutput QrRead([[maybe_unused]] const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, [[maybe_unused]] bool *shouldKill) { vips::VOption *options = vips::VImage::option()->set("access", "sequential"); vips::VImage in = vips::VImage::new_from_buffer(bufferdata, bufferLength, "", options) @@ -64,12 +64,9 @@ ArgumentMap QrRead([[maybe_unused]] const string &type, string &outType, const c ZXing::ImageView img(VIPS_IMAGE_ADDR(in.get_image(), 0, 0), in.width(), in.height(), ZXing::ImageFormat::Lum); ZXing::Result result = ZXing::ReadBarcode(img, opts); - ArgumentMap output; - if (!result.isValid()) { - output["buf"] = ""; outType = "empty"; - return output; + return {nullptr, 0}; } #if ZXING_VERSION_MAJOR >= 2 @@ -82,9 +79,7 @@ ArgumentMap QrRead([[maybe_unused]] const string &type, string &outType, const c char *data = reinterpret_cast(malloc(dataSize)); memcpy(data, resultText.c_str(), dataSize); - output["buf"] = data; - output["size"] = dataSize; outType = "text"; - return output; + return {data, dataSize}; } -#endif \ No newline at end of file +#endif diff --git a/natives/reddit.cc b/natives/reddit.cc index 947abdf6..69b2b79b 100644 --- a/natives/reddit.cc +++ b/natives/reddit.cc @@ -5,8 +5,13 @@ using namespace std; using namespace vips; -ArgumentMap Reddit(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs RedditArgs = { + {"caption", {typeid(string), true}}, + {"basePath", {typeid(string), true}} +}; + +CmdOutput Reddit(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string text = GetArgument(arguments, "caption"); string basePath = GetArgument(arguments, "basePath"); @@ -52,9 +57,5 @@ ArgumentMap Reddit(const string &type, string &outType, const char *bufferdata, final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/resize.cc b/natives/resize.cc index 28de1d4d..8c1659fd 100644 --- a/natives/resize.cc +++ b/natives/resize.cc @@ -5,8 +5,14 @@ using namespace std; using namespace vips; -ArgumentMap Resize(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs ResizeArgs = { + {"stretch", {typeid(bool), false}}, + {"wide", {typeid(bool), false}}, + {"amount", {typeid(int), false} } +}; + +CmdOutput Resize(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { bool stretch = GetArgumentWithFallback(arguments, "stretch", false); bool wide = GetArgumentWithFallback(arguments, "wide", false); int wideAmount = GetArgumentWithFallback(arguments, "amount", 19); @@ -23,10 +29,8 @@ ArgumentMap Resize(const string &type, string &outType, const char *bufferdata, in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -56,9 +60,5 @@ ArgumentMap Resize(const string &type, string &outType, const char *bufferdata, size_t dataSize = 0; out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/reverse.cc b/natives/reverse.cc index 85cf47a5..cddefd56 100644 --- a/natives/reverse.cc +++ b/natives/reverse.cc @@ -5,8 +5,12 @@ using namespace std; using namespace vips; -ArgumentMap Reverse([[maybe_unused]] const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs ReverseArgs = { + {"soos", {typeid(bool), false}} +}; + +CmdOutput Reverse([[maybe_unused]] const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { bool soos = GetArgumentWithFallback(arguments, "soos", false); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, false, false)); @@ -19,10 +23,8 @@ ArgumentMap Reverse([[maybe_unused]] const string &type, string &outType, const in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -32,11 +34,7 @@ ArgumentMap Reverse([[maybe_unused]] const string &type, string &outType, const char *data = reinterpret_cast(malloc(bufferLength)); memcpy(data, bufferdata, bufferLength); - ArgumentMap output; - output["buf"] = data; - output["size"] = dataSize; - - return output; + return {data, dataSize}; } vector out; @@ -76,9 +74,5 @@ ArgumentMap Reverse([[maybe_unused]] const string &type, string &outType, const final.write_to_buffer(outType == "webp" ? ".webp" : ".gif", reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/scott.cc b/natives/scott.cc index bf13c33d..ef86329c 100644 --- a/natives/scott.cc +++ b/natives/scott.cc @@ -5,8 +5,12 @@ using namespace std; using namespace vips; -ArgumentMap Scott(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs ScottArgs = { + {"basePath", {typeid(string), true}} +}; + +CmdOutput Scott(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string basePath = GetArgument(arguments, "basePath"); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, false)) @@ -21,10 +25,8 @@ ArgumentMap Scott(const string &type, string &outType, const char *bufferdata, s in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -55,9 +57,5 @@ ArgumentMap Scott(const string &type, string &outType, const char *bufferdata, s final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/slide.cc b/natives/slide.cc index 1589f8a9..89fd828e 100644 --- a/natives/slide.cc +++ b/natives/slide.cc @@ -5,10 +5,15 @@ using namespace std; using namespace vips; -ArgumentMap Slide(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { - bool vertical = GetArgument(arguments, "vertical"); - bool reverse = GetArgument(arguments, "reverse"); +FunctionArgs SlideArgs = { + {"vertical", {typeid(bool), false}}, + {"reverse", {typeid(bool), false}}, +}; + +CmdOutput Slide(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { + bool vertical = GetArgumentWithFallback(arguments, "vertical", false); + bool reverse = GetArgumentWithFallback(arguments, "reverse", false); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, true)) .colourspace(VIPS_INTERPRETATION_sRGB); @@ -22,10 +27,8 @@ ArgumentMap Slide(const string &type, string &outType, const char *bufferdata, s in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -59,9 +62,5 @@ ArgumentMap Slide(const string &type, string &outType, const char *bufferdata, s if (outType != "webp") outType = "gif"; - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; -} \ No newline at end of file + return {buf, dataSize}; +} diff --git a/natives/snapchat.cc b/natives/snapchat.cc index 73125a82..cf636433 100644 --- a/natives/snapchat.cc +++ b/natives/snapchat.cc @@ -5,10 +5,16 @@ using namespace std; using namespace vips; +FunctionArgs SnapchatArgs = { + {"caption", {typeid(string), true}}, + {"pos", {typeid(float), false}}, + {"basePath", {typeid(string), true}} +}; + const vector zeroVec178 = {0, 0, 0, 178}; -ArgumentMap Snapchat(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +CmdOutput Snapchat(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string caption = GetArgument(arguments, "caption"); float pos = GetArgumentWithFallback(arguments, "pos", 0.565); string basePath = GetArgument(arguments, "basePath"); @@ -52,9 +58,5 @@ ArgumentMap Snapchat(const string &type, string &outType, const char *bufferdata final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/sonic.cc b/natives/sonic.cc index d24bcca1..2ac9fb83 100644 --- a/natives/sonic.cc +++ b/natives/sonic.cc @@ -5,7 +5,12 @@ using namespace std; using namespace vips; -ArgumentMap Sonic([[maybe_unused]] const string &type, string &outType, ArgumentMap arguments, bool *shouldKill) { +FunctionArgs SonicArgs = { + {"text", {typeid(string), true}}, + {"basePath", {typeid(string), true}} +}; + +CmdOutput Sonic([[maybe_unused]] const string &type, string &outType, esmb::ArgumentMap arguments, bool *shouldKill) { string text = GetArgument(arguments, "text"); string basePath = GetArgument(arguments, "basePath"); @@ -30,9 +35,5 @@ ArgumentMap Sonic([[maybe_unused]] const string &type, string &outType, Argument size_t dataSize = 0; out.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/speed.cc b/natives/speed.cc index b29977c7..6438f366 100644 --- a/natives/speed.cc +++ b/natives/speed.cc @@ -1,5 +1,4 @@ #include -#include #include #include "common.h" @@ -7,6 +6,11 @@ using namespace std; using namespace vips; +FunctionArgs SpeedArgs = { + {"slow", {typeid(bool), false}}, + {"speed", {typeid(int), false} } +}; + void *memset16(void *m, uint16_t val, size_t count) { uint16_t *buf = (uint16_t *)m; @@ -39,12 +43,11 @@ char *vipsRemove(const char *data, size_t length, size_t &dataSize, int speed, s return buf; } -ArgumentMap Speed([[maybe_unused]] const string &type, [[maybe_unused]] string &outType, const char *bufferdata, - size_t bufferLength, ArgumentMap arguments, bool *shouldKill) { +CmdOutput Speed([[maybe_unused]] const string &type, [[maybe_unused]] string &outType, const char *bufferdata, + size_t bufferLength, esmb::ArgumentMap arguments, bool *shouldKill) { bool slow = GetArgumentWithFallback(arguments, "slow", false); int speed = GetArgumentWithFallback(arguments, "speed", 2); - ArgumentMap output; size_t dataSize = 0; char *fileData = reinterpret_cast(malloc(bufferLength)); @@ -127,8 +130,5 @@ ArgumentMap Speed([[maybe_unused]] const string &type, [[maybe_unused]] string & dataSize = bufferLength; } - output["buf"] = fileData; - output["size"] = dataSize; - - return output; + return {fileData, dataSize}; } diff --git a/natives/spin.cc b/natives/spin.cc index 9a4efb39..b1e935e6 100644 --- a/natives/spin.cc +++ b/natives/spin.cc @@ -5,8 +5,8 @@ using namespace std; using namespace vips; -ArgumentMap Spin(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Spin(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, true)); int width = in.width(); @@ -18,10 +18,8 @@ ArgumentMap Spin(const string &type, string &outType, const char *bufferdata, si in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -54,9 +52,5 @@ ArgumentMap Spin(const string &type, string &outType, const char *bufferdata, si if (outType != "webp") outType = "gif"; - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/spotify.cc b/natives/spotify.cc index 81b52a1d..09b174c1 100644 --- a/natives/spotify.cc +++ b/natives/spotify.cc @@ -5,8 +5,13 @@ using namespace std; using namespace vips; -ArgumentMap Spotify(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs SpotifyArgs = { + {"caption", {typeid(string), true}}, + {"basePath", {typeid(string), true}} +}; + +CmdOutput Spotify(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string text = GetArgument(arguments, "caption"); string basePath = GetArgument(arguments, "basePath"); @@ -52,9 +57,5 @@ ArgumentMap Spotify(const string &type, string &outType, const char *bufferdata, final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/squish.cc b/natives/squish.cc index 91d9fd8c..9b4ef8a8 100644 --- a/natives/squish.cc +++ b/natives/squish.cc @@ -7,8 +7,8 @@ using namespace std; using namespace vips; -ArgumentMap Squish(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Squish(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, true)); int width = in.width(); @@ -20,10 +20,8 @@ ArgumentMap Squish(const string &type, string &outType, const char *bufferdata, in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -58,9 +56,5 @@ ArgumentMap Squish(const string &type, string &outType, const char *bufferdata, if (outType != "webp") outType = "gif"; - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/swirl.cc b/natives/swirl.cc index 689a6ada..f02f3ab3 100644 --- a/natives/swirl.cc +++ b/natives/swirl.cc @@ -5,8 +5,8 @@ using namespace std; using namespace vips; -ArgumentMap Swirl(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Swirl(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, false, false)); int pageHeight = vips_image_get_page_height(in.get_image()); @@ -56,9 +56,5 @@ ArgumentMap Swirl(const string &type, string &outType, const char *bufferdata, s size_t dataSize = 0; final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/tile.cc b/natives/tile.cc index 94a5dcf0..7cda8409 100644 --- a/natives/tile.cc +++ b/natives/tile.cc @@ -5,8 +5,8 @@ using namespace std; using namespace vips; -ArgumentMap Tile(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Tile(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, false, false)); int width = in.width(); @@ -17,10 +17,8 @@ ArgumentMap Tile(const string &type, string &outType, const char *bufferdata, si in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -45,9 +43,5 @@ ArgumentMap Tile(const string &type, string &outType, const char *bufferdata, si final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/togif.cc b/natives/togif.cc index 1e37e591..cb6d9a19 100644 --- a/natives/togif.cc +++ b/natives/togif.cc @@ -5,18 +5,13 @@ using namespace std; using namespace vips; -ArgumentMap ToGif(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput ToGif(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { if (type == "gif") { char *data = reinterpret_cast(malloc(bufferLength)); memcpy(data, bufferdata, bufferLength); - ArgumentMap output; - output["buf"] = data; - output["size"] = bufferLength; - - return output; - + return {data, bufferLength}; } else { VOption *options = VImage::option()->set("access", "sequential"); @@ -29,10 +24,6 @@ ArgumentMap ToGif(const string &type, string &outType, const char *bufferdata, s in.write_to_buffer(".gif", reinterpret_cast(&buf), &dataSize); outType = "gif"; - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } } diff --git a/natives/uncanny.cc b/natives/uncanny.cc index 97114dbc..fc4dc525 100644 --- a/natives/uncanny.cc +++ b/natives/uncanny.cc @@ -5,11 +5,19 @@ using namespace std; using namespace vips; -ArgumentMap Uncanny(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs UncannyArgs = { + {"caption", {typeid(string), true} }, + {"caption2", {typeid(string), true} }, + {"font", {typeid(string), false}}, + {"path", {typeid(string), true} }, + {"basePath", {typeid(string), true} } +}; + +CmdOutput Uncanny(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string caption = GetArgument(arguments, "caption"); string caption2 = GetArgument(arguments, "caption2"); - string font = GetArgument(arguments, "font"); + string font = GetArgumentWithFallback(arguments, "font", "helvetica"); string path = GetArgument(arguments, "path"); string basePath = GetArgument(arguments, "basePath"); @@ -88,9 +96,5 @@ ArgumentMap Uncanny(const string &type, string &outType, const char *bufferdata, final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/uncaption.cc b/natives/uncaption.cc index ed1d63cd..44904ded 100644 --- a/natives/uncaption.cc +++ b/natives/uncaption.cc @@ -1,4 +1,3 @@ -#include #include #include "common.h" @@ -6,8 +5,12 @@ using namespace std; using namespace vips; -ArgumentMap Uncaption(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs UncaptionArgs = { + {"tolerance", {typeid(float), false}}, +}; + +CmdOutput Uncaption(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { float tolerance = GetArgumentWithFallback(arguments, "tolerance", 0.5); VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, true, true)); @@ -40,9 +43,5 @@ ArgumentMap Uncaption(const string &type, string &outType, const char *bufferdat final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/wall.cc b/natives/wall.cc index f82f3c0d..55706b41 100644 --- a/natives/wall.cc +++ b/natives/wall.cc @@ -5,8 +5,8 @@ using namespace std; using namespace vips; -ArgumentMap Wall(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - [[maybe_unused]] ArgumentMap arguments, bool *shouldKill) { +CmdOutput Wall(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + [[maybe_unused]] esmb::ArgumentMap arguments, bool *shouldKill) { VImage in = VImage::new_from_buffer(bufferdata, bufferLength, "", GetInputOptions(type, false, false)); if (!in.has_alpha()) in = in.bandjoin(255); @@ -18,10 +18,8 @@ ArgumentMap Wall(const string &type, string &outType, const char *bufferdata, si in = NormalizeVips(in, &width, &pageHeight, nPages); } catch (int e) { if (e == -1) { - ArgumentMap output; - output["buf"] = ""; outType = "frames"; - return output; + return {nullptr, 0}; } } @@ -64,9 +62,5 @@ ArgumentMap Wall(const string &type, string &outType, const char *bufferdata, si size_t dataSize = 0; final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/watermark.cc b/natives/watermark.cc index fd806c9b..11ea105e 100644 --- a/natives/watermark.cc +++ b/natives/watermark.cc @@ -1,4 +1,3 @@ -#include #include #include "common.h" @@ -6,8 +5,21 @@ using namespace std; using namespace vips; -ArgumentMap Watermark(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs WatermarkArgs = { + {"water", {typeid(string), true}}, + {"gravity", {typeid(int), true} }, + {"resize", {typeid(bool), false} }, + {"yscale", {typeid(float), false}}, + {"append", {typeid(bool), false} }, + {"alpha", {typeid(bool), false} }, + {"flipX", {typeid(bool), false} }, + {"flipY", {typeid(bool), false} }, + {"mc", {typeid(bool), false} }, + {"basePath", {typeid(string), true}} +}; + +CmdOutput Watermark(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string water = GetArgument(arguments, "water"); int gravity = GetArgument(arguments, "gravity"); @@ -20,7 +32,7 @@ ArgumentMap Watermark(const string &type, string &outType, const char *bufferdat bool flipX = GetArgumentWithFallback(arguments, "flipX", false); bool flipY = GetArgumentWithFallback(arguments, "flipY", false); - bool mc = MapContainsKey(arguments, "mc"); + bool mc = GetArgumentWithFallback(arguments, "mc", false); string basePath = GetArgument(arguments, "basePath"); @@ -143,9 +155,5 @@ ArgumentMap Watermark(const string &type, string &outType, const char *bufferdat final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/natives/whisper.cc b/natives/whisper.cc index 2d547e3d..59b74732 100644 --- a/natives/whisper.cc +++ b/natives/whisper.cc @@ -5,8 +5,13 @@ using namespace std; using namespace vips; -ArgumentMap Whisper(const string &type, string &outType, const char *bufferdata, size_t bufferLength, - ArgumentMap arguments, bool *shouldKill) { +FunctionArgs WhisperArgs = { + {"caption", {typeid(string), true}}, + {"basePath", {typeid(string), true}} +}; + +CmdOutput Whisper(const string &type, string &outType, const char *bufferdata, size_t bufferLength, + esmb::ArgumentMap arguments, bool *shouldKill) { string caption = GetArgument(arguments, "caption"); string basePath = GetArgument(arguments, "basePath"); @@ -52,9 +57,5 @@ ArgumentMap Whisper(const string &type, string &outType, const char *bufferdata, final.write_to_buffer(("." + outType).c_str(), reinterpret_cast(&buf), &dataSize, outType == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); - ArgumentMap output; - output["buf"] = buf; - output["size"] = dataSize; - - return output; + return {buf, dataSize}; } diff --git a/src/api/index.ts b/src/api/index.ts index 7931164a..dfe65456 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -6,12 +6,12 @@ import process from "node:process"; import { DiscordHTTPError, DiscordRESTError, type RawMessage } from "oceanic.js"; import type WSocket from "ws"; import { WebSocketServer, type ErrorEvent } from "ws"; -import run from "#utils/image-runner.js"; -import { img } from "#utils/imageLib.js"; import logger from "#utils/logger.js"; -import type { ImageParams } from "#utils/types.js"; +import { media } from "#utils/mediaLib.js"; +import run from "#utils/mediaRunner.js"; +import type { MediaParams } from "#utils/types.js"; -const formats = Object.keys(img.imageInit()); +const formats = Object.keys(media.init()); const cacheTimeout = 15 * 60 * 1000; // jobs are deleted 15 minutes after completion if not fetched @@ -40,7 +40,7 @@ interface VerifyEvents { interface Job { num: number; - msg: ImageParams; + msg: MediaParams; verifyEvent: EventEmitter; tag?: Buffer; error?: string; @@ -50,7 +50,7 @@ interface Job { interface MiniJob { id: bigint; - msg: ImageParams; + msg: MediaParams; num: number; } @@ -123,7 +123,7 @@ async function acceptJob(id: bigint, sock: WSocket): Promise { // we wait until all* jobs are finished before trimming to avoid potential issues. // See the comment in natives/node/image.cc for more info if (jobs.size <= 1) { - img.trim(); + media.trim(); } } @@ -142,7 +142,7 @@ wss.on("connection", (ws, request) => { const cur = Buffer.alloc(2); cur.writeUInt16LE(jobs.size); const cmdFormats: { [cmd: string]: string[] } = {}; - for (const cmd of img.funcs) { + for (const cmd of media.funcs) { cmdFormats[cmd] = formats; } const init = Buffer.concat([ @@ -349,7 +349,7 @@ const fileSize = 10485760; async function finishJob( data: { buffer: Buffer; fileExtension: string }, job: MiniJob, - object: ImageParams, + object: MediaParams, ws: WSocket, ) { log(`Sending result of job ${job.id}`, job.num); diff --git a/src/classes/imageCommand.ts b/src/classes/imageCommand.ts index 56f1fd70..4e832197 100644 --- a/src/classes/imageCommand.ts +++ b/src/classes/imageCommand.ts @@ -12,9 +12,9 @@ import messages from "#config/messages.json" with { type: "json" }; import { runningCommands, selectedImages } from "#utils/collections.js"; import { getAllLocalizations } from "#utils/i18n.js"; import { runImageJob } from "#utils/image.js"; -import imageDetect, { type ImageMeta } from "#utils/imagedetect.js"; +import imageDetect, { type ImageMeta } from "#utils/mediadetect.js"; import { clean, isEmpty, random } from "#utils/misc.js"; -import type { ImageParams } from "#utils/types.js"; +import type { MediaParams } from "#utils/types.js"; import Command from "./command.ts"; class ImageCommand extends Command { @@ -50,7 +50,7 @@ class ImageCommand extends Command { const staticProps = this.constructor as typeof ImageCommand; - let imageParams: ImageParams; + let imageParams: MediaParams; let needsSpoiler = false; if (staticProps.requiresImage) { diff --git a/src/utils/collections.ts b/src/utils/collections.ts index 664c08bf..338f728d 100644 --- a/src/utils/collections.ts +++ b/src/utils/collections.ts @@ -1,5 +1,5 @@ import type InteractionCollector from "../pagination/awaitinteractions.ts"; -import type { ImageMeta } from "./imagedetect.ts"; +import type { ImageMeta } from "./mediadetect.ts"; import type { CommandEntry, CommandInfo } from "./types.ts"; export const commands = new Map(); diff --git a/src/utils/image.ts b/src/utils/image.ts index 24c8c69b..8a3aa3d8 100644 --- a/src/utils/image.ts +++ b/src/utils/image.ts @@ -6,13 +6,13 @@ import process from "node:process"; import { fileTypeFromStream } from "file-type"; import ipaddr from "ipaddr.js"; import serversConfig from "#config/servers.json" with { type: "json" }; -import ImageConnection from "./imageConnection.ts"; import logger from "./logger.ts"; +import ImageConnection from "./mediaConnection.ts"; import { random } from "./misc.ts"; -import type { ImageParams, ImageTypeData } from "./types.ts"; +import type { MediaParams, MediaTypeData } from "./types.ts"; -const run = process.env.API_TYPE === "ws" ? null : (await import("../utils/image-runner.ts")).default; -let img: import("./imageLib.ts").ImageLib | undefined; +const run = process.env.API_TYPE === "ws" ? null : (await import("./mediaRunner.ts")).default; +let img: import("./mediaLib.ts").MediaLib | undefined; interface ServerConfig { name: string; @@ -37,13 +37,13 @@ export let servers: ServerConfig[] = process.env.API_TYPE === "ws" ? serversConf export function initImageLib() { const nodeRequire = createRequire(import.meta.url); const imgLib = nodeRequire( - `../../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`, + `../../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/esmbmedia.node`, ); - imgLib.imageInit(); + imgLib.init(); img = imgLib; } -export async function getType(image: URL, extraReturnTypes: boolean): Promise { +export async function getType(image: URL, extraReturnTypes: boolean): Promise { try { const remoteIP = await lookup(image.host); const parsedIP = ipaddr.parse(remoteIP.address); @@ -144,7 +144,7 @@ export async function reloadImageConnections() { return amount; } -async function getIdeal(object: ImageParams): Promise { +async function getIdeal(object: MediaParams): Promise { const idealServers = []; for (const connection of connections.values()) { if (connection.conn.readyState !== 0 && connection.conn.readyState !== 1) { @@ -163,7 +163,7 @@ async function getIdeal(object: ImageParams): Promise { +export async function runImageJob(params: MediaParams): Promise<{ buffer: Buffer; type: string }> { if (process.env.API_TYPE === "ws") { const currentServer = await getIdeal(params); if (!currentServer) diff --git a/src/utils/imageConnection.ts b/src/utils/mediaConnection.ts similarity index 94% rename from src/utils/imageConnection.ts rename to src/utils/mediaConnection.ts index f3917ef9..50246b4b 100644 --- a/src/utils/imageConnection.ts +++ b/src/utils/mediaConnection.ts @@ -23,7 +23,7 @@ interface RequestState { type WaitResponse = { sent: true; data: Buffer } | { sent: false }; -class ImageConnection { +class MediaConnection { requests: Map; host: string; auth?: string; @@ -73,7 +73,7 @@ class ImageConnection { onMessage(msg: Data) { if (!(msg instanceof Buffer)) return; const op = msg.readUint8(0); - logger.debug(`Received message from image server ${this.host} with opcode ${op}`); + logger.debug(`Received message from media server ${this.host} with opcode ${op}`); if (op === Rinit) { this.formats = JSON.parse(msg.toString("utf8", 7)); this.funcs = Object.keys(this.formats); @@ -139,7 +139,7 @@ class ImageConnection { } queue(jobid: bigint, jobobj: object): Promise { - logger.debug(`Queuing ${jobid} on image server ${this.host}`); + logger.debug(`Queuing ${jobid} on media server ${this.host}`); const str = JSON.stringify(jobobj); const buf = Buffer.alloc(8); buf.writeBigUint64LE(jobid); @@ -147,21 +147,21 @@ class ImageConnection { } wait(jobid: bigint): Promise { - logger.debug(`Waiting for ${jobid} on image server ${this.host}`); + logger.debug(`Waiting for ${jobid} on media server ${this.host}`); const buf = Buffer.alloc(8); buf.writeBigUint64LE(jobid); return this.do(Twait, jobid, buf); } cancel(jobid: bigint): Promise { - logger.debug(`Cancelling ${jobid} on image server ${this.host}`); + logger.debug(`Cancelling ${jobid} on media server ${this.host}`); const buf = Buffer.alloc(8); buf.writeBigUint64LE(jobid); return this.do(Tcancel, jobid, buf); } async getOutput(jobid: string) { - logger.debug(`Getting output of ${jobid} on image server ${this.host}`); + logger.debug(`Getting output of ${jobid} on media server ${this.host}`); const req = await fetch( `${this.httpurl}/image?id=${jobid}`, this.auth @@ -227,4 +227,4 @@ class ImageConnection { } } -export default ImageConnection; +export default MediaConnection; diff --git a/src/utils/imageLib.ts b/src/utils/mediaLib.ts similarity index 53% rename from src/utils/imageLib.ts rename to src/utils/mediaLib.ts index 3cce8b65..f0528fce 100644 --- a/src/utils/imageLib.ts +++ b/src/utils/mediaLib.ts @@ -1,21 +1,21 @@ import { Buffer } from "node:buffer"; import { createRequire } from "node:module"; import process from "node:process"; -import type { ImageParams } from "./types.ts"; +import type { MediaParams } from "./types.ts"; -export interface ImageLib { +export interface MediaLib { funcs: string[]; - image( + media( cmd: string, - params: ImageParams["params"], - input: ImageParams["input"], + params: MediaParams["params"], + input: MediaParams["input"], ): Promise<{ data: Buffer; type: string }>; - imageInit(): Record; + init(): Record; trim(): number; } const nodeRequire = createRequire(import.meta.url); -const relPath = `../../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`; +const relPath = `../../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/esmbmedia.node`; -export const img = nodeRequire(relPath) as ImageLib; +export const media = nodeRequire(relPath) as MediaLib; diff --git a/src/utils/image-runner.ts b/src/utils/mediaRunner.ts similarity index 76% rename from src/utils/image-runner.ts rename to src/utils/mediaRunner.ts index 3c46814c..2bdf26e0 100644 --- a/src/utils/image-runner.ts +++ b/src/utils/mediaRunner.ts @@ -1,12 +1,12 @@ import { Buffer } from "node:buffer"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import { img } from "./imageLib.ts"; -import type { ImageParams } from "./types.ts"; +import { media } from "./mediaLib.ts"; +import type { MediaParams } from "./types.ts"; -export default async function run(object: ImageParams): Promise<{ buffer: Buffer; fileExtension: string }> { +export default async function run(object: MediaParams): Promise<{ buffer: Buffer; fileExtension: string }> { // Check if command exists - if (!img.funcs.includes(object.cmd)) { + if (!media.funcs.includes(object.cmd)) { return { buffer: Buffer.alloc(0), fileExtension: "nocmd", @@ -15,7 +15,7 @@ export default async function run(object: ImageParams): Promise<{ buffer: Buffer let inputBuffer: ArrayBuffer | null = null; if (object.path) { - // If the image has a path, it must also have a type + // If the file has a path, it must also have a type if (object.input?.type !== "image/gif" && object.input?.type !== "image/webp" && object.onlyAnim) { return { buffer: Buffer.alloc(0), @@ -43,9 +43,9 @@ export default async function run(object: ImageParams): Promise<{ buffer: Buffer } } - // Convert from a MIME type (e.g. "image/png") to something the image processor understands (e.g. "png"). + // Convert from a MIME type (e.g. "image/png") to something the media processor understands (e.g. "png"). // Don't set `type` directly on the object we are passed as it will be read afterwards. - // If no image type is given (say, the command generates its own image), make it a PNG. + // If no type is given (say, the command generates its own output), make it a PNG. const fileExtension = object.input?.type?.split("/")[1] ?? "png"; if (object.input) { @@ -53,7 +53,7 @@ export default async function run(object: ImageParams): Promise<{ buffer: Buffer object.input.type = fileExtension; } object.params.basePath = path.join(path.dirname(fileURLToPath(import.meta.url)), "../../"); - const { data, type } = await img.image(object.cmd, object.params, object.input ?? {}); + const { data, type } = await media.media(object.cmd, object.params, object.input ?? {}); return { buffer: data, fileExtension: type, diff --git a/src/utils/imagedetect.ts b/src/utils/mediadetect.ts similarity index 99% rename from src/utils/imagedetect.ts rename to src/utils/mediadetect.ts index 52d6ff88..be11cb40 100644 --- a/src/utils/imagedetect.ts +++ b/src/utils/mediadetect.ts @@ -13,7 +13,7 @@ import { } from "oceanic.js"; import { getType } from "./image.ts"; import logger from "./logger.ts"; -import type { ImageTypeData } from "./types.ts"; +import type { MediaTypeData } from "./types.ts"; const tenorURLs = ["tenor.com", "www.tenor.com"]; const giphyURLs = ["giphy.com", "www.giphy.com", "i.giphy.com"]; @@ -137,7 +137,7 @@ async function getImage( payload.type = "image/webp"; } } else { - let result: ImageTypeData | undefined; + let result: MediaTypeData | undefined; if ( (imageURL.host === "cdn.discordapp.com" || imageURL.host === "media.discordapp.net") && imageURL.pathname.match(/^\/(?:ephemeral-)?attachments\/\d+\/\d+\//) diff --git a/src/utils/types.ts b/src/utils/types.ts index 1c24eaff..efe9f8da 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -61,7 +61,7 @@ export interface CommandInfo { type: Constants.ApplicationCommandTypes; } -export interface ImageParams { +export interface MediaParams { cmd: string; params: { [key: string]: string | number | boolean; @@ -80,7 +80,7 @@ export interface ImageParams { token?: string; } -export interface ImageTypeData { +export interface MediaTypeData { url?: string; type?: string; }