@pixerate/editor 0.248.0 → 0.250.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +1 -0
  2. package/dist/animation-editor/index.cjs +118 -114
  3. package/dist/animation-editor/index.js +11 -7
  4. package/dist/{brushstrokeRender-QLCXROJK.js → brushstrokeRender-2FHFLSEG.js} +8 -4
  5. package/dist/{brushstrokeRender-DTDPFBLC.cjs → brushstrokeRender-QGRXOKDA.cjs} +15 -11
  6. package/dist/canvas/index.cjs +71 -15
  7. package/dist/canvas/index.d.cts +1 -0
  8. package/dist/canvas/index.d.ts +1 -0
  9. package/dist/canvas/index.js +58 -2
  10. package/dist/canvas/stickers.d.cts +35 -0
  11. package/dist/canvas/stickers.d.ts +35 -0
  12. package/dist/{chunk-RXZL4NG5.js → chunk-226QDRO3.js} +1 -1
  13. package/dist/{chunk-SC2RZ5EF.js → chunk-2VJAVXLI.js} +2 -2
  14. package/dist/{chunk-OLNIPTB3.cjs → chunk-2VX55NFM.cjs} +1 -320
  15. package/dist/chunk-3K6HWEXZ.cjs +92 -0
  16. package/dist/{chunk-UOOK7HTX.js → chunk-3PPJRMIG.js} +1 -1
  17. package/dist/{chunk-ZFSLEOSQ.js → chunk-3TWOCSCY.js} +11 -9
  18. package/dist/chunk-4D6KP5BV.js +92 -0
  19. package/dist/chunk-4JNWA3VT.cjs +302 -0
  20. package/dist/{chunk-L3JFOTBQ.js → chunk-5E2Q7ZHI.js} +1 -1
  21. package/dist/{chunk-2ONK3ERD.cjs → chunk-75K3W4D6.cjs} +20 -20
  22. package/dist/{chunk-AU6MWQKZ.js → chunk-ABL7IWFZ.js} +1 -1
  23. package/dist/chunk-ATK6ABN3.cjs +303 -0
  24. package/dist/{chunk-7T7JWTVE.cjs → chunk-BOHDJJ2O.cjs} +8 -8
  25. package/dist/{chunk-2PBZBRP5.js → chunk-D5KGAO4Z.js} +10 -92
  26. package/dist/{chunk-HB4ICNNA.cjs → chunk-DPYAO5U6.cjs} +42 -42
  27. package/dist/{chunk-6G6ZDDDB.cjs → chunk-GT77U7QG.cjs} +303 -149
  28. package/dist/{chunk-PQ3H2AAN.cjs → chunk-I7NJPHWV.cjs} +122 -204
  29. package/dist/{chunk-42TWUPNJ.js → chunk-IRSTHLQQ.js} +1 -320
  30. package/dist/{chunk-GHCSC2WP.cjs → chunk-ISIO63Q5.cjs} +21 -15
  31. package/dist/{chunk-OFH6Q67U.js → chunk-JA57JIT5.js} +9 -3
  32. package/dist/{chunk-VMROIWLL.cjs → chunk-KBYB7OWB.cjs} +3 -3
  33. package/dist/{chunk-Q2HA52V4.js → chunk-KDLBJ6QR.js} +2 -2
  34. package/dist/{chunk-WVS5KQDH.cjs → chunk-M2VKFE5L.cjs} +246 -244
  35. package/dist/{chunk-5GLYUSNT.js → chunk-NOHJP5TK.js} +1 -1
  36. package/dist/{chunk-XNRBMYNB.js → chunk-NTRAVM2I.js} +1 -1
  37. package/dist/{chunk-VNBUDVD4.js → chunk-OTEPAQJX.js} +228 -74
  38. package/dist/chunk-OTTT5N3K.js +322 -0
  39. package/dist/{chunk-QOBCBGGI.cjs → chunk-QKXO6JPP.cjs} +14 -14
  40. package/dist/{chunk-NZ3O3A5C.js → chunk-SMSGP2HQ.js} +1 -1
  41. package/dist/chunk-SZTI6EER.js +13 -0
  42. package/dist/chunk-U4NUOKBT.js +303 -0
  43. package/dist/chunk-U67EN7GG.cjs +13 -0
  44. package/dist/chunk-W5M3J7PV.cjs +322 -0
  45. package/dist/{chunk-4P6H35HU.js → chunk-WA44NKPF.js} +2 -2
  46. package/dist/chunk-WKH5ZAUA.js +302 -0
  47. package/dist/{chunk-L6REDLNB.cjs → chunk-WPUXGDH4.cjs} +7 -7
  48. package/dist/{chunk-P3NIPIKS.js → chunk-WQCNC4DK.js} +1 -1
  49. package/dist/{chunk-IBDU6EGZ.cjs → chunk-X7WRL5ZZ.cjs} +35 -35
  50. package/dist/{chunk-XWTRATIM.cjs → chunk-YM6ZBTXG.cjs} +23 -23
  51. package/dist/{chunk-TPWB4Y6L.cjs → chunk-YW43M56C.cjs} +1 -1
  52. package/dist/{chunk-K5DS2JTA.cjs → chunk-Z3BRH4JK.cjs} +6 -6
  53. package/dist/{chunk-XNZFVYC2.cjs → chunk-ZBCT5MEA.cjs} +7 -7
  54. package/dist/effects/helpers.d.cts +6 -0
  55. package/dist/effects/helpers.d.ts +6 -0
  56. package/dist/effects/index.cjs +62 -60
  57. package/dist/effects/index.js +5 -3
  58. package/dist/effects/tools.d.cts +6 -0
  59. package/dist/effects/tools.d.ts +6 -0
  60. package/dist/image-editor/effects.d.cts +1 -1
  61. package/dist/image-editor/effects.d.ts +1 -1
  62. package/dist/image-editor/index.cjs +1097 -1069
  63. package/dist/image-editor/index.d.cts +1 -0
  64. package/dist/image-editor/index.d.ts +1 -0
  65. package/dist/image-editor/index.js +58 -30
  66. package/dist/image-editor/stickers.d.cts +9 -0
  67. package/dist/image-editor/stickers.d.ts +9 -0
  68. package/dist/paint/index.cjs +8 -5
  69. package/dist/paint/index.js +13 -10
  70. package/dist/paint-editor/controller.d.cts +37 -1
  71. package/dist/paint-editor/controller.d.ts +37 -1
  72. package/dist/paint-editor/index.cjs +753 -609
  73. package/dist/paint-editor/index.d.cts +3 -0
  74. package/dist/paint-editor/index.d.ts +3 -0
  75. package/dist/paint-editor/index.js +187 -43
  76. package/dist/paint-editor/sticker-art.d.cts +55 -0
  77. package/dist/paint-editor/sticker-art.d.ts +55 -0
  78. package/dist/paint-editor/stickers.d.cts +30 -17
  79. package/dist/paint-editor/stickers.d.ts +30 -17
  80. package/dist/paint-editor/stroke.d.cts +4 -0
  81. package/dist/paint-editor/stroke.d.ts +4 -0
  82. package/dist/paint-editor/ui.d.cts +10 -2
  83. package/dist/paint-editor/ui.d.ts +10 -2
  84. package/dist/raster/index.cjs +6 -4
  85. package/dist/raster/index.js +12 -10
  86. package/dist/stickers/browser.d.cts +48 -0
  87. package/dist/stickers/browser.d.ts +48 -0
  88. package/dist/stickers/combine.d.cts +10 -0
  89. package/dist/stickers/combine.d.ts +10 -0
  90. package/dist/stickers/conformance.d.cts +18 -0
  91. package/dist/stickers/conformance.d.ts +18 -0
  92. package/dist/stickers/editor.d.cts +14 -0
  93. package/dist/stickers/editor.d.ts +14 -0
  94. package/dist/stickers/errors.d.cts +6 -0
  95. package/dist/stickers/errors.d.ts +6 -0
  96. package/dist/stickers/fake.d.cts +16 -0
  97. package/dist/stickers/fake.d.ts +16 -0
  98. package/dist/stickers/helpers.d.cts +51 -0
  99. package/dist/stickers/helpers.d.ts +51 -0
  100. package/dist/stickers/index.cjs +337 -0
  101. package/dist/stickers/index.d.cts +16 -0
  102. package/dist/stickers/index.d.ts +16 -0
  103. package/dist/stickers/index.js +337 -0
  104. package/dist/stickers/stamps.d.cts +13 -0
  105. package/dist/stickers/stamps.d.ts +13 -0
  106. package/dist/stickers/tools.d.cts +81 -0
  107. package/dist/stickers/tools.d.ts +81 -0
  108. package/dist/stickers/types.d.cts +123 -0
  109. package/dist/stickers/types.d.ts +123 -0
  110. package/dist/vector/index.cjs +1018 -981
  111. package/dist/vector/index.d.cts +1 -0
  112. package/dist/vector/index.d.ts +1 -0
  113. package/dist/vector/index.js +44 -7
  114. package/dist/vector/stickers.d.cts +11 -0
  115. package/dist/vector/stickers.d.ts +11 -0
  116. package/dist/video-editor/index.cjs +344 -344
  117. package/dist/video-editor/index.js +4 -4
  118. package/package.json +11 -1
  119. package/skills/README.md +1 -0
  120. package/skills/pixerate-image-editor/SKILL.md +1 -1
  121. package/skills/pixerate-paint-editor/SKILL.md +8 -5
  122. package/skills/pixerate-stickers/SKILL.md +57 -0
@@ -6,10 +6,6 @@ import {
6
6
  tileKey,
7
7
  tilesInRect
8
8
  } from "./chunk-HVVR5PZW.js";
9
- import {
10
- deflate,
11
- inflate
12
- } from "./chunk-QGHEDC7B.js";
13
9
 
14
10
  // src/raster/pigment.ts
15
11
  var PIGMENT_BANDS = 36;
@@ -990,314 +986,6 @@ function keepDeepSamples(before, after) {
990
986
  return tiles ? new TiledSurface(ch, tiles, after.defaultValue) : after;
991
987
  }
992
988
 
993
- // src/raster/png.ts
994
- var SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];
995
- var crcTable = null;
996
- function crc32(bytes, start, end) {
997
- if (!crcTable) {
998
- crcTable = new Uint32Array(256);
999
- for (let n = 0; n < 256; n++) {
1000
- let c2 = n;
1001
- for (let k = 0; k < 8; k++) c2 = c2 & 1 ? 3988292384 ^ c2 >>> 1 : c2 >>> 1;
1002
- crcTable[n] = c2 >>> 0;
1003
- }
1004
- }
1005
- let c = 4294967295;
1006
- for (let i = start; i < end; i++) c = crcTable[(c ^ bytes[i]) & 255] ^ c >>> 8;
1007
- return (c ^ 4294967295) >>> 0;
1008
- }
1009
- function paeth(a, b, c) {
1010
- const p = a + b - c;
1011
- const pa = Math.abs(p - a);
1012
- const pb = Math.abs(p - b);
1013
- const pc = Math.abs(p - c);
1014
- return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
1015
- }
1016
- function encodePng(width, height, data, channels = 4) {
1017
- const stride = width * channels;
1018
- const raw = new Uint8Array((stride + 1) * height);
1019
- const bpp = channels;
1020
- const cand = [new Uint8Array(stride), new Uint8Array(stride), new Uint8Array(stride), new Uint8Array(stride), new Uint8Array(stride)];
1021
- for (let y = 0; y < height; y++) {
1022
- const row = y * stride;
1023
- const prevRow = (y - 1) * stride;
1024
- let best = 0;
1025
- let bestScore = Infinity;
1026
- for (let f = 0; f < 5; f++) {
1027
- const out2 = cand[f];
1028
- let score = 0;
1029
- for (let x = 0; x < stride; x++) {
1030
- const v = data[row + x];
1031
- const a = x >= bpp ? data[row + x - bpp] : 0;
1032
- const b = y > 0 ? data[prevRow + x] : 0;
1033
- const c = x >= bpp && y > 0 ? data[prevRow + x - bpp] : 0;
1034
- let r;
1035
- switch (f) {
1036
- case 0:
1037
- r = v;
1038
- break;
1039
- case 1:
1040
- r = v - a;
1041
- break;
1042
- case 2:
1043
- r = v - b;
1044
- break;
1045
- case 3:
1046
- r = v - (a + b >> 1);
1047
- break;
1048
- default:
1049
- r = v - paeth(a, b, c);
1050
- }
1051
- r &= 255;
1052
- out2[x] = r;
1053
- score += r < 128 ? r : 256 - r;
1054
- if (score >= bestScore) break;
1055
- }
1056
- if (score < bestScore) {
1057
- bestScore = score;
1058
- best = f;
1059
- }
1060
- }
1061
- const o = y * (stride + 1);
1062
- raw[o] = best;
1063
- raw.set(cand[best], o + 1);
1064
- }
1065
- const idat = deflate(raw);
1066
- const chunks = [];
1067
- const ihdr = new Uint8Array(13);
1068
- writeU32(ihdr, 0, width);
1069
- writeU32(ihdr, 4, height);
1070
- ihdr[8] = 8;
1071
- ihdr[9] = channels === 1 ? 0 : 6;
1072
- chunks.push(["IHDR", ihdr], ["IDAT", idat], ["IEND", new Uint8Array(0)]);
1073
- let size = 8;
1074
- for (const [, d] of chunks) size += 12 + d.length;
1075
- const out = new Uint8Array(size);
1076
- out.set(SIGNATURE, 0);
1077
- let p = 8;
1078
- for (const [type, d] of chunks) {
1079
- writeU32(out, p, d.length);
1080
- for (let i = 0; i < 4; i++) out[p + 4 + i] = type.charCodeAt(i);
1081
- out.set(d, p + 8);
1082
- writeU32(out, p + 8 + d.length, crc32(out, p + 4, p + 8 + d.length));
1083
- p += 12 + d.length;
1084
- }
1085
- return out;
1086
- }
1087
- function writeU32(b, o, v) {
1088
- b[o] = v >>> 24;
1089
- b[o + 1] = v >>> 16 & 255;
1090
- b[o + 2] = v >>> 8 & 255;
1091
- b[o + 3] = v & 255;
1092
- }
1093
- function readU32(b, o) {
1094
- return (b[o] << 24 | b[o + 1] << 16 | b[o + 2] << 8 | b[o + 3]) >>> 0;
1095
- }
1096
- function isPng(bytes) {
1097
- return bytes.length > 8 && SIGNATURE.every((v, i) => bytes[i] === v);
1098
- }
1099
- function decodePng(bytes, options = {}) {
1100
- if (!isPng(bytes)) throw new Error("Not a PNG image.");
1101
- let p = 8;
1102
- let width = 0;
1103
- let height = 0;
1104
- let depth = 0;
1105
- let type = 0;
1106
- let interlace = 0;
1107
- let palette = null;
1108
- let trns = null;
1109
- const idat = [];
1110
- while (p + 8 <= bytes.length) {
1111
- const len = readU32(bytes, p);
1112
- const t = String.fromCharCode(bytes[p + 4], bytes[p + 5], bytes[p + 6], bytes[p + 7]);
1113
- const body = bytes.subarray(p + 8, p + 8 + len);
1114
- if (p + 12 + len > bytes.length) throw new Error("Truncated PNG.");
1115
- if (t === "IHDR") {
1116
- width = readU32(body, 0);
1117
- height = readU32(body, 4);
1118
- depth = body[8];
1119
- type = body[9];
1120
- interlace = body[12];
1121
- } else if (t === "PLTE") palette = body;
1122
- else if (t === "tRNS") trns = body;
1123
- else if (t === "IDAT") idat.push(body);
1124
- else if (t === "IEND") break;
1125
- p += 12 + len;
1126
- }
1127
- if (!width || !height) throw new Error("PNG has no image header.");
1128
- if (interlace) throw new Error("Interlaced PNGs are not supported here; decode them with a canvas.");
1129
- const maxPixels = options.maxPixels ?? 1 << 28;
1130
- if (width * height > maxPixels) throw new Error(`PNG is too large (${width}\xD7${height}).`);
1131
- const samples = type === 0 ? 1 : type === 2 ? 3 : type === 3 ? 1 : type === 4 ? 2 : type === 6 ? 4 : 0;
1132
- if (!samples || ![1, 2, 4, 8, 16].includes(depth)) throw new Error(`Unsupported PNG format (type ${type}, depth ${depth}).`);
1133
- let total = 0;
1134
- for (const c of idat) total += c.length;
1135
- const z = new Uint8Array(total);
1136
- let o = 0;
1137
- for (const c of idat) {
1138
- z.set(c, o);
1139
- o += c.length;
1140
- }
1141
- const bitsPerPixel = samples * depth;
1142
- const stride = Math.ceil(width * bitsPerPixel / 8);
1143
- const raw = inflate(z, { maxOutput: (stride + 1) * height, sizeHint: (stride + 1) * height });
1144
- if (raw.length < (stride + 1) * height) throw new Error("PNG image data is truncated.");
1145
- const bpp = Math.max(1, bitsPerPixel >> 3);
1146
- const lines = new Uint8Array(stride * height);
1147
- for (let y = 0; y < height; y++) {
1148
- const f = raw[y * (stride + 1)];
1149
- const src = y * (stride + 1) + 1;
1150
- const dst = y * stride;
1151
- const up = dst - stride;
1152
- for (let x = 0; x < stride; x++) {
1153
- const v = raw[src + x];
1154
- const a = x >= bpp ? lines[dst + x - bpp] : 0;
1155
- const b = y > 0 ? lines[up + x] : 0;
1156
- const c = x >= bpp && y > 0 ? lines[up + x - bpp] : 0;
1157
- let r;
1158
- switch (f) {
1159
- case 0:
1160
- r = v;
1161
- break;
1162
- case 1:
1163
- r = v + a;
1164
- break;
1165
- case 2:
1166
- r = v + b;
1167
- break;
1168
- case 3:
1169
- r = v + (a + b >> 1);
1170
- break;
1171
- case 4:
1172
- r = v + paeth(a, b, c);
1173
- break;
1174
- default:
1175
- throw new Error(`Invalid PNG filter ${f}.`);
1176
- }
1177
- lines[dst + x] = r & 255;
1178
- }
1179
- }
1180
- const sample = (y, i) => {
1181
- const row = y * stride;
1182
- if (depth === 8) return lines[row + i];
1183
- if (depth === 16) return lines[row + i * 2];
1184
- const perByte = 8 / depth;
1185
- const byte = lines[row + Math.floor(i / perByte)];
1186
- const shift = 8 - depth * (i % perByte + 1);
1187
- const v = byte >> shift & (1 << depth) - 1;
1188
- return type === 3 ? v : Math.round(v * 255 / ((1 << depth) - 1));
1189
- };
1190
- const gray = options.keepGray && type === 0 && !trns;
1191
- const channels = gray ? 1 : 4;
1192
- const out = new Uint8ClampedArray(width * height * channels);
1193
- const trnsGray = trns && type === 0 ? depth === 16 ? trns[0] : sample16(trns, 0, depth) : -1;
1194
- const trnsRgb = trns && type === 2 ? [0, 1, 2].map((k) => depth === 16 ? trns[k * 2] : sample16(trns, k, depth)) : null;
1195
- for (let y = 0; y < height; y++) {
1196
- for (let x = 0; x < width; x++) {
1197
- const d = (y * width + x) * channels;
1198
- if (type === 0) {
1199
- const v = sample(y, x);
1200
- if (gray) out[d] = v;
1201
- else {
1202
- out[d] = out[d + 1] = out[d + 2] = v;
1203
- out[d + 3] = v === trnsGray && trns ? 0 : 255;
1204
- }
1205
- } else if (type === 2) {
1206
- const r = sample(y, x * 3);
1207
- const g = sample(y, x * 3 + 1);
1208
- const b = sample(y, x * 3 + 2);
1209
- out[d] = r;
1210
- out[d + 1] = g;
1211
- out[d + 2] = b;
1212
- out[d + 3] = trnsRgb && r === trnsRgb[0] && g === trnsRgb[1] && b === trnsRgb[2] ? 0 : 255;
1213
- } else if (type === 3) {
1214
- const i = sample(y, x);
1215
- if (!palette || i * 3 + 2 >= palette.length) throw new Error("PNG palette index out of range.");
1216
- out[d] = palette[i * 3];
1217
- out[d + 1] = palette[i * 3 + 1];
1218
- out[d + 2] = palette[i * 3 + 2];
1219
- out[d + 3] = trns && i < trns.length ? trns[i] : 255;
1220
- } else if (type === 4) {
1221
- const v = sample(y, x * 2);
1222
- out[d] = out[d + 1] = out[d + 2] = v;
1223
- out[d + 3] = sample(y, x * 2 + 1);
1224
- } else {
1225
- out[d] = sample(y, x * 4);
1226
- out[d + 1] = sample(y, x * 4 + 1);
1227
- out[d + 2] = sample(y, x * 4 + 2);
1228
- out[d + 3] = sample(y, x * 4 + 3);
1229
- }
1230
- }
1231
- }
1232
- return { width, height, channels, data: out };
1233
- }
1234
- function sample16(trns, k, depth) {
1235
- const v = trns[k * 2] << 8 | trns[k * 2 + 1];
1236
- if (depth === 8) return v & 255;
1237
- return Math.round((v & (1 << depth) - 1) * 255 / ((1 << depth) - 1));
1238
- }
1239
- var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1240
- var B64_INV = null;
1241
- function bytesToBase64(bytes) {
1242
- const parts = [];
1243
- const CHUNK = 3 * 4096;
1244
- for (let start = 0; start < bytes.length; start += CHUNK) {
1245
- const end = Math.min(bytes.length, start + CHUNK);
1246
- let s = "";
1247
- let i = start;
1248
- for (; i + 2 < end; i += 3) {
1249
- const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
1250
- s += B64[n >> 18] + B64[n >> 12 & 63] + B64[n >> 6 & 63] + B64[n & 63];
1251
- }
1252
- if (i < end) {
1253
- const n = bytes[i] << 16 | (i + 1 < end ? bytes[i + 1] << 8 : 0);
1254
- s += B64[n >> 18] + B64[n >> 12 & 63] + (i + 1 < end ? B64[n >> 6 & 63] : "=") + "=";
1255
- }
1256
- parts.push(s);
1257
- }
1258
- return parts.join("");
1259
- }
1260
- function base64ToBytes(text) {
1261
- if (!B64_INV) {
1262
- B64_INV = new Int16Array(128).fill(-1);
1263
- for (let i = 0; i < 64; i++) B64_INV[B64.charCodeAt(i)] = i;
1264
- B64_INV["-".charCodeAt(0)] = 62;
1265
- B64_INV["_".charCodeAt(0)] = 63;
1266
- }
1267
- const inv = B64_INV;
1268
- const clean = text.replace(/[\s=]/g, "");
1269
- const out = new Uint8Array(Math.floor(clean.length * 3 / 4));
1270
- let bits = 0;
1271
- let acc = 0;
1272
- let o = 0;
1273
- for (let i = 0; i < clean.length; i++) {
1274
- const c = clean.charCodeAt(i);
1275
- const v = c < 128 ? inv[c] : -1;
1276
- if (v < 0) throw new Error("Invalid base64 data.");
1277
- acc = acc << 6 | v;
1278
- bits += 6;
1279
- if (bits >= 8) {
1280
- bits -= 8;
1281
- out[o++] = acc >> bits & 255;
1282
- }
1283
- }
1284
- return out.subarray(0, o);
1285
- }
1286
- function parseDataUrl(url) {
1287
- const m = /^data:([^;,]*)((?:;[^;,]*)*?),/i.exec(url);
1288
- if (!m) return null;
1289
- const body = url.slice(m[0].length);
1290
- const isBase64 = /;base64/i.test(m[2]);
1291
- if (isBase64) return { mime: m[1] || "text/plain", bytes: base64ToBytes(body) };
1292
- const text = decodeURIComponent(body);
1293
- const bytes = new Uint8Array(text.length);
1294
- for (let i = 0; i < text.length; i++) bytes[i] = text.charCodeAt(i) & 255;
1295
- return { mime: m[1] || "text/plain", bytes };
1296
- }
1297
- function pngDataUrl(width, height, data, channels = 4) {
1298
- return `data:image/png;base64,${bytesToBase64(encodePng(width, height, data, channels))}`;
1299
- }
1300
-
1301
989
  export {
1302
990
  PIGMENT_BANDS,
1303
991
  PIGMENT_LAMBDA_MIN,
@@ -1350,12 +1038,5 @@ export {
1350
1038
  surfaceFromDeepPixels,
1351
1039
  convertSurfaceDepth,
1352
1040
  deepBytes,
1353
- keepDeepSamples,
1354
- encodePng,
1355
- isPng,
1356
- decodePng,
1357
- bytesToBase64,
1358
- base64ToBytes,
1359
- parseDataUrl,
1360
- pngDataUrl
1041
+ keepDeepSamples
1361
1042
  };
@@ -168,6 +168,10 @@ function applyEffectMask(result, mask, source) {
168
168
  }
169
169
  return result;
170
170
  }
171
+ function layerImageInput(d) {
172
+ const images = d.inputs.filter((i) => i.kind === "image");
173
+ return _nullishCoalesce(_optionalChain([(_nullishCoalesce(_nullishCoalesce(images.find((i) => i.name === "source"), () => ( images.find((i) => i.required))), () => ( images[0]))), 'optionalAccess', _9 => _9.name]), () => ( null));
174
+ }
171
175
  var EffectsSlot = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
172
176
  __init() {this.current = null}
173
177
  __init2() {this.listeners = /* @__PURE__ */ new Set()}
@@ -234,7 +238,7 @@ async function sampleEffectCameraMove(provider, id, request) {
234
238
  }
235
239
  var cameraMoveField = (role) => role === "transition" ? "in" : "during";
236
240
  function cameraMovesFor(catalog, role) {
237
- return catalog.filter((e) => e.kind === "camera" && _optionalChain([e, 'access', _9 => _9.camera, 'optionalAccess', _10 => _10.role]) === role);
241
+ return catalog.filter((e) => e.kind === "camera" && _optionalChain([e, 'access', _10 => _10.camera, 'optionalAccess', _11 => _11.role]) === role);
238
242
  }
239
243
  function cameraMoveIdList(catalog, role) {
240
244
  const ids = cameraMovesFor(catalog, role).map((e) => JSON.stringify(e.id));
@@ -324,12 +328,12 @@ var summaryOut = (e) => ({
324
328
  category: e.category,
325
329
  uses: e.uses,
326
330
  ...e.description ? { description: e.description } : {},
327
- ..._optionalChain([e, 'access', _11 => _11.tags, 'optionalAccess', _12 => _12.length]) ? { tags: e.tags } : {},
331
+ ..._optionalChain([e, 'access', _12 => _12.tags, 'optionalAccess', _13 => _13.length]) ? { tags: e.tags } : {},
328
332
  transparent: e.transparent,
329
333
  loop: e.loop,
330
334
  ...e.duration !== void 0 ? { duration: e.duration } : {},
331
335
  ...e.camera ? { camera: e.camera } : {},
332
- ..._optionalChain([e, 'access', _13 => _13.accepts, 'optionalAccess', _14 => _14.length]) ? { accepts: e.accepts } : {}
336
+ ..._optionalChain([e, 'access', _14 => _14.accepts, 'optionalAccess', _15 => _15.length]) ? { accepts: e.accepts } : {}
333
337
  });
334
338
  function createEffectToolProvider(host) {
335
339
  let catalog = null;
@@ -337,7 +341,7 @@ function createEffectToolProvider(host) {
337
341
  const notify = () => listeners.forEach((l) => l());
338
342
  const catalogFor = (provider) => {
339
343
  if (!provider) return null;
340
- if (_optionalChain([catalog, 'optionalAccess', _15 => _15.provider]) !== provider) {
344
+ if (_optionalChain([catalog, 'optionalAccess', _16 => _16.provider]) !== provider) {
341
345
  const entry = { provider, effects: null };
342
346
  catalog = entry;
343
347
  Promise.resolve().then(() => provider.list()).then((effects) => {
@@ -373,8 +377,9 @@ function createEffectToolProvider(host) {
373
377
  description: `${what}: control name \u2192 value, as listed by describe_effect (its "controls" schema: types, ranges, units and defaults). Only the given controls change; colours are "#rrggbb".${keyframes ? " A number control may instead be keyframes { keys: [{ t: ms from the start, v, ease }] }." : ""} Unknown controls and out-of-range values are refused with the valid ones.`
374
378
  });
375
379
  const effectIdSchema = (uses) => {
376
- const effects = _optionalChain([catalogFor, 'call', _16 => _16(host.provider()), 'optionalAccess', _17 => _17.filter, 'call', _18 => _18((e) => effectOffered(e, uses))]);
377
- const base = `An effect id from search_effects (use ${uses.map((u) => `"${u}"`).join(" or ")}).`;
380
+ const open = host.applyImageInputs && uses === host.applyUses;
381
+ const effects = open ? void 0 : _optionalChain([catalogFor, 'call', _17 => _17(host.provider()), 'optionalAccess', _18 => _18.filter, 'call', _19 => _19((e) => effectOffered(e, uses))]);
382
+ const base = `An effect id from search_effects (use ${uses.map((u) => `"${u}"`).join(" or ")}${open ? `, or any effect whose describe_effect inputs take an image: the ${host.target.noun} is its picture` : ""}).`;
378
383
  return effects && effects.length && effects.length <= ENUM_LIMIT ? { type: "string", enum: effects.map((e) => e.id), description: `${base} One of: ${effects.map((e) => `${e.id} (${e.name})`).join(", ")}.` } : { type: "string", minLength: 1, description: base };
379
384
  };
380
385
  const context = { requireProvider: writable, valuesSchema, effectIdSchema, annotations: ANNOTATIONS };
@@ -403,8 +408,8 @@ function createEffectToolProvider(host) {
403
408
  if (!p) return { available: false, reason: NO_PROVIDER, effects: [], total: 0 };
404
409
  const tags = args.tags;
405
410
  const accepts = args.accepts;
406
- let found = (await explain(async () => p.search(_nullishCoalesce(args.query, () => ( "")), { kind: args.kind, category: args.category, use: args.use, tags, ..._optionalChain([accepts, 'optionalAccess', _19 => _19.length]) ? { accepts } : {} }))).filter((e) => hasEffectTags(e, tags));
407
- if (_optionalChain([accepts, 'optionalAccess', _20 => _20.includes, 'call', _21 => _21("path")])) {
411
+ let found = (await explain(async () => p.search(_nullishCoalesce(args.query, () => ( "")), { kind: args.kind, category: args.category, use: args.use, tags, ..._optionalChain([accepts, 'optionalAccess', _20 => _20.length]) ? { accepts } : {} }))).filter((e) => hasEffectTags(e, tags));
412
+ if (_optionalChain([accepts, 'optionalAccess', _21 => _21.includes, 'call', _22 => _22("path")])) {
408
413
  const kept = [];
409
414
  for (const e of found) {
410
415
  if (e.accepts) {
@@ -415,7 +420,7 @@ function createEffectToolProvider(host) {
415
420
  }
416
421
  const limit = _nullishCoalesce(args.limit, () => ( 20));
417
422
  const out = { available: true, provider: { id: p.id, name: p.name, capabilities: p.capabilities }, effects: found.slice(0, limit).map(summaryOut), total: found.length, tags: countEffectTags(found).slice(0, TAG_LIMIT) };
418
- if (_optionalChain([tags, 'optionalAccess', _22 => _22.length]) && !found.length) {
423
+ if (_optionalChain([tags, 'optionalAccess', _23 => _23.length]) && !found.length) {
419
424
  const known = countEffectTags(await explain(async () => p.list()));
420
425
  const have = new Set(known.map((k) => k.tag));
421
426
  const unknown = tags.filter((t) => !have.has(normaliseEffectTag(t)));
@@ -435,7 +440,7 @@ function createEffectToolProvider(host) {
435
440
  if (!p) return { available: false, reason: NO_PROVIDER };
436
441
  const d = await explain(async () => p.describe(args.effect));
437
442
  const pathControls = pathControlsOf(d);
438
- return { available: true, ...summaryOut(d), controls: d.controls, defaults: d.defaults, presets: d.presets, inputs: d.inputs, appliesHere: effectOffered(d, host.applyUses), ...pathControls.length ? { pathControls } : {} };
443
+ return { available: true, ...summaryOut(d), controls: d.controls, defaults: d.defaults, presets: d.presets, inputs: d.inputs, appliesHere: effectOffered(d, host.applyUses) || !!host.applyImageInputs && d.kind !== "motion" && layerImageInput(d) !== null, ...pathControls.length ? { pathControls } : {} };
439
444
  }
440
445
  },
441
446
  {
@@ -531,16 +536,16 @@ function createEffectToolProvider(host) {
531
536
  ...host.description ? { description: host.description } : {},
532
537
  ...host.skill ? { skill: host.skill } : {},
533
538
  tools: () => {
534
- const extra = _nullishCoalesce(_optionalChain([host, 'access', _23 => _23.extraTools, 'optionalCall', _24 => _24(context)]), () => ( []));
535
- if (host.readOnlyReason()) return [...readTools(), ...extra.filter((t) => _optionalChain([t, 'access', _25 => _25.annotations, 'optionalAccess', _26 => _26.readOnlyHint]))];
539
+ const extra = _nullishCoalesce(_optionalChain([host, 'access', _24 => _24.extraTools, 'optionalCall', _25 => _25(context)]), () => ( []));
540
+ if (host.readOnlyReason()) return [...readTools(), ...extra.filter((t) => _optionalChain([t, 'access', _26 => _26.annotations, 'optionalAccess', _27 => _27.readOnlyHint]))];
536
541
  return [...readTools(), ...writeTools(), ...extra];
537
542
  },
538
543
  subscribe: (l) => {
539
544
  listeners.add(l);
540
- const off = _optionalChain([host, 'access', _27 => _27.subscribe, 'optionalCall', _28 => _28(l)]);
545
+ const off = _optionalChain([host, 'access', _28 => _28.subscribe, 'optionalCall', _29 => _29(l)]);
541
546
  return () => {
542
547
  listeners.delete(l);
543
- _optionalChain([off, 'optionalCall', _29 => _29()]);
548
+ _optionalChain([off, 'optionalCall', _30 => _30()]);
544
549
  };
545
550
  }
546
551
  };
@@ -592,4 +597,5 @@ function createEffectToolProvider(host) {
592
597
 
593
598
 
594
599
 
595
- exports.EFFECT_KINDS = EFFECT_KINDS; exports.EFFECT_USES = EFFECT_USES; exports.CAMERA_MOVE_ROLES = CAMERA_MOVE_ROLES; exports.EFFECT_ACCEPTS = EFFECT_ACCEPTS; exports.EFFECT_PATH_FORMAT = EFFECT_PATH_FORMAT; exports.EFFECT_SUBJECT_KINDS = EFFECT_SUBJECT_KINDS; exports.EFFECT_LAYER_ROLES = EFFECT_LAYER_ROLES; exports.EFFECT_TRANSITION_MS = EFFECT_TRANSITION_MS; exports.EFFECT_TEMPLATE_SLOT_TYPES = EFFECT_TEMPLATE_SLOT_TYPES; exports.EFFECT_ERROR_CODES = EFFECT_ERROR_CODES; exports.EffectError = EffectError; exports.UnknownEffectError = UnknownEffectError; exports.UnknownTemplateError = UnknownTemplateError; exports.EffectControlError = EffectControlError; exports.EffectUnsupportedError = EffectUnsupportedError; exports.EffectDisposedError = EffectDisposedError; exports.NoEffectsProviderError = NoEffectsProviderError; exports.isEffectError = isEffectError; exports.effectValueErrors = effectValueErrors; exports.resolveEffectValues = resolveEffectValues; exports.effectOffered = effectOffered; exports.normaliseEffectTag = normaliseEffectTag; exports.hasEffectTags = hasEffectTags; exports.countEffectTags = countEffectTags; exports.pathControlsOf = pathControlsOf; exports.searchEffectSummaries = searchEffectSummaries; exports.createEffectPixels = createEffectPixels; exports.isEffectPixels = isEffectPixels; exports.srgbToLinear = srgbToLinear; exports.linearToSrgb = linearToSrgb; exports.encodeEffectFloat = encodeEffectFloat; exports.applyEffectMask = applyEffectMask; exports.EffectsSlot = EffectsSlot; exports.isCameraView = isCameraView; exports.sampleCameraViews = sampleCameraViews; exports.sampleEffectCameraMove = sampleEffectCameraMove; exports.cameraMoveField = cameraMoveField; exports.cameraMovesFor = cameraMovesFor; exports.cameraMoveIdList = cameraMoveIdList; exports.cameraMoveParts = cameraMoveParts; exports.CAMERA_MOVE_MAX_MS = CAMERA_MOVE_MAX_MS; exports.resolveCameraMoveSpec = resolveCameraMoveSpec; exports.cameraViewOfBox = cameraViewOfBox; exports.cameraBoxOfView = cameraBoxOfView; exports.createEffectToolProvider = createEffectToolProvider;
600
+
601
+ exports.EFFECT_KINDS = EFFECT_KINDS; exports.EFFECT_USES = EFFECT_USES; exports.CAMERA_MOVE_ROLES = CAMERA_MOVE_ROLES; exports.EFFECT_ACCEPTS = EFFECT_ACCEPTS; exports.EFFECT_PATH_FORMAT = EFFECT_PATH_FORMAT; exports.EFFECT_SUBJECT_KINDS = EFFECT_SUBJECT_KINDS; exports.EFFECT_LAYER_ROLES = EFFECT_LAYER_ROLES; exports.EFFECT_TRANSITION_MS = EFFECT_TRANSITION_MS; exports.EFFECT_TEMPLATE_SLOT_TYPES = EFFECT_TEMPLATE_SLOT_TYPES; exports.EFFECT_ERROR_CODES = EFFECT_ERROR_CODES; exports.EffectError = EffectError; exports.UnknownEffectError = UnknownEffectError; exports.UnknownTemplateError = UnknownTemplateError; exports.EffectControlError = EffectControlError; exports.EffectUnsupportedError = EffectUnsupportedError; exports.EffectDisposedError = EffectDisposedError; exports.NoEffectsProviderError = NoEffectsProviderError; exports.isEffectError = isEffectError; exports.effectValueErrors = effectValueErrors; exports.resolveEffectValues = resolveEffectValues; exports.effectOffered = effectOffered; exports.normaliseEffectTag = normaliseEffectTag; exports.hasEffectTags = hasEffectTags; exports.countEffectTags = countEffectTags; exports.pathControlsOf = pathControlsOf; exports.searchEffectSummaries = searchEffectSummaries; exports.createEffectPixels = createEffectPixels; exports.isEffectPixels = isEffectPixels; exports.srgbToLinear = srgbToLinear; exports.linearToSrgb = linearToSrgb; exports.encodeEffectFloat = encodeEffectFloat; exports.applyEffectMask = applyEffectMask; exports.layerImageInput = layerImageInput; exports.EffectsSlot = EffectsSlot; exports.isCameraView = isCameraView; exports.sampleCameraViews = sampleCameraViews; exports.sampleEffectCameraMove = sampleEffectCameraMove; exports.cameraMoveField = cameraMoveField; exports.cameraMovesFor = cameraMovesFor; exports.cameraMoveIdList = cameraMoveIdList; exports.cameraMoveParts = cameraMoveParts; exports.CAMERA_MOVE_MAX_MS = CAMERA_MOVE_MAX_MS; exports.resolveCameraMoveSpec = resolveCameraMoveSpec; exports.cameraViewOfBox = cameraViewOfBox; exports.cameraBoxOfView = cameraBoxOfView; exports.createEffectToolProvider = createEffectToolProvider;
@@ -168,6 +168,10 @@ function applyEffectMask(result, mask, source) {
168
168
  }
169
169
  return result;
170
170
  }
171
+ function layerImageInput(d) {
172
+ const images = d.inputs.filter((i) => i.kind === "image");
173
+ return (images.find((i) => i.name === "source") ?? images.find((i) => i.required) ?? images[0])?.name ?? null;
174
+ }
171
175
  var EffectsSlot = class {
172
176
  current = null;
173
177
  listeners = /* @__PURE__ */ new Set();
@@ -373,8 +377,9 @@ function createEffectToolProvider(host) {
373
377
  description: `${what}: control name \u2192 value, as listed by describe_effect (its "controls" schema: types, ranges, units and defaults). Only the given controls change; colours are "#rrggbb".${keyframes ? " A number control may instead be keyframes { keys: [{ t: ms from the start, v, ease }] }." : ""} Unknown controls and out-of-range values are refused with the valid ones.`
374
378
  });
375
379
  const effectIdSchema = (uses) => {
376
- const effects = catalogFor(host.provider())?.filter((e) => effectOffered(e, uses));
377
- const base = `An effect id from search_effects (use ${uses.map((u) => `"${u}"`).join(" or ")}).`;
380
+ const open = host.applyImageInputs && uses === host.applyUses;
381
+ const effects = open ? void 0 : catalogFor(host.provider())?.filter((e) => effectOffered(e, uses));
382
+ const base = `An effect id from search_effects (use ${uses.map((u) => `"${u}"`).join(" or ")}${open ? `, or any effect whose describe_effect inputs take an image: the ${host.target.noun} is its picture` : ""}).`;
378
383
  return effects && effects.length && effects.length <= ENUM_LIMIT ? { type: "string", enum: effects.map((e) => e.id), description: `${base} One of: ${effects.map((e) => `${e.id} (${e.name})`).join(", ")}.` } : { type: "string", minLength: 1, description: base };
379
384
  };
380
385
  const context = { requireProvider: writable, valuesSchema, effectIdSchema, annotations: ANNOTATIONS };
@@ -435,7 +440,7 @@ function createEffectToolProvider(host) {
435
440
  if (!p) return { available: false, reason: NO_PROVIDER };
436
441
  const d = await explain(async () => p.describe(args.effect));
437
442
  const pathControls = pathControlsOf(d);
438
- return { available: true, ...summaryOut(d), controls: d.controls, defaults: d.defaults, presets: d.presets, inputs: d.inputs, appliesHere: effectOffered(d, host.applyUses), ...pathControls.length ? { pathControls } : {} };
443
+ return { available: true, ...summaryOut(d), controls: d.controls, defaults: d.defaults, presets: d.presets, inputs: d.inputs, appliesHere: effectOffered(d, host.applyUses) || !!host.applyImageInputs && d.kind !== "motion" && layerImageInput(d) !== null, ...pathControls.length ? { pathControls } : {} };
439
444
  }
440
445
  },
441
446
  {
@@ -579,6 +584,7 @@ export {
579
584
  linearToSrgb,
580
585
  encodeEffectFloat,
581
586
  applyEffectMask,
587
+ layerImageInput,
582
588
  EffectsSlot,
583
589
  isCameraView,
584
590
  sampleCameraViews,
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;
2
2
 
3
3
 
4
- var _chunkOLNIPTB3cjs = require('./chunk-OLNIPTB3.cjs');
4
+ var _chunk2VX55NFMcjs = require('./chunk-2VX55NFM.cjs');
5
5
 
6
6
 
7
7
 
@@ -64,8 +64,8 @@ function createPigmentTools() {
64
64
  const rgbs = items.map((item, i) => parseHex(item.color, i));
65
65
  const total = items.reduce((sum, item) => sum + item.weight, 0);
66
66
  if (!(total > 0)) throw new Error("Every weight is 0; give at least one colour a weight above 0.");
67
- const pigments = rgbs.map((rgb2, i) => _chunkOLNIPTB3cjs.createPigment.call(void 0, rgb2, { strength: items[i].strength }));
68
- const mixed = _chunkOLNIPTB3cjs.mixPigments.call(void 0, pigments, items.map((item) => item.weight));
67
+ const pigments = rgbs.map((rgb2, i) => _chunk2VX55NFMcjs.createPigment.call(void 0, rgb2, { strength: items[i].strength }));
68
+ const mixed = _chunk2VX55NFMcjs.mixPigments.call(void 0, pigments, items.map((item) => item.weight));
69
69
  const lerp = [0, 1, 2].map((c) => rgbs.reduce((sum, rgb2, i) => sum + rgb2[c] * items[i].weight, 0) / total);
70
70
  const rgb = args.model === "rgb";
71
71
  return {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BUILTIN_BRUSHES
3
- } from "./chunk-VNBUDVD4.js";
3
+ } from "./chunk-OTEPAQJX.js";
4
4
  import {
5
5
  parseProvenance
6
6
  } from "./chunk-M6DNZNVY.js";
@@ -47,7 +47,7 @@ import {
47
47
  GRAIN_PATTERNS,
48
48
  brushstrokeDataUrl,
49
49
  isBrushstrokeBrush
50
- } from "./chunk-2PBZBRP5.js";
50
+ } from "./chunk-D5KGAO4Z.js";
51
51
  import {
52
52
  oklabToRgb,
53
53
  rgbToOklab