@pixagram/renderart 0.2.2 → 0.3.1

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.
package/dist/index.mjs CHANGED
@@ -619,131 +619,88 @@ var HEX_PRESETS = {
619
619
 
620
620
  // src/wasm-loader.ts
621
621
  var wasm = null;
622
- var wasmMemory = null;
622
+ var wasmReady = false;
623
623
  var initPromise = null;
624
- var wasmUrl = "";
625
- var cachedUint8Memory = null;
626
- var WASM_VECTOR_LEN = 0;
627
- function getUint8Memory() {
628
- if (cachedUint8Memory === null || cachedUint8Memory.byteLength === 0) {
629
- cachedUint8Memory = new Uint8Array(wasmMemory.buffer);
630
- }
631
- return cachedUint8Memory;
632
- }
633
- function passArray8ToWasm(arg) {
634
- const ptr = wasm.__wbindgen_malloc(arg.length);
635
- getUint8Memory().set(arg, ptr);
636
- WASM_VECTOR_LEN = arg.length;
637
- return ptr;
638
- }
639
- function setWasmUrl(url) {
640
- wasmUrl = url;
641
- }
642
- function getDefaultWasmUrl() {
643
- if (wasmUrl) return wasmUrl;
644
- const paths = [
645
- "/renderart_wasm_bg.wasm",
646
- "/wasm/renderart_wasm_bg.wasm",
647
- "/static/wasm/renderart_wasm_bg.wasm",
648
- "/assets/wasm/renderart_wasm_bg.wasm"
649
- ];
650
- return paths[0];
651
- }
652
- async function initWasm(customUrl) {
653
- if (wasm) return;
624
+ var initError = null;
625
+ async function initWasm(wasmUrl) {
626
+ if (wasmReady) return;
627
+ if (initError) throw initError;
654
628
  if (initPromise) return initPromise;
655
- const url = customUrl || getDefaultWasmUrl();
656
629
  initPromise = (async () => {
657
630
  try {
658
- const response = await fetch(url);
659
- if (!response.ok) {
660
- throw new Error(`Failed to fetch WASM: ${response.status} ${response.statusText}`);
661
- }
662
- const bytes = await response.arrayBuffer();
663
- const imports = {
664
- __wbindgen_placeholder__: {
665
- __wbindgen_throw: (ptr, len) => {
666
- const msg = new TextDecoder().decode(getUint8Memory().subarray(ptr, ptr + len));
667
- throw new Error(msg);
668
- }
669
- },
670
- wbg: {
671
- __wbindgen_throw: (ptr, len) => {
672
- const msg = new TextDecoder().decode(getUint8Memory().subarray(ptr, ptr + len));
673
- throw new Error(msg);
674
- }
631
+ const wasmModule = await import('./renderart_wasm.js');
632
+ let url = wasmUrl;
633
+ if (!url) {
634
+ try {
635
+ url = new URL("./renderart_wasm_bg.wasm", import.meta.url).href;
636
+ } catch {
637
+ url = "renderart_wasm_bg.wasm";
675
638
  }
676
- };
677
- const { instance } = await WebAssembly.instantiate(bytes, imports);
678
- wasm = instance.exports;
679
- wasmMemory = wasm.memory;
680
- if (wasm.__wbindgen_start) {
681
- wasm.__wbindgen_start();
682
639
  }
640
+ await wasmModule.default(url);
641
+ wasm = wasmModule;
642
+ wasmReady = true;
683
643
  } catch (e) {
644
+ initError = new Error(`Failed to initialize WASM: ${e}`);
684
645
  initPromise = null;
685
- throw new Error(`Failed to initialize WASM: ${e}. Make sure the .wasm file is served at: ${url}`);
646
+ throw initError;
686
647
  }
687
648
  })();
688
649
  return initPromise;
689
650
  }
690
651
  function isWasmLoaded() {
691
- return wasm !== null;
652
+ return wasmReady;
653
+ }
654
+ function hasWasmError() {
655
+ return initError !== null;
656
+ }
657
+ function getWasmError() {
658
+ return initError;
692
659
  }
693
660
  async function ensureWasm() {
694
- if (!wasm) {
661
+ if (!wasmReady) {
695
662
  await initWasm();
696
663
  }
697
664
  }
698
- function getOutputData(ptr, len) {
699
- const buffer = getUint8Memory().subarray(ptr, ptr + len);
665
+ function getOutputData(result) {
666
+ const memory = wasm.get_memory();
667
+ const buffer = new Uint8Array(memory.buffer, result.ptr, result.len);
700
668
  return new Uint8ClampedArray(buffer.slice());
701
669
  }
702
670
  function toUint8Array(input) {
703
671
  const data = input instanceof ImageData ? input.data : input.data;
704
672
  return data instanceof Uint8Array ? data : new Uint8Array(data);
705
673
  }
706
- function parseColorToU32(color, defaultVal) {
707
- if (color === void 0) return defaultVal;
708
- if (typeof color === "number") return color;
709
- if (color === "transparent") return 0;
710
- if (color.startsWith("#")) {
711
- const hex = color.slice(1);
712
- if (hex.length === 6) {
713
- return parseInt(hex, 16) << 8 | 255;
714
- }
715
- if (hex.length === 8) {
716
- return parseInt(hex, 16);
717
- }
718
- }
719
- return defaultVal;
720
- }
721
674
  var CrtCpuRenderer = class _CrtCpuRenderer {
722
675
  constructor() {
723
- this.ready = false;
676
+ this.initialized = false;
724
677
  }
725
- /** Create and initialize renderer (auto-loads WASM) */
678
+ /** Create and initialize renderer */
726
679
  static async create() {
727
- await ensureWasm();
728
680
  const renderer = new _CrtCpuRenderer();
729
- renderer.ready = true;
681
+ await renderer.init();
730
682
  return renderer;
731
683
  }
684
+ /** Initialize (loads WASM if needed) */
685
+ async init() {
686
+ await ensureWasm();
687
+ this.initialized = true;
688
+ }
689
+ /** Check if renderer is ready */
732
690
  isReady() {
733
- return this.ready && isWasmLoaded();
691
+ return this.initialized && wasmReady;
734
692
  }
693
+ /** Render CRT effect */
735
694
  render(input, options = {}) {
736
- if (!this.ready || !wasm) {
737
- throw new Error("Renderer not initialized");
695
+ if (!this.initialized || !wasm) {
696
+ throw new Error("Renderer not initialized. Call init() first or use CrtCpuRenderer.create()");
738
697
  }
739
698
  const data = toUint8Array(input);
740
699
  const width = input.width;
741
700
  const height = input.height;
742
701
  const scale = Math.min(32, Math.max(2, options.scale ?? 3));
743
- const ptr = passArray8ToWasm(data);
744
- const resultPtr = wasm.crt_upscale_raw(
745
- ptr,
746
- WASM_VECTOR_LEN,
702
+ const result = wasm.crt_upscale_config(
703
+ data,
747
704
  width,
748
705
  height,
749
706
  scale,
@@ -752,118 +709,124 @@ var CrtCpuRenderer = class _CrtCpuRenderer {
752
709
  options.scanHardness ?? -4,
753
710
  options.scanOpacity ?? 0.5,
754
711
  options.maskOpacity ?? 0.3,
755
- options.enableWarp !== false ? 1 : 0,
756
- options.enableScanlines !== false ? 1 : 0,
757
- options.enableMask !== false ? 1 : 0
712
+ options.enableWarp !== false,
713
+ options.enableScanlines !== false,
714
+ options.enableMask !== false
758
715
  );
759
- const outWidth = width * scale;
760
- const outHeight = height * scale;
761
- const outLen = outWidth * outHeight * 4;
762
716
  return {
763
- data: getOutputData(resultPtr, outLen),
764
- width: outWidth,
765
- height: outHeight
717
+ data: getOutputData(result),
718
+ width: result.width,
719
+ height: result.height
766
720
  };
767
721
  }
722
+ /** Dispose resources */
768
723
  dispose() {
769
- this.ready = false;
724
+ this.initialized = false;
770
725
  }
771
726
  };
727
+ function parseColorToU32(color, defaultVal) {
728
+ if (color === void 0) return defaultVal;
729
+ if (typeof color === "number") return color;
730
+ if (color === "transparent") return 0;
731
+ if (color.startsWith("#")) {
732
+ const hex = color.slice(1);
733
+ if (hex.length === 6) {
734
+ return parseInt(hex, 16) << 8 | 255;
735
+ }
736
+ if (hex.length === 8) {
737
+ return parseInt(hex, 16);
738
+ }
739
+ }
740
+ return defaultVal;
741
+ }
772
742
  var HexCpuRenderer = class _HexCpuRenderer {
773
743
  constructor() {
774
- this.ready = false;
744
+ this.initialized = false;
775
745
  }
746
+ /** Create and initialize renderer */
776
747
  static async create() {
777
- await ensureWasm();
778
748
  const renderer = new _HexCpuRenderer();
779
- renderer.ready = true;
749
+ await renderer.init();
780
750
  return renderer;
781
751
  }
752
+ /** Initialize (loads WASM if needed) */
753
+ async init() {
754
+ await ensureWasm();
755
+ this.initialized = true;
756
+ }
757
+ /** Check if renderer is ready */
782
758
  isReady() {
783
- return this.ready && isWasmLoaded();
759
+ return this.initialized && wasmReady;
784
760
  }
761
+ /** Render hexagonal effect */
785
762
  render(input, options = {}) {
786
- if (!this.ready || !wasm) {
787
- throw new Error("Renderer not initialized");
763
+ if (!this.initialized || !wasm) {
764
+ throw new Error("Renderer not initialized. Call init() first or use HexCpuRenderer.create()");
788
765
  }
789
766
  const data = toUint8Array(input);
790
767
  const width = input.width;
791
768
  const height = input.height;
792
769
  const scale = Math.min(32, Math.max(2, options.scale ?? 16));
793
- const orientation = options.orientation === "pointy-top" ? 1 : 0;
794
- const ptr = passArray8ToWasm(data);
795
- const resultPtr = wasm.hex_upscale_raw(
796
- ptr,
797
- WASM_VECTOR_LEN,
770
+ const result = wasm.hex_upscale_config(
771
+ data,
798
772
  width,
799
773
  height,
800
774
  scale,
801
- orientation,
802
- options.drawBorders ? 1 : 0,
775
+ options.orientation === "pointy-top" ? 1 : 0,
776
+ options.drawBorders ?? false,
803
777
  parseColorToU32(options.borderColor, 673720575),
804
778
  options.borderThickness ?? 1,
805
779
  parseColorToU32(options.backgroundColor, 0)
806
780
  );
807
- const dims = this.getDimensions(width, height, scale, options.orientation);
808
- const outLen = dims.width * dims.height * 4;
809
781
  return {
810
- data: getOutputData(resultPtr, outLen),
811
- width: dims.width,
812
- height: dims.height
782
+ data: getOutputData(result),
783
+ width: result.width,
784
+ height: result.height
813
785
  };
814
786
  }
787
+ /** Get output dimensions */
815
788
  getDimensions(srcWidth, srcHeight, scale, orientation = "flat-top") {
816
- const SQRT3 = 1.732050808;
817
- scale = Math.min(32, Math.max(2, scale));
818
- if (orientation === "flat-top") {
819
- const hSpacing = scale * 1.5;
820
- const vSpacing = scale * SQRT3;
821
- const cellWidth = scale * 2;
822
- const cellHeight = scale * SQRT3;
823
- return {
824
- width: Math.ceil(srcWidth * hSpacing + cellWidth),
825
- height: Math.ceil(srcHeight * vSpacing + cellHeight)
826
- };
827
- } else {
828
- const hSpacing = scale * SQRT3;
829
- const vSpacing = scale * 1.5;
830
- const cellWidth = scale * SQRT3;
831
- const cellHeight = scale * 2;
832
- return {
833
- width: Math.ceil(srcWidth * hSpacing + cellWidth),
834
- height: Math.ceil(srcHeight * vSpacing + cellHeight)
835
- };
789
+ if (!this.initialized || !wasm) {
790
+ throw new Error("Renderer not initialized");
836
791
  }
792
+ const dims = wasm.hex_get_dimensions(srcWidth, srcHeight, scale, orientation === "pointy-top" ? 1 : 0);
793
+ return { width: dims[0], height: dims[1] };
837
794
  }
795
+ /** Dispose resources */
838
796
  dispose() {
839
- this.ready = false;
797
+ this.initialized = false;
840
798
  }
841
799
  };
842
800
  var XbrzCpuRenderer = class _XbrzCpuRenderer {
843
801
  constructor() {
844
- this.ready = false;
802
+ this.initialized = false;
845
803
  }
804
+ /** Create and initialize renderer */
846
805
  static async create() {
847
- await ensureWasm();
848
806
  const renderer = new _XbrzCpuRenderer();
849
- renderer.ready = true;
807
+ await renderer.init();
850
808
  return renderer;
851
809
  }
810
+ /** Initialize (loads WASM if needed) */
811
+ async init() {
812
+ await ensureWasm();
813
+ this.initialized = true;
814
+ }
815
+ /** Check if renderer is ready */
852
816
  isReady() {
853
- return this.ready && isWasmLoaded();
817
+ return this.initialized && wasmReady;
854
818
  }
819
+ /** Render xBRZ scaling */
855
820
  render(input, options = {}) {
856
- if (!this.ready || !wasm) {
857
- throw new Error("Renderer not initialized");
821
+ if (!this.initialized || !wasm) {
822
+ throw new Error("Renderer not initialized. Call init() first or use XbrzCpuRenderer.create()");
858
823
  }
859
824
  const data = toUint8Array(input);
860
825
  const width = input.width;
861
826
  const height = input.height;
862
827
  const scale = Math.min(6, Math.max(2, options.scale ?? 2));
863
- const ptr = passArray8ToWasm(data);
864
- const resultPtr = wasm.xbrz_upscale_raw(
865
- ptr,
866
- WASM_VECTOR_LEN,
828
+ const result = wasm.xbrz_upscale_config(
829
+ data,
867
830
  width,
868
831
  height,
869
832
  scale,
@@ -872,17 +835,15 @@ var XbrzCpuRenderer = class _XbrzCpuRenderer {
872
835
  options.dominantDirectionThreshold ?? 4.4,
873
836
  options.steepDirectionThreshold ?? 2.2
874
837
  );
875
- const outWidth = width * scale;
876
- const outHeight = height * scale;
877
- const outLen = outWidth * outHeight * 4;
878
838
  return {
879
- data: getOutputData(resultPtr, outLen),
880
- width: outWidth,
881
- height: outHeight
839
+ data: getOutputData(result),
840
+ width: result.width,
841
+ height: result.height
882
842
  };
883
843
  }
844
+ /** Dispose resources */
884
845
  dispose() {
885
- this.ready = false;
846
+ this.initialized = false;
886
847
  }
887
848
  };
888
849
  var XBRZ_PRESETS = {
@@ -1077,8 +1038,8 @@ var RenderArt = class _RenderArt {
1077
1038
  return new _RenderArt(true);
1078
1039
  }
1079
1040
  /** Pre-initialize WASM for faster first CPU render */
1080
- async preloadWasm(wasmUrl2) {
1081
- await initWasm(wasmUrl2);
1041
+ async preloadWasm(wasmUrl) {
1042
+ await initWasm(wasmUrl);
1082
1043
  }
1083
1044
  get capabilities() {
1084
1045
  return { ...this._capabilities };
@@ -1090,6 +1051,6 @@ var RenderArt = class _RenderArt {
1090
1051
  }
1091
1052
  };
1092
1053
 
1093
- export { CRT_PRESETS, CrtCpuRenderer, CrtEngine, CrtGpuRenderer, HEX_PRESETS, HexCpuRenderer, HexEngine, HexGpuRenderer, RenderArt, XBRZ_PRESETS, XbrzCpuRenderer, XbrzEngine, hexGetDimensions, initWasm, isWasmLoaded, setWasmUrl };
1054
+ export { CRT_PRESETS, CrtCpuRenderer, CrtEngine, CrtGpuRenderer, HEX_PRESETS, HexCpuRenderer, HexEngine, HexGpuRenderer, RenderArt, XBRZ_PRESETS, XbrzCpuRenderer, XbrzEngine, getWasmError, hasWasmError, hexGetDimensions, initWasm, isWasmLoaded };
1094
1055
  //# sourceMappingURL=index.mjs.map
1095
1056
  //# sourceMappingURL=index.mjs.map