From 60cac5804303b542468ce2188d09f559ce31d4d0 Mon Sep 17 00:00:00 2001 From: Essem Date: Mon, 12 Dec 2022 12:13:03 -0600 Subject: [PATCH] Convert freeze and speed --- natives/freeze.cc | 163 ++++++++++++++++++++++------------------------ natives/freeze.h | 6 +- natives/image.cc | 4 +- natives/speed.cc | 130 +++++++++++++++++------------------- natives/speed.h | 6 +- 5 files changed, 149 insertions(+), 160 deletions(-) diff --git a/natives/freeze.cc b/natives/freeze.cc index 81fd718..c40d7c2 100644 --- a/natives/freeze.cc +++ b/natives/freeze.cc @@ -1,103 +1,96 @@ -#include +#include "common.h" + +#include +#include #include using namespace std; using namespace vips; -Napi::Value Freeze(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Freeze(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>(); - bool loop = - obj.Has("loop") ? obj.Get("loop").As().Value() : false; - string type = obj.Get("type").As().Utf8Value(); - int frame = obj.Has("frame") - ? obj.Get("frame").As().Int32Value() - : -1; + bool loop = GetArgumentWithFallback(Arguments, "loop", false); + int frame = GetArgumentWithFallback(Arguments, "frame", -1); - char *fileData = data.Data(); - char *match = (char *)"\x21\xFF\x0BNETSCAPE2.0\x03\x01"; - char *descriptor = (char *)"\x2C\x00\x00\x00\x00"; - char *lastPos; + char *fileData = (char *)malloc(BufferLength); + memcpy(fileData, BufferData, BufferLength); - bool none = true; + char *match = (char *)"\x21\xFF\x0BNETSCAPE2.0\x03\x01"; + char *descriptor = (char *)"\x2C\x00\x00\x00\x00"; + char *lastPos; - if (loop) { - char *newData = (char *)malloc(data.Length() + 19); - memcpy(newData, fileData, data.Length()); - lastPos = (char *)memchr(newData, '\x2C', data.Length()); - while (lastPos != NULL) { - if (memcmp(lastPos, descriptor, 5) != 0) { - lastPos = (char *)memchr(lastPos + 1, '\x2C', - (data.Length() - (lastPos - newData)) - 1); - continue; - } + bool none = true; - memcpy(lastPos + 19, lastPos, (data.Length() - (lastPos - newData))); - memcpy(lastPos, match, 16); - memcpy(lastPos + 16, "\x00\x00\x00", 3); - result.Set("data", - Napi::Buffer::Copy(env, newData, data.Length() + 19)); - none = false; - break; + if (loop) { + char *newData = (char *)malloc(BufferLength + 19); + memcpy(newData, fileData, BufferLength); + lastPos = (char *)memchr(newData, '\x2C', BufferLength); + while (lastPos != NULL) { + if (memcmp(lastPos, descriptor, 5) != 0) { + lastPos = (char *)memchr(lastPos + 1, '\x2C', + (BufferLength - (lastPos - newData)) - 1); + continue; } - if (none) - result.Set("data", - Napi::Buffer::Copy(env, newData, data.Length())); - } 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) - .colourspace(VIPS_INTERPRETATION_sRGB); - if (!in.has_alpha()) - in = in.bandjoin(255); + memcpy(lastPos + 19, lastPos, (BufferLength - (lastPos - newData))); + memcpy(lastPos, match, 16); + memcpy(lastPos + 16, "\x00\x00\x00", 3); - int pageHeight = vips_image_get_page_height(in.get_image()); - int nPages = vips_image_get_n_pages(in.get_image()); - int framePos = clamp(frame, 0, (int)nPages); - VImage out = in.crop(0, 0, in.width(), pageHeight * (framePos + 1)); - out.set(VIPS_META_PAGE_HEIGHT, pageHeight); - out.set("loop", loop ? 0 : 1); - - void *buf; - size_t length; - out.write_to_buffer(("." + type).c_str(), &buf, &length); - - result.Set("data", Napi::Buffer::Copy(env, (char *)buf, length)); - } else { - lastPos = (char *)memchr(fileData, '\x21', data.Length()); - while (lastPos != NULL) { - if (memcmp(lastPos, match, 16) != 0) { - lastPos = (char *)memchr(lastPos + 1, '\x21', - (data.Length() - (lastPos - fileData)) - 1); - continue; - } - memcpy(lastPos, lastPos + 19, - (data.Length() - (lastPos - fileData)) - 19); - result.Set("data", - Napi::Buffer::Copy(env, fileData, data.Length() - 19)); - none = false; - break; - } - if (none) - result.Set("data", - Napi::Buffer::Copy(env, fileData, data.Length())); + none = false; + *DataSize = BufferLength + 19; + break; } + if (none) + *DataSize = BufferLength; - result.Set("type", type); - } catch (std::exception const &err) { - Napi::Error::New(env, err.what()).ThrowAsJavaScriptException(); - } catch (...) { - Napi::Error::New(env, "Unknown error").ThrowAsJavaScriptException(); + vips_error_clear(); + vips_thread_shutdown(); + + return newData; + } else if (frame >= 0 && !loop) { + 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); + + int pageHeight = vips_image_get_page_height(in.get_image()); + int nPages = vips_image_get_n_pages(in.get_image()); + int framePos = clamp(frame, 0, (int)nPages); + VImage out = in.crop(0, 0, in.width(), pageHeight * (framePos + 1)); + out.set(VIPS_META_PAGE_HEIGHT, pageHeight); + out.set("loop", 1); + + void *buf; + out.write_to_buffer(("." + type).c_str(), &buf, DataSize); + + vips_error_clear(); + vips_thread_shutdown(); + + return (char *)buf; + } else { + lastPos = (char *)memchr(fileData, '\x21', BufferLength); + while (lastPos != NULL) { + if (memcmp(lastPos, match, 16) != 0) { + lastPos = (char *)memchr(lastPos + 1, '\x21', + (BufferLength - (lastPos - fileData)) - 1); + continue; + } + memcpy(lastPos, lastPos + 19, (BufferLength - (lastPos - fileData)) - 19); + *DataSize = BufferLength - 19; + none = false; + break; + } + if (none) + *DataSize = BufferLength; + + vips_error_clear(); + vips_thread_shutdown(); + return fileData; } - - vips_error_clear(); - vips_thread_shutdown(); - return result; } diff --git a/natives/freeze.h b/natives/freeze.h index 71d091b..ae3a84d 100644 --- a/natives/freeze.h +++ b/natives/freeze.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Freeze(const Napi::CallbackInfo& info); +using std::string; + +char* Freeze(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file diff --git a/natives/image.cc b/natives/image.cc index 54d04e5..0cc34ba 100644 --- a/natives/image.cc +++ b/natives/image.cc @@ -62,13 +62,13 @@ std::map OldFunctionMap = { - {"speed", Speed}, - {"freeze", Freeze}, {"gamexplain", Gamexplain}, {"globe", Globe}, {"homebrew", Homebrew}, diff --git a/natives/speed.cc b/natives/speed.cc index 4f4e619..1498bb1 100644 --- a/natives/speed.cc +++ b/natives/speed.cc @@ -1,4 +1,7 @@ -#include +#include "common.h" + +#include +#include #include @@ -8,18 +11,18 @@ using namespace vips; void *memset16(void *m, uint16_t val, size_t count) { uint16_t *buf = (uint16_t *)m; - while (count--) *buf++ = val; + while (count--) + *buf++ = val; return m; } -void vipsRemove(Napi::Env *env, Napi::Object *result, Napi::Buffer data, - int speed) { +char *vipsRemove(char *data, size_t length, size_t *DataSize, int speed) { VOption *options = VImage::option()->set("access", "sequential"); - VImage in = VImage::new_from_buffer(data.Data(), data.Length(), "", - options->set("n", -1)) + VImage in = VImage::new_from_buffer(data, length, "", options->set("n", -1)) .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()); @@ -34,84 +37,73 @@ void vipsRemove(Napi::Env *env, Napi::Object *result, Napi::Buffer data, out.set(VIPS_META_PAGE_HEIGHT, pageHeight); void *buf; - size_t length; - out.write_to_buffer(".gif", &buf, &length); + out.write_to_buffer(".gif", &buf, DataSize); - result->Set("data", Napi::Buffer::Copy(*env, (char *)buf, length)); + return (char *)buf; } -Napi::Value Speed(const Napi::CallbackInfo &info) { - Napi::Env env = info.Env(); - Napi::Object result = Napi::Object::New(env); +char *Speed(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>(); - bool slow = - obj.Has("slow") ? obj.Get("slow").As().Value() : false; - string type = obj.Get("type").As().Utf8Value(); - int speed = - obj.Has("speed") ? obj.Get("speed").As().Int32Value() : 2; + bool slow = GetArgumentWithFallback(Arguments, "slow", false); + int speed = GetArgumentWithFallback(Arguments, "speed", 2); - char *fileData = data.Data(); + char *fileData = (char *)malloc(BufferLength); + memcpy(fileData, BufferData, BufferLength); - char *match = (char *)"\x00\x21\xF9\x04"; + char *match = (char *)"\x00\x21\xF9\x04"; - vector old_delays; - bool removeFrames = false; - char *lastPos; + vector old_delays; + bool removeFrames = false; + char *lastPos; - int amount = 0; + int amount = 0; - lastPos = (char *)memchr(fileData, '\x00', data.Length()); - while (lastPos != NULL) { - if (memcmp(lastPos, match, 4) != 0) { - lastPos = (char *)memchr(lastPos + 1, '\x00', - (data.Length() - (lastPos - fileData)) - 1); - continue; - } - ++amount; - uint16_t old_delay; - memcpy(&old_delay, lastPos + 5, 2); - old_delays.push_back(old_delay); + lastPos = (char *)memchr(fileData, '\x00', BufferLength); + while (lastPos != NULL) { + if (memcmp(lastPos, match, 4) != 0) { lastPos = (char *)memchr(lastPos + 1, '\x00', - (data.Length() - (lastPos - fileData)) - 1); + (BufferLength - (lastPos - fileData)) - 1); + continue; + } + ++amount; + uint16_t old_delay; + memcpy(&old_delay, lastPos + 5, 2); + old_delays.push_back(old_delay); + lastPos = (char *)memchr(lastPos + 1, '\x00', + (BufferLength - (lastPos - fileData)) - 1); + } + + int currentFrame = 0; + lastPos = (char *)memchr(fileData, '\x00', BufferLength); + while (lastPos != NULL) { + if (memcmp(lastPos, match, 4) != 0) { + lastPos = (char *)memchr(lastPos + 1, '\x00', + (BufferLength - (lastPos - fileData)) - 1); + continue; + } + uint16_t new_delay = slow ? old_delays[currentFrame] * speed + : old_delays[currentFrame] / speed; + if (!slow && new_delay <= 1) { + removeFrames = true; + break; } - int currentFrame = 0; - lastPos = (char *)memchr(fileData, '\x00', data.Length()); - while (lastPos != NULL) { - if (memcmp(lastPos, match, 4) != 0) { - lastPos = (char *)memchr(lastPos + 1, '\x00', - (data.Length() - (lastPos - fileData)) - 1); - continue; - } - uint16_t new_delay = slow ? old_delays[currentFrame] * speed - : old_delays[currentFrame] / speed; - if (!slow && new_delay <= 1) { - removeFrames = true; - break; - } + memset16(lastPos + 5, new_delay, 1); - memset16(lastPos + 5, new_delay, 1); + lastPos = (char *)memchr(lastPos + 1, '\x00', + (BufferLength - (lastPos - fileData)) - 1); + ++currentFrame; + } - lastPos = (char *)memchr(lastPos + 1, '\x00', - (data.Length() - (lastPos - fileData)) - 1); - ++currentFrame; - } - - result.Set("data", Napi::Buffer::Copy(env, fileData, data.Length())); - - if (removeFrames) vipsRemove(&env, &result, data, speed); - - 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 (removeFrames) { + fileData = vipsRemove(BufferData, BufferLength, DataSize, speed); + } else { + *DataSize = BufferLength; } vips_error_clear(); vips_thread_shutdown(); - return result; + + return fileData; } \ No newline at end of file diff --git a/natives/speed.h b/natives/speed.h index 1a0f97d..08c5c19 100644 --- a/natives/speed.h +++ b/natives/speed.h @@ -1,5 +1,7 @@ #pragma once -#include +#include "common.h" -Napi::Value Speed(const Napi::CallbackInfo &info); \ No newline at end of file +using std::string; + +char* Speed(string type, char* BufferData, size_t BufferLength, ArgumentMap Arguments, size_t* DataSize); \ No newline at end of file