From 7ee571dd2bf4be2d9bd000a82ac8903db71fd03b Mon Sep 17 00:00:00 2001 From: Essem Date: Sun, 27 Nov 2022 14:52:40 -0600 Subject: [PATCH] Some fixes and whatnot --- api/index.js | 4 +- natives/blur.cc | 40 +++---- natives/blur.h | 9 +- natives/caption.cc | 109 ++++++++++-------- natives/caption.h | 8 +- natives/caption2.cc | 130 ++++++++++----------- natives/caption2.h | 8 +- natives/circle.cc | 75 ++++++------ natives/circle.h | 9 +- natives/colors.cc | 41 +++---- natives/colors.h | 5 +- natives/common.h | 4 +- natives/crop.cc | 71 ++++++------ natives/crop.h | 5 +- natives/deepfry.cc | 87 +++++++------- natives/deepfry.h | 5 +- natives/explode.cc | 75 ++++++------ natives/explode.h | 7 +- natives/flag.cc | 89 ++++++++------- natives/flag.h | 5 +- natives/flip.cc | 70 ++++++------ natives/flip.h | 5 +- natives/freeze.cc | 9 +- natives/gamexplain.cc | 6 +- natives/globe.cc | 3 +- natives/image.cc | 57 ++++++++-- natives/uncaption.cc | 77 ++++++------- natives/uncaption.h | 8 +- natives/watermark.cc | 257 +++++++++++++++++++++--------------------- natives/watermark.h | 10 +- 30 files changed, 699 insertions(+), 589 deletions(-) diff --git a/api/index.js b/api/index.js index 867f4cd..7103031 100644 --- a/api/index.js +++ b/api/index.js @@ -11,7 +11,7 @@ import { createRequire } from "module"; import EventEmitter from "events"; const nodeRequire = createRequire(import.meta.url); -const magick = nodeRequire(`../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`); +const img = nodeRequire(`../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`); const Rerror = 0x01; const Tqueue = 0x02; @@ -92,7 +92,7 @@ wss.on("connection", (ws, request) => { const cur = Buffer.alloc(2); cur.writeUInt16LE(jobAmount); const formats = {}; - for (const cmd of Object.keys(magick)) { + for (const cmd of img.funcs) { formats[cmd] = ["image/png", "image/gif", "image/jpeg", "image/webp"]; } const init = Buffer.concat([Buffer.from([Rinit]), Buffer.from([0x00, 0x00]), num, cur, Buffer.from(JSON.stringify(formats))]); diff --git a/natives/blur.cc b/natives/blur.cc index 1cef83b..5ca0fd0 100644 --- a/natives/blur.cc +++ b/natives/blur.cc @@ -1,35 +1,35 @@ #include "common.h" -#include -#include #include +#include +#include using namespace std; using namespace vips; -char* Blur(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { - string caption = Arguments["caption"]; - string font = MAP_GET(Arguments, "font"); - bool sharp = MAP_GET(Arguments, "sharp") == "true"; - VOption *options = VImage::option()->set("access", "sequential"); +char *Blur(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { + bool sharp = MAP_GET(Arguments, "sharp", bool); + VOption *options = VImage::option()->set("access", "sequential"); - VImage in = + VImage in = VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); + type == "gif" ? options->set("n", -1) : options) + .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) in = in.bandjoin(255); + if (!in.has_alpha()) + in = in.bandjoin(255); - // TODO: find a better way to calculate the intensity for GIFs without - // splitting frames - VImage out = sharp ? in.sharpen(VImage::option()->set("sigma", 3)) - : in.gaussblur(15); + // TODO: find a better way to calculate the intensity for GIFs without + // splitting frames + VImage out = + sharp ? in.sharpen(VImage::option()->set("sigma", 3)) : in.gaussblur(15); - void *buf; - out.write_to_buffer(("." + type).c_str(), &buf, DataSize); + void *buf; + out.write_to_buffer(("." + type).c_str(), &buf, DataSize); - vips_error_clear(); - vips_thread_shutdown(); + vips_error_clear(); + vips_thread_shutdown(); - return (char*) buf; + return (char *)buf; } diff --git a/natives/blur.h b/natives/blur.h index 447ef20..82d611b 100644 --- a/natives/blur.h +++ b/natives/blur.h @@ -1,8 +1,11 @@ #pragma once -#include +#include +#include +#include -using std::string; +using std::any; using std::map; +using std::string; -char* Blur(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +char* Blur(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/caption.cc b/natives/caption.cc index 69c16da..881e25a 100644 --- a/natives/caption.cc +++ b/natives/caption.cc @@ -7,65 +7,76 @@ using namespace std; using namespace vips; -char* Caption(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Caption(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - string caption = Arguments["caption"]; - string font = MAP_GET(Arguments, "font"); + string caption = MAP_GET(Arguments, "caption", string); + string font = MAP_GET(Arguments, "font", string); + string basePath = MAP_GET(Arguments, "basePath", string); - VOption *options = VImage::option()->set("access", "sequential"); + VOption *options = VImage::option()->set("access", "sequential"); - VImage in = + VImage in = VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); - - if (!in.has_alpha()) - in = in.bandjoin(255); + type == "gif" ? options->set("n", -1) : options) + .colourspace(VIPS_INTERPRETATION_sRGB); - int width = in.width(); - int size = width / 10; - int pageHeight = vips_image_get_page_height(in.get_image()); - int nPages = vips_image_get_n_pages(in.get_image()); - int textWidth = width - ((width / 25) * 2); + if (!in.has_alpha()) + in = in.bandjoin(255); - string font_string = (font == "roboto" ? "Roboto Condensed" : font) + " " + - (font != "impact" ? "bold" : "normal") + " " + - to_string(size); + int width = in.width(); + int size = width / 10; + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = vips_image_get_n_pages(in.get_image()); + int textWidth = width - ((width / 25) * 2); - string captionText = "" + caption + ""; + string font_string = (font == "roboto" ? "Roboto Condensed" : font) + " " + + (font != "impact" ? "bold" : "normal") + " " + + to_string(size); - VImage text = - VImage::text(captionText.c_str(), VImage::option() - ->set("rgba", true) - ->set("align", VIPS_ALIGN_CENTRE) - ->set("font", font_string.c_str()) - ->set("width", textWidth)); - VImage captionImage = - ((text == (vector){0, 0, 0, 0}).bandand()) - .ifthenelse(255, text) - .gravity(VIPS_COMPASS_DIRECTION_CENTRE, width, text.height() + size, - VImage::option()->set("extend", "white")); + string captionText = "" + caption + ""; - vector img; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - VImage frame = captionImage.join( - img_frame, VIPS_DIRECTION_VERTICAL, - VImage::option()->set("background", 0xffffff)->set("expand", true)); - img.push_back(frame); - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight + captionImage.height()); + VImage text; + auto findResult = fontPaths.find(font); + if (findResult != fontPaths.end()) { + text = VImage::text( + ".", VImage::option()->set("fontfile", + (basePath + findResult->second).c_str())); + } + text = VImage::text( + captionText.c_str(), + VImage::option() + ->set("rgba", true) + ->set("align", VIPS_ALIGN_CENTRE) + ->set("font", font_string.c_str()) + ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) + ->set("width", textWidth)); + VImage captionImage = + ((text == (vector){0, 0, 0, 0}).bandand()) + .ifthenelse(255, text) + .gravity(VIPS_COMPASS_DIRECTION_CENTRE, width, text.height() + size, + VImage::option()->set("extend", "white")); - void* buf; - final.write_to_buffer( - ("." + type).c_str(), &buf, DataSize, - type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) - : 0); + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + VImage frame = captionImage.join( + img_frame, VIPS_DIRECTION_VERTICAL, + VImage::option()->set("background", 0xffffff)->set("expand", true)); + img.push_back(frame); + } + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight + captionImage.height()); - vips_error_clear(); - vips_thread_shutdown(); + void *buf; + final.write_to_buffer( + ("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) + : 0); - return (char*) buf; + vips_error_clear(); + vips_thread_shutdown(); + + return (char *)buf; } diff --git a/natives/caption.h b/natives/caption.h index d5ad71c..e354dae 100644 --- a/natives/caption.h +++ b/natives/caption.h @@ -1,7 +1,11 @@ #pragma once +#include #include #include -#include -char* Caption(std::string type, char* BufferData, size_t BufferLength, std::map Arguments, size_t* DataSize); \ No newline at end of file +using std::any; +using std::map; +using std::string; + +char* Caption(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/caption2.cc b/natives/caption2.cc index 1327065..eed3fb4 100644 --- a/natives/caption2.cc +++ b/natives/caption2.cc @@ -1,85 +1,85 @@ #include "common.h" -#include "common.h" -#include #include +#include #include using namespace std; using namespace vips; -char* CaptionTwo(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *CaptionTwo(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - bool top = MAP_GET(Arguments, "top") == "true"; - string caption = Arguments["caption"]; - string font = MAP_GET(Arguments, "font"); - string basePath = MAP_GET(Arguments, "basePath"); + bool top = MAP_GET(Arguments, "top", bool); + string caption = MAP_GET(Arguments, "caption", string); + string font = MAP_GET(Arguments, "font", string); + string basePath = MAP_GET(Arguments, "basePath", string); - VOption *options = VImage::option()->set("access", "sequential"); + VOption *options = VImage::option()->set("access", "sequential"); - VImage in = + VImage in = VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); - - if (!in.has_alpha()) - in = in.bandjoin(255); + type == "gif" ? options->set("n", -1) : options) + .colourspace(VIPS_INTERPRETATION_sRGB); - int width = in.width(); - int size = width / 13; - int pageHeight = vips_image_get_page_height(in.get_image()); - int nPages = vips_image_get_n_pages(in.get_image()); - int textWidth = width - ((width / 25) * 2); + if (!in.has_alpha()) + in = in.bandjoin(255); - string font_string = (font == "roboto" ? "Roboto Condensed" : font) + - ", Twemoji Color Emoji " + to_string(size); + int width = in.width(); + int size = width / 13; + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = vips_image_get_n_pages(in.get_image()); + int textWidth = width - ((width / 25) * 2); - string captionText = "" + caption + ""; + string font_string = (font == "roboto" ? "Roboto Condensed" : font) + + ", Twemoji Color Emoji " + to_string(size); - VImage text; - auto findResult = fontPaths.find(font); - if (findResult != fontPaths.end()) { - text = VImage::text( - ".", VImage::option()->set("fontfile", - (basePath + findResult->second).c_str())); - } + string captionText = "" + caption + ""; + + VImage text; + auto findResult = fontPaths.find(font); + if (findResult != fontPaths.end()) { text = VImage::text( - captionText.c_str(), - VImage::option() - ->set("rgba", true) - ->set("font", font_string.c_str()) - ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) - ->set("align", VIPS_ALIGN_LOW) - ->set("width", textWidth)); - VImage captionImage = - ((text == (vector){0, 0, 0, 0}).bandand()) - .ifthenelse(255, text) - .embed(width / 25, width / 25, width, text.height() + size, - VImage::option()->set("extend", "white")); + ".", VImage::option()->set("fontfile", + (basePath + findResult->second).c_str())); + } + text = VImage::text( + captionText.c_str(), + VImage::option() + ->set("rgba", true) + ->set("font", font_string.c_str()) + ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) + ->set("align", VIPS_ALIGN_LOW) + ->set("width", textWidth)); + VImage captionImage = + ((text == (vector){0, 0, 0, 0}).bandand()) + .ifthenelse(255, text) + .embed(width / 25, width / 25, width, text.height() + size, + VImage::option()->set("extend", "white")); - vector img; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - VImage frame = - (top ? captionImage : img_frame) - .join(top ? img_frame : captionImage, VIPS_DIRECTION_VERTICAL, - VImage::option() - ->set("background", 0xffffff) - ->set("expand", true)); - img.push_back(frame); - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight + captionImage.height()); + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + VImage frame = + (top ? captionImage : img_frame) + .join(top ? img_frame : captionImage, VIPS_DIRECTION_VERTICAL, + VImage::option() + ->set("background", 0xffffff) + ->set("expand", true)); + img.push_back(frame); + } + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight + captionImage.height()); - void *buf; - final.write_to_buffer( - ("." + type).c_str(), &buf, DataSize, - type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) - : 0); - - vips_error_clear(); - vips_thread_shutdown(); - - return (char*) buf; + void *buf; + final.write_to_buffer( + ("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) + : 0); + + vips_error_clear(); + vips_thread_shutdown(); + + return (char *)buf; } diff --git a/natives/caption2.h b/natives/caption2.h index a14bd07..77fe4bb 100644 --- a/natives/caption2.h +++ b/natives/caption2.h @@ -1,7 +1,11 @@ #pragma once +#include #include #include -#include -char* CaptionTwo(std::string type, char* BufferData, size_t BufferLength, std::map Arguments, size_t* DataSize); \ No newline at end of file +using std::any; +using std::map; +using std::string; + +char* CaptionTwo(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/circle.cc b/natives/circle.cc index 5a6897d..ed8917e 100644 --- a/natives/circle.cc +++ b/natives/circle.cc @@ -1,48 +1,53 @@ +#include "common.h" #include -#include +#include #include -#include -#include #include +#include +#include using namespace std; using namespace Magick; -char* Circle(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { - - Blob blob; +char *Circle(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - list frames; - list coalesced; - list blurred; - try { - readImages(&frames, Blob(BufferData, BufferLength)); - } catch (Magick::WarningCoder &warning) { - cerr << "Coder Warning: " << warning.what() << endl; - } catch (Magick::Warning &warning) { - cerr << "Warning: " << warning.what() << endl; + Blob blob; + + list frames; + list coalesced; + list blurred; + try { + readImages(&frames, Blob(BufferData, BufferLength)); + } catch (Magick::WarningCoder &warning) { + cerr << "Coder Warning: " << warning.what() << endl; + } catch (Magick::Warning &warning) { + cerr << "Warning: " << warning.what() << endl; + } + coalesceImages(&coalesced, frames.begin(), frames.end()); + + for (Image &image : coalesced) { + image.rotationalBlur(10); + image.magick(type); + blurred.push_back(image); + } + + optimizeTransparency(blurred.begin(), blurred.end()); + + if (type == "gif") { + for (Image &image : blurred) { + image.quantizeDitherMethod(FloydSteinbergDitherMethod); + image.quantize(); } - coalesceImages(&coalesced, frames.begin(), frames.end()); + } - for (Image &image : coalesced) { - image.rotationalBlur(10); - image.magick(type); - blurred.push_back(image); - } + writeImages(blurred.begin(), blurred.end(), &blob); - optimizeTransparency(blurred.begin(), blurred.end()); - - if (type == "gif") { - for (Image &image : blurred) { - image.quantizeDitherMethod(FloydSteinbergDitherMethod); - image.quantize(); - } - } - - writeImages(blurred.begin(), blurred.end(), &blob); - - *DataSize = blob.length(); - - return (char*) blob.data(); + *DataSize = blob.length(); + + // workaround because the data is tied to the blob + char *data = (char *)malloc(*DataSize); + memcpy(data, blob.data(), *DataSize); + return data; } \ No newline at end of file diff --git a/natives/circle.h b/natives/circle.h index 21a2cf1..9d1e78a 100644 --- a/natives/circle.h +++ b/natives/circle.h @@ -1,10 +1,11 @@ #pragma once -#include -#include +#include #include +#include -using std::string; +using std::any; using std::map; +using std::string; -char* Circle(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +char* Circle(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/colors.cc b/natives/colors.cc index 03eed17..ae6a885 100644 --- a/natives/colors.cc +++ b/natives/colors.cc @@ -1,8 +1,8 @@ -#include +#include "common.h" -#include #include #include +#include using namespace std; using namespace vips; @@ -10,30 +10,31 @@ using namespace vips; 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); -char* Colors(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Colors(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - string color = Arguments["color"]; + string color = MAP_GET(Arguments, "color", string); - VOption *options = VImage::option()->set("access", "sequential"); + VOption *options = VImage::option()->set("access", "sequential"); - VImage in = - VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); + VImage in = + VImage::new_from_buffer(BufferData, BufferLength, "", + type == "gif" ? options->set("n", -1) : options) + .colourspace(VIPS_INTERPRETATION_sRGB); - VImage out; + VImage out; - if (color == "grayscale") { - out = in.colourspace(VIPS_INTERPRETATION_B_W); - } else if (color == "sepia") { - out = in.flatten().recomb(sepia); - } + if (color == "grayscale") { + out = in.colourspace(VIPS_INTERPRETATION_B_W); + } else if (color == "sepia") { + out = in.flatten().recomb(sepia); + } - void *buf; - out.write_to_buffer(("." + type).c_str(), &buf, DataSize); + void *buf; + out.write_to_buffer(("." + type).c_str(), &buf, DataSize); - vips_error_clear(); - vips_thread_shutdown(); + vips_error_clear(); + vips_thread_shutdown(); - return (char*) buf; + return (char *)buf; } diff --git a/natives/colors.h b/natives/colors.h index 75ce917..a3f4665 100644 --- a/natives/colors.h +++ b/natives/colors.h @@ -1,10 +1,11 @@ #pragma once -#include +#include #include #include +using std::any; using std::map; using std::string; -char* Colors(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +char* Colors(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/common.h b/natives/common.h index 579e900..820adbb 100644 --- a/natives/common.h +++ b/natives/common.h @@ -1,10 +1,12 @@ #pragma once +#include #include #include #define MAP_HAS(ARRAY, KEY) (ARRAY.count(KEY) > 0) -#define MAP_GET(ARRAY, KEY) (MAP_HAS(ARRAY, KEY) ? ARRAY.at(KEY) : NULL) // C++ has forced my hand +#define MAP_GET(ARRAY, KEY, TYPE) (MAP_HAS(ARRAY, KEY) ? any_cast(ARRAY.at(KEY)) : NULL) // C++ has forced my hand +#define MAP_GET_FALLBACK(ARRAY, KEY, TYPE, FALLBACK) (MAP_HAS(ARRAY, KEY) ? any_cast(ARRAY.at(KEY)) : FALLBACK) const std::unordered_map fontPaths { {"futura", "assets/fonts/caption.otf"}, diff --git a/natives/crop.cc b/natives/crop.cc index fb98c46..4b9f527 100644 --- a/natives/crop.cc +++ b/natives/crop.cc @@ -1,4 +1,4 @@ -#include +#include "common.h" #include #include #include @@ -6,47 +6,48 @@ using namespace std; using namespace vips; -char* Crop(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Crop(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - VOption *options = VImage::option()->set("access", "sequential"); + VOption *options = VImage::option()->set("access", "sequential"); - VImage in = + VImage in = VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); + type == "gif" ? options->set("n", -1) : options) + .colourspace(VIPS_INTERPRETATION_sRGB); - int width = in.width(); - int pageHeight = vips_image_get_page_height(in.get_image()); - int nPages = vips_image_get_n_pages(in.get_image()); + int width = in.width(); + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = vips_image_get_n_pages(in.get_image()); - vector img; - int finalHeight = 0; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - int frameWidth = img_frame.width(); - int frameHeight = img_frame.height(); - bool widthOrHeight = frameWidth / frameHeight >= 1; - int size = widthOrHeight ? frameHeight : frameWidth; - // img_frame.crop(frameWidth - size, frameHeight - size, size, size); - VImage result = img_frame.smartcrop( - size, size, - VImage::option()->set("interesting", VIPS_INTERESTING_CENTRE)); - finalHeight = size; - img.push_back(result); - } + vector img; + int finalHeight = 0; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + int frameWidth = img_frame.width(); + int frameHeight = img_frame.height(); + bool widthOrHeight = frameWidth / frameHeight >= 1; + int size = widthOrHeight ? frameHeight : frameWidth; + // img_frame.crop(frameWidth - size, frameHeight - size, size, size); + VImage result = img_frame.smartcrop( + size, size, + VImage::option()->set("interesting", VIPS_INTERESTING_CENTRE)); + finalHeight = size; + img.push_back(result); + } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, finalHeight); + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, finalHeight); - void *buf; - final.write_to_buffer( - ("." + type).c_str(), &buf, DataSize, - type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) - : 0); + void *buf; + final.write_to_buffer( + ("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) + : 0); - vips_error_clear(); - vips_thread_shutdown(); + vips_error_clear(); + vips_thread_shutdown(); - return (char*) buf; + return (char *)buf; } \ No newline at end of file diff --git a/natives/crop.h b/natives/crop.h index ac23dab..aeea95c 100644 --- a/natives/crop.h +++ b/natives/crop.h @@ -1,10 +1,11 @@ #pragma once -#include +#include #include #include +using std::any; using std::map; using std::string; -char* Crop(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +char* Crop(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/deepfry.cc b/natives/deepfry.cc index 1b4fab9..03b4bad 100644 --- a/natives/deepfry.cc +++ b/natives/deepfry.cc @@ -1,63 +1,64 @@ +#include "common.h" #include #include using namespace std; using namespace vips; -char* Deepfry(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Deepfry(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - VOption *options = VImage::option()->set("access", "sequential"); + VOption *options = VImage::option()->set("access", "sequential"); - VImage in = + VImage in = VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); + type == "gif" ? options->set("n", -1) : options) + .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) - in = in.bandjoin(255); + if (!in.has_alpha()) + in = in.bandjoin(255); - int width = in.width(); - int pageHeight = vips_image_get_page_height(in.get_image()); - int totalHeight = in.height(); - int nPages = vips_image_get_n_pages(in.get_image()); + int width = in.width(); + int pageHeight = vips_image_get_page_height(in.get_image()); + int totalHeight = in.height(); + int nPages = vips_image_get_n_pages(in.get_image()); - VImage fried = (in * 1.3 - (255.0 * 1.3 - 255.0)) * 1.5; + VImage fried = (in * 1.3 - (255.0 * 1.3 - 255.0)) * 1.5; - VImage final; - if (totalHeight > 65500 && type == "gif") { - vector img; - for (int i = 0; i < nPages; i++) { - VImage img_frame = in.crop(0, i * pageHeight, width, pageHeight); - void *jpgBuf; - size_t jpgLength; - img_frame.write_to_buffer( - ".jpg", &jpgBuf, &jpgLength, - VImage::option()->set("Q", 1)->set("strip", true)); - VImage jpeged = VImage::new_from_buffer(jpgBuf, jpgLength, ""); - jpeged.set(VIPS_META_PAGE_HEIGHT, pageHeight); - jpeged.set("delay", in.get_array_int("delay")); - img.push_back(jpeged); - } - final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight); - } else { + VImage final; + if (totalHeight > 65500 && type == "gif") { + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = in.crop(0, i * pageHeight, width, pageHeight); void *jpgBuf; size_t jpgLength; - fried.write_to_buffer(".jpg", &jpgBuf, &jpgLength, - VImage::option()->set("Q", 1)->set("strip", true)); - final = VImage::new_from_buffer(jpgBuf, jpgLength, ""); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight); - if (type == "gif") - final.set("delay", fried.get_array_int("delay")); + img_frame.write_to_buffer( + ".jpg", &jpgBuf, &jpgLength, + VImage::option()->set("Q", 1)->set("strip", true)); + VImage jpeged = VImage::new_from_buffer(jpgBuf, jpgLength, ""); + jpeged.set(VIPS_META_PAGE_HEIGHT, pageHeight); + jpeged.set("delay", in.get_array_int("delay")); + img.push_back(jpeged); } + final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight); + } else { + void *jpgBuf; + size_t jpgLength; + fried.write_to_buffer(".jpg", &jpgBuf, &jpgLength, + VImage::option()->set("Q", 1)->set("strip", true)); + final = VImage::new_from_buffer(jpgBuf, jpgLength, ""); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight); + if (type == "gif") + final.set("delay", fried.get_array_int("delay")); + } - void *buf; - final.write_to_buffer(("." + type).c_str(), &buf, DataSize, - type == "gif" ? VImage::option()->set("dither", 0) - : 0); + void *buf; + final.write_to_buffer(("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0) : 0); - vips_error_clear(); - vips_thread_shutdown(); + vips_error_clear(); + vips_thread_shutdown(); - return (char*) buf; + return (char *)buf; } \ No newline at end of file diff --git a/natives/deepfry.h b/natives/deepfry.h index 64b89d5..b06cb6c 100644 --- a/natives/deepfry.h +++ b/natives/deepfry.h @@ -1,10 +1,11 @@ #pragma once -#include +#include #include #include +using std::any; using std::map; using std::string; -char* Deepfry(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +char* Deepfry(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/explode.cc b/natives/explode.cc index 06896fd..d2c9970 100644 --- a/natives/explode.cc +++ b/natives/explode.cc @@ -2,52 +2,57 @@ #include +#include #include -#include -#include #include +#include +#include using namespace std; using namespace Magick; -char* Explode(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Explode(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - int amount = stoi(Arguments.at("amount")); - int delay = MAP_HAS(Arguments, "delay") ? stoi(Arguments.at("delay")) : 0; + int amount = MAP_GET(Arguments, "amount", int); + int delay = MAP_GET_FALLBACK(Arguments, "delay", int, 0); - Blob blob; + Blob blob; - list frames; - list coalesced; - list blurred; - try { - readImages(&frames, Blob(BufferData, BufferLength)); - } catch (Magick::WarningCoder &warning) { - cerr << "Coder Warning: " << warning.what() << endl; - } catch (Magick::Warning &warning) { - cerr << "Warning: " << warning.what() << endl; + list frames; + list coalesced; + list blurred; + try { + readImages(&frames, Blob(BufferData, BufferLength)); + } catch (Magick::WarningCoder &warning) { + cerr << "Coder Warning: " << warning.what() << endl; + } catch (Magick::Warning &warning) { + cerr << "Warning: " << warning.what() << endl; + } + coalesceImages(&coalesced, frames.begin(), frames.end()); + + for (Image &image : coalesced) { + image.implode(amount); + image.magick(type); + blurred.push_back(image); + } + + optimizeTransparency(blurred.begin(), blurred.end()); + + if (type == "gif") { + for (Image &image : blurred) { + image.quantizeDither(false); + image.quantize(); + if (delay != 0) image.animationDelay(delay); } - coalesceImages(&coalesced, frames.begin(), frames.end()); + } - for (Image &image : coalesced) { - image.implode(amount); - image.magick(type); - blurred.push_back(image); - } + writeImages(blurred.begin(), blurred.end(), &blob); - optimizeTransparency(blurred.begin(), blurred.end()); + *DataSize = blob.length(); - if (type == "gif") { - for (Image &image : blurred) { - image.quantizeDither(false); - image.quantize(); - if (delay != 0) image.animationDelay(delay); - } - } - - writeImages(blurred.begin(), blurred.end(), &blob); - - *DataSize = blob.length(); - - return (char*) blob.data(); + // workaround because the data is tied to the blob + char *data = (char *)malloc(*DataSize); + memcpy(data, blob.data(), *DataSize); + return data; } \ No newline at end of file diff --git a/natives/explode.h b/natives/explode.h index aab879d..1b9126c 100644 --- a/natives/explode.h +++ b/natives/explode.h @@ -1,10 +1,11 @@ #pragma once -#include -#include +#include #include +#include +using std::any; using std::map; using std::string; -char* Explode(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +char* Explode(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/flag.cc b/natives/flag.cc index f882e22..4aae54e 100644 --- a/natives/flag.cc +++ b/natives/flag.cc @@ -1,61 +1,64 @@ -#include +#include "common.h" -#include -#include #include +#include +#include using namespace std; using namespace vips; -char* Flag(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Flag(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - string overlay = Arguments["overlay"]; - string basePath = Arguments["basePath"]; + string overlay = MAP_GET(Arguments, "overlay", string); + string basePath = MAP_GET(Arguments, "basePath", string); - VOption *options = VImage::option()->set("access", "sequential"); + VOption *options = VImage::option()->set("access", "sequential"); - VImage in = + VImage in = VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); + type == "gif" ? options->set("n", -1) : options) + .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) in = in.bandjoin(255); + if (!in.has_alpha()) + in = in.bandjoin(255); - int width = in.width(); - int pageHeight = vips_image_get_page_height(in.get_image()); - int nPages = vips_image_get_n_pages(in.get_image()); + int width = in.width(); + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = vips_image_get_n_pages(in.get_image()); - string assetPath = basePath + overlay; - VImage overlayInput = VImage::new_from_file(assetPath.c_str()); - VImage overlayImage = overlayInput.resize( - (double)width / (double)overlayInput.width(), - VImage::option()->set( - "vscale", (double)pageHeight / (double)overlayInput.height())); - if (!overlayImage.has_alpha()) { - overlayImage = overlayImage.bandjoin(127); - } else { - // this is a pretty cool line, just saying - overlayImage = overlayImage * vector{1, 1, 1, 0.5}; - } + string assetPath = basePath + overlay; + VImage overlayInput = VImage::new_from_file(assetPath.c_str()); + VImage overlayImage = overlayInput.resize( + (double)width / (double)overlayInput.width(), + VImage::option()->set("vscale", (double)pageHeight / + (double)overlayInput.height())); + if (!overlayImage.has_alpha()) { + overlayImage = overlayImage.bandjoin(127); + } else { + // this is a pretty cool line, just saying + overlayImage = overlayImage * vector{1, 1, 1, 0.5}; + } - vector img; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - VImage composited = - img_frame.composite2(overlayImage, VIPS_BLEND_MODE_OVER); - img.push_back(composited); - } + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + VImage composited = + img_frame.composite2(overlayImage, VIPS_BLEND_MODE_OVER); + img.push_back(composited); + } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight); + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight); - void *buf; - final.write_to_buffer( - ("." + type).c_str(), &buf, DataSize, - type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); + void *buf; + final.write_to_buffer( + ("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) + : 0); - vips_error_clear(); - vips_thread_shutdown(); - return (char*) buf; + vips_error_clear(); + vips_thread_shutdown(); + return (char *)buf; } \ No newline at end of file diff --git a/natives/flag.h b/natives/flag.h index c89bc02..9e6da56 100644 --- a/natives/flag.h +++ b/natives/flag.h @@ -1,10 +1,11 @@ #pragma once -#include +#include #include #include +using std::any; using std::map; using std::string; -char* Flag(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +char* Flag(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/flip.cc b/natives/flip.cc index b117ca6..5811fae 100644 --- a/natives/flip.cc +++ b/natives/flip.cc @@ -7,44 +7,46 @@ using namespace std; using namespace vips; -char* Flip(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Flip(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - bool flop = MAP_GET(Arguments, "flop") == "true"; + bool flop = MAP_GET(Arguments, "flop", bool); - VOption *options = VImage::option()->set("access", "sequential"); + VImage in = VImage::new_from_buffer(BufferData, BufferLength, "", + type == "gif" + ? VImage::option()->set("n", -1)->set( + "access", "sequential") + : 0) + .colourspace(VIPS_INTERPRETATION_sRGB); + if (!in.has_alpha()) + in = in.bandjoin(255); - VImage in = - VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? VImage::option()->set("n", -1)->set("access", "sequential") : 0) - .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) in = in.bandjoin(255); - - VImage out; - if (flop) { - out = in.flip(VIPS_DIRECTION_HORIZONTAL); - } else if (type == "gif") { - // libvips gif handling is both a blessing and a curse - vector img; - int pageHeight = vips_image_get_page_height(in.get_image()); - int nPages = vips_image_get_n_pages(in.get_image()); - for (int i = 0; i < nPages; i++) { - VImage img_frame = in.crop(0, i * pageHeight, in.width(), pageHeight); - VImage flipped = img_frame.flip(VIPS_DIRECTION_VERTICAL); - img.push_back(flipped); - } - out = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - out.set(VIPS_META_PAGE_HEIGHT, pageHeight); - } else { - out = in.flip(VIPS_DIRECTION_VERTICAL); + VImage out; + if (flop) { + out = in.flip(VIPS_DIRECTION_HORIZONTAL); + } else if (type == "gif") { + // libvips gif handling is both a blessing and a curse + vector img; + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = vips_image_get_n_pages(in.get_image()); + for (int i = 0; i < nPages; i++) { + VImage img_frame = in.crop(0, i * pageHeight, in.width(), pageHeight); + VImage flipped = img_frame.flip(VIPS_DIRECTION_VERTICAL); + img.push_back(flipped); } + out = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + out.set(VIPS_META_PAGE_HEIGHT, pageHeight); + } else { + out = in.flip(VIPS_DIRECTION_VERTICAL); + } - void* buf; - out.write_to_buffer( - ("." + type).c_str(), &buf, DataSize, - type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) - : 0); + void *buf; + out.write_to_buffer( + ("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) + : 0); - vips_error_clear(); - vips_thread_shutdown(); - return (char*) buf; + vips_error_clear(); + vips_thread_shutdown(); + return (char *)buf; } \ No newline at end of file diff --git a/natives/flip.h b/natives/flip.h index 9ee6085..aba5962 100644 --- a/natives/flip.h +++ b/natives/flip.h @@ -1,10 +1,11 @@ #pragma once -#include +#include #include #include +using std::any; using std::map; using std::string; -char* Flip(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +char* Flip(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/freeze.cc b/natives/freeze.cc index 3844bf9..81fd718 100644 --- a/natives/freeze.cc +++ b/natives/freeze.cc @@ -51,11 +51,12 @@ Napi::Value Freeze(const Napi::CallbackInfo &info) { } else if (frame >= 0 && !loop) { VOption *options = VImage::option()->set("access", "sequential"); - VImage in = VImage::new_from_buffer( - data.Data(), data.Length(), "", - type == "gif" ? options->set("n", -1) : options) + VImage in = VImage::new_from_buffer(data.Data(), data.Length(), "", + type == "gif" ? options->set("n", -1) + : options) .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) in = in.bandjoin(255); + if (!in.has_alpha()) + in = in.bandjoin(255); int pageHeight = vips_image_get_page_height(in.get_image()); int nPages = vips_image_get_n_pages(in.get_image()); diff --git a/natives/gamexplain.cc b/natives/gamexplain.cc index 65cc372..7edb425 100644 --- a/natives/gamexplain.cc +++ b/natives/gamexplain.cc @@ -21,7 +21,8 @@ Napi::Value Gamexplain(const Napi::CallbackInfo &info) { VImage::new_from_buffer(data.Data(), data.Length(), "", type == "gif" ? options->set("n", -1) : options) .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) in = in.bandjoin(255); + if (!in.has_alpha()) + in = in.bandjoin(255); string assetPath = basePath + "assets/images/gamexplain.png"; VImage tmpl = VImage::new_from_file(assetPath.c_str()); @@ -50,7 +51,8 @@ Napi::Value Gamexplain(const Napi::CallbackInfo &info) { size_t length; final.write_to_buffer( ("." + type).c_str(), &buf, &length, - type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); + type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) + : 0); result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); result.Set("type", type); diff --git a/natives/globe.cc b/natives/globe.cc index b0abc9a..d4ff5ea 100644 --- a/natives/globe.cc +++ b/natives/globe.cc @@ -23,7 +23,8 @@ Napi::Value Globe(const Napi::CallbackInfo &info) { type == "gif" ? options->set("n", -1)->set("access", "sequential") : options) .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) in = in.bandjoin(255); + if (!in.has_alpha()) + in = in.bandjoin(255); int width = in.width(); int pageHeight = vips_image_get_page_height(in.get_image()); diff --git a/natives/image.cc b/natives/image.cc index c636ae3..0ecbd53 100644 --- a/natives/image.cc +++ b/natives/image.cc @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "blur.h" #include "colors.h" @@ -42,7 +44,6 @@ #include "watermark.h" #include "whisper.h" #include "zamn.h" -#include #ifdef _WIN32 #include @@ -51,10 +52,10 @@ using namespace std; -std::map Arguments, size_t* DataSize)> FunctionMap = { +std::map Arguments, size_t* DataSize)> FunctionMap = { + {"blur", &Blur}, {"caption", &Caption}, - {"caption2", &CaptionTwo}, - {"blur", &Blur}, + {"captionTwo", &CaptionTwo}, {"circle", &Circle}, {"colors", &Colors}, {"crop", &Crop}, @@ -62,8 +63,8 @@ std::map OldFunctionMap = { @@ -94,6 +95,17 @@ std::map OldFuncti {"zamn", Zamn} }; +bool isNapiValueInt(Napi::Env& env, Napi::Value& num) { + return env.Global() + .Get("Number") + .ToObject() + .Get("isInteger") + .As() + .Call({num}) + .ToBoolean() + .Value(); +} + Napi::Value NewProcessImage(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); Napi::Object result = Napi::Object::New(env); @@ -106,7 +118,7 @@ Napi::Value NewProcessImage(const Napi::CallbackInfo &info) { Napi::Array properties = obj.GetPropertyNames(); - std::map Arguments; + std::map Arguments; for (unsigned int i = 0; i < properties.Length(); i++) { string property = properties.Get(uint32_t(i)).As().Utf8Value(); @@ -115,7 +127,21 @@ Napi::Value NewProcessImage(const Napi::CallbackInfo &info) { continue; } - Arguments[property] = obj.Get(property).ToString().As().Utf8Value(); + 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)) { + Arguments[property] = num.Int32Value(); + } else { + Arguments[property] = num.FloatValue(); + } + } else { + Arguments[property] = val; + } } size_t length = 0; @@ -159,6 +185,21 @@ Napi::Object Init(Napi::Env env, Napi::Object exports){ vips_error_exit(NULL); exports.Set(Napi::String::New(env, "image"), Napi::Function::New(env, ProcessImage)); // new function handler + Napi::Array arr = Napi::Array::New(env); + size_t i = 0; + for (auto const& imap: FunctionMap) { + Napi::HandleScope scope(env); + arr[i] = Napi::String::New(env, imap.first); + i++; + } + for(auto const& imap: OldFunctionMap) { + Napi::HandleScope scope(env); + arr[i] = Napi::String::New(env, imap.first); + i++; + } + + exports.Set(Napi::String::New(env, "funcs"), arr); + return exports; } diff --git a/natives/uncaption.cc b/natives/uncaption.cc index 10144ca..61bb468 100644 --- a/natives/uncaption.cc +++ b/natives/uncaption.cc @@ -1,56 +1,57 @@ #include "common.h" -#include #include +#include using namespace std; using namespace vips; -char* Uncaption(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Uncaption(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - float tolerance = MAP_HAS(Arguments, "tolerance") - ? stof(Arguments["tolerance"]) - : 0.5; + float tolerance = MAP_GET_FALLBACK(Arguments, "tolerance", float, 0.5); - VOption *options = VImage::option(); + VOption *options = VImage::option(); - VImage in = - VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1)->set("access", "sequential") : options) - .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) in = in.bandjoin(255); + VImage in = + VImage::new_from_buffer( + BufferData, BufferLength, "", + type == "gif" ? options->set("n", -1)->set("access", "sequential") + : options) + .colourspace(VIPS_INTERPRETATION_sRGB); + if (!in.has_alpha()) + in = in.bandjoin(255); - int width = in.width(); - int pageHeight = vips_image_get_page_height(in.get_image()); - int nPages = vips_image_get_n_pages(in.get_image()); + int width = in.width(); + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = vips_image_get_n_pages(in.get_image()); - VImage first = - in.crop(0, 0, 3, pageHeight).colourspace(VIPS_INTERPRETATION_B_W) > - (255 * tolerance); - int top, captionWidth, captionHeight; - first.find_trim(&top, &captionWidth, &captionHeight); + VImage first = + in.crop(0, 0, 3, pageHeight).colourspace(VIPS_INTERPRETATION_B_W) > + (255 * tolerance); + int top, captionWidth, captionHeight; + first.find_trim(&top, &captionWidth, &captionHeight); - vector img; - int newHeight = pageHeight - top; - if (top == pageHeight) { - newHeight = pageHeight; - top = 0; - } - for (int i = 0; i < nPages; i++) { - VImage img_frame = - in.crop(0, (i * pageHeight) + top, width, newHeight); - img.push_back(img_frame); - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, newHeight); - - void *buf; - final.write_to_buffer( - ("." + type).c_str(), &buf, DataSize, - type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); + vector img; + int newHeight = pageHeight - top; + if (top == pageHeight) { + newHeight = pageHeight; + top = 0; + } + for (int i = 0; i < nPages; i++) { + VImage img_frame = in.crop(0, (i * pageHeight) + top, width, newHeight); + img.push_back(img_frame); + } + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, newHeight); + void *buf; + final.write_to_buffer( + ("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) + : 0); vips_error_clear(); vips_thread_shutdown(); - return (char*) buf; + return (char *)buf; } diff --git a/natives/uncaption.h b/natives/uncaption.h index fd8e1b6..ebd4318 100644 --- a/natives/uncaption.h +++ b/natives/uncaption.h @@ -1,5 +1,11 @@ #pragma once +#include #include +#include -char* Uncaption(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +using std::any; +using std::map; +using std::string; + +char* Uncaption(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/watermark.cc b/natives/watermark.cc index 4ba2f75..9b53857 100644 --- a/natives/watermark.cc +++ b/natives/watermark.cc @@ -1,154 +1,157 @@ #include "common.h" -#include #include +#include using namespace std; using namespace vips; -char* Watermark(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize) { +char *Watermark(string type, char *BufferData, size_t BufferLength, + map Arguments, size_t *DataSize) { - string water = Arguments["water"]; - int gravity = stoi(Arguments["gravity"]); + string water = MAP_GET(Arguments, "water", string); + int gravity = MAP_GET(Arguments, "gravity", int); - bool resize = MAP_HAS(Arguments, "resize") ? Arguments["resize"] == "true" : false;; - float yscale = MAP_HAS(Arguments, "yscale") ? stof(Arguments["yscale"]) : false; + bool resize = MAP_GET_FALLBACK(Arguments, "resize", bool, false); + ; + float yscale = MAP_GET_FALLBACK(Arguments, "yscale", float, false); - bool append = MAP_HAS(Arguments, "append") ? Arguments["append"] == "true" : false; + bool append = MAP_GET_FALLBACK(Arguments, "append", bool, false); - bool alpha = MAP_HAS(Arguments, "alpha") ? Arguments["alpha"] == "true" : false; - bool flip = MAP_HAS(Arguments, "flip") ? Arguments["flip"] == "true" : false; - - bool mc = MAP_HAS(Arguments, "mc"); + bool alpha = MAP_GET_FALLBACK(Arguments, "alpha", bool, false); + bool flip = MAP_GET_FALLBACK(Arguments, "flip", bool, false); - string basePath = Arguments["basePath"]; + bool mc = MAP_HAS(Arguments, "mc"); - VOption *options = VImage::option()->set("access", "sequential"); + string basePath = MAP_GET(Arguments, "basePath", string); - VImage in = - VImage::new_from_buffer(BufferData, BufferLength, "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) in = in.bandjoin(255); + VOption *options = VImage::option()->set("access", "sequential"); - string merged = basePath + water; - VImage watermark = VImage::new_from_file(merged.c_str()); + VImage in = + VImage::new_from_buffer(BufferData, BufferLength, "", + type == "gif" ? options->set("n", -1) : options) + .colourspace(VIPS_INTERPRETATION_sRGB); + if (!in.has_alpha()) + in = in.bandjoin(255); - int width = in.width(); - int pageHeight = vips_image_get_page_height(in.get_image()); - int nPages = vips_image_get_n_pages(in.get_image()); + string merged = basePath + water; + VImage watermark = VImage::new_from_file(merged.c_str()); - if (flip) { - watermark = watermark.flip(VIPS_DIRECTION_HORIZONTAL); - } + int width = in.width(); + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = vips_image_get_n_pages(in.get_image()); - if (resize && append) { - watermark = watermark.resize((double)width / (double)watermark.width()); - } else if (resize && yscale) { - watermark = watermark.resize( - (double)width / (double)watermark.width(), - VImage::option()->set("vscale", (double)(pageHeight * yscale) / - (double)watermark.height())); - } else if (resize) { - watermark = - watermark.resize((double)pageHeight / (double)watermark.height()); - } + if (flip) { + watermark = watermark.flip(VIPS_DIRECTION_HORIZONTAL); + } - int x = 0, y = 0; - switch (gravity) { - case 1: - break; - case 2: - x = (width / 2) - (watermark.width() / 2); - break; - case 3: - x = width - watermark.width(); - break; - case 5: - x = (width / 2) - (watermark.width() / 2); - y = (pageHeight / 2) - (watermark.height() / 2); - break; - case 6: - x = width - watermark.width(); - y = (pageHeight / 2) - (watermark.height() / 2); - break; - case 8: - x = (width / 2) - (watermark.width() / 2); - y = pageHeight - watermark.height(); - break; - case 9: - x = width - watermark.width(); - y = pageHeight - watermark.height(); - break; - } + if (resize && append) { + watermark = watermark.resize((double)width / (double)watermark.width()); + } else if (resize && yscale) { + watermark = watermark.resize( + (double)width / (double)watermark.width(), + VImage::option()->set("vscale", (double)(pageHeight * yscale) / + (double)watermark.height())); + } else if (resize) { + watermark = + watermark.resize((double)pageHeight / (double)watermark.height()); + } - vector img; - int addedHeight = 0; - VImage contentAlpha; - VImage frameAlpha; - VImage bg; - VImage frame; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - if (append) { - VImage appended = img_frame.join(watermark, VIPS_DIRECTION_VERTICAL, - VImage::option()->set("expand", true)); - addedHeight = watermark.height(); - img.push_back(appended); - } else if (mc) { - VImage padded = - img_frame.embed(0, 0, width, pageHeight + 15, - VImage::option()->set("background", 0xffffff)); - VImage composited = - padded.composite2(watermark, VIPS_BLEND_MODE_OVER, - VImage::option() - ->set("x", width - 190) - ->set("y", padded.height() - 22)); - addedHeight = 15; - img.push_back(composited); - } else { - VImage composited; - if (alpha) { - if (i == 0) { - contentAlpha = watermark.extract_band(0).embed( - x, y, width, pageHeight, - VImage::option()->set("extend", "white")); - frameAlpha = watermark.extract_band(1).embed( - x, y, width, pageHeight, - VImage::option()->set("extend", "black")); - bg = - frameAlpha.new_from_image({0, 0, 0}).copy(VImage::option()->set( - "interpretation", VIPS_INTERPRETATION_sRGB)); - frame = bg.bandjoin(frameAlpha); - if (type == "jpg" || type == "jpeg") { - type = "png"; - } + int x = 0, y = 0; + switch (gravity) { + case 1: + break; + case 2: + x = (width / 2) - (watermark.width() / 2); + break; + case 3: + x = width - watermark.width(); + break; + case 5: + x = (width / 2) - (watermark.width() / 2); + y = (pageHeight / 2) - (watermark.height() / 2); + break; + case 6: + x = width - watermark.width(); + y = (pageHeight / 2) - (watermark.height() / 2); + break; + case 8: + x = (width / 2) - (watermark.width() / 2); + y = pageHeight - watermark.height(); + break; + case 9: + x = width - watermark.width(); + y = pageHeight - watermark.height(); + break; + } + + vector img; + int addedHeight = 0; + VImage contentAlpha; + VImage frameAlpha; + VImage bg; + VImage frame; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + if (append) { + VImage appended = img_frame.join(watermark, VIPS_DIRECTION_VERTICAL, + VImage::option()->set("expand", true)); + addedHeight = watermark.height(); + img.push_back(appended); + } else if (mc) { + VImage padded = + img_frame.embed(0, 0, width, pageHeight + 15, + VImage::option()->set("background", 0xffffff)); + VImage composited = + padded.composite2(watermark, VIPS_BLEND_MODE_OVER, + VImage::option() + ->set("x", width - 190) + ->set("y", padded.height() - 22)); + addedHeight = 15; + img.push_back(composited); + } else { + VImage composited; + if (alpha) { + if (i == 0) { + contentAlpha = watermark.extract_band(0).embed( + x, y, width, pageHeight, + VImage::option()->set("extend", "white")); + frameAlpha = watermark.extract_band(1).embed( + x, y, width, pageHeight, + VImage::option()->set("extend", "black")); + bg = frameAlpha.new_from_image({0, 0, 0}).copy(VImage::option()->set( + "interpretation", VIPS_INTERPRETATION_sRGB)); + frame = bg.bandjoin(frameAlpha); + if (type == "jpg" || type == "jpeg") { + type = "png"; } - VImage content = - img_frame.extract_band(0, VImage::option()->set("n", 3)) - .bandjoin(contentAlpha & img_frame.extract_band(3)); - - composited = - content.composite2(frame, VIPS_BLEND_MODE_OVER, - VImage::option()->set("x", x)->set("y", y)); - } else { - composited = - img_frame.composite2(watermark, VIPS_BLEND_MODE_OVER, - VImage::option()->set("x", x)->set("y", y)); } - img.push_back(composited); - } - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight + addedHeight); + VImage content = + img_frame.extract_band(0, VImage::option()->set("n", 3)) + .bandjoin(contentAlpha & img_frame.extract_band(3)); - void *buf; - final.write_to_buffer( - ("." + type).c_str(), &buf, DataSize, - type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0); + composited = + content.composite2(frame, VIPS_BLEND_MODE_OVER, + VImage::option()->set("x", x)->set("y", y)); + } else { + composited = + img_frame.composite2(watermark, VIPS_BLEND_MODE_OVER, + VImage::option()->set("x", x)->set("y", y)); + } + img.push_back(composited); + } + } + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight + addedHeight); + + void *buf; + final.write_to_buffer( + ("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) + : 0); vips_error_clear(); vips_thread_shutdown(); - return (char*) buf; + return (char *)buf; } diff --git a/natives/watermark.h b/natives/watermark.h index 5a82641..f67d916 100644 --- a/natives/watermark.h +++ b/natives/watermark.h @@ -1,5 +1,11 @@ #pragma once -#include +#include +#include +#include -char* Watermark(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file +using std::any; +using std::map; +using std::string; + +char* Watermark(string type, char* BufferData, size_t BufferLength, map Arguments, size_t* DataSize); \ No newline at end of file