feat: support 8gray. (#2)
10
tools/ble5_ctrl.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import asyncio
|
||||
from bleak import BleakScanner
|
||||
|
||||
async def main():
|
||||
devices = await BleakScanner.discover()
|
||||
for d in devices:
|
||||
print(d, d.metadata)
|
||||
BleakScanner.discovered_devices_and_advertisement_data = True
|
||||
|
||||
asyncio.run(main())
|
||||
BIN
tools/bwr_gray8.act
Normal file
@@ -1,28 +1,42 @@
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<style>
|
||||
div {
|
||||
padding: 12px;
|
||||
margin: 2 auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
let bleDevice;
|
||||
let gattServer;
|
||||
let Theservice;
|
||||
let epdService;
|
||||
let epochCharacter;
|
||||
|
||||
async function sleep(ms) {
|
||||
await new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function doConnect() {
|
||||
if (gattServer != null && gattServer.connected) {
|
||||
if (bleDevice != null && bleDevice.gatt.connected)
|
||||
bleDevice.gatt.disconnect();
|
||||
}
|
||||
else {
|
||||
bleDevice = await navigator.bluetooth.requestDevice({
|
||||
filters: [{ namePrefix: ['C26_'] }],
|
||||
optionalServices: [
|
||||
0xfff0,
|
||||
],
|
||||
//acceptAllDevices: true
|
||||
});
|
||||
await bleDevice.addEventListener('gattserverdisconnected', disconnect);
|
||||
await connect();
|
||||
}
|
||||
bleDevice = await navigator.bluetooth.requestDevice({
|
||||
filters: [{ namePrefix: ['C26_'] }],
|
||||
optionalServices: [
|
||||
0xfff0,
|
||||
],
|
||||
//acceptAllDevices: true
|
||||
});
|
||||
await bleDevice.addEventListener('gattserverdisconnected', disconnect);
|
||||
await connect();
|
||||
}
|
||||
}
|
||||
|
||||
async function connect() {
|
||||
@@ -34,66 +48,257 @@
|
||||
info('> Found EPD service');
|
||||
epochCharacter = await epdService.getCharacteristic(0xfff1);
|
||||
document.getElementById("btnConnect").innerHTML = 'Disconnect';
|
||||
document.getElementById('etagFn').style.visibility='';
|
||||
document.getElementById('etagFn').style.visibility = '';
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
bleDevice = null;
|
||||
epdService = null;
|
||||
epochCharacter = null;
|
||||
info('Disconnected.');
|
||||
|
||||
document.getElementById("btnConnect").innerHTML = 'Connect';
|
||||
document.getElementById('etagFn').style.visibility='hidden';
|
||||
bleDevice = null;
|
||||
epdService = null;
|
||||
epochCharacter = null;
|
||||
info('Disconnected.');
|
||||
|
||||
document.getElementById("btnConnect").innerHTML = 'Connect';
|
||||
document.getElementById('etagFn').style.visibility = 'hidden';
|
||||
}
|
||||
|
||||
async function doSetTime() {
|
||||
var epoch = Date.now() / 1000 | 0;
|
||||
var buf = new ArrayBuffer(4);
|
||||
var arr = new Uint32Array(buf);
|
||||
arr[0] = epoch;
|
||||
await epochCharacter.writeValueWithResponse(arr);
|
||||
info("Write unix epoch: " + epoch);
|
||||
var epoch = Date.now() / 1000 | 0;
|
||||
var buf = new ArrayBuffer(4);
|
||||
var arr = new Uint32Array(buf);
|
||||
arr[0] = epoch;
|
||||
await epochCharacter.writeValueWithResponse(arr);
|
||||
info("Write unix epoch: " + epoch);
|
||||
}
|
||||
|
||||
async function doReadEtag() {
|
||||
var host_epoch = Date.now() / 1000 | 0;
|
||||
var host_epoch = Date.now() / 1000 | 0;
|
||||
|
||||
// read current time
|
||||
var chr = await epdService.getCharacteristic(0xfff1);
|
||||
var epoch = (await chr.readValue()).getUint32(0, 1);
|
||||
// read current time
|
||||
var chr = await epdService.getCharacteristic(0xfff1);
|
||||
var epoch = (await chr.readValue()).getUint32(0, 1);
|
||||
|
||||
// read time zone
|
||||
var chr = await epdService.getCharacteristic(0xfff2);
|
||||
var tz_min = (await chr.readValue()).getInt32(0, 1);
|
||||
info(`# host time: ${host_epoch}, diff (${epoch - host_epoch}) seconds.`);
|
||||
info(`# etag time: ${epoch}, tz: ${tz_min} minutes of UTC.`);
|
||||
|
||||
// battery
|
||||
var chr = await epdService.getCharacteristic(0xfff3);
|
||||
var batt = (await chr.readValue()).getUint16(0, 1);
|
||||
// read time zone
|
||||
var chr = await epdService.getCharacteristic(0xfff2);
|
||||
var tz_min = (await chr.readValue()).getInt32(0, 1);
|
||||
info(`# host time: ${host_epoch}, diff (${epoch - host_epoch}) seconds.`);
|
||||
info(`# etag time: ${epoch}, tz: ${tz_min} minutes of UTC.`);
|
||||
|
||||
// Temperature
|
||||
var chr = await epdService.getCharacteristic(0xfff4);
|
||||
var temp = (await chr.readValue()).getInt8(0, 1);
|
||||
info(`# etag sensor: battery(${batt}mv), temperature(${temp}'C). `);
|
||||
// battery
|
||||
var chr = await epdService.getCharacteristic(0xfff3);
|
||||
var batt = (await chr.readValue()).getUint16(0, 1);
|
||||
|
||||
// RTC Collaborate
|
||||
var chr = await epdService.getCharacteristic(0xfff5);
|
||||
var rtc_collab = (await chr.readValue()).getInt8(0, 1);
|
||||
info(`# rtc collab: ${rtc_collab} every 1 second.`);
|
||||
// Temperature
|
||||
var chr = await epdService.getCharacteristic(0xfff4);
|
||||
var temp = (await chr.readValue()).getInt8(0, 1);
|
||||
info(`# etag sensor: battery(${batt}mv), temperature(${temp}'C). `);
|
||||
|
||||
// RTC Collaborate
|
||||
var chr = await epdService.getCharacteristic(0xfff5);
|
||||
var rtc_collab = (await chr.readValue()).getInt8(0, 1);
|
||||
info(`# rtc collab: ${rtc_collab} every 1 second.`);
|
||||
}
|
||||
|
||||
async function doRtcCollab() {
|
||||
var col = prompt("对 32.768kHz 晶振补偿频漂,走时快补偿负数,走时慢补偿正数。可选范围 (-3 ~ 3)", 0);
|
||||
if (col == null || col < -3 || col > 3) return;
|
||||
var chr = await epdService.getCharacteristic(0xfff5);
|
||||
var buf = new ArrayBuffer(1);
|
||||
var arr = new Int8Array(buf);
|
||||
arr[0] = parseInt(col);
|
||||
await chr.writeValueWithResponse(arr);
|
||||
info(`write RTC collabration: ${col}`);
|
||||
var col = prompt("对 32.768kHz 晶振补偿频漂,走时快补偿负数,走时慢补偿正数。可选范围 (-3 ~ 3)", 0);
|
||||
if (col == null || col < -3 || col > 3) return;
|
||||
var chr = await epdService.getCharacteristic(0xfff5);
|
||||
var buf = new ArrayBuffer(1);
|
||||
var arr = new Int8Array(buf);
|
||||
arr[0] = parseInt(col);
|
||||
await chr.writeValueWithResponse(arr);
|
||||
info(`write RTC collabration: ${col}`);
|
||||
}
|
||||
|
||||
async function doTest() {
|
||||
var chr = await epdService.getCharacteristic(0xfffe);
|
||||
var buf = new ArrayBuffer(62);
|
||||
var arr = new Int8Array(buf);
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
arr[i] = i % 8;
|
||||
}
|
||||
await chr.writeValueWithResponse(arr);
|
||||
info(`> write ${arr.length} bytes.`)
|
||||
//var out = await chr.readValue();
|
||||
//console.log(out);
|
||||
}
|
||||
|
||||
async function doCmd(cmd, data) {
|
||||
const epdCmd = {
|
||||
EPD_CMD_CLR: 1,
|
||||
EPD_CMD_MODE: 2,
|
||||
EPD_CMD_BUF: 3,
|
||||
EPD_CMD_BUF_CONT: 4,
|
||||
EPD_CMD_LUT: 5,
|
||||
EPD_CMD_RST: 6,
|
||||
EPD_CMD_BW: 7,
|
||||
EPD_CMD_RED: 8,
|
||||
EPD_CMD_DP: 9,
|
||||
EPD_CMD_FILL: 10,
|
||||
|
||||
EPD_CMD_BUF_PUT: 11,
|
||||
EPD_CMD_BUF_GET: 12,
|
||||
EPD_CMD_SNV_WRITE: 13,
|
||||
EPD_CMD_SNV_READ: 14,
|
||||
|
||||
EPD_CMD_SAVE_CFG: 15,
|
||||
};
|
||||
|
||||
var chr = await epdService.getCharacteristic(0xfffe);
|
||||
switch (cmd) {
|
||||
case 'clr':
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_CLR]));
|
||||
break;
|
||||
|
||||
case 'mode':
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_MODE, data == 'image'?0x01:0x00]));
|
||||
break;
|
||||
|
||||
case 'buf':
|
||||
for (var i = 0; i < data.length; i += 60) {
|
||||
let arr = [(i == 0 ? epdCmd.EPD_CMD_BUF : epdCmd.EPD_CMD_BUF_CONT)];
|
||||
arr.push(...data.slice(i, i + 60));
|
||||
//console.log(arr);
|
||||
await chr.writeValueWithResponse(Uint8Array.from(arr));
|
||||
//info(`> buf at ${i} size ${arr.length}`)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'lut':
|
||||
let arr = [epdCmd.EPD_CMD_LUT];
|
||||
arr.push(...data);
|
||||
await chr.writeValueWithResponse(Uint8Array.from(arr));
|
||||
break;
|
||||
|
||||
case 'rst':
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_RST]));
|
||||
break;
|
||||
|
||||
case 'bw':
|
||||
// write to bw ram
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_BW]));
|
||||
break;
|
||||
|
||||
case 'red':
|
||||
// write to bw ram
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_RED]));
|
||||
break;
|
||||
|
||||
case 'fill':
|
||||
// fill ram with black(0) or red(1)
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_FILL, data == 'red' ? 0x01:0x00]));
|
||||
break;
|
||||
|
||||
case 'dp':
|
||||
// show
|
||||
let lut = 0;
|
||||
switch (data) {
|
||||
case 'gray8':
|
||||
lut = 1;
|
||||
break;
|
||||
case 'user':
|
||||
lut = 0xff;
|
||||
break;
|
||||
case 'full':
|
||||
default:
|
||||
lut = 0;
|
||||
}
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_DP, lut]));
|
||||
break;
|
||||
|
||||
case 'snv_read':
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_SNV_READ, 0x80, 16]));
|
||||
break;
|
||||
|
||||
case 'snv_write':
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_SNV_WRITE, 0x80]));
|
||||
break;
|
||||
|
||||
case 'buf_get':
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_BUF_GET, 0x00]));
|
||||
break;
|
||||
|
||||
case 'buf_put':
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_BUF_PUT, 0x00, 0x01, 0x02, 0x03, 0x04]));
|
||||
break;
|
||||
|
||||
case 'save_cfg':
|
||||
await chr.writeValueWithResponse(Uint8Array.from([epdCmd.EPD_CMD_SAVE_CFG]));
|
||||
break;
|
||||
}
|
||||
info (`> epdCmd.${cmd}`)
|
||||
}
|
||||
|
||||
let ram_bw = [];
|
||||
let ram_red = [];
|
||||
function doImageGrey(type) {
|
||||
const canvas = document.getElementById('canvas');
|
||||
ram_bw = canvas2grey8(canvas, 'bw');
|
||||
ram_red = canvas2grey8(canvas, 'red');
|
||||
}
|
||||
|
||||
var step = 0;
|
||||
async function doUploadImageGray8() {
|
||||
await doCmd('clr');
|
||||
await sleep(15*1000);
|
||||
|
||||
doImageGrey();
|
||||
for (var i = 0; i < 8; i++) {
|
||||
await doCmd('rst');
|
||||
await sleep(2000);
|
||||
await doUploadImageRam8('bw');
|
||||
await doUploadImageRam8('red');
|
||||
await doCmd('dp', 'gray8');
|
||||
await sleep(8000);
|
||||
step++;
|
||||
}
|
||||
step = 0;
|
||||
info('> Upload done.')
|
||||
}
|
||||
async function doUploadImage(type) {
|
||||
if (type == 'gray8') {
|
||||
await doUploadImageGray8();
|
||||
} else {
|
||||
await doCmd('rst');
|
||||
await sleep(2000);
|
||||
await doUploadImageRam2('bw');
|
||||
await doUploadImageRam2('red');
|
||||
await doCmd('dp', 'full');
|
||||
await sleep(15*1000);
|
||||
}
|
||||
}
|
||||
|
||||
async function doUploadImageRam2(type = 'bw') {
|
||||
const canvas = document.getElementById('canvas');
|
||||
var arr = canvas2bytes(canvas, type = type);
|
||||
await doCmd('buf', arr);
|
||||
await doCmd(type)
|
||||
}
|
||||
|
||||
async function doUploadImageRam8(type = 'bw') {
|
||||
var ram = type == 'bw' ? ram_bw : ram_red;
|
||||
|
||||
// grey byte to bit
|
||||
var arr = [];
|
||||
var buffer = [];
|
||||
for (var x = 0; x < ram.length; x++) {
|
||||
const n = ram[x] > step ? 1 : 0;
|
||||
if (type == 'bw') {
|
||||
buffer.push(n ? 0 : 1);
|
||||
} else {
|
||||
buffer.push(n ? 1 : 0);
|
||||
}
|
||||
|
||||
if (buffer.length == 8) {
|
||||
arr.push(parseInt(buffer.join(''), 2));
|
||||
buffer = [];
|
||||
}
|
||||
}
|
||||
|
||||
info(`> write ram ${type} size ${arr.length}, step ${step}`);
|
||||
console.log(arr);
|
||||
await doCmd('buf', arr);
|
||||
await doCmd(type)
|
||||
}
|
||||
|
||||
function info(logTXT) {
|
||||
@@ -106,20 +311,173 @@
|
||||
document.getElementById("log").innerHTML = document.getElementById("log").innerHTML.substring(logs_br_position + 4);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>
|
||||
<label> Choose </label>
|
||||
<button id="btnConnect" type="button" onclick="doConnect()">Connect</button>
|
||||
</p>
|
||||
<p id="etagFn" style="visibility:hidden;">
|
||||
<button id="btnReadEtag" type="button" onclick="doReadEtag()">ReadEtag</button>
|
||||
<button id="btnSetTime" type="button" onclick="doSetTime()">SetTime</button>
|
||||
<button id="btnRtcCollab" type="button" onclick="doRtcCollab()">RtcCollab</button>
|
||||
</p>
|
||||
<p>
|
||||
<div id="log">
|
||||
CC2640R2-ETAG Webtool. <br/>
|
||||
</div>
|
||||
</p>
|
||||
async function load_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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clear_canvas() {
|
||||
if (confirm('确认清除屏幕?')) {
|
||||
const canvas = document.getElementById('canvas');
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
}
|
||||
|
||||
function canvas2bytes(canvas, type = 'bw') {
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
|
||||
const arr = [];
|
||||
let buffer = [];
|
||||
|
||||
for (let y = 0; y < canvas.height; y += 8) {
|
||||
for (let x = 0; x < canvas.width; x++) {
|
||||
for (let a = 0; a < 8; a++) {
|
||||
const i = (canvas.width * (y + a) + x) * 4;
|
||||
if (type !== 'red') {
|
||||
// 1 for white, 0 for black
|
||||
// black : 0, 0, 0
|
||||
buffer.push(imageData.data[i] === 0 && imageData.data[i + 1] === 0 && imageData.data[i + 2] === 0 ? 0 : 1);
|
||||
} else {
|
||||
// 1 for red, 0 for white
|
||||
buffer.push(imageData.data[i] > 0 && imageData.data[i + 1] === 0 && imageData.data[i + 2] === 0 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
arr.push(parseInt(buffer.join(''), 2));
|
||||
buffer = [];
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
function canvas2grey8(canvas, type = 'bw') {
|
||||
// each px = 4bit black + 4bit red.
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
|
||||
const arr = [];
|
||||
let buffer = [];
|
||||
|
||||
for (let y = 0; y < canvas.height; y += 8) {
|
||||
for (let x = 0; x < canvas.width; x++) {
|
||||
for (let a = 0; a < 8; a++) {
|
||||
const i = (canvas.width * (y + a) + x) * 4;
|
||||
const R = imageData.data[i];
|
||||
const G = imageData.data[i + 1];
|
||||
const B = imageData.data[i + 2];
|
||||
|
||||
let grey = 0; // white
|
||||
if (R == 255 && G != 255 && B != 255) { // red
|
||||
grey = (type == 'bw') ? 0 : (510 + 62 - G - B) >> 6;
|
||||
} else { // gray
|
||||
grey = (type == 'bw') ? (255 + 31 - R) >> 5 : 0;
|
||||
}
|
||||
arr.push(grey);
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
async function doMyLut() {
|
||||
const O = 0b00000000; // VSS
|
||||
const B = 0b01000000; // VSH1 for Black
|
||||
const W = 0b10000000; // VSL for white
|
||||
const R = 0b11000000; // VSH2 for Red
|
||||
const lut_gray8 = [
|
||||
// RP A B C D SRAB SRCD
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUTC
|
||||
0x01, R | 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, // LUTR
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUTW
|
||||
0x01, B | 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, // LUTB
|
||||
0x01, B | 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, // LUTB
|
||||
];
|
||||
await doCmd('lut', lut_gray8);
|
||||
}
|
||||
|
||||
async function doFill(color) {
|
||||
await doCmd('rst');
|
||||
await sleep(2000);
|
||||
await doCmd('fill', color);
|
||||
await doCmd('dp', 'full');
|
||||
await sleep(15*1000);
|
||||
}
|
||||
|
||||
async function doSnvRead(type) {
|
||||
var chr = await epdService.getCharacteristic(0xfffe);
|
||||
if (type == 'cfg') {
|
||||
await doCmd('snv_read', 0x01);
|
||||
await doCmd('buf_get', 0x00);
|
||||
var a = await chr.readValue();
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
|
||||
async function doSnvWrite() {
|
||||
//var chr = await epdService.getCharacteristic(0xfffe);
|
||||
await doCmd('buf_put', 0x00);
|
||||
await doCmd('snv_write', 0x80);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<label> Choose </label>
|
||||
<button id="btnConnect" type="button" onclick="doConnect()">Connect</button>
|
||||
</div>
|
||||
<div id="etagFn" style="visibility:hidden;">
|
||||
<button type="button" onclick="doCmd('mode', 'clock')">时钟模式</button>
|
||||
<button id="btnReadEtag" type="button" onclick="doReadEtag()">ReadEtag</button>
|
||||
<button id="btnSetTime" type="button" onclick="doSetTime()">SetTime</button>
|
||||
<button id="btnRtcCollab" type="button" onclick="doRtcCollab()">RtcCollab</button>
|
||||
<button id="btnTest" type="button" onclick="doTest()">Test</button>
|
||||
<button type="button" onclick="doCmd('save_cfg')">保存设置</button>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" onclick="doCmd('mode', 'image')">图片模式</button>
|
||||
<button type="button" onclick="doCmd('rst')">rst</button>
|
||||
<button type="button" onclick="doCmd('bw')">bw</button>
|
||||
<button type="button" onclick="doCmd('red')">red</button>
|
||||
<button type="button" onclick="doCmd('dp', 'full')">dp</button>
|
||||
<button type="button" onclick="doMyLut()">LUT</button>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" onclick="doCmd('clr')">清屏</button>
|
||||
<button type="button" onclick="doFill('black')">全黑</button>
|
||||
<button type="button" onclick="doFill('red')">全红</button>
|
||||
</div>
|
||||
<div id="canvas-box">
|
||||
<input type="file" id="image_file" onchange="load_image()" accept=".png,.jpg,.bmp,.webp,.gif">
|
||||
<br>
|
||||
<canvas id="canvas" width="296" height="128" style="border: black solid 1px;"></canvas>
|
||||
<br>
|
||||
<button onclick="doUploadImage('gray8')">8级灰度</button>
|
||||
<button onclick="doUploadImage('full')">默认刷新</button>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="button" onclick="doSnvWrite()">写入</button>
|
||||
<button type="button" onclick="doSnvRead('cfg')">读出</button>
|
||||
</div>
|
||||
<div id="log">
|
||||
CC2640R2-ETAG Webtool. <br>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
tools/pic/black.bmp
Normal file
|
After Width: | Height: | Size: 111 KiB |
74
tools/pic/gen_bmp.py
Normal file
@@ -0,0 +1,74 @@
|
||||
import os
|
||||
import struct
|
||||
|
||||
def flatten_list(nested_list):
|
||||
flat_list = []
|
||||
for item in nested_list:
|
||||
if isinstance(item, list):
|
||||
flat_list.extend(flatten_list(item))
|
||||
else:
|
||||
flat_list.append(item)
|
||||
return flat_list
|
||||
|
||||
def pkg(fmt, num):
|
||||
a = struct.pack(fmt, num)
|
||||
return [ x for x in a ]
|
||||
|
||||
def rgb(r, g, b):
|
||||
return [b, g, r]
|
||||
|
||||
def genTestBmp(fpath, type = 0):
|
||||
width = 296
|
||||
height = 128
|
||||
|
||||
# header
|
||||
out = [
|
||||
0x42, 0x4D,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x36, 0x00, 0x00, 0x00, # pixel data offset at 0x36
|
||||
]
|
||||
|
||||
out += [
|
||||
0x28, 0x00, 0x00, 0x00, # header size 40 bytes
|
||||
pkg('<I', width),
|
||||
pkg('<I', height),
|
||||
0x01, 0x00, # plane 1
|
||||
0x18, 0x00, # bpp 24 bits
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
|
||||
if type == 0:
|
||||
for y in range(0, height):
|
||||
for x in range(0, width):
|
||||
bg = ((x+1)//33)*32
|
||||
bg = bg - 1 if bg else 0
|
||||
if y > height/2:
|
||||
out += rgb(255, bg, bg)
|
||||
else:
|
||||
out += rgb(bg, bg, bg)
|
||||
# TBD: pad for 4 bytes alignment.
|
||||
|
||||
elif type == 1: # all black
|
||||
for y in range(0, height):
|
||||
for x in range(0, width):
|
||||
out += rgb(0, 0, 0)
|
||||
|
||||
elif type == 2: # all red
|
||||
for y in range(0, height):
|
||||
for x in range(0, width):
|
||||
out += rgb(255, 0, 0)
|
||||
|
||||
with open(fpath, 'wb') as f:
|
||||
f.write(bytes(flatten_list(out)))
|
||||
|
||||
if __name__ == "__main__":
|
||||
genTestBmp('grey.bmp', type = 0)
|
||||
genTestBmp('black.bmp', type = 1)
|
||||
genTestBmp('red.bmp', type = 2)
|
||||
BIN
tools/pic/grey.bmp
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
tools/pic/red.bmp
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
tools/pic/可莉.gif
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
tools/pic/可莉2.gif
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
tools/pic/可莉3.gif
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
tools/pic/水神1.gif
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
tools/pic/灰度测试.gif
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
tools/pic/灰度测试2.gif
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
tools/pic/绫华1.gif
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
tools/pic/胡桃1.gif
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
tools/pic/胡桃2.gif
Normal file
|
After Width: | Height: | Size: 8.6 KiB |