From 8d006da57b729f712c7cce0be339b5ff1b8f395e Mon Sep 17 00:00:00 2001 From: Dank074 Date: Thu, 29 Jul 2021 16:40:55 -0500 Subject: [PATCH] added pngencoder --- src/core/communication/codec/BinaryWriter.ts | 19 ++- src/nitro/utils/PNGEncoder.ts | 135 +++++++++++++++++++ 2 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 src/nitro/utils/PNGEncoder.ts diff --git a/src/core/communication/codec/BinaryWriter.ts b/src/core/communication/codec/BinaryWriter.ts index 8eae1ef7..3ae18385 100644 --- a/src/core/communication/codec/BinaryWriter.ts +++ b/src/core/communication/codec/BinaryWriter.ts @@ -1,10 +1,12 @@ export class BinaryWriter { private _buffer: Uint8Array; + private _position: number; constructor() { this._buffer = new Uint8Array(); + this._position = 0; } public writeByte(byte: number): BinaryWriter @@ -74,12 +76,13 @@ export class BinaryWriter { if(!array) return; - const mergedArray = new Uint8Array(this._buffer.length + array.length); + const mergedArray = new Uint8Array( ((this.position + array.length) > this._buffer.length) ? (this.position + array.length) : this._buffer.length); mergedArray.set(this._buffer); - mergedArray.set(array, this._buffer.length); + mergedArray.set(array, this.position); this._buffer = mergedArray; + this.position += array.length; } public getBuffer(): ArrayBuffer @@ -87,8 +90,18 @@ export class BinaryWriter return this._buffer.buffer; } + public get position(): number + { + return this._position; + } + + public set position(pos: number) + { + this._position = pos; + } + public toString(encoding?: string): string { return new TextDecoder(encoding).decode(this._buffer); } -} \ No newline at end of file +} diff --git a/src/nitro/utils/PNGEncoder.ts b/src/nitro/utils/PNGEncoder.ts new file mode 100644 index 00000000..ef7777ed --- /dev/null +++ b/src/nitro/utils/PNGEncoder.ts @@ -0,0 +1,135 @@ +import { RenderTexture } from '@pixi/core'; +import { BinaryWriter } from '../../core/communication/codec/BinaryWriter'; +import { TextureUtils } from '../../room'; + +export class PNGEncoder +{ + private static crcTable: number[]; + private static crcTableComputed: boolean = false; + + public static encode(texture: RenderTexture): ArrayBuffer + { + if(!texture) return null; + + const canvas = TextureUtils.generateCanvas(texture); + + if(!canvas) return null; + + const width = canvas.width; + const height = canvas.height; + const context = canvas.getContext('2d'); + const imageData = context.getImageData(0, 0, width, height); + + const writer1 = new BinaryWriter(); + writer1.writeInt(2303741511); + writer1.writeInt(218765834); + + const writer2 = new BinaryWriter(); + writer2.writeInt(width); + writer2.writeInt(height); + writer2.writeInt(134610944); + writer2.writeByte(0); + + PNGEncoder.writeChunk(writer1, 1229472850, writer2); + + const writer3 = new BinaryWriter(); + + let _local_5 = 0; + + while(_local_5 < texture.height) + { + writer3.writeByte(0); + + let _local_7 = 0; + + while(_local_7 < texture.width) + { + const _local_6 = PNGEncoder.getPixel(imageData, _local_7, _local_5); + + writer3.writeInt((((_local_6 & 0xFFFFFF) << 8) | 0xFF)); + + _local_7++; + } + + _local_5++; + } + + PNGEncoder.writeChunk(writer1, 1229209940, writer3); + PNGEncoder.writeChunk(writer1, 1229278788, null); + } + + private static getPixel(imageData: ImageData, x: number, y: number): number + { + const r = imageData.data[ ((y*(imageData.width*4)) + (x*4)) + 0 ]; + const g = imageData.data[ ((y*(imageData.width*4)) + (x*4)) + 1 ]; + const b = imageData.data[ ((y*(imageData.width*4)) + (x*4)) + 2 ]; + const a = imageData.data[ ((y*(imageData.width*4)) + (x*4)) + 3 ]; + + return (r << 16 | g << 8 | b | a << 24); + } + + private static writeChunk(writer1: BinaryWriter, _arg_2: number, writer2: BinaryWriter):void + { + if(!PNGEncoder.crcTableComputed) + { + PNGEncoder.crcTableComputed = true; + PNGEncoder.crcTable = []; + + let _local_9 = 0; + + while(_local_9 < 0x0100) + { + let _local_8 = _local_9; + let _local_10 = 0; + + while(_local_10 < 8) + { + if((_local_8 & 0x01)) + { + _local_8 = (3988292384 ^ (_local_8 >>> 1)); + } + else + { + _local_8 = (_local_8 >>> 1); + } + + _local_10++; + } + + PNGEncoder.crcTable[_local_9] = _local_8; + _local_9++; + } + } + + let _local_4 = 0; + + if(writer2 !== null) _local_4 = writer2.getBuffer().byteLength; + + writer1.writeInt(_local_4); + + const _local_5: number = writer1.position; + + writer1.writeInt(_arg_2); + + if(writer2 !== null) writer1.writeBytes(writer2.getBuffer()); + + const _local_6: number = writer1.position; + + writer1.position = _local_5; + + let _local_8 = 0xFFFFFFFF; + + let _local_7 = 0; + + while(_local_7 < (_local_6 - _local_5)) + { + _local_8 = (PNGEncoder.crcTable[((_local_8 ^ writer1.getBuffer()[--writer1.position]) & 0xFF)] ^ (_local_8 >>> 8)); + _local_7++; + } + + _local_8 = (_local_8 ^ 0xFFFFFFFF); + + writer1.position = _local_6; + writer1.writeInt(_local_8); + } +}