Compare commits
	
		
			No commits in common. "3272429cf6047bcc74d055b617defa7723f80d75" and "5ba033683727ea1cedc7ec5b4c1268646942c24b" have entirely different histories.
		
	
	
		
			3272429cf6
			...
			5ba0336837
		
	
		
					 97 changed files with 785 additions and 893 deletions
				
			
		| 
						 | 
				
			
			@ -2,34 +2,24 @@ cmake_minimum_required(VERSION 3.15)
 | 
			
		|||
cmake_policy(SET CMP0091 NEW)
 | 
			
		||||
cmake_policy(SET CMP0042 NEW)
 | 
			
		||||
project(image)
 | 
			
		||||
 | 
			
		||||
include_directories(${CMAKE_JS_INC})
 | 
			
		||||
file(GLOB SOURCE_FILES "natives/*.cc" "natives/*.h")
 | 
			
		||||
 | 
			
		||||
if (CMAKE_JS_VERSION)
 | 
			
		||||
  include_directories(${CMAKE_JS_INC})
 | 
			
		||||
  add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC} natives/node/image.cc)
 | 
			
		||||
  set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
 | 
			
		||||
  target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
 | 
			
		||||
else()
 | 
			
		||||
  add_executable(${PROJECT_NAME} ${SOURCE_FILES} natives/cli/image.cc)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
 | 
			
		||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
 | 
			
		||||
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
 | 
			
		||||
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
 | 
			
		||||
 | 
			
		||||
if(MSVC) # todo: change flags for more parity with GCC/clang, I don't know much about MSVC so pull requests are open
 | 
			
		||||
  set(CMAKE_CXX_FLAGS "/Wall /EHsc /GS")
 | 
			
		||||
  set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
 | 
			
		||||
  set(CMAKE_CXX_FLAGS_RELEASE "/Ox")
 | 
			
		||||
  set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
 | 
			
		||||
  set(BUILD_SHARED_LIBS TRUE)
 | 
			
		||||
set(CMAKE_CXX_FLAGS "/Wall /EHsc /GS")
 | 
			
		||||
set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
 | 
			
		||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox")
 | 
			
		||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
 | 
			
		||||
set(BUILD_SHARED_LIBS TRUE)
 | 
			
		||||
else()
 | 
			
		||||
  set(CMAKE_CXX_FLAGS "-Wall -Wextra -Werror=format-security -Wno-cast-function-type -fexceptions -D_GLIBCXX_ASSERTIONS -fstack-clash-protection -pedantic -D_GLIBCXX_USE_CXX11_ABI=1")
 | 
			
		||||
  set(CMAKE_CXX_FLAGS_DEBUG "-g")
 | 
			
		||||
  set(CMAKE_CXX_FLAGS_RELEASE "-O2")
 | 
			
		||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Werror=format-security -Wno-cast-function-type -fexceptions -D_GLIBCXX_ASSERTIONS -fstack-clash-protection -pedantic -D_GLIBCXX_USE_CXX11_ABI=1")
 | 
			
		||||
set(CMAKE_CXX_FLAGS_DEBUG "-g")
 | 
			
		||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 | 
			
		||||
 | 
			
		||||
find_package(ImageMagick REQUIRED COMPONENTS Magick++ MagickCore)
 | 
			
		||||
add_definitions(-DMAGICKCORE_QUANTUM_DEPTH=16)
 | 
			
		||||
add_definitions(-DMAGICKCORE_HDRI_ENABLE=0)
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +31,7 @@ include_directories(${VIPS_INCLUDE_DIRS})
 | 
			
		|||
link_directories(${VIPS_LIBRARY_DIRS})
 | 
			
		||||
target_link_libraries(${PROJECT_NAME} ${VIPS_LDFLAGS})
 | 
			
		||||
 | 
			
		||||
if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET AND CMAKE_JS_VERSION)
 | 
			
		||||
if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)
 | 
			
		||||
  # Generate node.lib
 | 
			
		||||
  execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})
 | 
			
		||||
endif()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ lavalink:
 | 
			
		|||
  plugins:
 | 
			
		||||
    - dependency: "com.github.esmBot:lava-xm-plugin:v0.2.1"
 | 
			
		||||
      repository: "https://jitpack.io"
 | 
			
		||||
    - dependency: "com.github.TopiSenpai.LavaSrc:lavasrc-plugin:3.2.0"
 | 
			
		||||
    - dependency: "com.github.TopiSenpai.LavaSrc:lavasrc-plugin:3.1.7"
 | 
			
		||||
      repository: "https://jitpack.io"
 | 
			
		||||
 | 
			
		||||
plugins:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 133 KiB  | 
| 
						 | 
				
			
			@ -25,9 +25,7 @@ class ImageCommand extends Command {
 | 
			
		|||
 | 
			
		||||
    const imageParams = {
 | 
			
		||||
      cmd: this.constructor.command,
 | 
			
		||||
      params: {
 | 
			
		||||
        togif: !!this.options.togif
 | 
			
		||||
      },
 | 
			
		||||
      params: {},
 | 
			
		||||
      id: (this.interaction ?? this.message).id
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -131,11 +129,6 @@ class ImageCommand extends Command {
 | 
			
		|||
        description: "An image/GIF URL"
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    this.flags.push({
 | 
			
		||||
      name: "togif",
 | 
			
		||||
      type: 5,
 | 
			
		||||
      description: "Force GIF output"
 | 
			
		||||
    });
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,11 +17,9 @@ class EvalCommand extends Command {
 | 
			
		|||
      const sendString = `\`\`\`js\n${cleaned}\n\`\`\``;
 | 
			
		||||
      if (sendString.length >= 2000) {
 | 
			
		||||
        return {
 | 
			
		||||
          content: "The result was too large, so here it is as a file:",
 | 
			
		||||
          files: [{
 | 
			
		||||
            contents: cleaned,
 | 
			
		||||
            name: "result.txt"
 | 
			
		||||
          }]
 | 
			
		||||
          text: "The result was too large, so here it is as a file:",
 | 
			
		||||
          file: cleaned,
 | 
			
		||||
          name: "result.txt"
 | 
			
		||||
        };
 | 
			
		||||
      } else {
 | 
			
		||||
        return sendString;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ class RestartCommand extends Command {
 | 
			
		|||
      this.success = false;
 | 
			
		||||
      return "Only the bot owner can restart me!";
 | 
			
		||||
    }
 | 
			
		||||
    await this.channel.createMessage(Object.assign({
 | 
			
		||||
    await this.message.channel.createMessage(Object.assign({
 | 
			
		||||
      content: "esmBot is restarting."
 | 
			
		||||
    }, this.reference));
 | 
			
		||||
    process.exit(1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,10 @@
 | 
			
		|||
import ImageCommand from "../../classes/imageCommand.js";
 | 
			
		||||
 | 
			
		||||
class ExplodeCommand extends ImageCommand {
 | 
			
		||||
  params = {
 | 
			
		||||
    amount: -1
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static description = "Explodes an image";
 | 
			
		||||
  static aliases = ["exp"];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
 | 
			
		|||
 | 
			
		||||
class ImplodeCommand extends ImageCommand {
 | 
			
		||||
  params = {
 | 
			
		||||
    implode: true
 | 
			
		||||
    amount: 1
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static description = "Implodes an image";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,6 +128,7 @@
 | 
			
		|||
    "$19 Fortnite Card",
 | 
			
		||||
    "Wild Woody",
 | 
			
		||||
    "RDI Halcyon",
 | 
			
		||||
    "cry about it",
 | 
			
		||||
    "KFC",
 | 
			
		||||
    "Cave Story",
 | 
			
		||||
    "YouTube ads",
 | 
			
		||||
| 
						 | 
				
			
			@ -158,6 +159,7 @@
 | 
			
		|||
    "Item Asylum",
 | 
			
		||||
    "TIC-80",
 | 
			
		||||
    "Ghetto Smosh",
 | 
			
		||||
    "brought to you by the DFS project",
 | 
			
		||||
    "Splatoon 3",
 | 
			
		||||
    "changed",
 | 
			
		||||
    "Chutes and Ladders",
 | 
			
		||||
| 
						 | 
				
			
			@ -194,9 +196,6 @@
 | 
			
		|||
    "ANTONBLAST",
 | 
			
		||||
    "[object Object]",
 | 
			
		||||
    "Xonotic",
 | 
			
		||||
    "Lario",
 | 
			
		||||
    "Hi-Fi Rush",
 | 
			
		||||
    "Calckey",
 | 
			
		||||
    "The clock is ticking."
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ As you can see, each command is grouped into categories, which are represented b
 | 
			
		|||
!!! tip
 | 
			
		||||
    The `message` category is special; commands in here act as right-click context menu message commands instead of "classic" or slash commands.
 | 
			
		||||
 | 
			
		||||
## Command Structure
 | 
			
		||||
## Commnand Structure
 | 
			
		||||
It's recommended to use the `Command` class located in `classes/command.js` to create a new command in most cases. This class provides various parameters and fields that will likely be useful when creating a command. Here is a simple example of a working command file:
 | 
			
		||||
```js
 | 
			
		||||
import Command from "../../classes/command.js";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
import { log } from "../utils/logger.js";
 | 
			
		||||
 | 
			
		||||
// run when the bot is added to a guild
 | 
			
		||||
export default async (client, guild) => {
 | 
			
		||||
  log(`[GUILD JOIN] ${guild.name} (${guild.id}) added the bot.`);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
import { players, queues, skipVotes } from "../utils/soundplayer.js";
 | 
			
		||||
import AwaitRejoin from "../utils/awaitrejoin.js";
 | 
			
		||||
import { random } from "../utils/misc.js";
 | 
			
		||||
import { logger } from "../utils/logger.js";
 | 
			
		||||
 | 
			
		||||
const isWaiting = new Map();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,10 +16,9 @@ export default async (client, member, oldChannel) => {
 | 
			
		|||
        content: "🔊 Waiting 10 seconds for someone to return..."
 | 
			
		||||
      });
 | 
			
		||||
      const awaitRejoin = new AwaitRejoin(oldChannel, true, member.id);
 | 
			
		||||
      awaitRejoin.once("end", async (rejoined, newMember, cancel) => {
 | 
			
		||||
      awaitRejoin.on("end", async (rejoined, newMember) => {
 | 
			
		||||
        isWaiting.delete(oldChannel.id);
 | 
			
		||||
        if (rejoined) {
 | 
			
		||||
          if (cancel) return;
 | 
			
		||||
          connection.player.setPaused(false);
 | 
			
		||||
          if (member.id !== newMember.id) {
 | 
			
		||||
            players.set(connection.voiceChannel.guildID, { player: connection.player, type: connection.type, host: newMember.id, voiceChannel: connection.voiceChannel, originalChannel: connection.originalChannel, loop: connection.loop, shuffle: connection.shuffle, playMessage: connection.playMessage });
 | 
			
		||||
| 
						 | 
				
			
			@ -31,20 +29,19 @@ export default async (client, member, oldChannel) => {
 | 
			
		|||
            try {
 | 
			
		||||
              await waitMessage.delete();
 | 
			
		||||
            } catch {
 | 
			
		||||
              logger.warn(`Failed to delete wait message ${waitMessage.id}`);
 | 
			
		||||
              // no-op
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          try {
 | 
			
		||||
            if (waitMessage.channel.messages.has(waitMessage.id)) await waitMessage.delete();
 | 
			
		||||
          } catch {
 | 
			
		||||
            logger.warn(`Failed to delete wait message ${waitMessage.id}`);
 | 
			
		||||
            // no-op
 | 
			
		||||
          }
 | 
			
		||||
          if (cancel) return;
 | 
			
		||||
          try {
 | 
			
		||||
            connection.player.node.leaveChannel(connection.originalChannel.guildID);
 | 
			
		||||
          } catch {
 | 
			
		||||
            logger.warn(`Failed to leave voice channel ${connection.originalChannel.guildID}`);
 | 
			
		||||
            // no-op
 | 
			
		||||
          }
 | 
			
		||||
          players.delete(connection.originalChannel.guildID);
 | 
			
		||||
          queues.delete(connection.originalChannel.guildID);
 | 
			
		||||
| 
						 | 
				
			
			@ -61,13 +58,13 @@ export default async (client, member, oldChannel) => {
 | 
			
		|||
        content: "🔊 Waiting 10 seconds for the host to return..."
 | 
			
		||||
      });
 | 
			
		||||
      const awaitRejoin = new AwaitRejoin(oldChannel, false, member.id);
 | 
			
		||||
      awaitRejoin.once("end", async (rejoined) => {
 | 
			
		||||
      awaitRejoin.on("end", async (rejoined) => {
 | 
			
		||||
        isWaiting.delete(oldChannel.id);
 | 
			
		||||
        if (rejoined) {
 | 
			
		||||
          try {
 | 
			
		||||
            if (waitMessage.channel.messages.has(waitMessage.id)) await waitMessage.delete();
 | 
			
		||||
          } catch {
 | 
			
		||||
            logger.warn(`Failed to delete wait message ${waitMessage.id}`);
 | 
			
		||||
            // no-op
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          const members = oldChannel.voiceMembers.filter((i) => i.id !== client.user.id && !i.bot);
 | 
			
		||||
| 
						 | 
				
			
			@ -75,12 +72,12 @@ export default async (client, member, oldChannel) => {
 | 
			
		|||
            try {
 | 
			
		||||
              if (waitMessage.channel.messages.has(waitMessage.id)) await waitMessage.delete();
 | 
			
		||||
            } catch {
 | 
			
		||||
              logger.warn(`Failed to delete wait message ${waitMessage.id}`);
 | 
			
		||||
              // no-op
 | 
			
		||||
            }
 | 
			
		||||
            try {
 | 
			
		||||
              connection.player.node.leaveChannel(connection.originalChannel.guildID);
 | 
			
		||||
            } catch {
 | 
			
		||||
              logger.warn(`Failed to leave voice channel ${connection.originalChannel.guildID}`);
 | 
			
		||||
              // no-op
 | 
			
		||||
            }
 | 
			
		||||
            players.delete(connection.originalChannel.guildID);
 | 
			
		||||
            queues.delete(connection.originalChannel.guildID);
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +99,7 @@ export default async (client, member, oldChannel) => {
 | 
			
		|||
      try {
 | 
			
		||||
        connection.player.node.leaveChannel(connection.originalChannel.guildID);
 | 
			
		||||
      } catch {
 | 
			
		||||
        logger.warn(`Failed to leave voice channel ${connection.originalChannel.guildID}`);
 | 
			
		||||
        // no-op
 | 
			
		||||
      }
 | 
			
		||||
      players.delete(connection.originalChannel.guildID);
 | 
			
		||||
      queues.delete(connection.originalChannel.guildID);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ site_name: esmBot
 | 
			
		|||
docs_dir: docs/
 | 
			
		||||
repo_name: 'esmBot/esmBot'
 | 
			
		||||
repo_url: 'https://github.com/esmBot/esmBot'
 | 
			
		||||
copyright: Copyright © 2018 - 2023 <a href="https://essem.space">Essem</a>
 | 
			
		||||
copyright: Copyright © 2018 - 2022 <a href="https://essem.space">Essem</a>
 | 
			
		||||
nav:
 | 
			
		||||
    - Home: index.md
 | 
			
		||||
    - setup.md
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,14 +7,14 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Blur(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
char *Blur(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool sharp = GetArgument<bool>(Arguments, "sharp");
 | 
			
		||||
  VOption *options = VImage::option()->set("access", "sequential");
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ char *Blur(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
      sharp ? in.sharpen(VImage::option()->set("sigma", 3)) : in.gaussblur(15);
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  out.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  out.write_to_buffer(("." + *type).c_str(), &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Blur(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Blur(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -7,29 +7,28 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Bounce(string type, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, [[maybe_unused]] ArgumentMap Arguments,
 | 
			
		||||
             size_t *DataSize) {
 | 
			
		||||
char *Bounce(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  VOption *options = VImage::option();
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(
 | 
			
		||||
          BufferData, BufferLength, "",
 | 
			
		||||
          type == "gif" ? options->set("n", -1)->set("access", "sequential")
 | 
			
		||||
                        : options)
 | 
			
		||||
          *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()) : 15;
 | 
			
		||||
  int nPages = *type == "gif" ? vips_image_get_n_pages(in.get_image()) : 15;
 | 
			
		||||
  double mult = M_PI / nPages;
 | 
			
		||||
  int halfHeight = pageHeight / 2;
 | 
			
		||||
 | 
			
		||||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    double height = halfHeight * ((abs(sin(i * mult)) * -1) + 1);
 | 
			
		||||
    VImage embedded =
 | 
			
		||||
        img_frame.embed(0, height, width, pageHeight + halfHeight);
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +36,7 @@ char *Bounce(string type, string *outType, char *BufferData,
 | 
			
		|||
  }
 | 
			
		||||
  VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
 | 
			
		||||
  final.set(VIPS_META_PAGE_HEIGHT, pageHeight + halfHeight);
 | 
			
		||||
  if (type != "gif") {
 | 
			
		||||
  if (*type != "gif") {
 | 
			
		||||
    vector<int> delay(30, 50);
 | 
			
		||||
    final.set("delay", delay);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +44,7 @@ char *Bounce(string type, string *outType, char *BufferData,
 | 
			
		|||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(".gif", &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  *outType = "gif";
 | 
			
		||||
  *type = "gif";
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Bounce(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Bounce(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -6,8 +6,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Caption(string type, string *outType, char *BufferData,
 | 
			
		||||
              size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Caption(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string caption = GetArgument<string>(Arguments, "caption");
 | 
			
		||||
  string font = GetArgument<string>(Arguments, "font");
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ char *Caption(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +57,7 @@ char *Caption(string type, string *outType, char *BufferData,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *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));
 | 
			
		||||
| 
						 | 
				
			
			@ -68,10 +68,9 @@ char *Caption(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Caption(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Caption(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -7,8 +7,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *CaptionTwo(string type, string *outType, char *BufferData,
 | 
			
		||||
                 size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *CaptionTwo(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
                 ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool top = GetArgument<bool>(Arguments, "top");
 | 
			
		||||
  string caption = GetArgument<string>(Arguments, "caption");
 | 
			
		||||
  string font = GetArgument<string>(Arguments, "font");
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ char *CaptionTwo(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ char *CaptionTwo(string type, string *outType, char *BufferData,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    VImage frame =
 | 
			
		||||
        (top ? captionImage : img_frame)
 | 
			
		||||
            .join(top ? img_frame : captionImage, VIPS_DIRECTION_VERTICAL,
 | 
			
		||||
| 
						 | 
				
			
			@ -72,10 +72,9 @@ char *CaptionTwo(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* CaptionTwo(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* CaptionTwo(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
                 ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -11,9 +11,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace Magick;
 | 
			
		||||
 | 
			
		||||
char *Circle(string type, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, [[maybe_unused]] ArgumentMap Arguments,
 | 
			
		||||
             size_t *DataSize) {
 | 
			
		||||
char *Circle(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  Blob blob;
 | 
			
		||||
 | 
			
		||||
  list<Image> frames;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,13 +29,13 @@ char *Circle(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  for (Image &image : coalesced) {
 | 
			
		||||
    image.rotationalBlur(10);
 | 
			
		||||
    image.magick(*outType);
 | 
			
		||||
    image.magick(*type);
 | 
			
		||||
    blurred.push_back(image);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  optimizeTransparency(blurred.begin(), blurred.end());
 | 
			
		||||
 | 
			
		||||
  if (*outType == "gif") {
 | 
			
		||||
  if (*type == "gif") {
 | 
			
		||||
    for (Image &image : blurred) {
 | 
			
		||||
      image.quantizeDitherMethod(FloydSteinbergDitherMethod);
 | 
			
		||||
      image.quantize();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Circle(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Circle(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,26 +0,0 @@
 | 
			
		|||
#include <cstring>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#include "../common.h"
 | 
			
		||||
 | 
			
		||||
void showUsage(char *path) {
 | 
			
		||||
	std::cout << "Usage: " << path << " operation [--arg=\"param\"] [...]" << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
  if (argc < 1 ||
 | 
			
		||||
      (argc == 1 && !strcmp(argv[1], "-h"))) {
 | 
			
		||||
    showUsage(argv[0]);
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    system("PAUSE");
 | 
			
		||||
#endif
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char *op = argv[1];
 | 
			
		||||
 | 
			
		||||
  //handleArguments(argc, argv);
 | 
			
		||||
 | 
			
		||||
  std::cout << "This does nothing yet, but it might in the future!" << std::endl;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,15 +10,15 @@ 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, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Colors(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string color = GetArgument<string>(Arguments, "color");
 | 
			
		||||
 | 
			
		||||
  VOption *options = VImage::option()->set("access", "sequential");
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
 | 
			
		||||
  VImage out;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ char *Colors(string type, string *outType, char *BufferData,
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  out.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  out.write_to_buffer(("." + *type).c_str(), &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Colors(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Colors(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -12,46 +12,6 @@ using std::variant;
 | 
			
		|||
typedef variant<string, float, bool, int> ArgumentVariant;
 | 
			
		||||
typedef map<string, ArgumentVariant> ArgumentMap;
 | 
			
		||||
 | 
			
		||||
#include "blur.h"
 | 
			
		||||
#include "bounce.h"
 | 
			
		||||
#include "caption.h"
 | 
			
		||||
#include "caption2.h"
 | 
			
		||||
#include "circle.h"
 | 
			
		||||
#include "colors.h"
 | 
			
		||||
#include "crop.h"
 | 
			
		||||
#include "deepfry.h"
 | 
			
		||||
#include "explode.h"
 | 
			
		||||
#include "flag.h"
 | 
			
		||||
#include "flip.h"
 | 
			
		||||
#include "freeze.h"
 | 
			
		||||
#include "gamexplain.h"
 | 
			
		||||
#include "globe.h"
 | 
			
		||||
#include "homebrew.h"
 | 
			
		||||
#include "invert.h"
 | 
			
		||||
#include "jpeg.h"
 | 
			
		||||
#include "magik.h"
 | 
			
		||||
#include "meme.h"
 | 
			
		||||
#include "mirror.h"
 | 
			
		||||
#include "motivate.h"
 | 
			
		||||
#include "reddit.h"
 | 
			
		||||
#include "resize.h"
 | 
			
		||||
#include "reverse.h"
 | 
			
		||||
#include "scott.h"
 | 
			
		||||
#include "snapchat.h"
 | 
			
		||||
#include "sonic.h"
 | 
			
		||||
#include "speed.h"
 | 
			
		||||
#include "spin.h"
 | 
			
		||||
#include "squish.h"
 | 
			
		||||
#include "swirl.h"
 | 
			
		||||
#include "tile.h"
 | 
			
		||||
#include "togif.h"
 | 
			
		||||
#include "uncanny.h"
 | 
			
		||||
#include "uncaption.h"
 | 
			
		||||
#include "wall.h"
 | 
			
		||||
#include "watermark.h"
 | 
			
		||||
#include "whisper.h"
 | 
			
		||||
#include "zamn.h"
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
T GetArgument(ArgumentMap map, string key) {
 | 
			
		||||
  try {
 | 
			
		||||
| 
						 | 
				
			
			@ -83,48 +43,3 @@ const std::unordered_map<std::string, std::string> fontPaths{
 | 
			
		|||
    {"futura", "assets/fonts/caption.otf"},
 | 
			
		||||
    {"helvetica", "assets/fonts/caption2.ttf"},
 | 
			
		||||
    {"roboto", "assets/fonts/reddit.ttf"}};
 | 
			
		||||
 | 
			
		||||
const std::map<std::string,
 | 
			
		||||
               char* (*)(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
                         ArgumentMap Arguments, size_t* DataSize)>
 | 
			
		||||
    FunctionMap = {{"blur", &Blur},
 | 
			
		||||
                   {"bounce", &Bounce},
 | 
			
		||||
                   {"caption", &Caption},
 | 
			
		||||
                   {"captionTwo", &CaptionTwo},
 | 
			
		||||
                   {"circle", &Circle},
 | 
			
		||||
                   {"colors", &Colors},
 | 
			
		||||
                   {"crop", &Crop},
 | 
			
		||||
                   {"deepfry", &Deepfry},
 | 
			
		||||
                   {"explode", &Explode},
 | 
			
		||||
                   {"flag", &Flag},
 | 
			
		||||
                   {"flip", &Flip},
 | 
			
		||||
                   {"freeze", &Freeze},
 | 
			
		||||
                   {"gamexplain", Gamexplain},
 | 
			
		||||
                   {"globe", Globe},
 | 
			
		||||
                   {"invert", Invert},
 | 
			
		||||
                   {"jpeg", Jpeg},
 | 
			
		||||
                   {"magik", Magik},
 | 
			
		||||
                   {"meme", Meme},
 | 
			
		||||
                   {"mirror", Mirror},
 | 
			
		||||
                   {"motivate", Motivate},
 | 
			
		||||
                   {"reddit", Reddit},
 | 
			
		||||
                   {"resize", Resize},
 | 
			
		||||
                   {"reverse", Reverse},
 | 
			
		||||
                   {"scott", Scott},
 | 
			
		||||
                   {"snapchat", Snapchat},
 | 
			
		||||
                   {"speed", &Speed},
 | 
			
		||||
                   {"spin", Spin},
 | 
			
		||||
                   {"squish", Squish},
 | 
			
		||||
                   {"swirl", Swirl},
 | 
			
		||||
                   {"tile", Tile},
 | 
			
		||||
                   {"togif", ToGif},
 | 
			
		||||
                   {"uncanny", Uncanny},
 | 
			
		||||
                   {"uncaption", &Uncaption},
 | 
			
		||||
                   {"wall", Wall},
 | 
			
		||||
                   {"watermark", &Watermark},
 | 
			
		||||
                   {"whisper", Whisper},
 | 
			
		||||
                   {"zamn", Zamn}};
 | 
			
		||||
 | 
			
		||||
const std::map<std::string,
 | 
			
		||||
               char* (*)(string type, string* outType, ArgumentMap Arguments, size_t* DataSize)>
 | 
			
		||||
    NoInputFunctionMap = {{"homebrew", Homebrew}, {"sonic", Sonic}};
 | 
			
		||||
| 
						 | 
				
			
			@ -7,13 +7,13 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Crop(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
           [[maybe_unused]] ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Crop(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  VOption *options = VImage::option()->set("access", "sequential");
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
 | 
			
		||||
  int width = in.width();
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ char *Crop(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  int finalHeight = 0;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *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;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,10 +42,9 @@ char *Crop(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Crop(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Crop(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -6,14 +6,13 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Deepfry(string type, string *outType, char *BufferData,
 | 
			
		||||
              size_t BufferLength, [[maybe_unused]] ArgumentMap Arguments,
 | 
			
		||||
              size_t *DataSize) {
 | 
			
		||||
char *Deepfry(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  VOption *options = VImage::option()->set("access", "sequential");
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +25,7 @@ char *Deepfry(string type, string *outType, char *BufferData,
 | 
			
		|||
  VImage fried = (in * 1.3 - (255.0 * 1.3 - 255.0)) * 1.5;
 | 
			
		||||
 | 
			
		||||
  VImage final;
 | 
			
		||||
  if (totalHeight > 65500 && type == "gif") {
 | 
			
		||||
  if (totalHeight > 65500 && *type == "gif") {
 | 
			
		||||
    vector<VImage> img;
 | 
			
		||||
    for (int i = 0; i < nPages; i++) {
 | 
			
		||||
      VImage img_frame = in.crop(0, i * pageHeight, width, pageHeight);
 | 
			
		||||
| 
						 | 
				
			
			@ -49,13 +48,13 @@ char *Deepfry(string type, string *outType, char *BufferData,
 | 
			
		|||
                          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"));
 | 
			
		||||
    if (*type == "gif") final.set("delay", fried.get_array_int("delay"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif" ? VImage::option()->set("dither", 0) : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0) : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Deepfry(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Deepfry(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,52 +1,58 @@
 | 
			
		|||
#include <vips/vips8>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#include <Magick++.h>
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
using namespace Magick;
 | 
			
		||||
 | 
			
		||||
char *Explode(string type, string *outType, char *BufferData,
 | 
			
		||||
              size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool implode = GetArgument<bool>(Arguments, "implode");
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
char *Explode(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
 | 
			
		||||
  VOption *options = VImage::option();
 | 
			
		||||
  int amount = GetArgument<int>(Arguments, "amount");
 | 
			
		||||
  int delay = GetArgumentWithFallback<int>(Arguments, "delay", 0);
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
  Blob blob;
 | 
			
		||||
 | 
			
		||||
  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 distortPath = basePath + "assets/images/" +
 | 
			
		||||
                       (implode ? "linearimplode.png" : "linearexplode.png");
 | 
			
		||||
  VImage distort =
 | 
			
		||||
      (VImage::new_from_file(distortPath.c_str())
 | 
			
		||||
           .resize(width / 500.0, VImage::option()
 | 
			
		||||
                                      ->set("vscale", pageHeight / 500.0)
 | 
			
		||||
                                      ->set("kernel", VIPS_KERNEL_CUBIC)) /
 | 
			
		||||
       65535);
 | 
			
		||||
 | 
			
		||||
  VImage distortImage = (distort[0] * width).bandjoin(distort[1] * pageHeight);
 | 
			
		||||
 | 
			
		||||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    VImage mapped = img_frame.mapim(distortImage);
 | 
			
		||||
    img.push_back(mapped);
 | 
			
		||||
  list<Image> frames;
 | 
			
		||||
  list<Image> coalesced;
 | 
			
		||||
  list<Image> 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;
 | 
			
		||||
  }
 | 
			
		||||
  VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
 | 
			
		||||
  final.set(VIPS_META_PAGE_HEIGHT, pageHeight);
 | 
			
		||||
  coalesceImages(&coalesced, frames.begin(), frames.end());
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  for (Image &image : coalesced) {
 | 
			
		||||
    image.implode(amount);
 | 
			
		||||
    image.magick(*type);
 | 
			
		||||
    blurred.push_back(image);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
  optimizeTransparency(blurred.begin(), blurred.end());
 | 
			
		||||
 | 
			
		||||
  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();
 | 
			
		||||
 | 
			
		||||
  // workaround because the data is tied to the blob
 | 
			
		||||
  char *data = (char *)malloc(*DataSize);
 | 
			
		||||
  memcpy(data, blob.data(), *DataSize);
 | 
			
		||||
  return data;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Explode(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Explode(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Flag(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
char *Flag(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string overlay = GetArgument<string>(Arguments, "overlay");
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ char *Flag(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
| 
						 | 
				
			
			@ -40,10 +40,9 @@ char *Flag(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Flag(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Flag(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -6,12 +6,12 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Flip(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
char *Flip(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool flop = GetArgument<bool>(Arguments, "flop");
 | 
			
		||||
 | 
			
		||||
  VImage in = VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                                      type == "gif"
 | 
			
		||||
                                      *type == "gif"
 | 
			
		||||
                                          ? VImage::option()->set("n", -1)->set(
 | 
			
		||||
                                                "access", "sequential")
 | 
			
		||||
                                          : 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ char *Flip(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  VImage out;
 | 
			
		||||
  if (flop) {
 | 
			
		||||
    out = in.flip(VIPS_DIRECTION_HORIZONTAL);
 | 
			
		||||
  } else if (type == "gif") {
 | 
			
		||||
  } else if (*type == "gif") {
 | 
			
		||||
    // libvips gif handling is both a blessing and a curse
 | 
			
		||||
    vector<VImage> img;
 | 
			
		||||
    int pageHeight = vips_image_get_page_height(in.get_image());
 | 
			
		||||
| 
						 | 
				
			
			@ -39,10 +39,9 @@ char *Flip(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  out.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Flip(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Flip(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -7,8 +7,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Freeze(string type, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Freeze(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool loop = GetArgumentWithFallback<bool>(Arguments, "loop", false);
 | 
			
		||||
  int frame = GetArgumentWithFallback<int>(Arguments, "frame", -1);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,10 +46,10 @@ char *Freeze(string type, string *outType, char *BufferData,
 | 
			
		|||
  } 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);
 | 
			
		||||
    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());
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +60,7 @@ char *Freeze(string type, string *outType, char *BufferData,
 | 
			
		|||
    out.set("loop", 1);
 | 
			
		||||
 | 
			
		||||
    void *buf;
 | 
			
		||||
    out.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
    out.write_to_buffer(("." + *type).c_str(), &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
    return (char *)buf;
 | 
			
		||||
  } else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Freeze(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Freeze(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,15 +5,15 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Gamexplain(string type, string *outType, char *BufferData,
 | 
			
		||||
                 size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Gamexplain(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
                 ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
 | 
			
		||||
  VOption *options = VImage::option()->set("access", "sequential");
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ char *Gamexplain(string type, string *outType, char *BufferData,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    VImage resized =
 | 
			
		||||
        img_frame
 | 
			
		||||
            .resize(1181.0 / (double)width,
 | 
			
		||||
| 
						 | 
				
			
			@ -41,10 +41,9 @@ char *Gamexplain(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Gamexplain(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Gamexplain(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
                 ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Globe(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
char *Globe(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,14 +14,14 @@ char *Globe(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(
 | 
			
		||||
          BufferData, BufferLength, "",
 | 
			
		||||
          type == "gif" ? options->set("n", -1)->set("access", "sequential")
 | 
			
		||||
          *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 nPages = *type == "gif" ? vips_image_get_n_pages(in.get_image()) : 30;
 | 
			
		||||
 | 
			
		||||
  double size = min(width, pageHeight);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +47,7 @@ char *Globe(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *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));
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ char *Globe(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  }
 | 
			
		||||
  VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
 | 
			
		||||
  final.set(VIPS_META_PAGE_HEIGHT, size);
 | 
			
		||||
  if (type != "gif") {
 | 
			
		||||
  if (*type != "gif") {
 | 
			
		||||
    vector<int> delay(30, 50);
 | 
			
		||||
    final.set("delay", delay);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Globe(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Globe(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,7 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Homebrew(string type, string *outType, ArgumentMap Arguments,
 | 
			
		||||
               size_t *DataSize) {
 | 
			
		||||
char *Homebrew(string *type, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string caption = GetArgument<string>(Arguments, "caption");
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +30,9 @@ char *Homebrew(string type, string *outType, ArgumentMap Arguments,
 | 
			
		|||
                                 ->set("y", 300 - (text.height() / 2) - 8));
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  out.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  out.write_to_buffer(".png", &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  *type = "png";
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,4 +4,4 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char *Homebrew(string type, string *outType, ArgumentMap Arguments, size_t *DataSize);
 | 
			
		||||
char *Homebrew(string *type, ArgumentMap Arguments, size_t *DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,46 @@
 | 
			
		|||
#include <map>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "../common.h"
 | 
			
		||||
#include "blur.h"
 | 
			
		||||
#include "bounce.h"
 | 
			
		||||
#include "caption.h"
 | 
			
		||||
#include "caption2.h"
 | 
			
		||||
#include "circle.h"
 | 
			
		||||
#include "colors.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "crop.h"
 | 
			
		||||
#include "deepfry.h"
 | 
			
		||||
#include "explode.h"
 | 
			
		||||
#include "flag.h"
 | 
			
		||||
#include "flip.h"
 | 
			
		||||
#include "freeze.h"
 | 
			
		||||
#include "gamexplain.h"
 | 
			
		||||
#include "globe.h"
 | 
			
		||||
#include "homebrew.h"
 | 
			
		||||
#include "invert.h"
 | 
			
		||||
#include "jpeg.h"
 | 
			
		||||
#include "magik.h"
 | 
			
		||||
#include "meme.h"
 | 
			
		||||
#include "mirror.h"
 | 
			
		||||
#include "motivate.h"
 | 
			
		||||
#include "reddit.h"
 | 
			
		||||
#include "resize.h"
 | 
			
		||||
#include "reverse.h"
 | 
			
		||||
#include "scott.h"
 | 
			
		||||
#include "snapchat.h"
 | 
			
		||||
#include "sonic.h"
 | 
			
		||||
#include "speed.h"
 | 
			
		||||
#include "spin.h"
 | 
			
		||||
#include "squish.h"
 | 
			
		||||
#include "swirl.h"
 | 
			
		||||
#include "tile.h"
 | 
			
		||||
#include "togif.h"
 | 
			
		||||
#include "uncanny.h"
 | 
			
		||||
#include "uncaption.h"
 | 
			
		||||
#include "wall.h"
 | 
			
		||||
#include "watermark.h"
 | 
			
		||||
#include "whisper.h"
 | 
			
		||||
#include "zamn.h"
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#include <Magick++.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -13,6 +52,51 @@
 | 
			
		|||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
std::map<std::string,
 | 
			
		||||
         char* (*)(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
                   ArgumentMap Arguments, size_t* DataSize)>
 | 
			
		||||
    FunctionMap = {{"blur", &Blur},
 | 
			
		||||
                   {"bounce", &Bounce},
 | 
			
		||||
                   {"caption", &Caption},
 | 
			
		||||
                   {"captionTwo", &CaptionTwo},
 | 
			
		||||
                   {"circle", &Circle},
 | 
			
		||||
                   {"colors", &Colors},
 | 
			
		||||
                   {"crop", &Crop},
 | 
			
		||||
                   {"deepfry", &Deepfry},
 | 
			
		||||
                   {"explode", &Explode},
 | 
			
		||||
                   {"flag", &Flag},
 | 
			
		||||
                   {"flip", &Flip},
 | 
			
		||||
                   {"freeze", &Freeze},
 | 
			
		||||
                   {"gamexplain", Gamexplain},
 | 
			
		||||
                   {"globe", Globe},
 | 
			
		||||
                   {"invert", Invert},
 | 
			
		||||
                   {"jpeg", Jpeg},
 | 
			
		||||
                   {"magik", Magik},
 | 
			
		||||
                   {"meme", Meme},
 | 
			
		||||
                   {"mirror", Mirror},
 | 
			
		||||
                   {"motivate", Motivate},
 | 
			
		||||
                   {"reddit", Reddit},
 | 
			
		||||
                   {"resize", Resize},
 | 
			
		||||
                   {"reverse", Reverse},
 | 
			
		||||
                   {"scott", Scott},
 | 
			
		||||
                   {"snapchat", Snapchat},
 | 
			
		||||
                   {"speed", &Speed},
 | 
			
		||||
                   {"spin", Spin},
 | 
			
		||||
                   {"squish", Squish},
 | 
			
		||||
                   {"swirl", Swirl},
 | 
			
		||||
                   {"tile", Tile},
 | 
			
		||||
                   {"togif", ToGif},
 | 
			
		||||
                   {"uncanny", Uncanny},
 | 
			
		||||
                   {"uncaption", &Uncaption},
 | 
			
		||||
                   {"wall", Wall},
 | 
			
		||||
                   {"watermark", &Watermark},
 | 
			
		||||
                   {"whisper", Whisper},
 | 
			
		||||
                   {"zamn", Zamn}};
 | 
			
		||||
 | 
			
		||||
std::map<std::string,
 | 
			
		||||
         char* (*)(string* type, ArgumentMap Arguments, size_t* DataSize)>
 | 
			
		||||
    NoInputFunctionMap = {{"homebrew", Homebrew}, {"sonic", Sonic}};
 | 
			
		||||
 | 
			
		||||
bool isNapiValueInt(Napi::Env& env, Napi::Value& num) {
 | 
			
		||||
  return env.Global()
 | 
			
		||||
      .Get("Number")
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +116,7 @@ Napi::Value ProcessImage(const Napi::CallbackInfo& info) {
 | 
			
		|||
    string command = info[0].As<Napi::String>().Utf8Value();
 | 
			
		||||
    Napi::Object obj = info[1].As<Napi::Object>();
 | 
			
		||||
    string type =
 | 
			
		||||
        obj.Has("type") ? obj.Get("type").As<Napi::String>().Utf8Value() : "png";
 | 
			
		||||
        obj.Has("type") ? obj.Get("type").As<Napi::String>().Utf8Value() : NULL;
 | 
			
		||||
 | 
			
		||||
    Napi::Array properties = obj.GetPropertyNames();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -64,28 +148,25 @@ Napi::Value ProcessImage(const Napi::CallbackInfo& info) {
 | 
			
		|||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    string outType = GetArgument<bool>(Arguments, "togif") ? "gif" : type;
 | 
			
		||||
 | 
			
		||||
    size_t length = 0;
 | 
			
		||||
    char* buf;
 | 
			
		||||
    if (obj.Has("data")) {
 | 
			
		||||
      Napi::Buffer<char> data = obj.Has("data")
 | 
			
		||||
                                    ? obj.Get("data").As<Napi::Buffer<char>>()
 | 
			
		||||
                                    : Napi::Buffer<char>::New(env, 0);
 | 
			
		||||
      buf = FunctionMap.at(command)(type, &outType, data.Data(), data.Length(),
 | 
			
		||||
      buf = FunctionMap.at(command)(&type, data.Data(), data.Length(),
 | 
			
		||||
                                    Arguments, &length);
 | 
			
		||||
    } else {
 | 
			
		||||
      buf = NoInputFunctionMap.at(command)(type, &outType, Arguments, &length);
 | 
			
		||||
      buf = NoInputFunctionMap.at(command)(&type, Arguments, &length);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vips_error_clear();
 | 
			
		||||
    vips_thread_shutdown();
 | 
			
		||||
 | 
			
		||||
    result.Set("data",
 | 
			
		||||
               Napi::Buffer<char>::New(env, buf, length,
 | 
			
		||||
                                       []([[maybe_unused]] Napi::Env env,
 | 
			
		||||
                                          void* data) { free(data); }));
 | 
			
		||||
    result.Set("type", outType);
 | 
			
		||||
    result.Set("data", Napi::Buffer<char>::New(
 | 
			
		||||
                           env, buf, length,
 | 
			
		||||
                           [](Napi::Env env, void* data) { free(data); }));
 | 
			
		||||
    result.Set("type", type);
 | 
			
		||||
  } catch (std::exception const& err) {
 | 
			
		||||
    Napi::Error::New(env, err.what()).ThrowAsJavaScriptException();
 | 
			
		||||
  } catch (...) {
 | 
			
		||||
| 
						 | 
				
			
			@ -5,14 +5,13 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Invert(string type, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, [[maybe_unused]] ArgumentMap Arguments,
 | 
			
		||||
             size_t *DataSize) {
 | 
			
		||||
char *Invert(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  VOption *options = VImage::option()->set("access", "sequential");
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +21,7 @@ char *Invert(string type, string *outType, char *BufferData,
 | 
			
		|||
  VImage out = inverted.bandjoin(in.extract_band(3));
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  out.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  out.write_to_buffer(("." + *type).c_str(), &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Invert(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Invert(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,13 +5,13 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Jpeg(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
char *Jpeg(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  int quality = GetArgumentWithFallback<int>(Arguments, "quality", 0);
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
 | 
			
		||||
  if (type == "gif") {
 | 
			
		||||
  if (*type == "gif") {
 | 
			
		||||
    VImage in = VImage::new_from_buffer(
 | 
			
		||||
                    BufferData, BufferLength, "",
 | 
			
		||||
                    VImage::option()->set("access", "sequential")->set("n", -1))
 | 
			
		||||
| 
						 | 
				
			
			@ -53,22 +53,13 @@ char *Jpeg(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    final.write_to_buffer(
 | 
			
		||||
        ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
        *outType == "gif" ? VImage::option()->set("dither", 0) : 0);
 | 
			
		||||
        ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
        *type == "gif" ? VImage::option()->set("dither", 0) : 0);
 | 
			
		||||
  } else {
 | 
			
		||||
    VImage in = VImage::new_from_buffer(BufferData, BufferLength, "");
 | 
			
		||||
    void *jpgBuf;
 | 
			
		||||
    in.write_to_buffer(".jpg", &jpgBuf, DataSize,
 | 
			
		||||
    in.write_to_buffer(".jpg", &buf, DataSize,
 | 
			
		||||
                       VImage::option()->set("Q", quality)->set("strip", true));
 | 
			
		||||
    if (*outType == "gif") {
 | 
			
		||||
      VImage gifIn = VImage::new_from_buffer((char *)jpgBuf, *DataSize, "");
 | 
			
		||||
      gifIn.write_to_buffer(
 | 
			
		||||
          ".gif", &buf, DataSize,
 | 
			
		||||
          VImage::option()->set("Q", quality)->set("strip", true));
 | 
			
		||||
    } else {
 | 
			
		||||
      *outType = "jpg";
 | 
			
		||||
      buf = jpgBuf;
 | 
			
		||||
    }
 | 
			
		||||
    *type = "jpg";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Jpeg(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Jpeg(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -9,8 +9,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace Magick;
 | 
			
		||||
 | 
			
		||||
char *Magik(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
            [[maybe_unused]] ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Magik(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  Blob blob;
 | 
			
		||||
 | 
			
		||||
  list<Image> frames;
 | 
			
		||||
| 
						 | 
				
			
			@ -29,13 +29,13 @@ char *Magik(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
    image.scale(Geometry("350x350"));
 | 
			
		||||
    image.liquidRescale(Geometry("175x175"));
 | 
			
		||||
    image.liquidRescale(Geometry("350x350"));
 | 
			
		||||
    image.magick(*outType);
 | 
			
		||||
    image.magick(*type);
 | 
			
		||||
    blurred.push_back(image);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  optimizeTransparency(blurred.begin(), blurred.end());
 | 
			
		||||
 | 
			
		||||
  if (*outType == "gif") {
 | 
			
		||||
  if (*type == "gif") {
 | 
			
		||||
    for (Image &image : blurred) {
 | 
			
		||||
      image.quantizeDitherMethod(FloydSteinbergDitherMethod);
 | 
			
		||||
      image.quantize();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Magik(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Magik(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Meme(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
char *Meme(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string top = GetArgument<string>(Arguments, "top");
 | 
			
		||||
  string bottom = GetArgument<string>(Arguments, "bottom");
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ char *Meme(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +110,7 @@ char *Meme(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    if (top != "") {
 | 
			
		||||
      img_frame = img_frame.composite2(
 | 
			
		||||
          topText, VIPS_BLEND_MODE_OVER,
 | 
			
		||||
| 
						 | 
				
			
			@ -130,10 +130,9 @@ char *Meme(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Meme(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Meme(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Mirror(string type, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Mirror(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool vertical = GetArgumentWithFallback<bool>(Arguments, "vertical", false);
 | 
			
		||||
  bool first = GetArgumentWithFallback<bool>(Arguments, "first", false);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,14 +14,14 @@ char *Mirror(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
  VImage out;
 | 
			
		||||
 | 
			
		||||
  if (vertical) {
 | 
			
		||||
    if (type == "gif") {
 | 
			
		||||
    if (*type == "gif") {
 | 
			
		||||
      // once again, libvips gif handling is both a blessing and a curse
 | 
			
		||||
      vector<VImage> img;
 | 
			
		||||
      int pageHeight = vips_image_get_page_height(in.get_image());
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ char *Mirror(string type, string *outType, char *BufferData,
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  out.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  out.write_to_buffer(("." + *type).c_str(), &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Mirror(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Mirror(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Motivate(string type, string *outType, char *BufferData,
 | 
			
		||||
               size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Motivate(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
               ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string top_text = GetArgument<string>(Arguments, "top");
 | 
			
		||||
  string bottom_text = GetArgument<string>(Arguments, "bottom");
 | 
			
		||||
  string font = GetArgument<string>(Arguments, "font");
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ char *Motivate(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +69,7 @@ char *Motivate(string type, string *outType, char *BufferData,
 | 
			
		|||
  int height;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
 | 
			
		||||
    int borderSize = max(2, width / 66);
 | 
			
		||||
    int borderSize2 = borderSize * 0.5;
 | 
			
		||||
| 
						 | 
				
			
			@ -116,8 +116,8 @@ char *Motivate(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif" ? VImage::option()->set("dither", 1) : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 1) : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Motivate(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Motivate(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
               ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Reddit(string type, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Reddit(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string text = GetArgument<string>(Arguments, "text");
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ char *Reddit(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ char *Reddit(string type, string *outType, char *BufferData,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *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);
 | 
			
		||||
| 
						 | 
				
			
			@ -58,10 +58,9 @@ char *Reddit(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Reddit(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Reddit(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Resize(string type, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Resize(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool stretch = GetArgumentWithFallback<bool>(Arguments, "stretch", false);
 | 
			
		||||
  bool wide = GetArgumentWithFallback<bool>(Arguments, "wide", false);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ char *Resize(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
 | 
			
		||||
  VImage out;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ char *Resize(string type, string *outType, char *BufferData,
 | 
			
		|||
    vector<VImage> img;
 | 
			
		||||
    for (int i = 0; i < nPages; i++) {
 | 
			
		||||
      VImage img_frame =
 | 
			
		||||
          type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
          *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);
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ char *Resize(string type, string *outType, char *BufferData,
 | 
			
		|||
  out.set(VIPS_META_PAGE_HEIGHT, finalHeight);
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  out.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  out.write_to_buffer(("." + *type).c_str(), &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Resize(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Resize(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -6,8 +6,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Reverse(string type, string *outType, char *BufferData,
 | 
			
		||||
              size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Reverse(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool soos = GetArgumentWithFallback<bool>(Arguments, "soos", false);
 | 
			
		||||
 | 
			
		||||
  VOption *options =
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ char *Reverse(string type, string *outType, char *BufferData,
 | 
			
		|||
  final.write_to_buffer(".gif", &buf, DataSize,
 | 
			
		||||
                        VImage::option()->set("dither", 0));
 | 
			
		||||
 | 
			
		||||
  *outType = "gif";
 | 
			
		||||
  *type = "gif";
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Reverse(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Reverse(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,55 +1,64 @@
 | 
			
		|||
#include <vips/vips8>
 | 
			
		||||
#include <Magick++.h>
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <list>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
using namespace Magick;
 | 
			
		||||
 | 
			
		||||
char *Scott(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
char *Scott(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
 | 
			
		||||
  VOption *options = VImage::option()->set("access", "sequential");
 | 
			
		||||
  Blob blob;
 | 
			
		||||
 | 
			
		||||
  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<VImage> 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);
 | 
			
		||||
  list<Image> frames;
 | 
			
		||||
  list<Image> coalesced;
 | 
			
		||||
  list<Image> 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 final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
 | 
			
		||||
  final.set(VIPS_META_PAGE_HEIGHT, 481);
 | 
			
		||||
  watermark.read(basePath + "assets/images/scott.png");
 | 
			
		||||
  coalesceImages(&coalesced, frames.begin(), frames.end());
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif" ? VImage::option()->set("dither", 1) : 0);
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
  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(*type);
 | 
			
		||||
    watermark_new.animationDelay(image.animationDelay());
 | 
			
		||||
    mid.push_back(watermark_new);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  optimizeTransparency(mid.begin(), mid.end());
 | 
			
		||||
 | 
			
		||||
  if (*type == "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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Scott(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Scott(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Snapchat(string type, string *outType, char *BufferData,
 | 
			
		||||
               size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Snapchat(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
               ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string caption = GetArgument<string>(Arguments, "caption");
 | 
			
		||||
  float pos = GetArgumentWithFallback<float>(Arguments, "pos", 0.5);
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ char *Snapchat(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +52,7 @@ char *Snapchat(string type, string *outType, char *BufferData,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    img_frame = img_frame.composite2(
 | 
			
		||||
        textIn, VIPS_BLEND_MODE_OVER,
 | 
			
		||||
        VImage::option()->set("x", 0)->set("y", pageHeight * pos));
 | 
			
		||||
| 
						 | 
				
			
			@ -63,10 +63,9 @@ char *Snapchat(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Snapchat(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Snapchat(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
               ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,7 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Sonic(string type, string *outType, ArgumentMap Arguments,
 | 
			
		||||
            size_t *DataSize) {
 | 
			
		||||
char *Sonic(string *type, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string text = GetArgument<string>(Arguments, "text");
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +28,9 @@ char *Sonic(string type, string *outType, ArgumentMap Arguments,
 | 
			
		|||
                             VImage::option()->set("x", 391)->set("y", 84));
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  out.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  out.write_to_buffer(".png", &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  *type = "png";
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,4 +4,4 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char *Sonic(string type, string *outType, ArgumentMap Arguments, size_t *DataSize);
 | 
			
		||||
char *Sonic(string *type, ArgumentMap Arguments, size_t *DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -39,8 +39,8 @@ char *vipsRemove(char *data, size_t length, size_t *DataSize, int speed) {
 | 
			
		|||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *Speed([[maybe_unused]] string type, string *outType, char *BufferData,
 | 
			
		||||
            size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Speed(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  bool slow = GetArgumentWithFallback<bool>(Arguments, "slow", false);
 | 
			
		||||
  int speed = GetArgumentWithFallback<int>(Arguments, "speed", 2);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ char *Speed([[maybe_unused]] string type, string *outType, char *BufferData,
 | 
			
		|||
  bool removeFrames = false;
 | 
			
		||||
  char *lastPos;
 | 
			
		||||
 | 
			
		||||
  // int amount = 0;
 | 
			
		||||
  int amount = 0;
 | 
			
		||||
 | 
			
		||||
  lastPos = (char *)memchr(fileData, '\x00', BufferLength);
 | 
			
		||||
  while (lastPos != NULL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ char *Speed([[maybe_unused]] string type, string *outType, char *BufferData,
 | 
			
		|||
                               (BufferLength - (lastPos - fileData)) - 1);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    //++amount;
 | 
			
		||||
    ++amount;
 | 
			
		||||
    uint16_t old_delay;
 | 
			
		||||
    memcpy(&old_delay, lastPos + 5, 2);
 | 
			
		||||
    old_delays.push_back(old_delay);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Speed(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Speed(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,16 +1,15 @@
 | 
			
		|||
#include "common.h"
 | 
			
		||||
#include <Magick++.h>
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <list>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace Magick;
 | 
			
		||||
 | 
			
		||||
char *Spin(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
           [[maybe_unused]] ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Spin(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  int delay = GetArgumentWithFallback<int>(Arguments, "delay", 0);
 | 
			
		||||
 | 
			
		||||
  Blob blob;
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +26,7 @@ char *Spin(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  }
 | 
			
		||||
  coalesceImages(&coalesced, frames.begin(), frames.end());
 | 
			
		||||
 | 
			
		||||
  if (type != "gif") {
 | 
			
		||||
  if (*type != "gif") {
 | 
			
		||||
    list<Image>::iterator it = coalesced.begin();
 | 
			
		||||
    for (int i = 0; i < 29; ++i) {
 | 
			
		||||
      coalesced.push_back(*it);
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +51,7 @@ char *Spin(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  optimizeTransparency(mid.begin(), mid.end());
 | 
			
		||||
  if (delay != 0) {
 | 
			
		||||
    for_each(mid.begin(), mid.end(), animationDelayImage(delay));
 | 
			
		||||
  } else if (type != "gif") {
 | 
			
		||||
  } else if (*type != "gif") {
 | 
			
		||||
    for_each(mid.begin(), mid.end(), animationDelayImage(5));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +62,7 @@ char *Spin(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  writeImages(mid.begin(), mid.end(), &blob);
 | 
			
		||||
 | 
			
		||||
  *outType = "gif";
 | 
			
		||||
  *type = "gif";
 | 
			
		||||
  *DataSize = blob.length();
 | 
			
		||||
 | 
			
		||||
  char *data = (char *)malloc(*DataSize);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Spin(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Spin(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -7,28 +7,27 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Squish(string type, string *outType, char *BufferData,
 | 
			
		||||
             size_t BufferLength, [[maybe_unused]] ArgumentMap Arguments,
 | 
			
		||||
             size_t *DataSize) {
 | 
			
		||||
char *Squish(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  VOption *options = VImage::option();
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(
 | 
			
		||||
          BufferData, BufferLength, "",
 | 
			
		||||
          type == "gif" ? options->set("n", -1)->set("access", "sequential")
 | 
			
		||||
                        : options)
 | 
			
		||||
          *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 nPages = *type == "gif" ? vips_image_get_n_pages(in.get_image()) : 30;
 | 
			
		||||
  double mult = (2 * M_PI) / nPages;
 | 
			
		||||
 | 
			
		||||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    double newWidth = (sin(i * mult) / 4) + 0.75;
 | 
			
		||||
    double newHeight = (cos(i * mult) / 4) + 0.75;
 | 
			
		||||
    VImage resized =
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +37,7 @@ char *Squish(string type, string *outType, char *BufferData,
 | 
			
		|||
  }
 | 
			
		||||
  VImage final = VImage::arrayjoin(img, VImage::option()->set("across", 1));
 | 
			
		||||
  final.set(VIPS_META_PAGE_HEIGHT, pageHeight);
 | 
			
		||||
  if (type != "gif") {
 | 
			
		||||
  if (*type != "gif") {
 | 
			
		||||
    vector<int> delay(30, 50);
 | 
			
		||||
    final.set("delay", delay);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +45,7 @@ char *Squish(string type, string *outType, char *BufferData,
 | 
			
		|||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(".gif", &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  *outType = "gif";
 | 
			
		||||
  *type = "gif";
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Squish(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Squish(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
             ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,13 +5,13 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Swirl(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
            [[maybe_unused]] ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Swirl(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  VOption *options = VImage::option()->set("access", "sequential");
 | 
			
		||||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ char *Swirl(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
 | 
			
		||||
    VImage distort =
 | 
			
		||||
        img_frame
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@ char *Swirl(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  final.set(VIPS_META_PAGE_HEIGHT, pageHeight);
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  final.write_to_buffer(".gif", &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Swirl(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Swirl(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -9,8 +9,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace Magick;
 | 
			
		||||
 | 
			
		||||
char *Tile(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
           [[maybe_unused]] ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Tile(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  Blob blob;
 | 
			
		||||
 | 
			
		||||
  list<Image> frames;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ char *Tile(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
    Image appended;
 | 
			
		||||
    list<Image> montage;
 | 
			
		||||
    Image frame;
 | 
			
		||||
    image.magick(*outType);
 | 
			
		||||
    image.magick(*type);
 | 
			
		||||
    for (int i = 0; i < 5; ++i) {
 | 
			
		||||
      duplicated.push_back(image);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ char *Tile(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  optimizeTransparency(mid.begin(), mid.end());
 | 
			
		||||
 | 
			
		||||
  if (*outType == "gif") {
 | 
			
		||||
  if (*type == "gif") {
 | 
			
		||||
    for (Image &image : mid) {
 | 
			
		||||
      image.quantizeDitherMethod(FloydSteinbergDitherMethod);
 | 
			
		||||
      image.quantize();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Tile(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Tile(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,9 +5,9 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *ToGif(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
            [[maybe_unused]] ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  if (type == "gif") {
 | 
			
		||||
char *ToGif(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  if (*type == "gif") {
 | 
			
		||||
    *DataSize = BufferLength;
 | 
			
		||||
    char *data = (char *)malloc(BufferLength);
 | 
			
		||||
    memcpy(data, BufferData, BufferLength);
 | 
			
		||||
| 
						 | 
				
			
			@ -17,11 +17,11 @@ char *ToGif(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
    VImage in = VImage::new_from_buffer(
 | 
			
		||||
        BufferData, BufferLength, "",
 | 
			
		||||
        type == "webp" ? options->set("n", -1) : options);
 | 
			
		||||
        *type == "webp" ? options->set("n", -1) : options);
 | 
			
		||||
 | 
			
		||||
    void *buf;
 | 
			
		||||
    in.write_to_buffer(".gif", &buf, DataSize);
 | 
			
		||||
    *outType = "gif";
 | 
			
		||||
    *type = "gif";
 | 
			
		||||
 | 
			
		||||
    return (char *)buf;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* ToGif(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* ToGif(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
            ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Uncanny(string type, string *outType, char *BufferData,
 | 
			
		||||
              size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Uncanny(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string caption = GetArgument<string>(Arguments, "caption");
 | 
			
		||||
  string caption2 = GetArgument<string>(Arguments, "caption2");
 | 
			
		||||
  string font = GetArgument<string>(Arguments, "font");
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ char *Uncanny(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB)
 | 
			
		||||
          .extract_band(0, VImage::option()->set("n", 3));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +79,7 @@ char *Uncanny(string type, string *outType, char *BufferData,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    VImage resized = img_frame.resize(690.0 / (double)width);
 | 
			
		||||
    if (resized.height() > 590) {
 | 
			
		||||
      double vscale = 590.0 / (double)resized.height();
 | 
			
		||||
| 
						 | 
				
			
			@ -94,8 +94,8 @@ char *Uncanny(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif" ? VImage::option()->set("reoptimise", 1) : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("reoptimise", 1) : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Uncanny(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Uncanny(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -6,8 +6,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Uncaption(string type, string *outType, char *BufferData,
 | 
			
		||||
                size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Uncaption(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
                ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  float tolerance = GetArgumentWithFallback<float>(Arguments, "tolerance", 0.5);
 | 
			
		||||
 | 
			
		||||
  VOption *options = VImage::option();
 | 
			
		||||
| 
						 | 
				
			
			@ -15,8 +15,8 @@ char *Uncaption(string type, string *outType, char *BufferData,
 | 
			
		|||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(
 | 
			
		||||
          BufferData, BufferLength, "",
 | 
			
		||||
          type == "gif" ? options->set("n", -1)->set("access", "sequential")
 | 
			
		||||
                        : options)
 | 
			
		||||
          *type == "gif" ? options->set("n", -1)->set("access", "sequential")
 | 
			
		||||
                         : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,10 +45,9 @@ char *Uncaption(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Uncaption(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Uncaption(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
                ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -9,8 +9,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace Magick;
 | 
			
		||||
 | 
			
		||||
char *Wall(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
           [[maybe_unused]] ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Wall(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  Blob blob;
 | 
			
		||||
 | 
			
		||||
  list<Image> frames;
 | 
			
		||||
| 
						 | 
				
			
			@ -35,13 +35,13 @@ char *Wall(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
                            128, 0, 140, 60, 128, 128, 140, 140};
 | 
			
		||||
    image.distort(Magick::PerspectiveDistortion, 16, arguments);
 | 
			
		||||
    image.scale(Geometry("800x800>"));
 | 
			
		||||
    image.magick(*outType);
 | 
			
		||||
    image.magick(*type);
 | 
			
		||||
    mid.push_back(image);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  optimizeTransparency(mid.begin(), mid.end());
 | 
			
		||||
 | 
			
		||||
  if (*outType == "gif") {
 | 
			
		||||
  if (*type == "gif") {
 | 
			
		||||
    for (Image &image : mid) {
 | 
			
		||||
      image.quantizeDitherMethod(FloydSteinbergDitherMethod);
 | 
			
		||||
      image.quantize();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Wall(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Wall(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -6,8 +6,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Watermark(string type, string *outType, char *BufferData,
 | 
			
		||||
                size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Watermark(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
                ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string water = GetArgument<string>(Arguments, "water");
 | 
			
		||||
  int gravity = GetArgument<int>(Arguments, "gravity");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ char *Watermark(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +91,7 @@ char *Watermark(string type, string *outType, char *BufferData,
 | 
			
		|||
  VImage frame;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *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));
 | 
			
		||||
| 
						 | 
				
			
			@ -121,8 +121,8 @@ char *Watermark(string type, string *outType, char *BufferData,
 | 
			
		|||
          bg = frameAlpha.new_from_image({0, 0, 0}).copy(VImage::option()->set(
 | 
			
		||||
              "interpretation", VIPS_INTERPRETATION_sRGB));
 | 
			
		||||
          frame = bg.bandjoin(frameAlpha);
 | 
			
		||||
          if (*outType == "jpg" || *outType == "jpeg") {
 | 
			
		||||
            *outType = "png";
 | 
			
		||||
          if (*type == "jpg" || *type == "jpeg") {
 | 
			
		||||
            *type = "png";
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        VImage content =
 | 
			
		||||
| 
						 | 
				
			
			@ -145,10 +145,9 @@ char *Watermark(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Watermark(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Watermark(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
                ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,8 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Whisper(string type, string *outType, char *BufferData,
 | 
			
		||||
              size_t BufferLength, ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
char *Whisper(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string caption = GetArgument<string>(Arguments, "caption");
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ char *Whisper(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ char *Whisper(string type, string *outType, char *BufferData,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    img_frame = img_frame.composite2(
 | 
			
		||||
        textImg, VIPS_BLEND_MODE_OVER,
 | 
			
		||||
        VImage::option()
 | 
			
		||||
| 
						 | 
				
			
			@ -77,10 +77,9 @@ char *Whisper(string type, string *outType, char *BufferData,
 | 
			
		|||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(
 | 
			
		||||
      ("." + *outType).c_str(), &buf, DataSize,
 | 
			
		||||
      *outType == "gif"
 | 
			
		||||
          ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
          : 0);
 | 
			
		||||
      ("." + *type).c_str(), &buf, DataSize,
 | 
			
		||||
      *type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
 | 
			
		||||
                     : 0);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Whisper(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Whisper(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
              ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
using namespace std;
 | 
			
		||||
using namespace vips;
 | 
			
		||||
 | 
			
		||||
char *Zamn(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		||||
char *Zamn(string *type, char *BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t *DataSize) {
 | 
			
		||||
  string basePath = GetArgument<string>(Arguments, "basePath");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ char *Zamn(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
 | 
			
		||||
  VImage in =
 | 
			
		||||
      VImage::new_from_buffer(BufferData, BufferLength, "",
 | 
			
		||||
                              type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
                              *type == "gif" ? options->set("n", -1) : options)
 | 
			
		||||
          .colourspace(VIPS_INTERPRETATION_sRGB);
 | 
			
		||||
  if (!in.has_alpha()) in = in.bandjoin(255);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ char *Zamn(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  vector<VImage> img;
 | 
			
		||||
  for (int i = 0; i < nPages; i++) {
 | 
			
		||||
    VImage img_frame =
 | 
			
		||||
        type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
        *type == "gif" ? in.crop(0, i * pageHeight, width, pageHeight) : in;
 | 
			
		||||
    VImage composited = tmpl.insert(
 | 
			
		||||
        img_frame.extract_band(0, VImage::option()->set("n", 3))
 | 
			
		||||
            .bandjoin(255)
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ char *Zamn(string type, string *outType, char *BufferData, size_t BufferLength,
 | 
			
		|||
  final.set(VIPS_META_PAGE_HEIGHT, 516);
 | 
			
		||||
 | 
			
		||||
  void *buf;
 | 
			
		||||
  final.write_to_buffer(("." + *outType).c_str(), &buf, DataSize);
 | 
			
		||||
  final.write_to_buffer(("." + *type).c_str(), &buf, DataSize);
 | 
			
		||||
 | 
			
		||||
  return (char *)buf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,5 +4,5 @@
 | 
			
		|||
 | 
			
		||||
using std::string;
 | 
			
		||||
 | 
			
		||||
char* Zamn(string type, string* outType, char* BufferData, size_t BufferLength,
 | 
			
		||||
char* Zamn(string* type, char* BufferData, size_t BufferLength,
 | 
			
		||||
           ArgumentMap Arguments, size_t* DataSize);
 | 
			
		||||
							
								
								
									
										30
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -29,37 +29,37 @@
 | 
			
		|||
  "dependencies": {
 | 
			
		||||
    "dotenv": "^16.0.3",
 | 
			
		||||
    "emoji-regex": "^10.2.1",
 | 
			
		||||
    "file-type": "^18.2.1",
 | 
			
		||||
    "format-duration": "^3.0.2",
 | 
			
		||||
    "file-type": "^18.0.0",
 | 
			
		||||
    "format-duration": "^2.0.0",
 | 
			
		||||
    "jsqr": "^1.4.0",
 | 
			
		||||
    "node-addon-api": "^5.1.0",
 | 
			
		||||
    "node-addon-api": "^5.0.0",
 | 
			
		||||
    "node-emoji": "^1.11.0",
 | 
			
		||||
    "oceanic.js": "1.5.1",
 | 
			
		||||
    "oceanic.js": "1.3.2",
 | 
			
		||||
    "qrcode": "^1.5.1",
 | 
			
		||||
    "sharp": "^0.31.3",
 | 
			
		||||
    "shoukaku": "^3.3.1",
 | 
			
		||||
    "undici": "^5.20.0",
 | 
			
		||||
    "sharp": "^0.31.2",
 | 
			
		||||
    "shoukaku": "^3.2.2",
 | 
			
		||||
    "undici": "^5.14.0",
 | 
			
		||||
    "winston": "^3.8.2",
 | 
			
		||||
    "winston-daily-rotate-file": "^4.7.1"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@babel/core": "^7.21.0",
 | 
			
		||||
    "@babel/core": "^7.20.5",
 | 
			
		||||
    "@babel/eslint-parser": "^7.19.1",
 | 
			
		||||
    "@babel/eslint-plugin": "^7.19.1",
 | 
			
		||||
    "@babel/plugin-proposal-class-properties": "^7.18.6",
 | 
			
		||||
    "cmake-js": "^7.2.1",
 | 
			
		||||
    "eslint": "^8.35.0",
 | 
			
		||||
    "eslint-plugin-unicorn": "^46.0.0"
 | 
			
		||||
    "cmake-js": "^7.0.0",
 | 
			
		||||
    "eslint": "^8.29.0",
 | 
			
		||||
    "eslint-plugin-unicorn": "^45.0.2"
 | 
			
		||||
  },
 | 
			
		||||
  "optionalDependencies": {
 | 
			
		||||
    "better-sqlite3": "^8.1.0",
 | 
			
		||||
    "better-sqlite3": "^8.0.1",
 | 
			
		||||
    "bufferutil": "^4.0.7",
 | 
			
		||||
    "erlpack": "^0.1.4",
 | 
			
		||||
    "pm2": "^5.2.2",
 | 
			
		||||
    "postgres": "^3.3.4",
 | 
			
		||||
    "postgres": "^3.3.2",
 | 
			
		||||
    "uuid": "^9.0.0",
 | 
			
		||||
    "ws": "^8.12.1",
 | 
			
		||||
    "zlib-sync": "^0.1.8"
 | 
			
		||||
    "ws": "^8.11.0",
 | 
			
		||||
    "zlib-sync": "^0.1.7"
 | 
			
		||||
  },
 | 
			
		||||
  "binary": {
 | 
			
		||||
    "napi_versions": [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										631
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										631
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -138,7 +138,7 @@ export default async (client, info, pages, timeout = 120000) => {
 | 
			
		|||
                } catch {
 | 
			
		||||
                  // no-op
 | 
			
		||||
                }
 | 
			
		||||
                page = Number(response.data.values.raw[0]);
 | 
			
		||||
                page = Number(response.data.values[0]);
 | 
			
		||||
                currentPage = await currentPage.edit(Object.assign(pages[page], options, components));
 | 
			
		||||
                ended = true;
 | 
			
		||||
                dropdownCollector.stop();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue