diff --git a/assets/images/spheremap.png b/assets/images/spheremap.png new file mode 100644 index 0000000..a5b1ea2 Binary files /dev/null and b/assets/images/spheremap.png differ diff --git a/commands/funky.js b/commands/funky.js index b0428c2..4d0ca93 100644 --- a/commands/funky.js +++ b/commands/funky.js @@ -1,13 +1,11 @@ -const gm = require("gm").subClass({ - imageMagick: true -}); +const magick = require("../build/Release/image.node"); +const { promisify } = require("util"); exports.run = async (message) => { message.channel.sendTyping(); const image = await require("../utils/imagedetect.js")(message); if (image === undefined) return `${message.author.mention}, you need to provide an image to add New Funky Mode!`; - const watermark = "./assets/images/funky.png"; - const buffer = await gm(image.path).coalesce().out("null:").out(watermark).gravity("NorthEast").scale(null, "%[fx:u.h]").out("-layers", "composite").bufferPromise(image.type, image.delay); + const buffer = await promisify(magick.watermark)(image.path, "./assets/images/funky.png", 3, true, image.type.toUpperCase(), image.delay ? (100 / image.delay.split("/")[0]) * image.delay.split("/")[1] : 0); return { file: buffer, name: `funky.${image.type}` diff --git a/commands/gamexplain.js b/commands/gamexplain.js index 029b395..94ef5e3 100644 --- a/commands/gamexplain.js +++ b/commands/gamexplain.js @@ -1,13 +1,11 @@ -const gm = require("gm").subClass({ - imageMagick: true -}); +const magick = require("../build/Release/image.node"); +const { promisify } = require("util"); exports.run = async (message) => { message.channel.sendTyping(); const image = await require("../utils/imagedetect.js")(message); if (image === undefined) return `${message.author.mention}, you need to provide an image to make a GameXplain thumbnail meme!`; - const template = "./assets/images/gamexplain.png"; - const buffer = await gm(template).background("white").out("null:").out("(").out(image.path).coalesce().out("-virtual-pixel", "transparent").scale("1181x571!").out(")").compose("over").gravity("Center").out("-geometry", "+0+40").out("-layers", "composite").bufferPromise(image.type, image.delay); + const buffer = await promisify(magick.gamexplain)(image.path, image.type.toUpperCase(), image.delay ? (100 / image.delay.split("/")[0]) * image.delay.split("/")[1] : 0); return { file: buffer, name: `gamexplain.${image.type}` diff --git a/commands/globe.js b/commands/globe.js new file mode 100644 index 0000000..eb92386 --- /dev/null +++ b/commands/globe.js @@ -0,0 +1,18 @@ +const magick = require("../build/Release/image.node"); +const { promisify } = require("util"); + +exports.run = async (message) => { + const image = await require("../utils/imagedetect.js")(message); + if (image === undefined) return `${message.author.mention}, you need to provide an image to spin!`; + const processMessage = await message.channel.createMessage(" Processing... This might take a while"); + const buffer = await promisify(magick.globe)(image.path, image.type.toUpperCase(), image.delay ? (100 / image.delay.split("/")[0]) * image.delay.split("/")[1] : 0); + await processMessage.delete(); + return { + file: buffer, + name: "globe.gif" + }; +}; + +exports.aliases = ["rotate"]; +exports.category = 5; +exports.help = "Spins an image"; \ No newline at end of file diff --git a/natives/globe.cc b/natives/globe.cc new file mode 100644 index 0000000..6f6a72a --- /dev/null +++ b/natives/globe.cc @@ -0,0 +1,77 @@ +#include +#include +#include +#include + +using namespace std; +using namespace Magick; + +class GlobeWorker : public Napi::AsyncWorker { + public: + GlobeWorker(Napi::Function& callback, string in_path, string type, int delay) + : Napi::AsyncWorker(callback), in_path(in_path), type(type), delay(delay) {} + ~GlobeWorker() {} + + void Execute() { + list frames; + list coalesced; + list mid; + list result; + Image distort; + readImages(&frames, in_path); + distort.read("./assets/images/spheremap.png"); + coalesceImages(&coalesced, frames.begin(), frames.end()); + + if (type != "GIF") { + list::iterator it = coalesced.begin(); + for (int i = 0; i < 29; ++i) { + coalesced.push_back(*it); + } + } + + int i = 0; + + for (Image &image : coalesced) { + image.scale(Geometry("500x500!")); + image.alphaChannel(Magick::SetAlphaChannel); + size_t width = image.columns(); + image.roll(Geometry("+" + to_string(width * i / coalesced.size()))); + image.composite(distort, Magick::CenterGravity, Magick::DistortCompositeOp); + image.magick("GIF"); + mid.push_back(image); + i++; + } + + optimizeImageLayers(&result, mid.begin(), mid.end()); + if (delay != 0) { + for_each(result.begin(), result.end(), animationDelayImage(delay)); + } else if (type != "GIF") { + for_each(result.begin(), result.end(), animationDelayImage(5)); + } + writeImages(result.begin(), result.end(), &blob); + } + + void OnOK() { + Callback().Call({Env().Undefined(), Napi::Buffer::Copy(Env(), (char *)blob.data(), blob.length())}); + } + + private: + string in_path, type; + int delay, wordlength, n; + size_t bytes, type_size; + Blob blob; +}; + +Napi::Value Globe(const Napi::CallbackInfo &info) +{ + Napi::Env env = info.Env(); + + string in_path = info[0].As().Utf8Value(); + string type = info[1].As().Utf8Value(); + int delay = info[2].As().Int32Value(); + Napi::Function cb = info[3].As(); + + GlobeWorker* blurWorker = new GlobeWorker(cb, in_path, type, delay); + blurWorker->Queue(); + return env.Undefined(); +} \ No newline at end of file diff --git a/natives/globe.h b/natives/globe.h new file mode 100644 index 0000000..de8a13c --- /dev/null +++ b/natives/globe.h @@ -0,0 +1,8 @@ +#ifndef ESMBOT_NATIVES_GLOBE_H_ +#define ESMBOT_NATIVES_GLOBE_H_ + +#include + +Napi::Value Globe(const Napi::CallbackInfo& info); + +#endif \ No newline at end of file diff --git a/natives/image.cc b/natives/image.cc index b17080d..ebed45d 100644 --- a/natives/image.cc +++ b/natives/image.cc @@ -9,6 +9,8 @@ #include "flip.h" #include "flop.h" #include "freeze.h" +#include "gamexplain.h" +#include "globe.h" #include "invert.h" #include "watermark.h" @@ -24,6 +26,8 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) exports.Set(Napi::String::New(env, "flip"), Napi::Function::New(env, Flip)); exports.Set(Napi::String::New(env, "flop"), Napi::Function::New(env, Flop)); exports.Set(Napi::String::New(env, "freeze"), Napi::Function::New(env, Freeze)); + exports.Set(Napi::String::New(env, "gamexplain"), Napi::Function::New(env, Gamexplain)); + exports.Set(Napi::String::New(env, "globe"), Napi::Function::New(env, Globe)); exports.Set(Napi::String::New(env, "invert"), Napi::Function::New(env, Invert)); exports.Set(Napi::String::New(env, "watermark"), Napi::Function::New(env, Watermark)); return exports;