diff --git a/assets/images/scottmap.png b/assets/images/scottmap.png new file mode 100644 index 0000000..f57e04e Binary files /dev/null and b/assets/images/scottmap.png differ diff --git a/natives/scott.cc b/natives/scott.cc index aabd828..d6e6ea6 100644 --- a/natives/scott.cc +++ b/natives/scott.cc @@ -1,64 +1,55 @@ -#include - -#include -#include -#include +#include #include "common.h" using namespace std; -using namespace Magick; +using namespace vips; char *Scott(string type, string *outType, char *BufferData, size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) { string basePath = GetArgument(Arguments, "basePath"); - Blob blob; + VOption *options = VImage::option()->set("access", "sequential"); - list frames; - list coalesced; - list mid; - Image watermark; - 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; + 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 assetPath = basePath + "assets/images/scott.png"; + VImage bg = VImage::new_from_file(assetPath.c_str()); + + string distortPath = basePath + "assets/images/scottmap.png"; + VImage distort = VImage::new_from_file(distortPath.c_str()); + + VImage distortImage = + ((distort[1] / 255) * 414).bandjoin((distort[0] / 255) * 233); + + 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( + 415 / (double)width, + VImage::option()->set("vscale", 234 / (double)pageHeight)); + VImage mapped = resized.mapim(distortImage) + .extract_band(0, VImage::option()->set("n", 3)) + .bandjoin(distort[2]); + VImage offset = mapped.embed(127, 181, 864, 481); + VImage composited = bg.composite2(offset, VIPS_BLEND_MODE_OVER); + img.push_back(composited); } - watermark.read(basePath + "assets/images/scott.png"); - coalesceImages(&coalesced, frames.begin(), frames.end()); + VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1)); + final.set(VIPS_META_PAGE_HEIGHT, 481); - for (Image &image : coalesced) { - Image watermark_new = watermark; - image.virtualPixelMethod(Magick::TransparentVirtualPixelMethod); - image.backgroundColor("none"); - image.scale(Geometry("415x234!")); - double arguments[16] = {0, 0, 129, 187, 415, 0, 517, 182, - 415, 234, 517, 465, 0, 234, 132, 418}; - image.distort(Magick::PerspectiveDistortion, 16, arguments, true); - image.extent(Geometry("864x481"), Magick::CenterGravity); - watermark_new.composite(image, Geometry("-110+83"), - Magick::OverCompositeOp); - watermark_new.magick(*outType); - watermark_new.animationDelay(image.animationDelay()); - mid.push_back(watermark_new); - } - - optimizeTransparency(mid.begin(), mid.end()); - - if (*outType == "gif") { - for (Image &image : mid) { - image.quantizeDitherMethod(FloydSteinbergDitherMethod); - image.quantize(); - } - } - - writeImages(mid.begin(), mid.end(), &blob); - - *DataSize = blob.length(); - - char *data = (char *)malloc(*DataSize); - memcpy(data, blob.data(), *DataSize); - return data; + void *buf; + final.write_to_buffer( + ("." + *outType).c_str(), &buf, DataSize, + *outType == "gif" ? VImage::option()->set("dither", 1) : 0); + return (char *)buf; } \ No newline at end of file diff --git a/package.json b/package.json index 62a751b..8eff11b 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "jsqr": "^1.4.0", "node-addon-api": "^5.1.0", "node-emoji": "^1.11.0", - "oceanic.js": "1.4.1", + "oceanic.js": "1.5.1", "qrcode": "^1.5.1", "sharp": "^0.31.3", "shoukaku": "^3.3.1", @@ -49,7 +49,7 @@ "@babel/plugin-proposal-class-properties": "^7.18.6", "cmake-js": "^7.2.1", "eslint": "^8.35.0", - "eslint-plugin-unicorn": "^45.0.2" + "eslint-plugin-unicorn": "^46.0.0" }, "optionalDependencies": { "better-sqlite3": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dccf57d..4f4f486 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,13 +12,13 @@ specifiers: emoji-regex: ^10.2.1 erlpack: ^0.1.4 eslint: ^8.35.0 - eslint-plugin-unicorn: ^45.0.2 + eslint-plugin-unicorn: ^46.0.0 file-type: ^18.2.1 format-duration: ^3.0.2 jsqr: ^1.4.0 node-addon-api: ^5.1.0 node-emoji: ^1.11.0 - oceanic.js: 1.4.1 + oceanic.js: 1.5.1 pm2: ^5.2.2 postgres: ^3.3.4 qrcode: ^1.5.1 @@ -39,7 +39,7 @@ dependencies: jsqr: 1.4.0 node-addon-api: 5.1.0 node-emoji: 1.11.0 - oceanic.js: 1.4.1_bufferutil@4.0.7 + oceanic.js: 1.5.1_bufferutil@4.0.7 qrcode: 1.5.1 sharp: 0.31.3 shoukaku: 3.3.1_bufferutil@4.0.7 @@ -64,7 +64,7 @@ devDependencies: '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.21.0 cmake-js: 7.2.1 eslint: 8.35.0 - eslint-plugin-unicorn: 45.0.2_eslint@8.35.0 + eslint-plugin-unicorn: 46.0.0_eslint@8.35.0 packages: @@ -389,8 +389,8 @@ packages: kuler: 2.0.0 dev: false - /@discordjs/voice/0.13.0_bufferutil@4.0.7: - resolution: {integrity: sha512-ZzwDmVINaLgkoDUeTJfpN9TkjINMLfTVoLMtEygm0YC5jTTw7AvKGqhc+Ae/2kNLywd0joyFVNrLp94yCkQ9SA==} + /@discordjs/voice/0.14.0_bufferutil@4.0.7: + resolution: {integrity: sha512-/LV8LSFuJ1c4OEW1ubPg3al2QNpUpwX8ZL+KL+LORmnUFVCtehSaEh+38uDfWg1O/TgiGI5vOLj4ZKql43drcw==} engines: {node: '>=16.9.0'} requiresBuild: true dependencies: @@ -1352,8 +1352,8 @@ packages: dev: false optional: true - /eslint-plugin-unicorn/45.0.2_eslint@8.35.0: - resolution: {integrity: sha512-Y0WUDXRyGDMcKLiwgL3zSMpHrXI00xmdyixEGIg90gHnj0PcHY4moNv3Ppje/kDivdAy5vUeUr7z211ImPv2gw==} + /eslint-plugin-unicorn/46.0.0_eslint@8.35.0: + resolution: {integrity: sha512-j07WkC+PFZwk8J33LYp6JMoHa1lXc1u6R45pbSAipjpfpb7KIGr17VE2D685zCxR5VL4cjrl65kTJflziQWMDA==} engines: {node: '>=14.18'} peerDependencies: eslint: '>=8.28.0' @@ -2361,14 +2361,14 @@ packages: engines: {node: '>= 6'} dev: false - /oceanic.js/1.4.1_bufferutil@4.0.7: - resolution: {integrity: sha512-wwL31SyGc6JrF0wXlgNapSR5Ziu3oBrETKpWvCXMG3YrM4EdcCGYRdwwsPtKp5lfrW9K0/+X6mvJonSyU6TByw==} + /oceanic.js/1.5.1_bufferutil@4.0.7: + resolution: {integrity: sha512-N4c25J8UCxYJ5BtqTc2EVmcRLyBO/ZGhMhwsIiodYBwBen9AX4ipqwAsAhoosOJi8+WrWiDzAI3mSJ4Lxt2Mww==} engines: {node: '>=16.16.0'} dependencies: undici: 5.20.0 ws: 8.12.1_bufferutil@4.0.7 optionalDependencies: - '@discordjs/voice': 0.13.0_bufferutil@4.0.7 + '@discordjs/voice': 0.14.0_bufferutil@4.0.7 transitivePeerDependencies: - '@discordjs/opus' - bufferutil