Skip to content

Commit 599e764

Browse files
committed
Add image processor
1 parent 3d0fb5e commit 599e764

File tree

4 files changed

+94
-63
lines changed

4 files changed

+94
-63
lines changed

libraries/Camera/extras/WebSerialCamera/app.js

Lines changed: 7 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,14 @@ const ctx = canvas.getContext('2d');
88
const UserActionAbortError = 8;
99
const ArduinoUSBVendorId = 0x2341;
1010

11-
let config = {
12-
"RGB565": {
13-
"convert": convertRGB565ToRGB888,
11+
config = {
12+
"RGB565": {
1413
"bytesPerPixel": 2
1514
},
16-
"GRAYSCALE": {
17-
"convert": convertGrayScaleToRGB888,
15+
"GRAYSCALE": {
1816
"bytesPerPixel": 1
1917
},
20-
"RGB888": {
21-
"convert": convertToRGB888,
18+
"RGB888": {
2219
"bytesPerPixel": 3
2320
}
2421
};
@@ -37,6 +34,7 @@ const dataBits = 8; // Adjust this value based on your device's data bits
3734
const stopBits = 2; // Adjust this value based on your device's stop bits
3835

3936
let currentPort, currentReader;
37+
const imageDataProcessor = new ImageDataProcessor(ctx, mode, imageWidth, imageHeight);
4038

4139
async function requestSerialPort(){
4240
try {
@@ -83,7 +81,6 @@ async function connectSerial(port, baudRate = 115200, dataBits = 8, stopBits = 2
8381
}
8482
}
8583

86-
8784
async function readBytes(port, numBytes, timeout = null){
8885
if(port.readable.locked){
8986
console.log('🔒 Stream is already locked. Ignoring request...');
@@ -145,44 +142,10 @@ async function readBytes(port, numBytes, timeout = null){
145142
return bytesRead;
146143
}
147144

148-
// Get the pixel value using big endian
149-
// Big-endian: the most significant byte comes first
150-
function getPixelValue(data, index, bytesPerPixel){
151-
if(bytesPerPixel == 1){
152-
return data[index];
153-
} else if(bytesPerPixel == 2){
154-
return (data[index] << 8) | data[index + 1];
155-
} else if(bytesPerPixel == 3){
156-
return (data[index] << 16) | (data[index + 1] << 8) | data[index + 2];
157-
} else if(bytesPerPixel == 4){
158-
return (data[index] << 24) | (data[index + 1] << 16) | (data[index + 2] << 8) | data[index + 3];
159-
}
160-
161-
return 0;
162-
}
163-
164145
function renderBitmap(bytes, width, height) {
165146
canvas.width = width;
166147
canvas.height = height;
167-
const bytesPerPixel = config[mode].bytesPerPixel;
168-
const BYTES_PER_ROW = width * bytesPerPixel;
169-
170-
const imageData = ctx.createImageData(canvas.width, canvas.height);
171-
const dataContainer = imageData.data;
172-
173-
for (let row = 0; row < height; row++) {
174-
for (let col = 0; col < width; col++) {
175-
const sourceDataIndex = (row * BYTES_PER_ROW) + (col * bytesPerPixel);
176-
const pixelValue = getPixelValue(bytes, sourceDataIndex, bytesPerPixel);
177-
const [r, g, b] = config[mode].convert(pixelValue);
178-
179-
const pixelIndex = ((row * width) + col) * 4;
180-
dataContainer[pixelIndex] = r; // Red channel
181-
dataContainer[pixelIndex + 1] = g; // Green channel
182-
dataContainer[pixelIndex + 2] = b; // Blue channel
183-
dataContainer[pixelIndex + 3] = 255; // Alpha channel (opacity)
184-
}
185-
}
148+
const imageData = imageDataProcessor.getImageDataBytes(bytes, width, height);
186149
ctx.clearRect(0, 0, canvas.width, canvas.height);
187150
ctx.putImageData(imageData, 0, 0);
188151
}
@@ -198,6 +161,7 @@ async function requestFrame(port){
198161
await writer.write(new Uint8Array([1]));
199162
await writer.close();
200163
}
164+
201165
async function renderStream(){
202166
while(true && currentPort){
203167
await renderFrame(currentPort);

libraries/Camera/extras/WebSerialCamera/conversion.js

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
class ImageDataProcessor {
2+
3+
constructor(context, mode) {
4+
this.canvas = context.canvas;
5+
this.context = context;
6+
this.mode = mode;
7+
this.config = {
8+
"RGB565": {
9+
"convert": this.convertRGB565ToRGB888,
10+
"bytesPerPixel": 2
11+
},
12+
"GRAYSCALE": {
13+
"convert": this.convertGrayScaleToRGB888,
14+
"bytesPerPixel": 1
15+
},
16+
"RGB888": {
17+
"convert": this.convertToRGB888,
18+
"bytesPerPixel": 3
19+
}
20+
};
21+
this.setMode(mode);
22+
}
23+
24+
setMode(mode) {
25+
this.mode = mode;
26+
this.bytesPerPixel = this.config[mode].bytesPerPixel;
27+
}
28+
29+
convertRGB565ToRGB888(pixelValue) {
30+
// RGB565
31+
let r = (pixelValue >> (6 + 5)) & 0x1F;
32+
let g = (pixelValue >> 5) & 0x3F;
33+
let b = pixelValue & 0x1F;
34+
// RGB888 - amplify
35+
r <<= 3;
36+
g <<= 2;
37+
b <<= 3;
38+
return [r, g, b];
39+
}
40+
41+
convertGrayScaleToRGB888(pixelValue) {
42+
return [pixelValue, pixelValue, pixelValue];
43+
}
44+
45+
convertToRGB888(pixelValue){
46+
return [pixelValue[0], pixelValue[1], pixelValue[2]];
47+
}
48+
49+
// Get the pixel value using big endian
50+
// Big-endian: the most significant byte comes first
51+
getPixelValue(sourceData, index) {
52+
if (this.bytesPerPixel == 1) {
53+
return sourceData[index];
54+
} else if (this.bytesPerPixel == 2) {
55+
return (sourceData[index] << 8) | sourceData[index + 1];
56+
} else if (this.bytesPerPixel == 3) {
57+
return (sourceData[index] << 16) | (sourceData[index + 1] << 8) | sourceData[index + 2];
58+
} else if (this.bytesPerPixel == 4) {
59+
return (sourceData[index] << 24) | (sourceData[index + 1] << 16) | (sourceData[index + 2] << 8) | sourceData[index + 3];
60+
}
61+
62+
return 0;
63+
}
64+
65+
getImageDataBytes(bytes, width, height) {
66+
const BYTES_PER_ROW = width * this.bytesPerPixel;
67+
68+
const imageData = this.context.createImageData(width, height);
69+
const dataContainer = imageData.data;
70+
71+
for (let row = 0; row < height; row++) {
72+
for (let col = 0; col < width; col++) {
73+
const sourceDataIndex = (row * BYTES_PER_ROW) + (col * this.bytesPerPixel);
74+
const pixelValue = this.getPixelValue(bytes, sourceDataIndex, this.bytesPerPixel);
75+
const [r, g, b] = this.config[mode].convert(pixelValue);
76+
77+
const pixelIndex = ((row * width) + col) * 4;
78+
dataContainer[pixelIndex] = r; // Red channel
79+
dataContainer[pixelIndex + 1] = g; // Green channel
80+
dataContainer[pixelIndex + 2] = b; // Blue channel
81+
dataContainer[pixelIndex + 3] = 255; // Alpha channel (opacity)
82+
}
83+
}
84+
return imageData;
85+
}
86+
}

libraries/Camera/extras/WebSerialCamera/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<button id="start">Start</button>
1717
</div>
1818
</div>
19-
<script src="conversion.js"></script>
19+
<script src="imageDataProcessor.js"></script>
2020
<script src="app.js"></script>
2121
</body>
2222
</html>

0 commit comments

Comments
 (0)