// src/convert.ts
import lodash from "lodash";

// src/schema.ts
import { z } from "zod";

// src/common/uri.ts
function isAbsoluteURI(url) {
  const regExp = new RegExp("^(?:[a-z+]+:)?//", "i");
  return regExp.test(url);
}
function ensureAbsoluteURI(url, baseUrl) {
  if (isAbsoluteURI(url)) {
    return new URL(url);
  } else {
    return new URL(url, baseUrl);
  }
}
function isURI(s) {
  try {
    new URL(s);
    return true;
  } catch (err) {
    return false;
  }
}

// src/schema.ts
if (false)
  throw new Error("process.env.NAME is not defined");
if (false)
  throw new Error("process.env.VERSION is not defined");
function deg2rad(degrees) {
  return degrees * (Math.PI / 180);
}
var ColorSchema = z.tuple([z.number(), z.number(), z.number(), z.number()]);
var OptionsSchema = z.object({
  mode: z.enum(["spline", "polygon", "none"]).default("spline"),
  clustering_mode: z.literal("color").default("color"),
  hierarchical: z.enum(["stacked", "cutout"]).default("cutout"),
  corner_threshold: z.number().min(deg2rad(0)).max(deg2rad(180)).default(deg2rad(60)),
  // does not do much
  length_threshold: z.number().int().min(1).default(4),
  // In pixel, no path smaller than that will be approximated
  max_iterations: z.number().int().default(64),
  // does not do much
  splice_threshold: z.number().int().max(4).default(1),
  // better stay at <=1
  // detail spefific
  filter_speckle: z.number().int().min(1).max(512).default(64),
  // higher is less detail
  layer_difference: z.number().int().min(1).max(64).default(16),
  path_precision: z.number().int().default(8),
  // this is the number of points per path in the float to string conversion
  // color specific
  color_precision: z.number().int().step(1).min(0).max(8).default(2),
  //
  color_threshold: z.number().int().step(1).default(2),
  //
  key_color: ColorSchema.default([0, 0, 0, 0]),
  discard_key_color: z.boolean().default(true),
  drop_background: z.boolean().default(false)
}).strict().default({});
var PublicPathSchema = z.string().optional().describe("The public path to the data files.").transform((val) => {
  return val?.replace("${PACKAGE_NAME}", "@imgly/vectorizer").replace("${PACKAGE_VERSION}", "0.1.0-rc7");
}).refine((val) => val ? isURI(val) : true, {
  message: "String must be a valid uri"
});
var LogFunctionSchema = z.function().args(z.string()).returns(z.void());
var ProgressFunctionSchema = z.function().args(z.string(), z.number(), z.number()).returns(z.void());
var SchedulerFunctionSchema = z.function().args(z.function().returns(z.void())).returns(z.void());
var ConfigSchema = z.object({
  publicPath: PublicPathSchema,
  callbacks: z.object({
    trace: LogFunctionSchema.optional(),
    debug: LogFunctionSchema.optional(),
    info: LogFunctionSchema.optional(),
    warn: LogFunctionSchema.optional(),
    error: LogFunctionSchema.optional(),
    fatal: LogFunctionSchema.optional(),
    progress: ProgressFunctionSchema.optional()
    // scheduler: SchedulerFunctionSchema.optional().default(queueMicrotask)
  }).default({}),
  options: OptionsSchema
}).strict().default({});

// src/common/MimeType.ts
var MimeType = class _MimeType {
  type = "application/octet-stream";
  params = {};
  constructor(type, params) {
    this.type = type;
    this.params = params;
  }
  toString() {
    const paramsStr = [];
    for (const key in this.params) {
      const value = this.params[key];
      paramsStr.push(`${key}=${value}`);
    }
    return [this.type, ...paramsStr].join(";");
  }
  static create(type, params) {
    return new _MimeType(type, params);
  }
  isIdentical(other) {
    return this.type === other.type && this.params === other.params;
  }
  isEqual(other) {
    return this.type === other.type;
  }
  static fromString(mimeType) {
    const [type, ...paramsArr] = mimeType.split(";");
    const params = {};
    for (const param of paramsArr) {
      const [key, value] = param.split("=");
      params[key.trim()] = value.trim();
    }
    return new _MimeType(type, params);
  }
};

// src/common/platform.ts
if (false)
  throw new Error("process.env.NAME is not defined");
if (false)
  throw new Error("process.env.VERSION is not defined");
var isNodeRuntime = () => {
  return typeof process !== "undefined" && process.release.name.search(/node|io.js/) !== -1;
};
var isBrowserRuntime = () => {
  return typeof window !== "undefined" && typeof window.document !== "undefined";
};
var isWebWorkerRuntime = () => {
  return typeof self !== "undefined" && typeof self.postMessage === "function";
};
var publicURI = async () => {
  if (isNodeRuntime()) {
    const path = await import("node:path");
    return `file://${path.resolve(`node_modules/${"@imgly/vectorizer"}/dist/`)}/`;
  } else if (isBrowserRuntime() || isWebWorkerRuntime()) {
    return import.meta.url;
  }
  throw new Error("Not implemented");
};
var readFile = async (path) => {
  if (isNodeRuntime()) {
    const fs = await import("fs/promises");
    const pkg = await import("url");
    const { readFile: readFile2 } = fs;
    const { fileURLToPath } = pkg;
    return await readFile2(fileURLToPath(path));
  }
  throw new Error("Not implemented");
};
var base64ToBuffer = (str) => {
  if (isNodeRuntime()) {
    const buffer = Buffer.from(str, "base64");
    return buffer;
  } else if (isBrowserRuntime() || isWebWorkerRuntime()) {
    const decodedString = atob(str);
    return Uint8Array.from(decodedString, (m) => m.codePointAt(0));
  }
};

// src/common/resource.ts
async function loadFromURI(uri, config = { headers: { "Content-Type": "application/octet-stream" } }) {
  switch (uri.protocol) {
    case "http:":
    case "https:":
      return await fetch(uri, config);
    case "file:": {
      const buffer = await readFile(uri);
      return new Response(buffer, { status: 200, headers: config.headers });
    }
    case "data:": {
      const data = uri.toString();
      const [header, body] = data.split(",");
      const [mime, ...params] = header.split(";");
      const headers = params.reduce((acc, param) => {
        const [key, value] = param.split("=");
        acc[key] = value;
        return acc;
      }, {});
      const buffer = base64ToBuffer(body);
      return new Response(buffer, {
        status: 200,
        headers: { ...headers, "Content-Type": mime }
      });
    }
    default:
      throw new Error(`Unsupported protocol: ${uri.protocol}`);
  }
}
async function loadAsBlob(key, config) {
  const manifest = (await import("./resources-52AN7CG2.mjs")).default;
  const entry = manifest[key];
  if (!entry) {
    throw new Error(
      `Resource ${key} not found. Ensure that the config.publicPath is configured correctly.`
    );
  }
  const chunks = entry.chunks;
  let downloadedSize = 0;
  const responses = chunks.map(async (chunk) => {
    if (chunk.url === void 0) {
      chunk.url = chunk.hash;
    }
    const url = ensureAbsoluteURI(chunk.url, config.publicPath);
    const chunkSize = chunk.offsets[1] - chunk.offsets[0];
    const response = await loadFromURI(url, {
      headers: { "Content-Type": entry.mime }
    });
    const blob = await response.blob();
    if (chunkSize !== blob.size) {
      throw new Error(
        `Failed to fetch ${key} with size ${chunkSize} but got ${blob.size}`
      );
    }
    downloadedSize += chunkSize;
    config.callbacks?.progress?.(`fetch:${key}`, downloadedSize, entry.size);
    return blob;
  });
  const allChunkData = await Promise.all(responses);
  const data = new Blob(allChunkData, { type: entry.mime });
  if (data.size !== entry.size) {
    throw new Error(
      `Failed to fetch ${key} with size ${entry.size} but got ${data.size}`
    );
  }
  return data;
}

// ../rs/dist/web/vectorizer_rs.js
var wasm;
var cachedTextDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8", { ignoreBOM: true, fatal: true }) : { decode: () => {
  throw Error("TextDecoder not available");
} };
if (typeof TextDecoder !== "undefined") {
  cachedTextDecoder.decode();
}
var cachedUint8Memory0 = null;
function getUint8Memory0() {
  if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
    cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
  }
  return cachedUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
  ptr = ptr >>> 0;
  return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
var heap = new Array(128).fill(void 0);
heap.push(void 0, null, true, false);
var heap_next = heap.length;
function addHeapObject(obj) {
  if (heap_next === heap.length)
    heap.push(heap.length + 1);
  const idx = heap_next;
  heap_next = heap[idx];
  heap[idx] = obj;
  return idx;
}
function getObject(idx) {
  return heap[idx];
}
function dropObject(idx) {
  if (idx < 132)
    return;
  heap[idx] = heap_next;
  heap_next = idx;
}
function takeObject(idx) {
  const ret = getObject(idx);
  dropObject(idx);
  return ret;
}
var WASM_VECTOR_LEN = 0;
var cachedTextEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder("utf-8") : { encode: () => {
  throw Error("TextEncoder not available");
} };
var encodeString = typeof cachedTextEncoder.encodeInto === "function" ? function(arg, view) {
  return cachedTextEncoder.encodeInto(arg, view);
} : function(arg, view) {
  const buf = cachedTextEncoder.encode(arg);
  view.set(buf);
  return {
    read: arg.length,
    written: buf.length
  };
};
function passStringToWasm0(arg, malloc, realloc) {
  if (realloc === void 0) {
    const buf = cachedTextEncoder.encode(arg);
    const ptr2 = malloc(buf.length, 1) >>> 0;
    getUint8Memory0().subarray(ptr2, ptr2 + buf.length).set(buf);
    WASM_VECTOR_LEN = buf.length;
    return ptr2;
  }
  let len = arg.length;
  let ptr = malloc(len, 1) >>> 0;
  const mem = getUint8Memory0();
  let offset = 0;
  for (; offset < len; offset++) {
    const code = arg.charCodeAt(offset);
    if (code > 127)
      break;
    mem[ptr + offset] = code;
  }
  if (offset !== len) {
    if (offset !== 0) {
      arg = arg.slice(offset);
    }
    ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
    const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
    const ret = encodeString(arg, view);
    offset += ret.written;
    ptr = realloc(ptr, len, offset, 1) >>> 0;
  }
  WASM_VECTOR_LEN = offset;
  return ptr;
}
function passArray8ToWasm0(arg, malloc) {
  const ptr = malloc(arg.length * 1, 1) >>> 0;
  getUint8Memory0().set(arg, ptr / 1);
  WASM_VECTOR_LEN = arg.length;
  return ptr;
}
function isLikeNone(x) {
  return x === void 0 || x === null;
}
var cachedInt32Memory0 = null;
function getInt32Memory0() {
  if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
    cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
  }
  return cachedInt32Memory0;
}
var cachedUint32Memory0 = null;
function getUint32Memory0() {
  if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) {
    cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer);
  }
  return cachedUint32Memory0;
}
function getArrayJsValueFromWasm0(ptr, len) {
  ptr = ptr >>> 0;
  const mem = getUint32Memory0();
  const slice = mem.subarray(ptr / 4, ptr / 4 + len);
  const result = [];
  for (let i = 0; i < slice.length; i++) {
    result.push(takeObject(slice[i]));
  }
  return result;
}
var ColorImageConverterFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
}, unregister: () => {
} } : new FinalizationRegistry((ptr) => wasm.__wbg_colorimageconverter_free(ptr >>> 0));
var ColorImageConverter = class _ColorImageConverter {
  static __wrap(ptr) {
    ptr = ptr >>> 0;
    const obj = Object.create(_ColorImageConverter.prototype);
    obj.__wbg_ptr = ptr;
    ColorImageConverterFinalization.register(obj, obj.__wbg_ptr, obj);
    return obj;
  }
  __destroy_into_raw() {
    const ptr = this.__wbg_ptr;
    this.__wbg_ptr = 0;
    ColorImageConverterFinalization.unregister(this);
    return ptr;
  }
  free() {
    const ptr = this.__destroy_into_raw();
    wasm.__wbg_colorimageconverter_free(ptr);
  }
  /**
  * @param {string} params
  * @returns {ColorImageConverter}
  */
  static new_with_string(params) {
    const ptr0 = passStringToWasm0(params, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
    const len0 = WASM_VECTOR_LEN;
    const ret = wasm.colorimageconverter_new_with_string(ptr0, len0);
    return _ColorImageConverter.__wrap(ret);
  }
  /**
  * @param {Uint8Array} bytes
  * @param {string | undefined} [mime]
  */
  init_from_encoded(bytes, mime) {
    const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
    const len0 = WASM_VECTOR_LEN;
    var ptr1 = isLikeNone(mime) ? 0 : passStringToWasm0(mime, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
    var len1 = WASM_VECTOR_LEN;
    wasm.colorimageconverter_init_from_encoded(this.__wbg_ptr, ptr0, len0, ptr1, len1);
  }
  /**
  * @param {Uint8Array} pixels
  * @param {number} width
  * @param {number} height
  */
  init_from_rgba8(pixels, width, height) {
    const ptr0 = passArray8ToWasm0(pixels, wasm.__wbindgen_malloc);
    const len0 = WASM_VECTOR_LEN;
    wasm.colorimageconverter_init_from_rgba8(this.__wbg_ptr, ptr0, len0, width, height);
  }
  /**
  * @returns {boolean}
  */
  tick() {
    const ret = wasm.colorimageconverter_tick(this.__wbg_ptr);
    return ret !== 0;
  }
  /**
  * @returns {(string)[]}
  */
  svg_paths() {
    try {
      const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
      wasm.colorimageconverter_svg_paths(retptr, this.__wbg_ptr);
      var r0 = getInt32Memory0()[retptr / 4 + 0];
      var r1 = getInt32Memory0()[retptr / 4 + 1];
      var v1 = getArrayJsValueFromWasm0(r0, r1).slice();
      wasm.__wbindgen_free(r0, r1 * 4, 4);
      return v1;
    } finally {
      wasm.__wbindgen_add_to_stack_pointer(16);
    }
  }
  /**
  * @returns {string}
  */
  svg() {
    let deferred1_0;
    let deferred1_1;
    try {
      const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
      wasm.colorimageconverter_svg(retptr, this.__wbg_ptr);
      var r0 = getInt32Memory0()[retptr / 4 + 0];
      var r1 = getInt32Memory0()[retptr / 4 + 1];
      deferred1_0 = r0;
      deferred1_1 = r1;
      return getStringFromWasm0(r0, r1);
    } finally {
      wasm.__wbindgen_add_to_stack_pointer(16);
      wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
    }
  }
  /**
  * @returns {string}
  */
  json() {
    let deferred1_0;
    let deferred1_1;
    try {
      const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
      wasm.colorimageconverter_json(retptr, this.__wbg_ptr);
      var r0 = getInt32Memory0()[retptr / 4 + 0];
      var r1 = getInt32Memory0()[retptr / 4 + 1];
      deferred1_0 = r0;
      deferred1_1 = r1;
      return getStringFromWasm0(r0, r1);
    } finally {
      wasm.__wbindgen_add_to_stack_pointer(16);
      wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
    }
  }
  /**
  * @returns {string}
  */
  stage() {
    let deferred1_0;
    let deferred1_1;
    try {
      const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
      wasm.colorimageconverter_stage(retptr, this.__wbg_ptr);
      var r0 = getInt32Memory0()[retptr / 4 + 0];
      var r1 = getInt32Memory0()[retptr / 4 + 1];
      deferred1_0 = r0;
      deferred1_1 = r1;
      return getStringFromWasm0(r0, r1);
    } finally {
      wasm.__wbindgen_add_to_stack_pointer(16);
      wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
    }
  }
  /**
  * @returns {number}
  */
  progress() {
    const ret = wasm.colorimageconverter_progress(this.__wbg_ptr);
    return ret;
  }
};
async function __wbg_load(module, imports) {
  if (typeof Response === "function" && module instanceof Response) {
    if (typeof WebAssembly.instantiateStreaming === "function") {
      try {
        return await WebAssembly.instantiateStreaming(module, imports);
      } catch (e) {
        if (module.headers.get("Content-Type") != "application/wasm") {
          console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
        } else {
          throw e;
        }
      }
    }
    const bytes = await module.arrayBuffer();
    return await WebAssembly.instantiate(bytes, imports);
  } else {
    const instance = await WebAssembly.instantiate(module, imports);
    if (instance instanceof WebAssembly.Instance) {
      return { instance, module };
    } else {
      return instance;
    }
  }
}
function __wbg_get_imports() {
  const imports = {};
  imports.wbg = {};
  imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
    const ret = getStringFromWasm0(arg0, arg1);
    return addHeapObject(ret);
  };
  imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
    takeObject(arg0);
  };
  imports.wbg.__wbg_debug_a0de8bb323ed3e46 = function(arg0, arg1, arg2, arg3) {
    console.debug(getObject(arg0), getObject(arg1), getObject(arg2), getObject(arg3));
  };
  imports.wbg.__wbg_error_621c11091f132493 = function(arg0, arg1, arg2, arg3) {
    console.error(getObject(arg0), getObject(arg1), getObject(arg2), getObject(arg3));
  };
  imports.wbg.__wbg_info_0d0cfdd0035dc3f3 = function(arg0, arg1, arg2, arg3) {
    console.info(getObject(arg0), getObject(arg1), getObject(arg2), getObject(arg3));
  };
  imports.wbg.__wbg_log_c957bb910fba09c1 = function(arg0, arg1, arg2, arg3) {
    console.log(getObject(arg0), getObject(arg1), getObject(arg2), getObject(arg3));
  };
  imports.wbg.__wbg_warn_0912b6f3e9479355 = function(arg0, arg1, arg2, arg3) {
    console.warn(getObject(arg0), getObject(arg1), getObject(arg2), getObject(arg3));
  };
  imports.wbg.__wbg_new_abda76e883ba8a5f = function() {
    const ret = new Error();
    return addHeapObject(ret);
  };
  imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) {
    const ret = getObject(arg1).stack;
    const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
    const len1 = WASM_VECTOR_LEN;
    getInt32Memory0()[arg0 / 4 + 1] = len1;
    getInt32Memory0()[arg0 / 4 + 0] = ptr1;
  };
  imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) {
    let deferred0_0;
    let deferred0_1;
    try {
      deferred0_0 = arg0;
      deferred0_1 = arg1;
      console.error(getStringFromWasm0(arg0, arg1));
    } finally {
      wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
    }
  };
  imports.wbg.__wbindgen_throw = function(arg0, arg1) {
    throw new Error(getStringFromWasm0(arg0, arg1));
  };
  return imports;
}
function __wbg_init_memory(imports, maybe_memory) {
}
function __wbg_finalize_init(instance, module) {
  wasm = instance.exports;
  __wbg_init.__wbindgen_wasm_module = module;
  cachedInt32Memory0 = null;
  cachedUint32Memory0 = null;
  cachedUint8Memory0 = null;
  wasm.__wbindgen_start();
  return wasm;
}
async function __wbg_init(input) {
  if (wasm !== void 0)
    return wasm;
  if (typeof input === "undefined") {
    input = new URL("vectorizer_rs_bg.wasm", import.meta.url);
  }
  const imports = __wbg_get_imports();
  if (typeof input === "string" || typeof Request === "function" && input instanceof Request || typeof URL === "function" && input instanceof URL) {
    input = fetch(input);
  }
  __wbg_init_memory(imports);
  const { instance, module } = await __wbg_load(await input, imports);
  return __wbg_finalize_init(instance, module);
}
var vectorizer_rs_default = __wbg_init;

// src/convert.ts
var { memoize } = lodash;
async function imageSourceToBlob(image, _) {
  if (image instanceof ArrayBuffer || ArrayBuffer.isView(image)) {
    image = new Blob([image], { type: "application/octet-stream" });
  }
  return image;
}
var initializer = memoize(
  async (config) => {
    config = ConfigSchema.parse(config ?? {});
    config.publicPath ??= await publicURI();
    config.callbacks?.debug?.(`Config:  ${JSON.stringify(config, null, 2)}`);
    const wasmData = await loadAsBlob("/wasm/vectorizer_rs_bg.wasm", config);
    await vectorizer_rs_default(await wasmData.arrayBuffer());
    return config;
  },
  (config) => JSON.stringify(config)
);
async function __convert(image, config) {
  config = await initializer(config);
  const converter = ColorImageConverter.new_with_string(
    JSON.stringify(config.options)
  );
  const blob = await imageSourceToBlob(image, config);
  const arrayBuffer = await blob.arrayBuffer();
  const uint8Array = new Uint8Array(arrayBuffer);
  const mime = MimeType.fromString(blob.type);
  switch (mime.type) {
    case "image/x-rgba8": {
      const width = parseInt(mime.params.width);
      const height = parseInt(mime.params.height);
      if (width * height * 4 !== uint8Array.length) {
        throw new Error("Invalid image size");
      }
      converter.init_from_rgba8(uint8Array, width, height);
      break;
    }
    case "image/png":
    case "image/jpeg":
    case "image/avif":
    case "image/gif":
    case "image/bmp":
    case "image/tga":
    case "image/webp": {
      converter.init_from_encoded(uint8Array, mime.type);
      break;
    }
    case "application/octet-stream":
      converter.init_from_encoded(uint8Array);
      break;
    default:
      throw new Error(`Unsupported format: ${mime.type}`);
  }
  return await new Promise((resolve, reject) => {
    queueMicrotask(function tick() {
      let done = false;
      done = converter.tick();
      config.callbacks?.progress?.(
        `convert:${converter.stage()}`,
        converter.progress(),
        100
      );
      if (!done) {
        queueMicrotask(tick);
      } else {
        resolve(converter);
      }
    });
  });
}

// src/lib/lib.ts
var lib_default = imageToSvg;
async function imageToSvg(image, config) {
  try {
    const svgString = (await __convert(image, config)).svg();
    return new Blob([svgString], { type: "image/svg+xml" });
  } catch (err) {
    if (err instanceof Error) {
      throw { kind: "InternalError", message: err.message, stack: err.stack };
    }
    throw { kind: "UnknownError", error: err };
  }
}
async function imageToJson(image, config) {
  try {
    const json = (await __convert(image, config)).json();
    return new Blob([json], { type: "application/json" });
  } catch (err) {
    if (err instanceof Error) {
      throw { kind: "InternalError", message: err.message, stack: err.stack };
    }
    throw { kind: "UnknownError", error: err };
  }
}
export {
  lib_default as default,
  imageToJson,
  imageToSvg
};
//# sourceMappingURL=lib.mjs.map
