offload raw image data to Blob for off-heap storage

This commit is contained in:
Anthony Kim
2026-02-07 23:30:06 -08:00
parent cf3939af4a
commit d320898231
3 changed files with 11 additions and 8 deletions
@@ -303,9 +303,9 @@ export class KittyGraphicsHandler implements IApcHandler, IResetHandler {
switch (action) {
case KittyAction.TRANSMIT:
return this._handleTransmit(cmd, new Uint8Array(bytes), decodeError);
return this._handleTransmit(cmd, bytes, decodeError);
case KittyAction.TRANSMIT_DISPLAY:
return this._handleTransmitDisplay(cmd, new Uint8Array(bytes), decodeError);
return this._handleTransmitDisplay(cmd, bytes, decodeError);
case KittyAction.QUERY:
return this._handleQuery(cmd, bytes, decodeError);
default:
@@ -329,7 +329,7 @@ export class KittyGraphicsHandler implements IApcHandler, IResetHandler {
const id = cmd.id ?? this._nextImageId++;
const image: IKittyImageData = {
id,
data: bytes,
data: new Blob([bytes as BlobPart]),
width: cmd.width ?? 0,
height: cmd.height ?? 0,
format: (cmd.format ?? KittyFormat.PNG) as 24 | 32 | 100,
@@ -475,8 +475,7 @@ export class KittyGraphicsHandler implements IApcHandler, IResetHandler {
* Create ImageBitmap from already-decoded image data.
*/
private async _createBitmap(image: IKittyImageData): Promise<ImageBitmap> {
let bytes = image.data;
let bytes: Uint8Array = new Uint8Array(await image.data.arrayBuffer());
if (image.compression === KittyCompression.ZLIB) {
bytes = await this._decompressZlib(bytes);
@@ -116,8 +116,8 @@ export interface IPendingTransmission {
*/
export interface IKittyImageData {
id: number;
/** Decoded image bytes (already decoded from base64) */
data: Uint8Array;
/** Decoded image data stored as Blob (off JS heap) to avoid 2GB heap limit */
data: Blob;
width: number;
height: number;
format: 24 | 32 | 100;
@@ -156,7 +156,11 @@ test.describe('Kitty Graphics Protocol', () => {
await ctx.proxy.write(`\x1b_Ga=t,f=100,i=99;${part2}\x1b\\`);
await timeout(100);
const storedData = await ctx.page.evaluate(`Array.from(window.imageAddon._handlers.get('kitty').images.get(99).data)`);
const storedData = await ctx.page.evaluate(async () => {
const blob = (window as any).imageAddon._handlers.get('kitty').images.get(99).data;
const buffer = await blob.arrayBuffer();
return Array.from(new Uint8Array(buffer));
});
deepStrictEqual(storedData, KITTY_BLACK_1X1_BYTES);
});