@pixagram/renderart 0.2.1 → 0.3.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.
package/pkg/README.md ADDED
@@ -0,0 +1,223 @@
1
+ # @pixagram/renderart
2
+
3
+ High-performance pixel art rendering engines with GPU (WebGL2) and CPU (WASM) support.
4
+
5
+ ## Features
6
+
7
+ - **CRT Effect** (2-32x) - Classic CRT display simulation with barrel distortion, scanlines, and shadow mask
8
+ - **HEX Upscaling** (2-32x) - Transform pixel art into hexagonal grid representations
9
+ - **XBRZ Scaling** (2-6x) - Edge-preserving pixel art scaling algorithm
10
+
11
+ All engines support:
12
+ - ⚡ **GPU acceleration** via WebGL2 (CRT, HEX)
13
+ - 🦀 **CPU fallback** via Rust/WASM (all engines)
14
+ - 🎨 **Customizable presets** and fine-grained options
15
+ - 🔄 **Auto-initialization** - WASM loads automatically on first use
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @pixagram/renderart
21
+ ```
22
+
23
+ ## ⚠️ Building from Source (Required)
24
+
25
+ The package includes placeholder WASM. You **must** build the actual WASM module:
26
+
27
+ ```bash
28
+ # Prerequisites: Rust + wasm-pack
29
+ # Install wasm-pack: https://rustwasm.github.io/wasm-pack/installer/
30
+
31
+ cd node_modules/@pixagram/renderart
32
+ npm run build:wasm
33
+ ```
34
+
35
+ Or build everything:
36
+ ```bash
37
+ npm run build
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```typescript
43
+ import { RenderArt } from '@pixagram/renderart';
44
+
45
+ // Create renderer (auto-initializes WASM)
46
+ const renderer = await RenderArt.create();
47
+
48
+ // Get your image data
49
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
50
+
51
+ // Apply CRT effect
52
+ const crtResult = await renderer.crt.render(imageData, { scale: 3 });
53
+
54
+ // Apply HEX effect
55
+ const hexResult = await renderer.hex.render(imageData, { scale: 16 });
56
+
57
+ // Apply XBRZ scaling
58
+ const xbrzResult = await renderer.xbrz.render(imageData, { scale: 4 });
59
+
60
+ // Use the result
61
+ ctx.putImageData(new ImageData(crtResult.data, crtResult.width, crtResult.height), 0, 0);
62
+ ```
63
+
64
+ ### GPU-Only Mode (Sync, No WASM)
65
+
66
+ ```typescript
67
+ import { RenderArt } from '@pixagram/renderart';
68
+
69
+ // Create GPU-only renderer (no WASM loading)
70
+ const renderer = RenderArt.createGpuOnly();
71
+
72
+ // Synchronous rendering
73
+ const result = renderer.crt.renderSync(imageData, { scale: 3 });
74
+ ```
75
+
76
+ ### Direct Renderer Usage
77
+
78
+ ```typescript
79
+ import { CrtGpuRenderer } from '@pixagram/renderart';
80
+
81
+ // Use GPU renderer directly (no WASM needed)
82
+ const crt = CrtGpuRenderer.create();
83
+ const result = crt.render(imageData, { scale: 3 });
84
+ crt.dispose();
85
+ ```
86
+
87
+ ## Webpack Configuration
88
+
89
+ For webpack 5, add to your webpack.config.js:
90
+
91
+ ```javascript
92
+ module.exports = {
93
+ experiments: {
94
+ asyncWebAssembly: true,
95
+ },
96
+ module: {
97
+ rules: [
98
+ {
99
+ test: /\.wasm$/,
100
+ type: 'webassembly/async',
101
+ },
102
+ ],
103
+ },
104
+ };
105
+ ```
106
+
107
+ ## API Reference
108
+
109
+ ### RenderArt (Unified API)
110
+
111
+ ```typescript
112
+ // With CPU fallback (auto-loads WASM)
113
+ const renderer = await RenderArt.create();
114
+
115
+ // GPU-only mode
116
+ const renderer = RenderArt.createGpuOnly();
117
+
118
+ // Access capabilities
119
+ console.log(renderer.capabilities);
120
+ // { gpu: true, cpu: true, maxTextureSize: 16384, recommendedBackend: 'gpu' }
121
+
122
+ // Cleanup
123
+ renderer.dispose();
124
+ ```
125
+
126
+ ### CRT Engine
127
+
128
+ ```typescript
129
+ // Async with auto backend selection
130
+ const result = await renderer.crt.render(imageData, {
131
+ scale: 3, // 2-32 (default: 3)
132
+ warpX: 0.015, // Horizontal curvature
133
+ warpY: 0.02, // Vertical curvature
134
+ scanHardness: -4.0, // Scanline sharpness
135
+ scanOpacity: 0.5, // Scanline intensity
136
+ maskOpacity: 0.3, // Shadow mask intensity
137
+ enableWarp: true,
138
+ enableScanlines: true,
139
+ enableMask: true,
140
+ backend: 'auto', // 'gpu', 'cpu', or 'auto'
141
+ });
142
+
143
+ // With preset
144
+ const result = await renderer.crt.render(imageData, 'authentic');
145
+ // Presets: 'default', 'authentic', 'subtle', 'flat'
146
+
147
+ // Sync GPU-only
148
+ const result = renderer.crt.renderSync(imageData, { scale: 3 });
149
+ ```
150
+
151
+ ### HEX Engine
152
+
153
+ ```typescript
154
+ const result = await renderer.hex.render(imageData, {
155
+ scale: 16, // 2-32 (default: 16)
156
+ orientation: 'flat-top', // 'flat-top' or 'pointy-top'
157
+ drawBorders: true,
158
+ borderColor: '#282828',
159
+ borderThickness: 1,
160
+ backgroundColor: 'transparent',
161
+ });
162
+
163
+ // Presets: 'default', 'bordered', 'pointy'
164
+ const result = await renderer.hex.render(imageData, 'bordered');
165
+
166
+ // Get output dimensions
167
+ const dims = renderer.hex.getDimensions(64, 64, { scale: 16 });
168
+ ```
169
+
170
+ ### XBRZ Engine (CPU Only)
171
+
172
+ ```typescript
173
+ const result = await renderer.xbrz.render(imageData, {
174
+ scale: 4, // 2-6 (default: 2)
175
+ luminanceWeight: 1.0,
176
+ equalColorTolerance: 30,
177
+ dominantDirectionThreshold: 4.4,
178
+ steepDirectionThreshold: 2.2,
179
+ });
180
+
181
+ // Presets: 'default', 'sharp', 'smooth'
182
+ const result = await renderer.xbrz.render(imageData, 'sharp');
183
+ ```
184
+
185
+ ## Backend Support
186
+
187
+ | Engine | GPU (WebGL2) | CPU (WASM) |
188
+ |--------|--------------|------------|
189
+ | CRT | ✅ Primary | ✅ Fallback |
190
+ | HEX | ✅ Primary | ✅ Fallback |
191
+ | XBRZ | ❌ N/A | ✅ Only |
192
+
193
+ ## Browser Support
194
+
195
+ - Chrome 79+
196
+ - Firefox 75+
197
+ - Safari 15+
198
+ - Edge 79+
199
+
200
+ ## Development
201
+
202
+ ```bash
203
+ # Clone and install
204
+ git clone https://github.com/pixagram/renderart.git
205
+ cd renderart
206
+ npm install
207
+
208
+ # Build WASM (requires Rust + wasm-pack)
209
+ npm run build:wasm
210
+
211
+ # Build TypeScript
212
+ npm run build:ts
213
+
214
+ # Full build
215
+ npm run build
216
+
217
+ # Run tests
218
+ npm test
219
+ ```
220
+
221
+ ## License
222
+
223
+ MIT © Pixagram SA
@@ -0,0 +1,52 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ export class UpscaleResult {
5
+ private constructor();
6
+ free(): void;
7
+ [Symbol.dispose](): void;
8
+ ptr: number;
9
+ len: number;
10
+ width: number;
11
+ height: number;
12
+ }
13
+
14
+ /**
15
+ * CRT upscale with default config
16
+ */
17
+ export function crt_upscale(data: Uint8Array, width: number, height: number, scale: number): UpscaleResult;
18
+
19
+ /**
20
+ * CRT upscale with full config
21
+ */
22
+ export function crt_upscale_config(data: Uint8Array, width: number, height: number, scale: number, warp_x: number, warp_y: number, scan_hardness: number, scan_opacity: number, mask_opacity: number, enable_warp: boolean, enable_scanlines: boolean, enable_mask: boolean): UpscaleResult;
23
+
24
+ /**
25
+ * Get WASM memory for reading output buffers
26
+ */
27
+ export function get_memory(): any;
28
+
29
+ /**
30
+ * Get HEX output dimensions
31
+ */
32
+ export function hex_get_dimensions(width: number, height: number, scale: number, orientation: number): Uint32Array;
33
+
34
+ /**
35
+ * HEX upscale with default config
36
+ */
37
+ export function hex_upscale(data: Uint8Array, width: number, height: number, scale: number): UpscaleResult;
38
+
39
+ /**
40
+ * HEX upscale with full config
41
+ */
42
+ export function hex_upscale_config(data: Uint8Array, width: number, height: number, scale: number, orientation: number, draw_borders: boolean, border_color: number, border_thickness: number, background_color: number): UpscaleResult;
43
+
44
+ /**
45
+ * XBRZ upscale with default config
46
+ */
47
+ export function xbrz_upscale(data: Uint8Array, width: number, height: number, scale: number): UpscaleResult;
48
+
49
+ /**
50
+ * XBRZ upscale with full config
51
+ */
52
+ export function xbrz_upscale_config(data: Uint8Array, width: number, height: number, scale: number, luminance_weight: number, equal_color_tolerance: number, dominant_direction_threshold: number, steep_direction_threshold: number): UpscaleResult;
@@ -0,0 +1,5 @@
1
+ import * as wasm from "./renderart_wasm_bg.wasm";
2
+ export * from "./renderart_wasm_bg.js";
3
+ import { __wbg_set_wasm } from "./renderart_wasm_bg.js";
4
+ __wbg_set_wasm(wasm);
5
+ wasm.__wbindgen_start();
@@ -0,0 +1,283 @@
1
+ let wasm;
2
+ export function __wbg_set_wasm(val) {
3
+ wasm = val;
4
+ }
5
+
6
+ function getArrayU32FromWasm0(ptr, len) {
7
+ ptr = ptr >>> 0;
8
+ return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
9
+ }
10
+
11
+ function getStringFromWasm0(ptr, len) {
12
+ ptr = ptr >>> 0;
13
+ return decodeText(ptr, len);
14
+ }
15
+
16
+ let cachedUint32ArrayMemory0 = null;
17
+ function getUint32ArrayMemory0() {
18
+ if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) {
19
+ cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer);
20
+ }
21
+ return cachedUint32ArrayMemory0;
22
+ }
23
+
24
+ let cachedUint8ArrayMemory0 = null;
25
+ function getUint8ArrayMemory0() {
26
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
27
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
28
+ }
29
+ return cachedUint8ArrayMemory0;
30
+ }
31
+
32
+ function passArray8ToWasm0(arg, malloc) {
33
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
34
+ getUint8ArrayMemory0().set(arg, ptr / 1);
35
+ WASM_VECTOR_LEN = arg.length;
36
+ return ptr;
37
+ }
38
+
39
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
40
+ cachedTextDecoder.decode();
41
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
42
+ let numBytesDecoded = 0;
43
+ function decodeText(ptr, len) {
44
+ numBytesDecoded += len;
45
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
46
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
47
+ cachedTextDecoder.decode();
48
+ numBytesDecoded = len;
49
+ }
50
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
51
+ }
52
+
53
+ let WASM_VECTOR_LEN = 0;
54
+
55
+ const UpscaleResultFinalization = (typeof FinalizationRegistry === 'undefined')
56
+ ? { register: () => {}, unregister: () => {} }
57
+ : new FinalizationRegistry(ptr => wasm.__wbg_upscaleresult_free(ptr >>> 0, 1));
58
+
59
+ /**
60
+ * Result of an upscale operation
61
+ */
62
+ export class UpscaleResult {
63
+ static __wrap(ptr) {
64
+ ptr = ptr >>> 0;
65
+ const obj = Object.create(UpscaleResult.prototype);
66
+ obj.__wbg_ptr = ptr;
67
+ UpscaleResultFinalization.register(obj, obj.__wbg_ptr, obj);
68
+ return obj;
69
+ }
70
+ __destroy_into_raw() {
71
+ const ptr = this.__wbg_ptr;
72
+ this.__wbg_ptr = 0;
73
+ UpscaleResultFinalization.unregister(this);
74
+ return ptr;
75
+ }
76
+ free() {
77
+ const ptr = this.__destroy_into_raw();
78
+ wasm.__wbg_upscaleresult_free(ptr, 0);
79
+ }
80
+ /**
81
+ * @returns {number}
82
+ */
83
+ get ptr() {
84
+ const ret = wasm.__wbg_get_upscaleresult_ptr(this.__wbg_ptr);
85
+ return ret >>> 0;
86
+ }
87
+ /**
88
+ * @param {number} arg0
89
+ */
90
+ set ptr(arg0) {
91
+ wasm.__wbg_set_upscaleresult_ptr(this.__wbg_ptr, arg0);
92
+ }
93
+ /**
94
+ * @returns {number}
95
+ */
96
+ get len() {
97
+ const ret = wasm.__wbg_get_upscaleresult_len(this.__wbg_ptr);
98
+ return ret >>> 0;
99
+ }
100
+ /**
101
+ * @param {number} arg0
102
+ */
103
+ set len(arg0) {
104
+ wasm.__wbg_set_upscaleresult_len(this.__wbg_ptr, arg0);
105
+ }
106
+ /**
107
+ * @returns {number}
108
+ */
109
+ get width() {
110
+ const ret = wasm.__wbg_get_upscaleresult_width(this.__wbg_ptr);
111
+ return ret >>> 0;
112
+ }
113
+ /**
114
+ * @param {number} arg0
115
+ */
116
+ set width(arg0) {
117
+ wasm.__wbg_set_upscaleresult_width(this.__wbg_ptr, arg0);
118
+ }
119
+ /**
120
+ * @returns {number}
121
+ */
122
+ get height() {
123
+ const ret = wasm.__wbg_get_upscaleresult_height(this.__wbg_ptr);
124
+ return ret >>> 0;
125
+ }
126
+ /**
127
+ * @param {number} arg0
128
+ */
129
+ set height(arg0) {
130
+ wasm.__wbg_set_upscaleresult_height(this.__wbg_ptr, arg0);
131
+ }
132
+ }
133
+ if (Symbol.dispose) UpscaleResult.prototype[Symbol.dispose] = UpscaleResult.prototype.free;
134
+
135
+ /**
136
+ * CRT upscale with default config
137
+ * @param {Uint8Array} data
138
+ * @param {number} width
139
+ * @param {number} height
140
+ * @param {number} scale
141
+ * @returns {UpscaleResult}
142
+ */
143
+ export function crt_upscale(data, width, height, scale) {
144
+ const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
145
+ const len0 = WASM_VECTOR_LEN;
146
+ const ret = wasm.crt_upscale(ptr0, len0, width, height, scale);
147
+ return UpscaleResult.__wrap(ret);
148
+ }
149
+
150
+ /**
151
+ * CRT upscale with full config
152
+ * @param {Uint8Array} data
153
+ * @param {number} width
154
+ * @param {number} height
155
+ * @param {number} scale
156
+ * @param {number} warp_x
157
+ * @param {number} warp_y
158
+ * @param {number} scan_hardness
159
+ * @param {number} scan_opacity
160
+ * @param {number} mask_opacity
161
+ * @param {boolean} enable_warp
162
+ * @param {boolean} enable_scanlines
163
+ * @param {boolean} enable_mask
164
+ * @returns {UpscaleResult}
165
+ */
166
+ export function crt_upscale_config(data, width, height, scale, warp_x, warp_y, scan_hardness, scan_opacity, mask_opacity, enable_warp, enable_scanlines, enable_mask) {
167
+ const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
168
+ const len0 = WASM_VECTOR_LEN;
169
+ const ret = wasm.crt_upscale_config(ptr0, len0, width, height, scale, warp_x, warp_y, scan_hardness, scan_opacity, mask_opacity, enable_warp, enable_scanlines, enable_mask);
170
+ return UpscaleResult.__wrap(ret);
171
+ }
172
+
173
+ /**
174
+ * Get WASM memory for reading output buffers
175
+ * @returns {any}
176
+ */
177
+ export function get_memory() {
178
+ const ret = wasm.get_memory();
179
+ return ret;
180
+ }
181
+
182
+ /**
183
+ * Get HEX output dimensions
184
+ * @param {number} width
185
+ * @param {number} height
186
+ * @param {number} scale
187
+ * @param {number} orientation
188
+ * @returns {Uint32Array}
189
+ */
190
+ export function hex_get_dimensions(width, height, scale, orientation) {
191
+ const ret = wasm.hex_get_dimensions(width, height, scale, orientation);
192
+ var v1 = getArrayU32FromWasm0(ret[0], ret[1]).slice();
193
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
194
+ return v1;
195
+ }
196
+
197
+ /**
198
+ * HEX upscale with default config
199
+ * @param {Uint8Array} data
200
+ * @param {number} width
201
+ * @param {number} height
202
+ * @param {number} scale
203
+ * @returns {UpscaleResult}
204
+ */
205
+ export function hex_upscale(data, width, height, scale) {
206
+ const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
207
+ const len0 = WASM_VECTOR_LEN;
208
+ const ret = wasm.hex_upscale(ptr0, len0, width, height, scale);
209
+ return UpscaleResult.__wrap(ret);
210
+ }
211
+
212
+ /**
213
+ * HEX upscale with full config
214
+ * @param {Uint8Array} data
215
+ * @param {number} width
216
+ * @param {number} height
217
+ * @param {number} scale
218
+ * @param {number} orientation
219
+ * @param {boolean} draw_borders
220
+ * @param {number} border_color
221
+ * @param {number} border_thickness
222
+ * @param {number} background_color
223
+ * @returns {UpscaleResult}
224
+ */
225
+ export function hex_upscale_config(data, width, height, scale, orientation, draw_borders, border_color, border_thickness, background_color) {
226
+ const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
227
+ const len0 = WASM_VECTOR_LEN;
228
+ const ret = wasm.hex_upscale_config(ptr0, len0, width, height, scale, orientation, draw_borders, border_color, border_thickness, background_color);
229
+ return UpscaleResult.__wrap(ret);
230
+ }
231
+
232
+ /**
233
+ * XBRZ upscale with default config
234
+ * @param {Uint8Array} data
235
+ * @param {number} width
236
+ * @param {number} height
237
+ * @param {number} scale
238
+ * @returns {UpscaleResult}
239
+ */
240
+ export function xbrz_upscale(data, width, height, scale) {
241
+ const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
242
+ const len0 = WASM_VECTOR_LEN;
243
+ const ret = wasm.xbrz_upscale(ptr0, len0, width, height, scale);
244
+ return UpscaleResult.__wrap(ret);
245
+ }
246
+
247
+ /**
248
+ * XBRZ upscale with full config
249
+ * @param {Uint8Array} data
250
+ * @param {number} width
251
+ * @param {number} height
252
+ * @param {number} scale
253
+ * @param {number} luminance_weight
254
+ * @param {number} equal_color_tolerance
255
+ * @param {number} dominant_direction_threshold
256
+ * @param {number} steep_direction_threshold
257
+ * @returns {UpscaleResult}
258
+ */
259
+ export function xbrz_upscale_config(data, width, height, scale, luminance_weight, equal_color_tolerance, dominant_direction_threshold, steep_direction_threshold) {
260
+ const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
261
+ const len0 = WASM_VECTOR_LEN;
262
+ const ret = wasm.xbrz_upscale_config(ptr0, len0, width, height, scale, luminance_weight, equal_color_tolerance, dominant_direction_threshold, steep_direction_threshold);
263
+ return UpscaleResult.__wrap(ret);
264
+ }
265
+
266
+ export function __wbg___wbindgen_memory_a342e963fbcabd68() {
267
+ const ret = wasm.memory;
268
+ return ret;
269
+ };
270
+
271
+ export function __wbg___wbindgen_throw_dd24417ed36fc46e(arg0, arg1) {
272
+ throw new Error(getStringFromWasm0(arg0, arg1));
273
+ };
274
+
275
+ export function __wbindgen_init_externref_table() {
276
+ const table = wasm.__wbindgen_externrefs;
277
+ const offset = table.grow(4);
278
+ table.set(0, undefined);
279
+ table.set(offset + 0, undefined);
280
+ table.set(offset + 1, null);
281
+ table.set(offset + 2, true);
282
+ table.set(offset + 3, false);
283
+ };
Binary file
@@ -0,0 +1,24 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export const __wbg_upscaleresult_free: (a: number, b: number) => void;
5
+ export const __wbg_get_upscaleresult_ptr: (a: number) => number;
6
+ export const __wbg_set_upscaleresult_ptr: (a: number, b: number) => void;
7
+ export const __wbg_get_upscaleresult_len: (a: number) => number;
8
+ export const __wbg_set_upscaleresult_len: (a: number, b: number) => void;
9
+ export const __wbg_get_upscaleresult_width: (a: number) => number;
10
+ export const __wbg_set_upscaleresult_width: (a: number, b: number) => void;
11
+ export const __wbg_get_upscaleresult_height: (a: number) => number;
12
+ export const __wbg_set_upscaleresult_height: (a: number, b: number) => void;
13
+ export const get_memory: () => any;
14
+ export const crt_upscale: (a: number, b: number, c: number, d: number, e: number) => number;
15
+ export const crt_upscale_config: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => number;
16
+ export const hex_upscale: (a: number, b: number, c: number, d: number, e: number) => number;
17
+ export const hex_upscale_config: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => number;
18
+ export const hex_get_dimensions: (a: number, b: number, c: number, d: number) => [number, number];
19
+ export const xbrz_upscale: (a: number, b: number, c: number, d: number, e: number) => number;
20
+ export const xbrz_upscale_config: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => number;
21
+ export const __wbindgen_externrefs: WebAssembly.Table;
22
+ export const __wbindgen_malloc: (a: number, b: number) => number;
23
+ export const __wbindgen_free: (a: number, b: number, c: number) => void;
24
+ export const __wbindgen_start: () => void;