port rle encoding to wasm. deprecate js but preserve as legacy for debugging
This commit is contained in:
parent
32dca7586c
commit
18e0d11803
3 changed files with 173 additions and 73 deletions
|
|
@ -32,7 +32,10 @@ let gs_kiri_sla = exports;
|
||||||
preview,
|
preview,
|
||||||
previewSmall,
|
previewSmall,
|
||||||
previewLarge,
|
previewLarge,
|
||||||
fill_cache;
|
fill_cache,
|
||||||
|
legacy = false;
|
||||||
|
|
||||||
|
if (legacy) console.log("SLA Driver in Legacy Mode");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DRIVER SLICE CONTRACT - runs in worker
|
* DRIVER SLICE CONTRACT - runs in worker
|
||||||
|
|
@ -48,9 +51,9 @@ let gs_kiri_sla = exports;
|
||||||
work_total,
|
work_total,
|
||||||
work_remain;
|
work_remain;
|
||||||
|
|
||||||
// if (!self.OffscreenCanvas) {
|
if (legacy && !self.OffscreenCanvas) {
|
||||||
// return ondone("browser lacks support for OffscreenCanvas",true);
|
return ondone("browser lacks support for OffscreenCanvas",true);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// calculate % complete and call onupdate()
|
// calculate % complete and call onupdate()
|
||||||
function doupdate(work, msg) {
|
function doupdate(work, msg) {
|
||||||
|
|
@ -594,7 +597,6 @@ let gs_kiri_sla = exports;
|
||||||
device = settings.device,
|
device = settings.device,
|
||||||
process = settings.process,
|
process = settings.process,
|
||||||
output = print.output,
|
output = print.output,
|
||||||
images = [],
|
|
||||||
layermax = 0,
|
layermax = 0,
|
||||||
width = 2560,
|
width = 2560,
|
||||||
height = 1440,
|
height = 1440,
|
||||||
|
|
@ -602,26 +604,35 @@ let gs_kiri_sla = exports;
|
||||||
height2 = height/2,
|
height2 = height/2,
|
||||||
scaleX = width / device.bedWidth,
|
scaleX = width / device.bedWidth,
|
||||||
scaleY = height / device.bedDepth,
|
scaleY = height / device.bedDepth,
|
||||||
mark = Date.now();
|
mark = Date.now(),
|
||||||
|
layers = process.slaAntiAlias || 1,
|
||||||
|
masks = [],
|
||||||
|
images = [],
|
||||||
|
slices = [];
|
||||||
|
|
||||||
|
let d = 8 / layers;
|
||||||
|
for (let i=0; i<layers; i++) {
|
||||||
|
masks.push((1 << (8 - i * d)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// find max layer count
|
// find max layer count
|
||||||
widgets.forEach(widget => {
|
widgets.forEach(widget => {
|
||||||
layermax = Math.max(widget.slices.length);
|
layermax = Math.max(widget.slices.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
// let render = renderLayer;
|
let render = legacy ? renderLayer : renderLayerWasm;
|
||||||
let render = renderLayerWasm;
|
|
||||||
|
|
||||||
// generate layer 8-bit bitaps using canvas
|
// generate layer 8-bit bitaps using canvas
|
||||||
for (let index=0; index < layermax; index++) {
|
for (let index=0; index < layermax; index++) {
|
||||||
let param = { index, width, height, widgets, scaleX, scaleY };
|
let param = { index, width, height, widgets, scaleX, scaleY, masks };
|
||||||
let {data, end} = render(param);
|
let {image, layers, end} = render(param);
|
||||||
images.push(data);
|
images.push(image);
|
||||||
|
slices.push(layers);
|
||||||
// transfer images to browser main
|
// transfer images to browser main
|
||||||
online({
|
online({
|
||||||
progress: (index / layermax) * 0.25,
|
progress: (index / layermax) * 0.85,
|
||||||
message: "image_gen",
|
message: "image_gen",
|
||||||
data: data
|
data: image
|
||||||
});
|
});
|
||||||
if (end) break;
|
if (end) break;
|
||||||
}
|
}
|
||||||
|
|
@ -640,11 +651,12 @@ let gs_kiri_sla = exports;
|
||||||
let file = exp_func(print, {
|
let file = exp_func(print, {
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
lines: images,
|
|
||||||
small: previewSmall.data,
|
small: previewSmall.data,
|
||||||
large: previewLarge.data
|
large: previewLarge.data,
|
||||||
|
lines: images,
|
||||||
|
slices: slices
|
||||||
}, (progress, message) => {
|
}, (progress, message) => {
|
||||||
online({progress: progress * 0.75 + 0.25, message});
|
online({progress: progress * 0.15 + 0.85, message});
|
||||||
});
|
});
|
||||||
|
|
||||||
ondone({
|
ondone({
|
||||||
|
|
@ -833,42 +845,57 @@ let gs_kiri_sla = exports;
|
||||||
layerBytes = width * height,
|
layerBytes = width * height,
|
||||||
small = conf.small,
|
small = conf.small,
|
||||||
large = conf.large,
|
large = conf.large,
|
||||||
|
slices = conf.slices,
|
||||||
subcount = process.slaAntiAlias || 1,
|
subcount = process.slaAntiAlias || 1,
|
||||||
masks = [];
|
masks = [],
|
||||||
|
coded;
|
||||||
|
|
||||||
let d = 8 / subcount;
|
if (legacy) {
|
||||||
for (let i=0; i<subcount; i++) {
|
let d = 8 / subcount;
|
||||||
masks.push((1 << (8 - i * d)) - 1);
|
for (let i=0; i<subcount; i++) {
|
||||||
}
|
masks.push((1 << (8 - i * d)) - 1);
|
||||||
let ccl = 0;
|
|
||||||
let tcl = conf.lines.length * subcount;
|
|
||||||
let converted = conf.lines.map((line, index) => {
|
|
||||||
let count = line.length;
|
|
||||||
let lineDV = new DataView(line.buffer);
|
|
||||||
let bits = new Uint8Array(line.length);
|
|
||||||
let bitsDV = new DataView(bits.buffer);
|
|
||||||
let subs = [{ data: bits, view: bitsDV }];
|
|
||||||
for (let sl=1; sl<subcount; sl++) {
|
|
||||||
bits = bits.slice();
|
|
||||||
bitsDV = new DataView(bits.buffer);
|
|
||||||
subs.push({ data: bits, view: bitsDV });
|
|
||||||
}
|
}
|
||||||
// use R from RGB since that was painted on the canvas
|
let ccl = 0;
|
||||||
for (let s=0; s<subcount; s++) {
|
let tcl = conf.lines.length * subcount;
|
||||||
let view = subs[s].view;
|
let converted = conf.lines.map((line, index) => {
|
||||||
let mask = masks[s];
|
let count = line.length;
|
||||||
for (let i = 0; i < count; i++) {
|
let lineDV = new DataView(line.buffer);
|
||||||
let dv = lineDV.getUint8(i);
|
let bits = new Uint8Array(line.length);
|
||||||
view.setUint8(i, (dv / subcount) & mask ? 1 : 0);
|
let bitsDV = new DataView(bits.buffer);
|
||||||
|
let subs = [{ data: bits, view: bitsDV }];
|
||||||
|
for (let sl=1; sl<subcount; sl++) {
|
||||||
|
bits = bits.slice();
|
||||||
|
bitsDV = new DataView(bits.buffer);
|
||||||
|
subs.push({ data: bits, view: bitsDV });
|
||||||
}
|
}
|
||||||
progress((ccl++/tcl) * 0.4, `layer_convert`);
|
// use R from RGB since that was painted on the canvas
|
||||||
}
|
for (let s=0; s<subcount; s++) {
|
||||||
return { subs };
|
let view = subs[s].view;
|
||||||
});
|
let mask = masks[s];
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
let dv = lineDV.getUint8(i);
|
||||||
|
view.setUint8(i, (dv / subcount) & mask ? 1 : 0);
|
||||||
|
}
|
||||||
|
progress((ccl++/tcl) * 0.4, `layer_convert`);
|
||||||
|
}
|
||||||
|
return { subs };
|
||||||
|
});
|
||||||
|
|
||||||
|
coded = encodeLayers(converted, "photon", (pro => {
|
||||||
|
progress(pro * 0.4 + 0.4, "layer_encode");
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
let codedlen = slices.reduce((t,l) => {
|
||||||
|
return t + l.reduce((t,a) => {
|
||||||
|
return t + a.length
|
||||||
|
}, 0);
|
||||||
|
}, 0);
|
||||||
|
coded = {
|
||||||
|
layers: slices.map(slice => { return { sublayers: slice }}),
|
||||||
|
length: codedlen
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let coded = encodeLayers(converted, "photon", (pro => {
|
|
||||||
progress(pro * 0.4 + 0.4, "layer_encode");
|
|
||||||
}));
|
|
||||||
let buflen = 3000 + coded.length + (layerCount * subcount * 28) + small.byteLength + large.byteLength;
|
let buflen = 3000 + coded.length + (layerCount * subcount * 28) + small.byteLength + large.byteLength;
|
||||||
let filebuf = new ArrayBuffer(buflen);
|
let filebuf = new ArrayBuffer(buflen);
|
||||||
let filedat = new DataWriter(new DataView(filebuf));
|
let filedat = new DataWriter(new DataView(filebuf));
|
||||||
|
|
@ -972,27 +999,41 @@ let gs_kiri_sla = exports;
|
||||||
device = printset.device,
|
device = printset.device,
|
||||||
width = conf.width,
|
width = conf.width,
|
||||||
height = conf.height,
|
height = conf.height,
|
||||||
|
slices = conf.slices,
|
||||||
layerCount = conf.lines.length,
|
layerCount = conf.lines.length,
|
||||||
layerBytes = width * height;
|
layerBytes = width * height,
|
||||||
|
coded;
|
||||||
|
|
||||||
let converted = conf.lines.map((line, index) => {
|
if (legacy) {
|
||||||
let count = line.length / 4;
|
let converted = conf.lines.map((line, index) => {
|
||||||
let bits = new Uint8Array(line.length / 4);
|
let count = line.length / 4;
|
||||||
let bitsDV = new DataView(bits.buffer);
|
let bits = new Uint8Array(line.length / 4);
|
||||||
let lineDV = new DataView(line.buffer);
|
let bitsDV = new DataView(bits.buffer);
|
||||||
// reduce RGB to R = 0||1
|
let lineDV = new DataView(line.buffer);
|
||||||
for (let i = 0; i < count; i++) {
|
// reduce RGB to R = 0||1
|
||||||
// defeat anti-aliasing for the moment
|
for (let i = 0; i < count; i++) {
|
||||||
bitsDV.setUint8(i, lineDV.getUint8(i * 4) > 0 ? 1 : 0);
|
// defeat anti-aliasing for the moment
|
||||||
}
|
bitsDV.setUint8(i, lineDV.getUint8(i * 4) > 0 ? 1 : 0);
|
||||||
progress(index / conf.lines.length);
|
}
|
||||||
return { subs: [{
|
progress(index / conf.lines.length);
|
||||||
exposureTime: process.slaLayerOn,
|
return { subs: [{
|
||||||
data: bits
|
exposureTime: process.slaLayerOn,
|
||||||
}] };
|
data: bits
|
||||||
});
|
}] };
|
||||||
|
});
|
||||||
|
coded = encodeLayers(converted, "photons");
|
||||||
|
} else {
|
||||||
|
let codedlen = slices.reduce((t,l) => {
|
||||||
|
return t + l.reduce((t,a) => {
|
||||||
|
return t + a.length
|
||||||
|
}, 0);
|
||||||
|
}, 0);
|
||||||
|
coded = {
|
||||||
|
layers: slices.map(slice => { return { sublayers: slice }}),
|
||||||
|
length: codedlen
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let coded = encodeLayers(converted, "photons");
|
|
||||||
let filebuf = new ArrayBuffer(75366 + coded.length + 28 * layerCount);
|
let filebuf = new ArrayBuffer(75366 + coded.length + 28 * layerCount);
|
||||||
let filedat = new DataView(filebuf);
|
let filedat = new DataView(filebuf);
|
||||||
let filePos = 0;
|
let filePos = 0;
|
||||||
|
|
@ -1282,13 +1323,14 @@ let gs_kiri_sla = exports;
|
||||||
self.wasm = {
|
self.wasm = {
|
||||||
heap,
|
heap,
|
||||||
memory: exports.memory,
|
memory: exports.memory,
|
||||||
render: exports.render
|
render: exports.render,
|
||||||
|
rle_encode: exports.rle_encode
|
||||||
};
|
};
|
||||||
// console.log({heap});
|
// console.log({heap});
|
||||||
});
|
});
|
||||||
|
|
||||||
self.renderLayerWasm = function renderLayer(params) {
|
self.renderLayerWasm = function renderLayer(params) {
|
||||||
let { width, height, index, widgets, scaleX, scaleY } = params;
|
let { width, height, index, widgets, scaleX, scaleY, masks } = params;
|
||||||
let width2 = width / 2, height2 = height / 2;
|
let width2 = width / 2, height2 = height / 2;
|
||||||
let array = [];
|
let array = [];
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
@ -1359,10 +1401,15 @@ let gs_kiri_sla = exports;
|
||||||
writePoly(writer, poly);
|
writePoly(writer, poly);
|
||||||
}
|
}
|
||||||
|
|
||||||
let out = wasm.render(0, imagelen, 0);
|
wasm.render(0, imagelen, 0);
|
||||||
let data = wasm.heap.slice(0, imagelen);
|
let image = wasm.heap.slice(0, imagelen), layers = [];
|
||||||
|
|
||||||
return { data: data, end: count === 0 };
|
for (let l=0; l<masks.length; l++) {
|
||||||
|
let rlelen = wasm.rle_encode(0, 0, imagelen, masks[l], imagelen, 0);
|
||||||
|
layers.push(wasm.heap.slice(imagelen, imagelen + rlelen));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { image, layers, end: count === 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
function polyout(poly, ctx, opt) {
|
function polyout(poly, ctx, opt) {
|
||||||
|
|
@ -1414,7 +1461,7 @@ let gs_kiri_sla = exports;
|
||||||
for (let i=0; i<red.length; i++) {
|
for (let i=0; i<red.length; i++) {
|
||||||
red[i] = data[i*4];
|
red[i] = data[i*4];
|
||||||
}
|
}
|
||||||
return { data: red, end: count === 0 };
|
return { image: red, end: count === 0 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,12 @@ void rasterize_poly(unsigned char *m, Uint32 o, Uint32 height) {
|
||||||
readoff = nextpoly;
|
readoff = nextpoly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* m = memory base pointer
|
||||||
|
* i = input memory location (polygon records)
|
||||||
|
* o = output memory location (for raster)
|
||||||
|
* returns last read position in memory
|
||||||
|
*/
|
||||||
EMSCRIPTEN_KEEPALIVE
|
EMSCRIPTEN_KEEPALIVE
|
||||||
Uint32 render(unsigned char *m, Uint32 i, Uint32 o) {
|
Uint32 render(unsigned char *m, Uint32 i, Uint32 o) {
|
||||||
struct info *info = (struct info *)(m + i);
|
struct info *info = (struct info *)(m + i);
|
||||||
|
|
@ -160,5 +166,52 @@ Uint32 render(unsigned char *m, Uint32 i, Uint32 o) {
|
||||||
rasterize_poly(m, o, info->height);
|
rasterize_poly(m, o, info->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return readoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint8 rle_byte(Uint8 color, Uint8 count, Uint8 type) {
|
||||||
|
if (type == 0) {
|
||||||
|
return (count & 0x7f) | ((color << 7) & 0x80);
|
||||||
|
} else {
|
||||||
|
Uint8 run = count - 1;
|
||||||
|
return
|
||||||
|
(run & 1 ? 128 : 0) |
|
||||||
|
(run & 2 ? 64 : 0) |
|
||||||
|
(run & 4 ? 32 : 0) |
|
||||||
|
(run & 8 ? 16 : 0) |
|
||||||
|
(run & 16 ? 8 : 0) |
|
||||||
|
(run & 32 ? 4 : 0) |
|
||||||
|
(run & 64 ? 2 : 0) | color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mem = memory base pointer
|
||||||
|
* in = input memory location (raster)
|
||||||
|
* ilen = input raster length in bytes
|
||||||
|
* out = output memory location (for rle-encoded image)
|
||||||
|
* type = 0=photon, 1=photons
|
||||||
|
* returns length of rle-encoded image
|
||||||
|
*/
|
||||||
|
EMSCRIPTEN_KEEPALIVE
|
||||||
|
Uint32 rle_encode(unsigned char *mem, Uint32 in, Uint32 ilen, Uint8 mask, Uint32 out, Uint8 type) {
|
||||||
|
Uint8 color = (mem[in++] & mask) ? 1 : 0; // current color
|
||||||
|
Uint8 count = 1; // number of color matches
|
||||||
|
Uint8 cmax = type == 0 ? 125 : 128; // count max
|
||||||
|
Uint8 next; // next color
|
||||||
|
Uint32 opos = out;
|
||||||
|
while (--ilen > 0) {
|
||||||
|
next = (mem[in++] & mask) ? 1 : 0;
|
||||||
|
if (color != next || count == cmax) {
|
||||||
|
mem[opos++] = rle_byte(color, count, type);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
color = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
mem[opos++] = rle_byte(color, count, type);
|
||||||
|
}
|
||||||
|
return opos - out;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in a new issue