From e1a31d6ddc296ade44f6c55481cc77d776254992 Mon Sep 17 00:00:00 2001 From: Essem Date: Mon, 26 Dec 2022 00:28:56 -0600 Subject: [PATCH] Portablized more natives --- natives/gamexplain.cc | 88 ++++++-------- natives/gamexplain.h | 6 +- natives/globe.cc | 132 ++++++++++----------- natives/globe.h | 6 +- natives/homebrew.cc | 63 ++++------ natives/homebrew.h | 6 +- natives/image.cc | 43 ++++--- natives/invert.cc | 48 +++----- natives/invert.h | 6 +- natives/jpeg.cc | 111 +++++++----------- natives/jpeg.h | 6 +- natives/meme.cc | 264 ++++++++++++++++++++---------------------- natives/meme.h | 6 +- natives/mirror.cc | 113 ++++++++---------- natives/mirror.h | 6 +- natives/motivate.cc | 236 +++++++++++++++++-------------------- natives/motivate.h | 6 +- natives/reddit.cc | 114 ++++++++---------- natives/reddit.h | 6 +- natives/resize.cc | 96 +++++++-------- natives/resize.h | 6 +- natives/reverse.cc | 103 ++++++++-------- natives/reverse.h | 6 +- natives/sonic.cc | 58 ++++------ natives/sonic.h | 6 +- 25 files changed, 698 insertions(+), 843 deletions(-) diff --git a/natives/gamexplain.cc b/natives/gamexplain.cc index 7edb425..7521ee3 100644 --- a/natives/gamexplain.cc +++ b/natives/gamexplain.cc @@ -1,68 +1,54 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Gamexplain(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Gamexplain(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - string type = obj.Get("type").As().Utf8Value(); - string basePath = obj.Get("basePath").As().Utf8Value(); + string basePath = GetArgument(Arguments, "basePath"); - VOption *options = VImage::option()->set("access", "sequential"); + VOption *options = VImage::option()->set("access", "sequential"); - 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); + 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); - string assetPath = basePath + "assets/images/gamexplain.png"; - VImage tmpl = VImage::new_from_file(assetPath.c_str()); + string assetPath = basePath + "assets/images/gamexplain.png"; + VImage tmpl = VImage::new_from_file(assetPath.c_str()); - 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; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - VImage resized = img_frame - .resize(1181.0 / (double)width, - VImage::option()->set( - "vscale", 571.0 / (double)pageHeight)) - .embed(10, 92, 1200, 675, - VImage::option()->set("extend", "white")); - VImage composited = resized.composite2(tmpl, VIPS_BLEND_MODE_OVER); - img.push_back(composited); - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, 675); - - void *buf; - size_t length; - final.write_to_buffer( - ("." + type).c_str(), &buf, &length, - 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); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + VImage resized = + img_frame + .resize(1181.0 / (double)width, + VImage::option()->set("vscale", 571.0 / (double)pageHeight)) + .embed(10, 92, 1200, 675, VImage::option()->set("extend", "white")); + VImage composited = resized.composite2(tmpl, VIPS_BLEND_MODE_OVER); + img.push_back(composited); } + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, 675); + + 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 result; + + return (char *)buf; } \ No newline at end of file diff --git a/natives/gamexplain.h b/natives/gamexplain.h index 233a502..c408c05 100644 --- a/natives/gamexplain.h +++ b/natives/gamexplain.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Gamexplain(const Napi::CallbackInfo& info); +using std::string; + +char* Gamexplain(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/globe.cc b/natives/globe.cc index d4ff5ea..96a6f62 100644 --- a/natives/globe.cc +++ b/natives/globe.cc @@ -1,93 +1,79 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Globe(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Globe(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - string type = obj.Get("type").As().Utf8Value(); - string basePath = obj.Get("basePath").As().Utf8Value(); + string basePath = GetArgument(Arguments, "basePath"); - VOption *options = VImage::option(); + VOption *options = VImage::option(); - VImage in = - VImage::new_from_buffer( - data.Data(), data.Length(), "", - 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 = type == "gif" ? vips_image_get_n_pages(in.get_image()) : 30; + int width = in.width(); + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = type == "gif" ? vips_image_get_n_pages(in.get_image()) : 30; - double size = min(width, pageHeight); + double size = min(width, pageHeight); - string diffPath = basePath + "assets/images/globediffuse.png"; - VImage diffuse = - VImage::new_from_file(diffPath.c_str()) - .resize(size / 500.0, - VImage::option()->set("kernel", VIPS_KERNEL_CUBIC)) / - 255; + string diffPath = basePath + "assets/images/globediffuse.png"; + VImage diffuse = + VImage::new_from_file(diffPath.c_str()) + .resize(size / 500.0, + VImage::option()->set("kernel", VIPS_KERNEL_CUBIC)) / + 255; - string specPath = basePath + "assets/images/globespec.png"; - VImage specular = - VImage::new_from_file(specPath.c_str()) - .resize(size / 500.0, - VImage::option()->set("kernel", VIPS_KERNEL_CUBIC)); + string specPath = basePath + "assets/images/globespec.png"; + VImage specular = + VImage::new_from_file(specPath.c_str()) + .resize(size / 500.0, + VImage::option()->set("kernel", VIPS_KERNEL_CUBIC)); - string distortPath = basePath + "assets/images/spheremap.png"; - VImage distort = - (VImage::new_from_file(distortPath.c_str()) - .resize(size / 500.0, - VImage::option()->set("kernel", VIPS_KERNEL_CUBIC)) / - 65535) * - size; + string distortPath = basePath + "assets/images/spheremap.png"; + VImage distort = + (VImage::new_from_file(distortPath.c_str()) + .resize(size / 500.0, + VImage::option()->set("kernel", VIPS_KERNEL_CUBIC)) / + 65535) * + size; - vector img; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - VImage resized = img_frame.resize( - size / (double)width, - VImage::option()->set("vscale", size / (double)pageHeight)); - VImage rolled = img_frame.wrap( - VImage::option()->set("x", width * i / nPages)->set("y", 0)); - VImage extracted = rolled.extract_band(0, VImage::option()->set("n", 3)); - VImage mapped = extracted.mapim(distort); - VImage composited = mapped * diffuse + specular; - VImage frame = composited.bandjoin(diffuse > 0.0); - img.push_back(frame); - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, size); - if (type != "gif") { - vector delay(30, 50); - final.set("delay", delay); - } - - void *buf; - size_t length; - final.write_to_buffer(".gif", &buf, &length); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", "gif"); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + VImage resized = img_frame.resize( + size / (double)width, + VImage::option()->set("vscale", size / (double)pageHeight)); + VImage rolled = img_frame.wrap( + VImage::option()->set("x", width * i / nPages)->set("y", 0)); + VImage extracted = rolled.extract_band(0, VImage::option()->set("n", 3)); + VImage mapped = extracted.mapim(distort); + VImage composited = mapped * diffuse + specular; + VImage frame = composited.bandjoin(diffuse > 0.0); + img.push_back(frame); } + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, size); + if (type != "gif") { + vector delay(30, 50); + final.set("delay", delay); + } + + void *buf; + final.write_to_buffer(".gif", &buf, DataSize); vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } \ No newline at end of file diff --git a/natives/globe.h b/natives/globe.h index b3c27fa..5ad036f 100644 --- a/natives/globe.h +++ b/natives/globe.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Globe(const Napi::CallbackInfo& info); +using std::string; + +char* Globe(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/homebrew.cc b/natives/homebrew.cc index 7d16b3a..1f2c90e 100644 --- a/natives/homebrew.cc +++ b/natives/homebrew.cc @@ -1,53 +1,40 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Homebrew(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Homebrew(string *type, ArgumentMap Arguments, size_t *DataSize) { + string caption = GetArgument(Arguments, "caption"); + string basePath = GetArgument(Arguments, "basePath"); - try { - Napi::Object obj = info[1].As(); - string caption = obj.Get("caption").As().Utf8Value(); - string basePath = obj.Get("basePath").As().Utf8Value(); + string assetPath = basePath + "assets/images/hbc.png"; + VImage bg = VImage::new_from_file(assetPath.c_str()); - string assetPath = basePath + "assets/images/hbc.png"; - VImage bg = VImage::new_from_file(assetPath.c_str()); + VImage text = VImage::text( + ".", VImage::option()->set("fontfile", + (basePath + "assets/fonts/hbc.ttf").c_str())); + text = VImage::text( + ("" + caption + "") + .c_str(), + VImage::option() + ->set("rgba", true) + ->set("align", VIPS_ALIGN_CENTRE) + ->set("font", "PF Square Sans Pro, Twemoji Color Font 96") + ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())); - VImage text = VImage::text( - ".", VImage::option()->set( - "fontfile", (basePath + "assets/fonts/hbc.ttf").c_str())); - text = VImage::text( - ("" + caption + - "") - .c_str(), - VImage::option() - ->set("rgba", true) - ->set("align", VIPS_ALIGN_CENTRE) - ->set("font", "PF Square Sans Pro, Twemoji Color Font 96") - ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())); + VImage out = bg.composite2(text, VIPS_BLEND_MODE_OVER, + VImage::option() + ->set("x", 400 - (text.width() / 2)) + ->set("y", 300 - (text.height() / 2) - 8)); - VImage out = bg.composite2(text, VIPS_BLEND_MODE_OVER, - VImage::option() - ->set("x", 400 - (text.width() / 2)) - ->set("y", 300 - (text.height() / 2) - 8)); + void *buf; + out.write_to_buffer(".png", &buf, DataSize); - void *buf; - size_t length; - out.write_to_buffer(".png", &buf, &length); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", "png"); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); - } + *type = "png"; vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } \ No newline at end of file diff --git a/natives/homebrew.h b/natives/homebrew.h index f689355..bc89ac0 100644 --- a/natives/homebrew.h +++ b/natives/homebrew.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Homebrew(const Napi::CallbackInfo& info); +using std::string; + +char* Homebrew(string *type, ArgumentMap Arguments, size_t *DataSize); \ No newline at end of file diff --git a/natives/image.cc b/natives/image.cc index 0cc34ba..f326f5b 100644 --- a/natives/image.cc +++ b/natives/image.cc @@ -63,27 +63,30 @@ std::map OldFunctionMap = { {"gamexplain", Gamexplain}, {"globe", Globe}, - {"homebrew", Homebrew}, {"invert", Invert}, {"jpeg", Jpeg}, - {"magik", Magik}, {"meme", Meme}, {"mirror", Mirror}, {"motivate", Motivate}, {"reddit", Reddit}, {"resize", Resize}, {"reverse", Reverse}, + {"speed", &Speed}, + {"uncaption", &Uncaption}, + {"watermark", &Watermark} +}; + +std::map NoInputFunctionMap = { + {"homebrew", Homebrew}, + {"sonic", Sonic} +}; + +std::map OldFunctionMap = { + {"magik", Magik}, {"scott", Scott}, {"snapchat", Snapchat}, - {"sonic", Sonic}, {"spin", Spin}, {"swirl", Swirl}, {"tile", Tile}, @@ -105,15 +108,14 @@ bool isNapiValueInt(Napi::Env& env, Napi::Value& num) { .Value(); } -Napi::Value NewProcessImage(const Napi::CallbackInfo &info) { +Napi::Value NewProcessImage(const Napi::CallbackInfo &info, bool input) { Napi::Env env = info.Env(); Napi::Object result = Napi::Object::New(env); try { string command = info[0].As().Utf8Value(); Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - string type = obj.Get("type").As().Utf8Value(); + string type = obj.Has("type") ? obj.Get("type").As().Utf8Value() : NULL; Napi::Array properties = obj.GetPropertyNames(); @@ -145,7 +147,13 @@ Napi::Value NewProcessImage(const Napi::CallbackInfo &info) { } size_t length = 0; - char* buf = FunctionMap.at(command)(type, data.Data(), data.Length(), Arguments, &length); + char* buf; + if (input) { + Napi::Buffer data = obj.Has("data") ? obj.Get("data").As>() : Napi::Buffer::New(env, 0); + buf = FunctionMap.at(command)(type, data.Data(), data.Length(), Arguments, &length); + } else { + buf = NoInputFunctionMap.at(command)(&type, Arguments, &length); + } result.Set("data", Napi::Buffer::New(env, buf, length, [](Napi::Env env, void* data) { free(data); })); @@ -169,7 +177,9 @@ Napi::Value ProcessImage(const Napi::CallbackInfo &info) { // janky solution for string command = info[0].As().Utf8Value(); if (MAP_HAS(FunctionMap, command)) { - return NewProcessImage(info); + return NewProcessImage(info, true); + } else if (MAP_HAS(NoInputFunctionMap, command)) { + return NewProcessImage(info, false); } else if (MAP_HAS(OldFunctionMap, command)) { return OldProcessImage(command, info); } else { @@ -193,6 +203,11 @@ Napi::Object Init(Napi::Env env, Napi::Object exports){ arr[i] = Napi::String::New(env, imap.first); i++; } + for (auto const& imap: NoInputFunctionMap) { + 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); diff --git a/natives/invert.cc b/natives/invert.cc index 4a97802..3e64192 100644 --- a/natives/invert.cc +++ b/natives/invert.cc @@ -1,45 +1,31 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Invert(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Invert(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - string type = obj.Get("type").As().Utf8Value(); + 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); + if (!in.has_alpha()) + in = in.bandjoin(255); - 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); + VImage noAlpha = + in.extract_band(0, VImage::option()->set("n", in.bands() - 1)); + VImage inverted = noAlpha.invert(); + VImage out = inverted.bandjoin(in.extract_band(3)); - VImage noAlpha = - in.extract_band(0, VImage::option()->set("n", in.bands() - 1)); - VImage inverted = noAlpha.invert(); - VImage out = inverted.bandjoin(in.extract_band(3)); - - void *buf; - size_t length; - out.write_to_buffer(("." + type).c_str(), &buf, &length); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", type); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); - } + void *buf; + out.write_to_buffer(("." + type).c_str(), &buf, DataSize); vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } \ No newline at end of file diff --git a/natives/invert.h b/natives/invert.h index 3306fa9..de6f32a 100644 --- a/natives/invert.h +++ b/natives/invert.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Invert(const Napi::CallbackInfo& info); +using std::string; + +char* Invert(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/jpeg.cc b/natives/jpeg.cc index 5298c81..46412d6 100644 --- a/natives/jpeg.cc +++ b/natives/jpeg.cc @@ -1,91 +1,70 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Jpeg(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Jpeg(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { + int quality = GetArgumentWithFallback(Arguments, "quality", 0); - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - int quality = obj.Has("quality") - ? obj.Get("quality").As().Int32Value() - : 0; - string type = obj.Get("type").As().Utf8Value(); + void *buf; - if (type == "gif") { - VImage in = - VImage::new_from_buffer( - data.Data(), data.Length(), "", - VImage::option()->set("access", "sequential")->set("n", -1)) - .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) - in = in.bandjoin(255); + if (type == "gif") { + VImage in = VImage::new_from_buffer( + BufferData, BufferLength, "", + VImage::option()->set("access", "sequential")->set("n", -1)) + .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 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 final; + VImage final; - if (totalHeight > 65500) { - 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", quality)->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 { + if (totalHeight > 65500) { + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = in.crop(0, i * pageHeight, width, pageHeight); void *jpgBuf; size_t jpgLength; - in.write_to_buffer( + img_frame.write_to_buffer( ".jpg", &jpgBuf, &jpgLength, VImage::option()->set("Q", quality)->set("strip", true)); - final = VImage::new_from_buffer(jpgBuf, jpgLength, ""); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight); - final.set("delay", in.get_array_int("delay")); + 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); } - - void *buf; - size_t length; - final.write_to_buffer(("." + type).c_str(), &buf, &length, - type == "gif" ? VImage::option()->set("dither", 0) - : 0); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", type); + final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight); } else { - VImage in = VImage::new_from_buffer(data.Data(), data.Length(), ""); - void *buf; - size_t length; + void *jpgBuf; + size_t jpgLength; in.write_to_buffer( - ".jpg", &buf, &length, + ".jpg", &jpgBuf, &jpgLength, VImage::option()->set("Q", quality)->set("strip", true)); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", "jpg"); + final = VImage::new_from_buffer(jpgBuf, jpgLength, ""); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight); + final.set("delay", in.get_array_int("delay")); } - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + + final.write_to_buffer(("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 0) + : 0); + } else { + VImage in = VImage::new_from_buffer(BufferData, BufferLength, ""); + in.write_to_buffer(".jpg", &buf, DataSize, + VImage::option()->set("Q", quality)->set("strip", true)); + + type = "jpg"; } vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } diff --git a/natives/jpeg.h b/natives/jpeg.h index c65e79c..1f75b6b 100644 --- a/natives/jpeg.h +++ b/natives/jpeg.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Jpeg(const Napi::CallbackInfo& info); +using std::string; + +char* Jpeg(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/meme.cc b/natives/meme.cc index 250581e..9ecf8c7 100644 --- a/natives/meme.cc +++ b/natives/meme.cc @@ -1,160 +1,142 @@ #include "common.h" -#include #include using namespace std; using namespace vips; -Napi::Value Meme(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Meme(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { + string top = GetArgument(Arguments, "top"); + string bottom = GetArgument(Arguments, "bottom"); + string font = GetArgument(Arguments, "font"); + string basePath = GetArgument(Arguments, "basePath"); - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - string top = obj.Get("top").As().Utf8Value(); - string bottom = obj.Get("bottom").As().Utf8Value(); - string font = obj.Get("font").As().Utf8Value(); - string type = obj.Get("type").As().Utf8Value(); - string basePath = obj.Get("basePath").As().Utf8Value(); + 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); + if (!in.has_alpha()) + in = in.bandjoin(255); - 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); + 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 size = width / 9; + int dividedWidth = width / 1000; + int rad = 1; + vector zeroVec = {0, 0, 0, 0}; - 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 size = width / 9; - int dividedWidth = width / 1000; - int rad = 1; - vector zeroVec = {0, 0, 0, 0}; + string font_string = + (font == "roboto" ? "Roboto Condensed" : font) + ", Twemoji Color Font " + + (font != "impact" ? "bold" : "normal") + " " + to_string(size); - string font_string = (font == "roboto" ? "Roboto Condensed" : font) + ", Twemoji Color Font " + - (font != "impact" ? "bold" : "normal") + - " " + to_string(size); + VImage mask = VImage::black(rad * 2 + 1, rad * 2 + 1) + 128; + mask.draw_circle({255}, rad, rad, rad, VImage::option()->set("fill", true)); - VImage mask = VImage::black(rad * 2 + 1, rad * 2 + 1) + 128; - mask.draw_circle({255}, rad, rad, rad, VImage::option()->set("fill", true)); + VImage altMask; - VImage altMask; - - if (dividedWidth >= 1) { - altMask = VImage::black(dividedWidth * 2 + 1, dividedWidth * 2 + 1) + 128; - altMask.draw_circle({255}, dividedWidth, dividedWidth, dividedWidth, - VImage::option()->set("fill", true)); - } - - auto findResult = fontPaths.find(font); - if (findResult != fontPaths.end()) { - VImage::text( - ".", VImage::option()->set("fontfile", - (basePath + findResult->second).c_str())); - } - - VImage topText; - if (top != "") { - VImage topIn = VImage::text( - ("" + top + "").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", width)); - - topIn = topIn.embed(rad + 10, rad + 10, (topIn.width() + 2 * rad) + 20, - (topIn.height() + 2 * rad) + 20); - - VImage topOutline = - topIn.morph(mask, VIPS_OPERATION_MORPHOLOGY_DILATE) - .gaussblur(0.5, VImage::option()->set("min_ampl", 0.1)); - if (dividedWidth >= 1) { - topOutline = - topOutline.morph(altMask, VIPS_OPERATION_MORPHOLOGY_DILATE); - } - topOutline = (topOutline == zeroVec); - VImage topInvert = topOutline.extract_band(3).invert(); - topOutline = - topOutline - .extract_band(0, - VImage::option()->set("n", topOutline.bands() - 1)) - .bandjoin(topInvert); - topText = topOutline.composite2(topIn, VIPS_BLEND_MODE_OVER); - } - - VImage bottomText; - if (bottom != "") { - VImage bottomIn = VImage::text( - ("" + bottom + "").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", width)); - bottomIn = - bottomIn.embed(rad + 10, rad + 10, (bottomIn.width() + 2 * rad) + 20, - (bottomIn.height() + 2 * rad) + 20); - VImage bottomOutline = - bottomIn.morph(mask, VIPS_OPERATION_MORPHOLOGY_DILATE) - .gaussblur(0.5, VImage::option()->set("min_ampl", 0.1)); - if (dividedWidth >= 1) { - bottomOutline = - bottomOutline.morph(altMask, VIPS_OPERATION_MORPHOLOGY_DILATE); - } - bottomOutline = (bottomOutline == zeroVec); - VImage bottomInvert = bottomOutline.extract_band(3).invert(); - bottomOutline = bottomOutline - .extract_band(0, VImage::option()->set( - "n", bottomOutline.bands() - 1)) - .bandjoin(bottomInvert); - bottomText = bottomOutline.composite2(bottomIn, VIPS_BLEND_MODE_OVER); - } - - vector img; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - if (top != "") { - img_frame = img_frame.composite2( - topText, VIPS_BLEND_MODE_OVER, - VImage::option()->set("x", (width / 2) - (topText.width() / 2))); - } - if (bottom != "") { - img_frame = img_frame.composite2( - bottomText, VIPS_BLEND_MODE_OVER, - VImage::option() - ->set("x", (width / 2) - (bottomText.width() / 2)) - ->set("y", pageHeight - bottomText.height())); - } - img.push_back(img_frame); - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight); - - void *buf; - size_t length; - final.write_to_buffer( - ("." + type).c_str(), &buf, &length, - 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); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + if (dividedWidth >= 1) { + altMask = VImage::black(dividedWidth * 2 + 1, dividedWidth * 2 + 1) + 128; + altMask.draw_circle({255}, dividedWidth, dividedWidth, dividedWidth, + VImage::option()->set("fill", true)); } + auto findResult = fontPaths.find(font); + if (findResult != fontPaths.end()) { + VImage::text(".", VImage::option()->set( + "fontfile", (basePath + findResult->second).c_str())); + } + + VImage topText; + if (top != "") { + VImage topIn = VImage::text( + ("" + top + "").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", width)); + + topIn = topIn.embed(rad + 10, rad + 10, (topIn.width() + 2 * rad) + 20, + (topIn.height() + 2 * rad) + 20); + + VImage topOutline = + topIn.morph(mask, VIPS_OPERATION_MORPHOLOGY_DILATE) + .gaussblur(0.5, VImage::option()->set("min_ampl", 0.1)); + if (dividedWidth >= 1) { + topOutline = topOutline.morph(altMask, VIPS_OPERATION_MORPHOLOGY_DILATE); + } + topOutline = (topOutline == zeroVec); + VImage topInvert = topOutline.extract_band(3).invert(); + topOutline = + topOutline + .extract_band(0, VImage::option()->set("n", topOutline.bands() - 1)) + .bandjoin(topInvert); + topText = topOutline.composite2(topIn, VIPS_BLEND_MODE_OVER); + } + + VImage bottomText; + if (bottom != "") { + VImage bottomIn = VImage::text( + ("" + bottom + "").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", width)); + bottomIn = + bottomIn.embed(rad + 10, rad + 10, (bottomIn.width() + 2 * rad) + 20, + (bottomIn.height() + 2 * rad) + 20); + VImage bottomOutline = + bottomIn.morph(mask, VIPS_OPERATION_MORPHOLOGY_DILATE) + .gaussblur(0.5, VImage::option()->set("min_ampl", 0.1)); + if (dividedWidth >= 1) { + bottomOutline = + bottomOutline.morph(altMask, VIPS_OPERATION_MORPHOLOGY_DILATE); + } + bottomOutline = (bottomOutline == zeroVec); + VImage bottomInvert = bottomOutline.extract_band(3).invert(); + bottomOutline = + bottomOutline + .extract_band(0, + VImage::option()->set("n", bottomOutline.bands() - 1)) + .bandjoin(bottomInvert); + bottomText = bottomOutline.composite2(bottomIn, VIPS_BLEND_MODE_OVER); + } + + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + if (top != "") { + img_frame = img_frame.composite2( + topText, VIPS_BLEND_MODE_OVER, + VImage::option()->set("x", (width / 2) - (topText.width() / 2))); + } + if (bottom != "") { + img_frame = img_frame.composite2( + bottomText, VIPS_BLEND_MODE_OVER, + VImage::option() + ->set("x", (width / 2) - (bottomText.width() / 2)) + ->set("y", pageHeight - bottomText.height())); + } + img.push_back(img_frame); + } + 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); + vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } \ No newline at end of file diff --git a/natives/meme.h b/natives/meme.h index bc87332..f0079f5 100644 --- a/natives/meme.h +++ b/natives/meme.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Meme(const Napi::CallbackInfo& info); +using std::string; + +char* Meme(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/mirror.cc b/natives/mirror.cc index 5467aa1..07457ed 100644 --- a/natives/mirror.cc +++ b/natives/mirror.cc @@ -1,84 +1,67 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Mirror(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Mirror(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { + bool vertical = GetArgumentWithFallback(Arguments, "vertical", false); + bool first = GetArgumentWithFallback(Arguments, "first", false); - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - bool vertical = obj.Has("vertical") - ? obj.Get("vertical").As().Value() - : false; - bool first = - obj.Has("first") ? obj.Get("first").As().Value() : false; - string type = obj.Get("type").As().Utf8Value(); + 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); + if (!in.has_alpha()) + in = in.bandjoin(255); - 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); + VImage out; - VImage out; - - if (vertical) { - if (type == "gif") { - // once again, 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()); - bool isOdd = pageHeight % 2; - for (int i = 0; i < nPages; i++) { - int x = (i * pageHeight) + (first ? 0 : (pageHeight / 2)); - VImage cropped = in.crop(0, x, in.width(), pageHeight / 2); - VImage flipped = cropped.flip(VIPS_DIRECTION_VERTICAL); - VImage final = VImage::arrayjoin( - {first ? cropped : flipped, first ? flipped : cropped}, - VImage::option()->set("across", 1)); - img.push_back(final); - } - out = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - out.set(VIPS_META_PAGE_HEIGHT, pageHeight - (isOdd ? 1 : 0)); - } else { - VImage cropped = in.extract_area(0, 0, in.width(), in.height() / 2); + if (vertical) { + if (type == "gif") { + // once again, 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()); + bool isOdd = pageHeight % 2; + for (int i = 0; i < nPages; i++) { + int x = (i * pageHeight) + (first ? 0 : (pageHeight / 2)); + VImage cropped = in.crop(0, x, in.width(), pageHeight / 2); VImage flipped = cropped.flip(VIPS_DIRECTION_VERTICAL); - out = VImage::arrayjoin({cropped, flipped}, - VImage::option()->set("across", 1)); + VImage final = VImage::arrayjoin( + {first ? cropped : flipped, first ? flipped : cropped}, + VImage::option()->set("across", 1)); + img.push_back(final); } + out = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + out.set(VIPS_META_PAGE_HEIGHT, pageHeight - (isOdd ? 1 : 0)); } else { - if (first) { - VImage cropped = in.extract_area(0, 0, in.width() / 2, in.height()); - VImage flipped = cropped.flip(VIPS_DIRECTION_HORIZONTAL); - out = VImage::arrayjoin({cropped, flipped}); - } else { - int size = in.width() / 2; - VImage cropped = in.extract_area(size, 0, size, in.height()); - VImage flipped = cropped.flip(VIPS_DIRECTION_HORIZONTAL); - out = VImage::arrayjoin({flipped, cropped}); - } + VImage cropped = in.extract_area(0, 0, in.width(), in.height() / 2); + VImage flipped = cropped.flip(VIPS_DIRECTION_VERTICAL); + out = VImage::arrayjoin({cropped, flipped}, + VImage::option()->set("across", 1)); + } + } else { + if (first) { + VImage cropped = in.extract_area(0, 0, in.width() / 2, in.height()); + VImage flipped = cropped.flip(VIPS_DIRECTION_HORIZONTAL); + out = VImage::arrayjoin({cropped, flipped}); + } else { + int size = in.width() / 2; + VImage cropped = in.extract_area(size, 0, size, in.height()); + VImage flipped = cropped.flip(VIPS_DIRECTION_HORIZONTAL); + out = VImage::arrayjoin({flipped, cropped}); } - - void *buf; - size_t length; - out.write_to_buffer(("." + type).c_str(), &buf, &length); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", type); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); } + void *buf; + out.write_to_buffer(("." + type).c_str(), &buf, DataSize); + vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } diff --git a/natives/mirror.h b/natives/mirror.h index 0137365..4b947cd 100644 --- a/natives/mirror.h +++ b/natives/mirror.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Mirror(const Napi::CallbackInfo& info); +using std::string; + +char* Mirror(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/motivate.cc b/natives/motivate.cc index 0bce582..aafbc26 100644 --- a/natives/motivate.cc +++ b/natives/motivate.cc @@ -1,144 +1,126 @@ #include "common.h" -#include #include using namespace std; using namespace vips; -Napi::Value Motivate(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Motivate(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { + string top_text = GetArgument(Arguments, "top"); + string bottom_text = GetArgument(Arguments, "bottom"); + string font = GetArgument(Arguments, "font"); + string basePath = GetArgument(Arguments, "basePath"); - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - string top_text = obj.Get("top").As().Utf8Value(); - string bottom_text = obj.Get("bottom").As().Utf8Value(); - string font = obj.Get("font").As().Utf8Value(); - string type = obj.Get("type").As().Utf8Value(); - string basePath = obj.Get("basePath").As().Utf8Value(); + 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); + if (!in.has_alpha()) + in = in.bandjoin(255); - 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); + int width = in.width(); + int size = width / 5; + 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); - int width = in.width(); - int size = width / 5; - 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 font_string = + (font == "roboto" ? "Roboto Condensed" : font) + ", Twemoji Color Font"; - string font_string = - (font == "roboto" ? "Roboto Condensed" : font) + ", Twemoji Color Font"; - - auto findResult = fontPaths.find(font); - if (findResult != fontPaths.end()) { - VImage::text( - ".", VImage::option()->set("fontfile", - (basePath + findResult->second).c_str())); - } - - VImage topImage; - if (top_text != "") { - string topText = "" + - top_text + ""; - - topImage = VImage::text( - topText.c_str(), - VImage::option() - ->set("rgba", true) - ->set("align", VIPS_ALIGN_CENTRE) - ->set("font", (font_string + " " + to_string(size)).c_str()) - ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) - ->set("width", textWidth)); - } - - VImage bottomImage; - if (bottom_text != "") { - string bottomText = "" + - bottom_text + ""; - - bottomImage = VImage::text( - bottomText.c_str(), - VImage::option() - ->set("rgba", true) - ->set("align", VIPS_ALIGN_CENTRE) - ->set("font", (font_string + " " + to_string(size * 0.4)).c_str()) - ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) - ->set("width", textWidth)); - } - - vector img; - int height; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - - int borderSize = max(2, width / 66); - int borderSize2 = borderSize * 0.5; - VImage bordered = - img_frame.embed(borderSize, borderSize, width + (borderSize * 2), - pageHeight + (borderSize * 2), - VImage::option()->set("extend", "black")); - VImage bordered2 = bordered.embed( - borderSize2, borderSize2, bordered.width() + (borderSize2 * 2), - bordered.height() + (borderSize2 * 2), - VImage::option()->set("extend", "white")); - - int addition = width / 8; - int sideAddition = pageHeight * 0.4; - - VImage bordered3 = bordered2.embed( - sideAddition / 2, addition / 2, bordered2.width() + sideAddition, - bordered2.height() + addition, - VImage::option()->set("extend", "black")); - VImage frame; - if (top_text != "") { - frame = bordered3.join( - topImage.gravity(VIPS_COMPASS_DIRECTION_NORTH, bordered3.width(), - topImage.height() + (size / 4), - VImage::option()->set("extend", "black")), - VIPS_DIRECTION_VERTICAL, - VImage::option()->set("background", 0x000000)->set("expand", true)); - } - if (bottom_text != "") { - if (top_text == "") - frame = bordered3; - frame = frame.join( - bottomImage.gravity(VIPS_COMPASS_DIRECTION_NORTH, bordered3.width(), - bottomImage.height() + (size / 4), - VImage::option()->set("extend", "black")), - VIPS_DIRECTION_VERTICAL, - VImage::option()->set("background", 0x000000)->set("expand", true)); - } - height = frame.height(); - img.push_back(frame); - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)) - .extract_band(0, VImage::option()->set("n", 3)); - final.set(VIPS_META_PAGE_HEIGHT, height); - - void *buf; - size_t length; - final.write_to_buffer(("." + type).c_str(), &buf, &length, - type == "gif" ? VImage::option()->set("dither", 1) - : 0); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", type); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + auto findResult = fontPaths.find(font); + if (findResult != fontPaths.end()) { + VImage::text(".", VImage::option()->set( + "fontfile", (basePath + findResult->second).c_str())); } + VImage topImage; + if (top_text != "") { + string topText = "" + + top_text + ""; + + topImage = VImage::text( + topText.c_str(), + VImage::option() + ->set("rgba", true) + ->set("align", VIPS_ALIGN_CENTRE) + ->set("font", (font_string + " " + to_string(size)).c_str()) + ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) + ->set("width", textWidth)); + } + + VImage bottomImage; + if (bottom_text != "") { + string bottomText = "" + + bottom_text + ""; + + bottomImage = VImage::text( + bottomText.c_str(), + VImage::option() + ->set("rgba", true) + ->set("align", VIPS_ALIGN_CENTRE) + ->set("font", (font_string + " " + to_string(size * 0.4)).c_str()) + ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) + ->set("width", textWidth)); + } + + vector img; + int height; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + + int borderSize = max(2, width / 66); + int borderSize2 = borderSize * 0.5; + VImage bordered = + img_frame.embed(borderSize, borderSize, width + (borderSize * 2), + pageHeight + (borderSize * 2), + VImage::option()->set("extend", "black")); + VImage bordered2 = bordered.embed(borderSize2, borderSize2, + bordered.width() + (borderSize2 * 2), + bordered.height() + (borderSize2 * 2), + VImage::option()->set("extend", "white")); + + int addition = width / 8; + int sideAddition = pageHeight * 0.4; + + VImage bordered3 = bordered2.embed( + sideAddition / 2, addition / 2, bordered2.width() + sideAddition, + bordered2.height() + addition, + VImage::option()->set("extend", "black")); + VImage frame; + if (top_text != "") { + frame = bordered3.join( + topImage.gravity(VIPS_COMPASS_DIRECTION_NORTH, bordered3.width(), + topImage.height() + (size / 4), + VImage::option()->set("extend", "black")), + VIPS_DIRECTION_VERTICAL, + VImage::option()->set("background", 0x000000)->set("expand", true)); + } + if (bottom_text != "") { + if (top_text == "") + frame = bordered3; + frame = frame.join( + bottomImage.gravity(VIPS_COMPASS_DIRECTION_NORTH, bordered3.width(), + bottomImage.height() + (size / 4), + VImage::option()->set("extend", "black")), + VIPS_DIRECTION_VERTICAL, + VImage::option()->set("background", 0x000000)->set("expand", true)); + } + height = frame.height(); + img.push_back(frame); + } + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)) + .extract_band(0, VImage::option()->set("n", 3)); + final.set(VIPS_META_PAGE_HEIGHT, height); + + void *buf; + final.write_to_buffer(("." + type).c_str(), &buf, DataSize, + type == "gif" ? VImage::option()->set("dither", 1) : 0); + vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } diff --git a/natives/motivate.h b/natives/motivate.h index eb4d439..eccf83a 100644 --- a/natives/motivate.h +++ b/natives/motivate.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Motivate(const Napi::CallbackInfo& info); +using std::string; + +char* Motivate(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/reddit.cc b/natives/reddit.cc index 7958e16..d7a4b80 100644 --- a/natives/reddit.cc +++ b/natives/reddit.cc @@ -1,84 +1,70 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Reddit(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Reddit(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - string text = obj.Get("caption").As().Utf8Value(); - string type = obj.Get("type").As().Utf8Value(); - string basePath = obj.Get("basePath").As().Utf8Value(); + string text = GetArgument(Arguments, "text"); + string basePath = GetArgument(Arguments, "basePath"); - VOption *options = VImage::option()->set("access", "sequential"); + VOption *options = VImage::option()->set("access", "sequential"); - 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); + 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); - string assetPath = basePath + "assets/images/reddit.png"; - VImage tmpl = VImage::new_from_file(assetPath.c_str()); + string assetPath = basePath + "assets/images/reddit.png"; + VImage tmpl = VImage::new_from_file(assetPath.c_str()); - 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 captionText = "" + text + ""; + string captionText = "" + text + ""; - VImage textImage = VImage::text( - ".", VImage::option()->set( - "fontfile", (basePath + "assets/fonts/reddit.ttf").c_str())); - textImage = VImage::text( - captionText.c_str(), - VImage::option() - ->set("rgba", true) - ->set("font", "Roboto, Twemoji Color Font 62") - ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) - ->set("align", VIPS_ALIGN_LOW)); + VImage textImage = VImage::text( + ".", VImage::option()->set( + "fontfile", (basePath + "assets/fonts/reddit.ttf").c_str())); + textImage = VImage::text( + captionText.c_str(), + VImage::option() + ->set("rgba", true) + ->set("font", "Roboto, Twemoji Color Font 62") + ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) + ->set("align", VIPS_ALIGN_LOW)); - VImage composited = - tmpl.composite2(textImage, VIPS_BLEND_MODE_OVER, - VImage::option()->set("x", 375)->set( - "y", (tmpl.height() - textImage.height()) - 64)); - VImage watermark = - composited.resize((double)width / (double)composited.width()); + VImage composited = + tmpl.composite2(textImage, VIPS_BLEND_MODE_OVER, + VImage::option()->set("x", 375)->set( + "y", (tmpl.height() - textImage.height()) - 64)); + VImage watermark = + composited.resize((double)width / (double)composited.width()); - vector img; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - VImage frame = img_frame.join(watermark, VIPS_DIRECTION_VERTICAL, - VImage::option()->set("expand", true)); - img.push_back(frame); - } - VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight + watermark.height()); - - void *buf; - size_t length; - final.write_to_buffer( - ("." + type).c_str(), &buf, &length, - 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); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + VImage frame = img_frame.join(watermark, VIPS_DIRECTION_VERTICAL, + VImage::option()->set("expand", true)); + img.push_back(frame); } + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight + watermark.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 result; + return (char *)buf; } \ No newline at end of file diff --git a/natives/reddit.h b/natives/reddit.h index b80c11d..608bbe4 100644 --- a/natives/reddit.h +++ b/natives/reddit.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Reddit(const Napi::CallbackInfo& info); +using std::string; + +char* Reddit(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/resize.cc b/natives/resize.cc index 6597801..d0fb87e 100644 --- a/natives/resize.cc +++ b/natives/resize.cc @@ -1,74 +1,56 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Resize(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Resize(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { + bool stretch = GetArgumentWithFallback(Arguments, "stretch", false); + bool wide = GetArgumentWithFallback(Arguments, "wide", false); - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - bool stretch = obj.Has("stretch") - ? obj.Get("stretch").As().Value() - : false; - bool wide = - obj.Has("wide") ? obj.Get("wide").As().Value() : false; - string type = obj.Get("type").As().Utf8Value(); + 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(data.Data(), data.Length(), "", - type == "gif" ? options->set("n", -1) : options) - .colourspace(VIPS_INTERPRETATION_sRGB); + VImage out; - VImage out; + 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()); - - int finalHeight; - if (stretch) { - out = in.resize( - 512.0 / (double)width, - VImage::option()->set("vscale", 512.0 / (double)pageHeight)); - finalHeight = 512; - } else if (wide) { - out = in.resize(9.5, VImage::option()->set("vscale", 0.5)); - finalHeight = pageHeight / 2; - } else { - // Pain. Pain. Pain. Pain. Pain. - vector img; - for (int i = 0; i < nPages; i++) { - VImage img_frame = - type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; - VImage resized = img_frame.resize(0.1).resize( - 10, VImage::option()->set("kernel", VIPS_KERNEL_NEAREST)); - img.push_back(resized); - finalHeight = resized.height(); - } - out = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + int finalHeight; + if (stretch) { + out = + in.resize(512.0 / (double)width, + VImage::option()->set("vscale", 512.0 / (double)pageHeight)); + finalHeight = 512; + } else if (wide) { + out = in.resize(9.5, VImage::option()->set("vscale", 0.5)); + finalHeight = pageHeight / 2; + } else { + // Pain. Pain. Pain. Pain. Pain. + vector img; + for (int i = 0; i < nPages; i++) { + VImage img_frame = + type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in; + VImage resized = img_frame.resize(0.1).resize( + 10, VImage::option()->set("kernel", VIPS_KERNEL_NEAREST)); + img.push_back(resized); + finalHeight = resized.height(); } - out.set(VIPS_META_PAGE_HEIGHT, finalHeight); - - void *buf; - size_t length; - out.write_to_buffer(("." + type).c_str(), &buf, &length); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", type); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + out = VImage::arrayjoin(img, VImage::option()->set("across", 1)); } + out.set(VIPS_META_PAGE_HEIGHT, finalHeight); + + void *buf; + out.write_to_buffer(("." + type).c_str(), &buf, DataSize); vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } \ No newline at end of file diff --git a/natives/resize.h b/natives/resize.h index 496b332..5ecb7cd 100644 --- a/natives/resize.h +++ b/natives/resize.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Resize(const Napi::CallbackInfo& info); +using std::string; + +char* Resize(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/reverse.cc b/natives/reverse.cc index c03576f..1c507da 100644 --- a/natives/reverse.cc +++ b/natives/reverse.cc @@ -1,72 +1,61 @@ -#include +#include "common.h" +#include #include using namespace std; using namespace vips; -Napi::Value Reverse(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Reverse(string type, char *BufferData, size_t BufferLength, + ArgumentMap Arguments, size_t *DataSize) { + bool soos = GetArgumentWithFallback(Arguments, "soos", false); - try { - Napi::Object obj = info[1].As(); - Napi::Buffer data = obj.Get("data").As>(); - bool soos = - obj.Has("soos") ? obj.Get("soos").As().Value() : false; + VOption *options = + VImage::option()->set("access", "sequential")->set("n", -1); - VOption *options = - VImage::option()->set("access", "sequential")->set("n", -1); + VImage in = VImage::new_from_buffer(BufferData, BufferLength, "", options) + .colourspace(VIPS_INTERPRETATION_sRGB); - VImage in = VImage::new_from_buffer(data.Data(), data.Length(), "", 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 split; - // todo: find a better way of getting individual frames (or at least getting the frames in reverse order) - for (int i = 0; i < nPages; i++) { - VImage img_frame = in.crop(0, i * pageHeight, width, pageHeight); - split.push_back(img_frame); - } - - vector delays = in.get_array_int("delay"); - if (soos) { - vector copy = split; - vector copy2 = delays; - reverse(copy.begin(), copy.end()); - reverse(copy2.begin(), copy2.end()); - copy.pop_back(); - copy2.pop_back(); - copy.erase(copy.begin()); - copy2.erase(copy2.begin()); - split.insert(split.end(), copy.begin(), copy.end()); - delays.insert(delays.end(), copy2.begin(), copy2.end()); - } else { - reverse(split.begin(), split.end()); - reverse(delays.begin(), delays.end()); - } - - VImage final = VImage::arrayjoin(split, VImage::option()->set("across", 1)); - final.set(VIPS_META_PAGE_HEIGHT, pageHeight); - final.set("delay", delays); - - void *buf; - size_t length; - final.write_to_buffer(".gif", &buf, &length, - VImage::option()->set("dither", 0)); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", "gif"); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + vector split; + // todo: find a better way of getting individual frames (or at least getting + // the frames in reverse order) + for (int i = 0; i < nPages; i++) { + VImage img_frame = in.crop(0, i * pageHeight, width, pageHeight); + split.push_back(img_frame); } + vector delays = in.get_array_int("delay"); + if (soos) { + vector copy = split; + vector copy2 = delays; + reverse(copy.begin(), copy.end()); + reverse(copy2.begin(), copy2.end()); + copy.pop_back(); + copy2.pop_back(); + copy.erase(copy.begin()); + copy2.erase(copy2.begin()); + split.insert(split.end(), copy.begin(), copy.end()); + delays.insert(delays.end(), copy2.begin(), copy2.end()); + } else { + reverse(split.begin(), split.end()); + reverse(delays.begin(), delays.end()); + } + + VImage final = VImage::arrayjoin(split, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, pageHeight); + final.set("delay", delays); + + void *buf; + final.write_to_buffer(".gif", &buf, DataSize, + VImage::option()->set("dither", 0)); + + type = "gif"; + vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } \ No newline at end of file diff --git a/natives/reverse.h b/natives/reverse.h index 622c68f..9b2959d 100644 --- a/natives/reverse.h +++ b/natives/reverse.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Reverse(const Napi::CallbackInfo& info); +using std::string; + +char* Reverse(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/sonic.cc b/natives/sonic.cc index 0f501b3..b5e986e 100644 --- a/natives/sonic.cc +++ b/natives/sonic.cc @@ -1,50 +1,38 @@ -#include +#include "common.h" #include using namespace std; using namespace vips; -Napi::Value Sonic(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Sonic(string *type, ArgumentMap Arguments, size_t *DataSize) { + string text = GetArgument(Arguments, "text"); + string basePath = GetArgument(Arguments, "basePath"); - try { - Napi::Object obj = info[1].As(); - string text = obj.Get("text").As().Utf8Value(); - string basePath = obj.Get("basePath").As().Utf8Value(); + string assetPath = basePath + "assets/images/sonic.jpg"; + VImage bg = VImage::new_from_file(assetPath.c_str()); - string assetPath = basePath + "assets/images/sonic.jpg"; - VImage bg = VImage::new_from_file(assetPath.c_str()); + VImage textImage = + VImage::text( + ("" + text + "").c_str(), + VImage::option() + ->set("rgba", true) + ->set("align", VIPS_ALIGN_CENTRE) + ->set("font", "Verdana, Twemoji Color Font") + ->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()) + ->set("width", 542) + ->set("height", 390)) + .gravity(VIPS_COMPASS_DIRECTION_CENTRE, 542, 390); - VImage textImage = - VImage::text(("" + text + "").c_str(), - VImage::option() - ->set("rgba", true) - ->set("align", VIPS_ALIGN_CENTRE) - ->set("font", "Verdana, Twemoji Color Font") - ->set("fontfile", - (basePath + "assets/fonts/twemoji.otf").c_str()) - ->set("width", 542) - ->set("height", 390)) - .gravity(VIPS_COMPASS_DIRECTION_CENTRE, 542, 390); + VImage out = bg.composite2(textImage, VIPS_BLEND_MODE_OVER, + VImage::option()->set("x", 391)->set("y", 84)); - VImage out = bg.composite2(textImage, VIPS_BLEND_MODE_OVER, - VImage::option()->set("x", 391)->set("y", 84)); + void *buf; + out.write_to_buffer(".png", &buf, DataSize); - void *buf; - size_t length; - out.write_to_buffer(".png", &buf, &length); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - result.Set("type", "png"); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); - } + *type = "png"; vips_error_clear(); vips_thread_shutdown(); - return result; + return (char *)buf; } \ No newline at end of file diff --git a/natives/sonic.h b/natives/sonic.h index 46398e8..5cedb52 100644 --- a/natives/sonic.h +++ b/natives/sonic.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Sonic(const Napi::CallbackInfo& info); +using std::string; + +char* Sonic(string *type, ArgumentMap Arguments, size_t *DataSize); \ No newline at end of file