| <!DOCTYPE html> |
| <script> |
| (async () => { |
| const W = 255, H = 255; |
| const maskRowSize = Math.floor((W + 31) / 32) * 4; |
| const maskBytes = maskRowSize * H; |
| const bytesInRes = 40 + 12 + maskBytes; |
| |
| function buildChunk1() { |
| const c = new Uint8Array(62); |
| c.set([0,0, 1,0, 1,0], 0); |
| c[6] = W; c[7] = H; |
| c[10] = 1; c[12] = 32; |
| c[14] = bytesInRes & 0xff; |
| c[15] = (bytesInRes >> 8) & 0xff; |
| c[16] = (bytesInRes >> 16) & 0xff; |
| c[17] = (bytesInRes >> 24) & 0xff; |
| c[18] = 22; |
| const bih = new DataView(c.buffer, 22, 40); |
| bih.setUint32(0, 40, true); |
| bih.setInt32(4, W, true); |
| bih.setInt32(8, H * 2, true); |
| bih.setUint16(12, 1, true); |
| bih.setUint16(14, 32, true); |
| bih.setUint32(16, 3, true); |
| bih.setUint32(20, 0, true); |
| return c; |
| } |
| |
| function buildChunk2() { |
| const c = new Uint8Array(12 + maskBytes); |
| const bf = new DataView(c.buffer, 0, 12); |
| bf.setUint32(0, 0x00FF0000, true); |
| bf.setUint32(4, 0x0000FF00, true); |
| bf.setUint32(8, 0x000000FF, true); |
| return c; |
| } |
| |
| let deliver2; |
| const stream = new ReadableStream({ |
| async start(controller) { |
| controller.enqueue(buildChunk1()); |
| await new Promise(r => { deliver2 = r; }); |
| controller.enqueue(buildChunk2()); |
| controller.close(); |
| } |
| }); |
| |
| const decoder = new ImageDecoder({ |
| type: 'image/x-icon', |
| data: stream, |
| desiredWidth: 16, |
| desiredHeight: 16, |
| }); |
| |
| await decoder.tracks.ready; |
| const decodePromise = decoder.decode(); |
| await new Promise(r => step_timeout(r, 500)); |
| deliver2(); |
| try { await decodePromise; } catch(e) {} |
| await new Promise(r => step_timeout(r, 2000)); |
| })(); |
| </script> |