diff --git a/html/index.html b/html/index.html index 6d75d20..0b778d7 100644 --- a/html/index.html +++ b/html/index.html @@ -9,7 +9,7 @@ fieldset legend { font-weight: bold; } code { padding: .2em .4em; margin: 0; font-size: 85%; background: #CCC; border-radius: 3px; } - #toolbar { margin-bottom: 10px; border-bottom: 1px dotted #AAA;} + #toolbar { margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px dotted #AAA;} #status { margin: 10px 0; } #filebox { margin-bottom: 10px; } #cmdIMAGE { width: 350px; height: 300px; float: right} @@ -49,14 +49,14 @@
EPD_4in2 驱动支持 4 级灰度,其它驱动选择此选项结果未知。系统睡眠后可通过线圈(NFC/无线充电器)唤醒(需正确配置线圈对应的引脚才有效),否则一旦系统睡眠只有重新上电才能开启蓝牙。如果价签上带有 LED,系统启动时 LED 会闪一下(需正确配置 LED 对应的引脚才有效),以便知道系统是否已经被线圈唤醒。 @@ -119,6 +123,7 @@
+ diff --git a/html/js/dithering.js b/html/js/dithering.js index 05696d4..2f5e39a 100644 --- a/html/js/dithering.js +++ b/html/js/dithering.js @@ -38,7 +38,10 @@ function dithering(ctx, width, height, threshold, type) { let newPixel, err; for (let currentPixel = 0; currentPixel <= imageDataLength; currentPixel+=4) { - if (type ==="none") { + if (type === "gray") { + const factor = 255 / (threshold - 1); + imageData.data[currentPixel] = Math.round(imageData.data[currentPixel] / factor) * factor; + } else if (type ==="none") { // No dithering imageData.data[currentPixel] = imageData.data[currentPixel] < threshold ? 0 : 255; } else if (type ==="bayer") { @@ -78,6 +81,46 @@ function dithering(ctx, width, height, threshold, type) { ctx.putImageData(imageData, 0, 0); } +/****Color display description**** + white gray1 gray2 black +0x10| 01 01 00 00 +0x13| 01 00 01 00 +*********************************/ +function canvas2gray(canvas) { + const ctx = canvas.getContext("2d"); + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + + const arr10 = []; + const arr13 = []; + let buffer10 = []; + let buffer13 = []; + + for (let y = 0; y < canvas.height; y++) { + for (let x = 0; x < canvas.width; x++) { + const i = (canvas.width * y + x) * 4; + const level = imageData.data[i] / 85; + const bin = level.toString(2).split('').map(bit => parseInt(bit, 2)); + if (bin.length > 1) { + buffer10.push(bin[0]); + buffer13.push(bin[1]); + } else { + buffer10.push(0); + buffer13.push(bin[0]); + } + + if (buffer10.length === 8) { + arr10.push(parseInt(buffer10.join(''), 2)); + buffer10 = []; + } + if (buffer13.length === 8) { + arr13.push(parseInt(buffer13.join(''), 2)); + buffer13 = []; + } + } + } + return arr10.concat(arr13); +} + // white: 1, black/red: 0 function canvas2bytes(canvas, type='bw') { const ctx = canvas.getContext("2d"); diff --git a/html/js/main.js b/html/js/main.js index 47b22f8..3a39464 100644 --- a/html/js/main.js +++ b/html/js/main.js @@ -44,10 +44,10 @@ async function sendcmd(cmdTXT) { } async function setDriver() { - const epdDriver = document.getElementById("epddriver").value; + const driver = document.getElementById("epddriver").value; const pins = document.getElementById("epdpins").value; - await sendcmd("00" + pins); - await sendcmd("01" + epdDriver); + await sendcmd(`00${pins}`); + await sendcmd(`01${driver}`); } async function clearscreen() { @@ -56,36 +56,49 @@ async function clearscreen() { } } -async function sendIMGArray(imgArray, type = 'bw'){ - const count = Math.round(imgArray.length / chunkSize); +async function sendCmWithData(cmd, data){ + const count = Math.round(data.length / chunkSize); let chunkIdx = 0; - for (let i = 0; i < imgArray.length; i += chunkSize) { + await sendcmd(`03${cmd}`); + for (let i = 0; i < data.length; i += chunkSize) { let currentTime = (new Date().getTime() - startTime) / 1000.0; - let chunk = imgArray.substring(i, i + chunkSize); - setStatus(`发送${type === 'bwr' ? "红色" : '黑白'}块: ${chunkIdx+1}/${count+1}, 用时: ${currentTime}s`); - addLog(`发送块: ${chunk}`); - await sendCommand(hexToBytes(`04${chunk}`)) + let chunk = data.substring(i, i + chunkSize); + setStatus(`命令:0x${cmd}, 数据块: ${chunkIdx+1}/${count+1}, 总用时: ${currentTime}s`); + await sendcmd(`04${chunk}`); chunkIdx++; } } +async function send4GrayLut() { + await sendCmWithData("20", "000A0000000160141400000100140000000100130A010001000000000000000000000000000000000000"); // vcom + await sendCmWithData("21", "400A0000000190141400000110140A000001A01301000001000000000000000000000000000000000000"); // red not use + await sendCmWithData("22", "400A0000000190141400000100140A000001990C01030401000000000000000000000000000000000000"); // bw r + await sendCmWithData("23", "400A0000000190141400000100140A000001990B04040101000000000000000000000000000000000000"); // wb w + await sendCmWithData("24", "800A0000000190141400000120140A000001501301000001000000000000000000000000000000000000"); // bb b + await sendCmWithData("25", "400A0000000190141400000110140A000001A01301000001000000000000000000000000000000000000"); // vcom +} + async function sendimg(cmdIMG) { startTime = new Date().getTime(); - const epdDriver = document.getElementById("epddriver").value; + const driver = document.getElementById("epddriver").value; + const mode = document.getElementById('dithering').value; const imgArray = cmdIMG.replace(/(?:\r\n|\r|\n|,|0x| )/g, ''); const bwArrLen = (canvas.width/8) * canvas.height * 2; if (imgArray.length == bwArrLen * 2) { - await sendcmd("0310"); - await sendIMGArray(imgArray.slice(0, bwArrLen - 1)); - await sendcmd("0313"); - await sendIMGArray(imgArray.slice(bwArrLen), 'bwr'); + await sendCmWithData("10", imgArray.slice(0, bwArrLen - 1)); + await sendCmWithData("13", imgArray.slice(bwArrLen)); } else { - await sendcmd(epdDriver === "03" ? "0310" : "0313"); - await sendIMGArray(imgArray); + await sendCmWithData(driver === "03" ? "10" : "13", imgArray); + } + if (mode === "4gray") { + await send4GrayLut(); + await sendcmd("05"); + await sendcmd(`01${driver}`); + } else { + await sendcmd("05"); } - await sendcmd("05"); const sendTime = (new Date().getTime() - startTime) / 1000.0; addLog(`发送完成!耗时: ${sendTime}s`); @@ -200,34 +213,40 @@ function intToHex(intIn) { } function updateImageData(canvas) { - const epdDriver = document.getElementById("epddriver").value; - const dithering = document.getElementById('dithering').value; - document.getElementById('cmdIMAGE').value = bytesToHex(canvas2bytes(canvas, 'bw')); - if (epdDriver === '03') { - if (dithering.startsWith('bwr')) { - document.getElementById('cmdIMAGE').value += bytesToHex(canvas2bytes(canvas, 'red')); - } else { - const count = document.getElementById('cmdIMAGE').value.length; - document.getElementById('cmdIMAGE').value += 'F'.repeat(count); + const driver = document.getElementById("epddriver").value; + const mode = document.getElementById('dithering').value; + if (mode === '4gray') { + document.getElementById('cmdIMAGE').value = bytesToHex(canvas2gray(canvas)); + } else { + document.getElementById('cmdIMAGE').value = bytesToHex(canvas2bytes(canvas, 'bw')); + if (driver === '03') { + if (mode.startsWith('bwr')) { + document.getElementById('cmdIMAGE').value += bytesToHex(canvas2bytes(canvas, 'red')); + } else { + const count = document.getElementById('cmdIMAGE').value.length; + document.getElementById('cmdIMAGE').value += 'F'.repeat(count); + } } } } async function update_image () { + const canvas = document.getElementById("canvas"); + const ctx = canvas.getContext("2d"); + + let image = new Image();; const image_file = document.getElementById('image_file'); if (image_file.files.length > 0) { const file = image_file.files[0]; - - const canvas = document.getElementById("canvas"); - const ctx = canvas.getContext("2d"); - - const image = new Image(); image.src = URL.createObjectURL(file); - image.onload = function(event) { - URL.revokeObjectURL(this.src); - ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height); - convert_dithering() - } + } else { + image.src = document.getElementById('demo-img').src; + } + + image.onload = function(event) { + URL.revokeObjectURL(this.src); + ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height); + convert_dithering() } } @@ -245,6 +264,8 @@ function convert_dithering() { const mode = document.getElementById('dithering').value; if (mode.startsWith('bwr')) { ditheringCanvasByPalette(canvas, bwrPalette, mode); + } else if (mode === '4gray') { + dithering(ctx, canvas.width, canvas.height, 4, "gray"); } else { dithering(ctx, canvas.width, canvas.height, parseInt(document.getElementById('threshold').value), mode); } @@ -255,7 +276,7 @@ document.body.onload = () => { canvas = document.getElementById('canvas'); updateButtonStatus(); - bytes2canvas(hexToBytes(document.getElementById('cmdIMAGE').value), canvas); + update_image(); document.getElementById('dithering').value = 'none'; } \ No newline at end of file