diff --git a/extensions/SharkPool/Image-Effects.js b/extensions/SharkPool/Image-Effects.js
new file mode 100644
index 0000000000..5ecc029f41
--- /dev/null
+++ b/extensions/SharkPool/Image-Effects.js
@@ -0,0 +1,1297 @@
+// Name: Image Effects
+// ID: imgEffectsSP
+// Description: Apply a variety of new effects to the data URI of Images or Costumes.
+// By: SharkPool
+// Licence: MIT
+
+// Version V.2.5.01
+
+(function (Scratch) {
+ "use strict";
+ if (!Scratch.extensions.unsandboxed) throw new Error("Image Effects must run unsandboxed");
+
+ const menuIconURI =
+"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMzUuNzMxIiBoZWlnaHQ9IjEzNS43MzEiIHZpZXdCb3g9IjAgMCAxMzUuNzMxIDEzNS43MzEiPjxnIGZpbGw9IiM5NmYiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCI+PHBhdGggZD0iTTMuNzUgNjcuODY1YzAtMzUuNDEgMjguNzA1LTY0LjExNSA2NC4xMTUtNjQuMTE1czY0LjExNSAyOC43MDUgNjQuMTE1IDY0LjExNS0yOC43MDUgNjQuMTE1LTY0LjExNSA2NC4xMTVTMy43NSAxMDMuMjc1IDMuNzUgNjcuODY1eiIgc3Ryb2tlPSIjNzc0ZGNiIiBzdHJva2Utd2lkdGg9IjcuNSIvPjxwYXRoIGQ9Ik02OC4zMSA2MS4xMzNjNC4wOTUtMS42NzQgOS4zMDItMS4xOSAxMi4xMzktNS4wNTYgMi45NC00LjAwNiAzLjgyMi0xMi4zNTUgNC40NDgtMTcuMjU4LjYxLTQuNzc4IDEuNzYyLTQuNjExIDIuNjM2LjI0LjkyNSA1LjEzNSAyLjAzNSAxMy42NzggNC42NTQgMTcuMjQ3IDIuOTkzIDQuMDc4IDguOTIzIDMuODQ0IDEzLjMwNiA1LjUyMiAzLjA3NyAxLjE3OCAyLjgwMyAxLjg1My0uNTU4IDIuNTYzLTQuMzE1LjkxMy05LjkwMyAxLjY1OC0xMi45MTYgNS43NjMtMy4xNzkgNC4zMzItNC4yNjIgMTQuNjktNS4wMDYgMjAuODQzLS41MSA0LjIyLTEuOTQ5IDIuNDIyLTIuMjE2LjI3Ni0uNzctNi4xODktMS45NjYtMTYuODMxLTUuNTIyLTIxLjY3Ni0yLjUxNy0zLjQzLTYuNjk2LTQuMDQ4LTEwLjExOC01LTQuNjE2LTEuMjg2LTUuMTMyLTEuNzEzLS44NDctMy40NjR6IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMTUiLz48cGF0aCBkPSJNODAuNDQ5IDU2LjA3N2MyLjk0LTQuMDA2IDIuODIyLTEyLjM1NSAzLjQ0OC0xNy4yNTguNjEtNC43NzggMy44NzMtNC42MTEgNC43NDcuMjQuOTI1IDUuMTM1LjkyNCAxMy42NzggMy41NDMgMTcuMjQ3IDIuOTkzIDQuMDc4IDguMzY3IDIuNzMzIDEyLjc1IDQuNDExIDMuMDc4IDEuMTc4IDMuMzU5IDMuODUzLS4wMDIgNC41NjMtNC4zMTUuOTEzLTkuOTAzLjc2OS0xMi45MTYgNC44NzQtMy4xNzkgNC4zMzItMy40ODQgMTQuOTEyLTQuMjI4IDIxLjA2NS0uNTEgNC4yMi0zLjcyNyAyLjItMy45OTQuMDU0LS43Ny02LjE4OS0uOTY2LTE2LjgzMS00LjUyMi0yMS42NzYtMi41MTctMy40My03LjQ3NC0zLjM4MS0xMC44OTYtNC4zMzQtNC42MTYtMS4yODUtNC4zNTQtMy4yNjgtLjA3LTUuMDIgMCAwIDkuMzAzLS4zIDEyLjE0LTQuMTY2Ii8+PHBhdGggZD0iTTQyLjAzIDQwLjJjMS40OTMtMS42NDcgMS45NC01LjA3OCAyLjI1OS03LjA5NC4zMS0xLjk2My44OTQtMS44OTUgMS4zMzguMS40NyAyLjExIDEuMDMzIDUuNjIgMi4zNjMgNy4wODggMS41MiAxLjY3NiA0LjUzIDEuNTggNi43NTYgMi4yNyAxLjU2Mi40ODQgMS40MjMuNzYtLjI4MyAxLjA1My0yLjE5MS4zNzUtNS4wMjguNjgtNi41NTggMi4zNjgtMS42MTQgMS43OC0yLjE2NCA2LjAzOC0yLjU0MiA4LjU2Ny0uMjU5IDEuNzM0LS45OS45OTUtMS4xMjUuMTEzLS4zOS0yLjU0My0uOTk4LTYuOTE3LTIuODA0LTguOTA5LTEuMjc3LTEuNDEtMy40LTEuNjYzLTUuMTM3LTIuMDU1LTIuMzQ0LS41MjgtMi42MDYtLjcwNC0uNDMtMS40MjQgMCAwIDQuNzIzLS40ODkgNi4xNjMtMi4wNzd6IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMTAiLz48cGF0aCBkPSJNNDIuMDMgNDAuMmMxLjQ5My0xLjY0NyAxLjI3NC00Ljk2NyAxLjU5Mi02Ljk4Mi4zMS0xLjk2NCAyLjExNy0yLjAwNyAyLjU2LS4wMTMuNDcgMi4xMS40NzggNS42MjIgMS44MDggNy4wODkgMS41MiAxLjY3NiA0LjMwOC42MzUgNi41MzQgMS4zMjUgMS41NjIuNDg0IDEuNjQ1IDIuMjYxLS4wNjEgMi41NTMtMi4xOTEuMzc1LTUuMDI4LjEyNi02LjU1OCAxLjgxMy0xLjYxNCAxLjc4LTEuMTY0IDYuMDM4LTEuNTQyIDguNTY3LS4yNTkgMS43MzQtMi43NjcuOTk1LTIuOTAzLjExMy0uMzktMi41NDMtLjIyLTYuOTE3LTIuMDI2LTguOTA5LTEuMjc3LTEuNDEtNC4yODgtLjk5Ny02LjAyNi0xLjM4OC0yLjAwNC0uNDUyLTEuMjY0LTIuMjAxIDAtMi42OTguMjE0LS4wODQgNS4xODIuMTE4IDYuNjIyLTEuNDciLz48cGF0aCBkPSJNNDguNzIxIDkyLjY3NWMxLjU2Mi0xLjk1NyAyLjAzLTYuMDMzIDIuMzYzLTguNDI3LjMyNC0yLjMzMy45MzYtMi4yNTEgMS40LjExOC40OTIgMi41MDcgMS4wODIgNi42NzcgMi40NzMgOC40MiAxLjU5IDEuOTkxIDQuNzQgMS44NzcgNy4wNjggMi42OTYgMS42MzUuNTc2IDEuNDkuOTA1LS4yOTYgMS4yNTItMi4yOTIuNDQ1LTUuMjYuODA5LTYuODYxIDIuODE0LTEuNjg5IDIuMTE1LTIuMjY0IDcuMTcyLTIuNjYgMTAuMTc2LS4yNyAyLjA2LTEuMDM1IDEuMTgzLTEuMTc3LjEzNS0uNDA5LTMuMDIyLTEuMDQ0LTguMjE4LTIuOTMzLTEwLjU4NC0xLjMzNy0xLjY3NC0zLjU1Ny0xLjk3Ni01LjM3NS0yLjQ0MS0yLjQ1Mi0uNjI4LTIuNzI2LS44MzYtLjQ1LTEuNjkxIDAgMCA0Ljk0Mi0uNTgxIDYuNDQ4LTIuNDY4eiIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjEwIi8+PHBhdGggZD0iTTQ4LjcyMSA5Mi42NzVjMS41NjItMS45NTcgMS4zNjQtNi4wMzMgMS42OTctOC40MjcuMzI0LTIuMzMzIDIuMzgtMi4yNTEgMi44NDQuMTE4LjQ5MiAyLjUwNy4zMDQgNi42NzcgMS42OTUgOC40MiAxLjU5IDEuOTkxIDQuMjk2Ljk0NyA2LjYyNCAxLjc2NiAxLjYzNS41NzUgMS45MzMgMi4zOS4xNDggMi43MzctMi4yOTIuNDQ2LTUuMjYuMjU0LTYuODYxIDIuMjU5LTEuNjg5IDIuMTE1LTEuNDg2IDcuMTcyLTEuODgyIDEwLjE3Ni0uMjcgMi4wNi0yLjU5IDEuMTgzLTIuNzMyLjEzNS0uNDEtMy4wMjItLjI2Ny04LjIxOC0yLjE1Ni0xMC41ODQtMS4zMzctMS42NzQtNC4wMDItMS41MzItNS44Mi0xLjk5Ny0yLjQ1Mi0uNjI3LTIuMjgxLTEuODM2LS4wMDUtMi42OSAwIDAgNC45NDItLjAyNiA2LjQ0OC0xLjkxNHoiLz48L2c+PC9zdmc+";
+
+ const cast = Scratch.Cast;
+ const hexToRgb = (hex) => {
+ return [
+ parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16),
+ hex.length === 9 ? parseInt(hex.slice(7, 9), 16) : 255
+ ];
+ };
+ const rgbaToHex = (r, g, b, a) => {
+ const alpha = a !== undefined ? Math.round(a).toString(16).padStart(2, "0") : "";
+ return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1)}${alpha}`;
+ };
+ const imageEffectMenu = [
+ "Saturation", "Contrast", "Opaque", "Glitch", "Chunk Glitch", "Clip Glitch", "Vignette",
+ "Ripple", "Displacement", "Posterize", "Blur", "Sepia", "Scanlines", "Grain", "Cubism",
+ ];
+
+ class imgEffectsSP {
+ constructor() {
+ this.cutPos = [0, 0];
+ this.scale = [100, 100];
+ this.cutoutDirection = 90;
+ this.softness = 10;
+ this.allShards = [];
+ }
+ getInfo() {
+ return {
+ id: "imgEffectsSP",
+ name: "Image Effects",
+ menuIconURI,
+ color1: "#9966FF",
+ color2: "#774DCB",
+ blocks: [
+ {
+ opcode: "applyHueEffect",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "apply hue [COLOR] to URI [SVG]",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ COLOR: { type: Scratch.ArgumentType.COLOR }
+ }
+ },
+ "---",
+ {
+ opcode: "deleteColor",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "remove color [COLOR] from [DATA_URI]",
+ arguments: {
+ COLOR: { type: Scratch.ArgumentType.COLOR },
+ DATA_URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" }
+ }
+ },
+ {
+ opcode: "replaceColor",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "replace color [COLOR] with [REPLACE] from [DATA_URI]",
+ arguments: {
+ COLOR: { type: Scratch.ArgumentType.COLOR },
+ REPLACE: { type: Scratch.ArgumentType.COLOR, defaultValue: "#00ff00" },
+ DATA_URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" }
+ }
+ },
+ {
+ opcode: "setSoftness",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "set color detection softness to [AMT]%",
+ arguments: {
+ AMT: { type: Scratch.ArgumentType.NUMBER, defaultValue: 10 }
+ }
+ },
+ "---",
+ {
+ opcode: "applyEffect",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "set [EFFECT] effect of URI [SVG] to [PERCENTAGE]%",
+ arguments: {
+ EFFECT: { type: Scratch.ArgumentType.STRING, menu: "EFFECTS" },
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ PERCENTAGE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 50 }
+ }
+ },
+ {
+ opcode: "applyBulgeEffect",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "set bulge effect of URI [SVG] to [STRENGTH]% at x [CENTER_X] y [CENTER_Y]",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ STRENGTH: { type: Scratch.ArgumentType.NUMBER, defaultValue: 50 },
+ CENTER_X: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 },
+ CENTER_Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }
+ }
+ },
+ {
+ opcode: "applyWaveEffect",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "set wave effect of URI [SVG] to amplitude x [AMPX] y [AMPY] and frequency x [FREQX] y [FREQY]",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ AMPX: { type: Scratch.ArgumentType.NUMBER, defaultValue: 50 },
+ AMPY: { type: Scratch.ArgumentType.NUMBER, defaultValue: 50 },
+ FREQX: { type: Scratch.ArgumentType.NUMBER, defaultValue: 5 },
+ FREQY: { type: Scratch.ArgumentType.NUMBER, defaultValue: 5 }
+ }
+ },
+ {
+ opcode: "applyLineGlitchEffect",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "set line glitch of URI [SVG] to [PERCENTAGE]% on [DIRECT] axis and line width [WIDTH]",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ PERCENTAGE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 50 },
+ DIRECT: { type: Scratch.ArgumentType.STRING, menu: "POSITIONS" },
+ WIDTH: { type: Scratch.ArgumentType.NUMBER, defaultValue: 5 }
+ }
+ },
+ {
+ opcode: "applyAbberationEffect",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "set abberation of URI [SVG] to colors [COLOR1] and [COLOR2] at [PERCENTAGE]% on [DIRECT] axis",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ PERCENTAGE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 5 },
+ COLOR1: { type: Scratch.ArgumentType.COLOR, defaultValue: "#ff0000" },
+ COLOR2: { type: Scratch.ArgumentType.COLOR, defaultValue: "#00f7ff" },
+ DIRECT: { type: Scratch.ArgumentType.STRING, menu: "POSITIONS" }
+ }
+ },
+ "---",
+ {
+ opcode: "removeTransparencyEffect",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "remove pixels from URI [SVG] [REMOVE] [THRESHOLD]% transparency",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ THRESHOLD: { type: Scratch.ArgumentType.NUMBER, defaultValue: 50 },
+ REMOVE: { type: Scratch.ArgumentType.STRING, menu: "REMOVAL" }
+ }
+ },
+ {
+ opcode: "applyEdgeOutlineEffect",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "add outline to URI [SVG] thickness [THICKNESS] color [COLOR]",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ THICKNESS: { type: Scratch.ArgumentType.NUMBER, defaultValue: 1 },
+ COLOR: { type: Scratch.ArgumentType.COLOR, defaultValue: "#ff0000" }
+ }
+ },
+ { blockType: Scratch.BlockType.LABEL, text: "Clipping" },
+ {
+ opcode: "maskImage", blockType: Scratch.BlockType.REPORTER,
+ text: "[TYPE] [MASK] from [IMG]",
+ arguments: {
+ TYPE: { type: Scratch.ArgumentType.STRING, menu: "MASKING" },
+ IMG: { type: Scratch.ArgumentType.STRING, defaultValue: "source-here" },
+ MASK: { type: Scratch.ArgumentType.STRING, defaultValue: "cutout-here" }
+ }
+ },
+ "---",
+ {
+ opcode: "setCutout",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "set clipping position to x [X] y [Y]",
+ arguments: {
+ X: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 },
+ Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }
+ }
+ },
+ {
+ opcode: "changeCutout",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "change clipping position by x [X] y [Y]",
+ arguments: {
+ X: { type: Scratch.ArgumentType.NUMBER, defaultValue: 10 },
+ Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }
+ }
+ },
+ {
+ opcode: "currentCut",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "clipping [POS]",
+ disableMonitor: true,
+ arguments: {
+ POS: { type: Scratch.ArgumentType.STRING, menu: "POSITIONS" }
+ }
+ },
+ "---",
+ {
+ opcode: "setScale",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "set clipping size to x [SIZE] y [Y]",
+ arguments: {
+ SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100 },
+ Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100 }
+ }
+ },
+ {
+ opcode: "changeScale",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "change clipping size by x [SIZE] y [Y]",
+ arguments: {
+ SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 10 },
+ Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }
+ }
+ },
+ {
+ opcode: "currentScale",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "clipping size [POS]",
+ disableMonitor: true,
+ arguments: {
+ POS: { type: Scratch.ArgumentType.STRING, menu: "POSITIONS" }
+ }
+ },
+ "---",
+ {
+ opcode: "setDirection",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "set clipping direction to [ANGLE]",
+ arguments: {
+ ANGLE: { type: Scratch.ArgumentType.ANGLE, defaultValue: 90 }
+ }
+ },
+ {
+ opcode: "changeDirection",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "change clipping direction by [ANGLE]",
+ arguments: {
+ ANGLE: { type: Scratch.ArgumentType.ANGLE, defaultValue: 15 }
+ }
+ },
+ {
+ opcode: "currentDir",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "clipping direction"
+ },
+ "---",
+ {
+ opcode: "crackImage",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "crack [URI] into [SHARDS] shards",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ SHARDS: { type: Scratch.ArgumentType.NUMBER, defaultValue: 5 }
+ }
+ },
+ {
+ opcode: "getShard",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "get shard #[SHARD]",
+ arguments: {
+ SHARD: { type: Scratch.ArgumentType.NUMBER, defaultValue: 1 }
+ }
+ },
+ { blockType: Scratch.BlockType.LABEL, text: "Pixels" },
+ {
+ opcode: "commonCol",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "[TYPE] common color in [URI]",
+ arguments: {
+ TYPE: { type: Scratch.ArgumentType.STRING, menu: "DOMINANT" },
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" }
+ }
+ },
+ "---",
+ {
+ opcode: "numPixels",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "number of pixels [TYPE] in [URI]",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ TYPE: { type: Scratch.ArgumentType.STRING, menu: "PIXELTYPE" }
+ }
+ },
+ {
+ opcode: "getPixel",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "get hex of pixel #[NUM] in [URI]",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 1 }
+ }
+ },
+ {
+ opcode: "setPixel",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "set color of pixel #[NUM] to [COLOR] in [URI]",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 1 },
+ COLOR: { type: Scratch.ArgumentType.COLOR }
+ }
+ },
+ {
+ opcode: "setPixels",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "set color of pixels from #[NUM] to [NUM2] to [COLOR] in [URI]",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 1 },
+ NUM2: { type: Scratch.ArgumentType.NUMBER, defaultValue: 10 },
+ COLOR: { type: Scratch.ArgumentType.COLOR }
+ }
+ },
+ { blockType: Scratch.BlockType.LABEL, text: "Image Conversions" },
+ {
+ opcode: "svgToBitmap",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "convert svg content [SVG] to bitmap with width [WIDTH] height [HEIGHT]",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "" },
+ WIDTH: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100 },
+ HEIGHT: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100 }
+ }
+ },
+ {
+ opcode: "convertImageToSVG",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "convert bitmap URI [URI] to svg [TYPE]",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ TYPE: { type: Scratch.ArgumentType.STRING, menu: "fileType" }
+ }
+ },
+ {
+ opcode: "makeSVGimage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "make svg with image URI [URI] to svg [TYPE]",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ TYPE: { type: Scratch.ArgumentType.STRING, menu: "fileType" }
+ }
+ },
+ {
+ opcode: "upscaleImage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "upscale image URI [URI] by [NUM] %",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ NUM: { type: Scratch.ArgumentType.NUMBER, defaultValue: 5 }
+ }
+ },
+ "---",
+ {
+ opcode: "stretchImg",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "stretch URI [URI] to width [W] height [H]",
+ arguments: {
+ URI: { type: Scratch.ArgumentType.STRING, defaultValue: "svg/data-uri" },
+ W: { type: Scratch.ArgumentType.NUMBER, defaultValue: 200 },
+ H: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100 }
+ }
+ },
+ "---",
+ {
+ opcode: "audioToImage",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "convert audio URI [AUDIO_URI] to PNG with width [W] height [H]",
+ arguments: {
+ AUDIO_URI: { type: Scratch.ArgumentType.STRING, defaultValue: "audio_uri_here" },
+ W: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100 },
+ H: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100 }
+ }
+ },
+ {
+ opcode: "skewSVG",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "skew SVG content [SVG] at x [Y] y [X] as [TYPE]",
+ arguments: {
+ SVG: { type: Scratch.ArgumentType.STRING, defaultValue: "