Alex Perry | d5e1357 | 2020-02-22 15:15:08 -0800 | [diff] [blame^] | 1 | import {CameraImage} from 'y2020/vision/vision_generated'; |
Alex Perry | 5f474f2 | 2020-02-01 12:14:24 -0800 | [diff] [blame] | 2 | |
| 3 | export class ImageHandler { |
| 4 | private canvas = document.createElement('canvas'); |
| 5 | |
| 6 | constructor() { |
| 7 | document.body.appendChild(this.canvas); |
| 8 | } |
| 9 | |
| 10 | handleImage(data: Uint8Array) { |
| 11 | const fbBuffer = new flatbuffers.ByteBuffer(data); |
Alex Perry | d5e1357 | 2020-02-22 15:15:08 -0800 | [diff] [blame^] | 12 | const image = CameraImage.getRootAsCameraImage(fbBuffer); |
Alex Perry | 5f474f2 | 2020-02-01 12:14:24 -0800 | [diff] [blame] | 13 | |
| 14 | const width = image.cols(); |
| 15 | const height = image.rows(); |
| 16 | if (width === 0 || height === 0) { |
| 17 | return; |
| 18 | } |
| 19 | const imageBuffer = new Uint8ClampedArray(width * height * 4); // RGBA |
| 20 | |
| 21 | // Read four bytes (YUYV) from the data and transform into two pixels of |
| 22 | // RGBA for canvas |
| 23 | for (const j = 0; j < height; j++) { |
| 24 | for (const i = 0; i < width; i += 2) { |
| 25 | const y1 = image.data((j * width + i) * 2); |
| 26 | const u = image.data((j * width + i) * 2 + 1); |
| 27 | const y2 = image.data((j * width + i + 1) * 2); |
| 28 | const v = image.data((j * width + i + 1) * 2 + 1); |
| 29 | |
| 30 | // Based on https://en.wikipedia.org/wiki/YUV#Converting_between_Y%E2%80%B2UV_and_RGB |
| 31 | const c1 = y1 - 16; |
| 32 | const c2 = y2 - 16; |
| 33 | const d = u - 128; |
| 34 | const e = v - 128; |
| 35 | |
| 36 | imageBuffer[(j * width + i) * 4 + 0] = (298 * c1 + 409 * e + 128) >> 8; |
| 37 | imageBuffer[(j * width + i) * 4 + 1] = |
| 38 | (298 * c1 - 100 * d - 208 * e + 128) >> 8; |
| 39 | imageBuffer[(j * width + i) * 4 + 2] = (298 * c1 + 516 * d + 128) >> 8; |
| 40 | imageBuffer[(j * width + i) * 4 + 3] = 255; |
| 41 | imageBuffer[(j * width + i) * 4 + 4] = (298 * c2 + 409 * e + 128) >> 8; |
| 42 | imageBuffer[(j * width + i) * 4 + 5] = |
| 43 | (298 * c2 - 100 * d - 208 * e + 128) >> 8; |
| 44 | imageBuffer[(j * width + i) * 4 + 6] = (298 * c2 + 516 * d + 128) >> 8; |
| 45 | imageBuffer[(j * width + i) * 4 + 7] = 255; |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | const ctx = this.canvas.getContext('2d'); |
| 50 | |
| 51 | this.canvas.width = width; |
| 52 | this.canvas.height = height; |
| 53 | const idata = ctx.createImageData(width, height); |
| 54 | idata.data.set(imageBuffer); |
| 55 | ctx.putImageData(idata, 0, 0); |
| 56 | } |
| 57 | |
| 58 | getId() { |
Alex Perry | d5e1357 | 2020-02-22 15:15:08 -0800 | [diff] [blame^] | 59 | return CameraImage.getFullyQualifiedName(); |
Alex Perry | 5f474f2 | 2020-02-01 12:14:24 -0800 | [diff] [blame] | 60 | } |
| 61 | } |