{"ScriptPreparationCode":"class GifReader {\r\n constructor(buf) {\r\n this.buf = buf;\r\n this.p = 0;\r\n\r\n if (\r\n this.buf[this.p\u002B\u002B] !== 0x47 ||\r\n this.buf[this.p\u002B\u002B] !== 0x49 ||\r\n this.buf[this.p\u002B\u002B] !== 0x46 ||\r\n this.buf[this.p\u002B\u002B] !== 0x38 ||\r\n this.buf[this.p\u002B\u002B] !== 0x39 ||\r\n // (this.buf[this.p\u002B\u002B] \u002B 1 \u0026 0xFD) !== 0x38 ||\r\n this.buf[this.p\u002B\u002B] !== 0x61\r\n ) {\r\n throw new Error(\u0022Invalid GIF 87a/89a header.\u0022);\r\n }\r\n\r\n this.width = this.buf[this.p\u002B\u002B] | this.buf[this.p\u002B\u002B] \u003C\u003C 8;\r\n this.height = this.buf[this.p\u002B\u002B] | this.buf[this.p\u002B\u002B] \u003C\u003C 8;\r\n var pf0 = this.buf[this.p\u002B\u002B];\r\n var globalPaletteFlag = pf0 \u003E\u003E 7;\r\n var numGlobalColorsPow2 = (pf0 \u0026 0x7) \u002B 1;\r\n var numGlobalColors = 1 \u003C\u003C numGlobalColorsPow2;\r\n this.backgroundIndex = this.buf[this.p\u002B\u002B];\r\n // const aspectRatio = this.buf[this.p\u002B\u002B];\r\n this.buf[this.p\u002B\u002B];\r\n var globalPaletteOffset = null;\r\n var globalPaletteSize = null;\r\n\r\n if (globalPaletteFlag) {\r\n globalPaletteOffset = this.p;\r\n globalPaletteSize = numGlobalColors;\r\n this.p \u002B= numGlobalColors * 3;\r\n }\r\n\r\n let noEOF = true;\r\n let delay = 0;\r\n\r\n this.frames = [];\r\n\r\n var transparentIndex = null;\r\n var disposal = 0;\r\n this.loopCount = null;\r\n\r\n while (noEOF \u0026\u0026 this.p \u003C this.buf.length) {\r\n switch (this.buf[this.p\u002B\u002B]) {\r\n case 0x21:\r\n switch (this.buf[this.p\u002B\u002B]) {\r\n case 0xFF:\r\n if (\r\n this.buf[this.p] !== 0x0B ||\r\n this.buf[this.p \u002B 1] == 0x4E \u0026\u0026\r\n this.buf[this.p \u002B 2] == 0x45 \u0026\u0026\r\n this.buf[this.p \u002B 3] == 0x54 \u0026\u0026\r\n this.buf[this.p \u002B 4] == 0x53 \u0026\u0026\r\n this.buf[this.p \u002B 5] == 0x43 \u0026\u0026\r\n this.buf[this.p \u002B 6] == 0x41 \u0026\u0026\r\n this.buf[this.p \u002B 7] == 0x50 \u0026\u0026\r\n this.buf[this.p \u002B 8] == 0x45 \u0026\u0026\r\n this.buf[this.p \u002B 9] == 0x32 \u0026\u0026\r\n this.buf[this.p \u002B 10] == 0x2E \u0026\u0026\r\n this.buf[this.p \u002B 11] == 0x30 \u0026\u0026\r\n this.buf[this.p \u002B 12] == 0x03 \u0026\u0026\r\n this.buf[this.p \u002B 13] == 0x01 \u0026\u0026\r\n this.buf[this.p \u002B 16] == 0\r\n ) {\r\n this.p \u002B= 14;\r\n this.loopCount = this.buf[this.p\u002B\u002B] | this.buf[this.p\u002B\u002B] \u003C\u003C 8;\r\n this.p\u002B\u002B;\r\n }\r\n else {\r\n this.p \u002B= 12;\r\n\r\n while (true) {\r\n var blockSize = this.buf[this.p\u002B\u002B];\r\n\r\n if (!(blockSize \u003E= 0)) {\r\n throw Error(\u0022Invalid block size\u0022);\r\n }\r\n if (blockSize === 0) {\r\n break;\r\n }\r\n\r\n this.p \u002B= blockSize;\r\n }\r\n }\r\n break;\r\n case 0xF9:\r\n if (this.buf[this.p\u002B\u002B] !== 0x4 || this.buf[this.p \u002B 4] !== 0) {\r\n throw new Error(\u0022Invalid graphics extension block.\u0022);\r\n }\r\n\r\n var pf1 = this.buf[this.p\u002B\u002B];\r\n\r\n delay = this.buf[this.p\u002B\u002B] | this.buf[this.p\u002B\u002B] \u003C\u003C 8;\r\n transparentIndex = this.buf[this.p\u002B\u002B];\r\n\r\n if ((pf1 \u0026 1) === 0) {\r\n transparentIndex = null;\r\n }\r\n\r\n disposal = pf1 \u003E\u003E 2 \u0026 0x7;\r\n this.p\u002B\u002B;\r\n\r\n break;\r\n case 0x01:\r\n case 0xFE:\r\n while (true) {\r\n var blockSize = this.buf[this.p\u002B\u002B];\r\n\r\n if (!(blockSize \u003E= 0)) {\r\n throw Error(\u0022Invalid block size\u0022);\r\n }\r\n if (blockSize === 0) {\r\n break;\r\n }\r\n\r\n this.p \u002B= blockSize;\r\n }\r\n break;\r\n default:\r\n throw new Error(\u0060Unknown graphic control label: 0x${ this.buf[this.p - 1].toString(16) }\u0060);\r\n }\r\n break;\r\n case 0x2C:\r\n var x = this.buf[this.p\u002B\u002B] | this.buf[this.p\u002B\u002B] \u003C\u003C 8;\r\n var y = this.buf[this.p\u002B\u002B] | this.buf[this.p\u002B\u002B] \u003C\u003C 8;\r\n var w = this.buf[this.p\u002B\u002B] | this.buf[this.p\u002B\u002B] \u003C\u003C 8;\r\n var h = this.buf[this.p\u002B\u002B] | this.buf[this.p\u002B\u002B] \u003C\u003C 8;\r\n var pf2 = this.buf[this.p\u002B\u002B];\r\n var localPaletteFlag = pf2 \u003E\u003E 7;\r\n var interlaceFlag = pf2 \u003E\u003E 6 \u0026 1;\r\n var numLocalColorsPow2 = (pf2 \u0026 0x7) \u002B 1;\r\n var numLocalColors = 1 \u003C\u003C numLocalColorsPow2;\r\n var paletteOffset = globalPaletteOffset;\r\n var paletteSize = globalPaletteSize;\r\n var hasLocalPalette = false;\r\n\r\n if (localPaletteFlag) {\r\n var hasLocalPalette = true;\r\n paletteOffset = this.p;\r\n paletteSize = numLocalColors;\r\n this.p \u002B= numLocalColors * 3;\r\n }\r\n\r\n var dataOffset = this.p;\r\n this.p\u002B\u002B;\r\n\r\n while (true) {\r\n var blockSize = this.buf[this.p\u002B\u002B];\r\n\r\n if (!(blockSize \u003E= 0)) {\r\n throw Error(\u0022Invalid block size\u0022);\r\n }\r\n if (blockSize === 0) {\r\n break;\r\n }\r\n\r\n this.p \u002B= blockSize;\r\n }\r\n this.frames.push({\r\n x: x,\r\n y: y,\r\n width: w,\r\n height: h,\r\n has_local_palette: hasLocalPalette,\r\n palette_offset: paletteOffset,\r\n palette_size: paletteSize,\r\n data_offset: dataOffset,\r\n data_length: this.p - dataOffset,\r\n transparent_index: transparentIndex,\r\n interlaced: !!interlaceFlag,\r\n delay: delay,\r\n disposal: disposal,\r\n });\r\n break;\r\n case 0x3B:\r\n noEOF = false;\r\n break;\r\n default:\r\n throw new Error(\u0060Unknown gif block: 0x${ this.buf[this.p - 1].toString(16) }\u0060);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n numFrames() {\r\n return this.frames.length;\r\n };\r\n getLoopCount() {\r\n return this.loopCount;\r\n };\r\n getBackgroundIndex() {\r\n return this.backgroundIndex;\r\n }\r\n frameInfo(frameIndex) {\r\n if (frameIndex \u003C 0 || frameIndex \u003E= this.frames.length) {\r\n throw new Error(\u0022Frame index out of range.\u0022);\r\n }\r\n return this.frames[frameIndex];\r\n };\r\n decodeAndBlitFrameRGBA(frameIndex) {\r\n const pixels = new Uint8Array(this.width * this.height * 4);\r\n const frame = this.frameInfo(frameIndex);\r\n const numPixels = frame.width * frame.height;\r\n const indexStream = new Uint8Array(numPixels);\r\n \r\n GifReader.LZWOutputIndexStream(this.buf, frame.data_offset, indexStream, numPixels);\r\n\r\n const paletteOffset = frame.palette_offset;\r\n const trans = frame.transparent_index ?? 256;\r\n const frameWidth = frame.width;\r\n const framestride = this.width - frameWidth;\r\n const opbeg = 4 * (frame.y * this.width \u002B frame.x);\r\n const opend = opbeg \u002B 4 * this.width * frame.height;\r\n let xleft = frameWidth;\r\n let op = opbeg;\r\n let scanstride = 4 * (framestride \u002B (frame.interlaced \u0026\u0026 this.width * 7));\r\n let interlaceskip = 8;\r\n\r\n for (let i = 0, il = indexStream.length; i \u003C il; \u002B\u002Bi) {\r\n const index = indexStream[i];\r\n\r\n if (xleft === 0) {\r\n op \u002B= scanstride;\r\n xleft = frameWidth;\r\n\r\n if (op \u003E= opend) {\r\n scanstride = 4 * (framestride \u002B this.width * (interlaceskip - 1));\r\n op = opbeg \u002B (frameWidth \u002B framestride) * (interlaceskip \u003C\u003C 1);\r\n interlaceskip \u003E\u003E= 1;\r\n }\r\n }\r\n\r\n const bufIndex = paletteOffset \u002B index * 3;\r\n pixels[op\u002B\u002B] = this.buf[bufIndex];\r\n pixels[op\u002B\u002B] = this.buf[bufIndex \u002B 1];\r\n pixels[op\u002B\u002B] = this.buf[bufIndex \u002B 2];\r\n pixels[op\u002B\u002B] = index === trans ? 0 : 255;\r\n\r\n --xleft;\r\n }\r\n\r\n return pixels;\r\n };\r\n\r\n static LZWOutputIndexStream(codeStream, p, output, outputLength) {\r\n var minCodeSize = codeStream[p\u002B\u002B];\r\n var clearCode = 1 \u003C\u003C minCodeSize;\r\n var eoiCode = clearCode \u002B 1;\r\n var nextCode = eoiCode \u002B 1;\r\n var curCodeSize = minCodeSize \u002B 1;\r\n var codeMask = (1 \u003C\u003C curCodeSize) - 1;\r\n var curShift = 0;\r\n var cur = 0;\r\n var op = 0;\r\n var subblockSize = codeStream[p\u002B\u002B];\r\n var codeTable = new Int32Array(4096);\r\n var prevCode = null;\r\n while (true) {\r\n while (curShift \u003C 16) {\r\n if (subblockSize === 0) {\r\n break;\r\n }\r\n\r\n cur |= codeStream[p\u002B\u002B] \u003C\u003C curShift;\r\n curShift \u002B= 8;\r\n\r\n if (subblockSize === 1) {\r\n subblockSize = codeStream[p\u002B\u002B];\r\n }\r\n else {\r\n --subblockSize;\r\n }\r\n }\r\n\r\n if (curShift \u003C curCodeSize) {\r\n break;\r\n }\r\n\r\n var code = cur \u0026 codeMask;\r\n cur \u003E\u003E= curCodeSize;\r\n curShift -= curCodeSize;\r\n\r\n if (code === clearCode) {\r\n nextCode = eoiCode \u002B 1;\r\n curCodeSize = minCodeSize \u002B 1;\r\n codeMask = (1 \u003C\u003C curCodeSize) - 1;\r\n prevCode = null;\r\n continue;\r\n }\r\n else if (code === eoiCode) {\r\n break;\r\n }\r\n\r\n var chaseCode = code \u003C nextCode ? code : prevCode;\r\n var chaseLength = 0;\r\n var chase = chaseCode;\r\n\r\n while (chase \u003E clearCode) {\r\n chase = codeTable[chase] \u003E\u003E 8;\r\n \u002B\u002BchaseLength;\r\n }\r\n\r\n var k = chase;\r\n var opEnd = op \u002B chaseLength \u002B (chaseCode !== code ? 1 : 0);\r\n\r\n if (opEnd \u003E outputLength) {\r\n console.log(\u0022Warning, gif stream longer than expected.\u0022);\r\n return;\r\n }\r\n\r\n output[op\u002B\u002B] = k;\r\n op \u002B= chaseLength;\r\n var b = op;\r\n\r\n if (chaseCode !== code) {\r\n output[op\u002B\u002B] = k;\r\n }\r\n\r\n chase = chaseCode;\r\n\r\n while (chaseLength--) {\r\n chase = codeTable[chase];\r\n output[--b] = chase \u0026 0xFF;\r\n chase \u003E\u003E= 8;\r\n }\r\n\r\n if (prevCode !== null \u0026\u0026 nextCode \u003C 4096) {\r\n codeTable[nextCode\u002B\u002B] = prevCode \u003C\u003C 8 | k;\r\n\r\n if (nextCode \u003E= codeMask \u002B 1 \u0026\u0026 curCodeSize \u003C 12) {\r\n \u002B\u002BcurCodeSize;\r\n codeMask = codeMask \u003C\u003C 1 | 1;\r\n }\r\n }\r\n\r\n prevCode = code;\r\n }\r\n\r\n if (op !== outputLength) {\r\n console.log(\u0022Warning, gif stream shorter than expected.\u0022);\r\n }\r\n\r\n return output;\r\n }\r\n}\r\n\r\nclass GifWriter {\r\n constructor(buf, width, height, gopts = {}) {\r\n if (width \u003C= 0 || height \u003C= 0 || width \u003E 0XFFFF || height \u003E 0xFFFF) {\r\n throw new Error(\u0022Width/Height invalid.\u0022);\r\n }\r\n\r\n this.buf = buf;\r\n this.p = 0;\r\n this.globalPalette = gopts.palette ?? null;\r\n this.ended = false;\r\n const loopCount = gopts.loop ?? null;\r\n const gpNumColors = GifWriter.checkPaletteLength(this.globalPalette).length;\r\n const gpNumColorsPow2 = GifWriter.calculateMinCodeSize(gpNumColors);\r\n\r\n const background = (this.globalPalette \u0026\u0026 gopts.background) ?? null;\r\n if (background \u003E= gpNumColors) {\r\n throw new Error(\u0022Background index out of range.\u0022);\r\n }\r\n if (background === 0) {\r\n throw new Error(\u0022Background index explicitly passed as 0.\u0022);\r\n }\r\n\r\n this.buf[this.p\u002B\u002B] = 0x47;\r\n this.buf[this.p\u002B\u002B] = 0x49;\r\n this.buf[this.p\u002B\u002B] = 0x46;\r\n this.buf[this.p\u002B\u002B] = 0x38;\r\n this.buf[this.p\u002B\u002B] = 0x39;\r\n this.buf[this.p\u002B\u002B] = 0x61;\r\n this.buf[this.p\u002B\u002B] = width \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = width \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = height \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = height \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = !!this.globalPalette \u003C\u003C 7 | (gpNumColorsPow2 - 1);\r\n this.buf[this.p\u002B\u002B] = background;\r\n this.buf[this.p\u002B\u002B] = 0;\r\n\r\n if (this.globalPalette) {\r\n for (let i = 0, il = this.globalPalette.length; i \u003C il; \u002B\u002Bi) {\r\n const rgb = this.globalPalette[i];\r\n this.buf[this.p\u002B\u002B] = rgb \u003E\u003E 16 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = rgb \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = rgb \u0026 0xFF;\r\n }\r\n }\r\n\r\n if (loopCount !== null) {\r\n if (loopCount \u003C 0 || loopCount \u003E 0xFFFF) {\r\n throw new Error(\u0022Loop count invalid.\u0022);\r\n }\r\n\r\n this.buf[this.p\u002B\u002B] = 0x21;\r\n this.buf[this.p\u002B\u002B] = 0xFF;\r\n this.buf[this.p\u002B\u002B] = 0x0B;\r\n this.buf[this.p\u002B\u002B] = 0x4E;\r\n this.buf[this.p\u002B\u002B] = 0x45;\r\n this.buf[this.p\u002B\u002B] = 0x54;\r\n this.buf[this.p\u002B\u002B] = 0x53;\r\n this.buf[this.p\u002B\u002B] = 0x43;\r\n this.buf[this.p\u002B\u002B] = 0x41;\r\n this.buf[this.p\u002B\u002B] = 0x50;\r\n this.buf[this.p\u002B\u002B] = 0x45;\r\n this.buf[this.p\u002B\u002B] = 0x32;\r\n this.buf[this.p\u002B\u002B] = 0x2E;\r\n this.buf[this.p\u002B\u002B] = 0x30;\r\n this.buf[this.p\u002B\u002B] = 0x03;\r\n this.buf[this.p\u002B\u002B] = 0x01;\r\n this.buf[this.p\u002B\u002B] = loopCount \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = loopCount \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = 0x00;\r\n }\r\n }\r\n\r\n addFrame(x, y, w, h, indexedPixels, opts = {}) {\r\n if (this.ended) {\r\n --this.p;\r\n this.ended = false;\r\n }\r\n\r\n if (x \u003C 0 || y \u003C 0 || x \u003E 0xFFFF || y \u003E 0xFFFF) {\r\n throw new Error(\u0022x/y invalid.\u0022);\r\n }\r\n if (w \u003C= 0 || h \u003C= 0 || w \u003E 0xFFFF || h \u003E 0xFFFF) {\r\n throw new Error(\u0022Width/Height invalid.\u0022);\r\n }\r\n if (indexedPixels.length \u003C w * h) {\r\n throw new Error(\u0022Not enough pixels for the frame size.\u0022);\r\n }\r\n\r\n const usingLocalPalette = !!opts.palette;\r\n const palette = opts.palette ?? this.globalPalette;\r\n if (!palette) {\r\n throw new Error(\u0022Must supply either a local or global palette.\u0022);\r\n }\r\n\r\n const numColors = GifWriter.checkPaletteLength(palette).length;\r\n const minCodeSize = GifWriter.calculateMinCodeSize(numColors);\r\n\r\n const delay = opts.delay ?? 0;\r\n const disposal = opts.disposal ?? 0;\r\n\r\n if (disposal \u003C 0 || disposal \u003E 3) {\r\n throw new Error(\u0022Disposal out of range.\u0022);\r\n }\r\n\r\n const useTrancparency = !!opts.transparent;\r\n const transparentIndex = opts.transparent ?? 0;\r\n if (transparentIndex \u003C 0 || transparentIndex \u003E= numColors) {\r\n throw new Error(\u0022Transparent color index.\u0022);\r\n }\r\n\r\n if (disposal !== 0 || useTrancparency || delay !== 0) {\r\n this.buf[this.p\u002B\u002B] = 0x21;\r\n this.buf[this.p\u002B\u002B] = 0xF9;\r\n this.buf[this.p\u002B\u002B] = 4;\r\n this.buf[this.p\u002B\u002B] = disposal \u003C\u003C 2 | useTrancparency;\r\n this.buf[this.p\u002B\u002B] = delay \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = delay \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = transparentIndex;\r\n this.buf[this.p\u002B\u002B] = 0;\r\n }\r\n\r\n this.buf[this.p\u002B\u002B] = 0x2C;\r\n this.buf[this.p\u002B\u002B] = x \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = x \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = y \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = y \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = w \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = w \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = h \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = h \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = usingLocalPalette ? (0x80 | (minCodeSize - 1)) : 0;\r\n\r\n if (usingLocalPalette) {\r\n for (let i = 0, il = palette.length; i \u003C il; \u002B\u002Bi) {\r\n const rgb = palette[i];\r\n this.buf[this.p\u002B\u002B] = rgb \u003E\u003E 16 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = rgb \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = rgb \u0026 0xFF;\r\n }\r\n }\r\n\r\n // this.p = GifWriter.OutputLZWCodeStream(this.buf, this.p, minCodeSize \u003C 2 ? 2 : minCodeSize, indexedPixels);\r\n this.OutputLZWCodeStream(indexedPixels, minCodeSize \u003C 2 ? 2 : minCodeSize);\r\n\r\n return this.p;\r\n };\r\n\r\n end() {\r\n if (!this.ended) {\r\n this.buf[this.p\u002B\u002B] = 0x3B;\r\n this.ended = true;\r\n }\r\n\r\n return this.p;\r\n };\r\n getOutputBuffer() {\r\n return this.buf;\r\n };\r\n setOutputBuffer(v) {\r\n this.buf = v;\r\n };\r\n getOutputBufferPosition() {\r\n return this.p;\r\n };\r\n setOutputBufferPosition(v) {\r\n this.p = v;\r\n };\r\n\r\n emitBytesToBuffer(bitBlockSize) {\r\n while (this.curShift \u003E= bitBlockSize) {\r\n this.buf[this.p\u002B\u002B] = this.cur \u0026 0xFF;\r\n this.cur \u003E\u003E= 8;\r\n this.curShift -= 8;\r\n\r\n if (this.p === this.curSubblock \u002B 256) {\r\n this.buf[this.curSubblock] = 255;\r\n this.curSubblock = this.p\u002B\u002B;\r\n }\r\n }\r\n }\r\n\r\n emitCode(c) {\r\n this.cur |= c \u003C\u003C this.curShift;\r\n this.curShift \u002B= this.curCodeSize;\r\n this.emitBytesToBuffer(8);\r\n }\r\n\r\n OutputLZWCodeStream(indexStream, minCodeSize) {\r\n this.buf[this.p\u002B\u002B] = minCodeSize;\r\n const clearCode = 1 \u003C\u003C minCodeSize;\r\n const codeMask = clearCode - 1;\r\n const eoiCode = clearCode \u002B 1;\r\n this.curSubblock = this.p\u002B\u002B;\r\n this.curCodeSize = minCodeSize \u002B 1;\r\n this.curShift = 0;\r\n this.cur = 0;\r\n let nextCode = eoiCode \u002B 1;\r\n let ibCode = indexStream[0] \u0026 codeMask;\r\n let codeTable = {};\r\n\r\n this.emitCode(clearCode);\r\n\r\n for (let i = 1, il = indexStream.length; i \u003C il; \u002B\u002Bi) {\r\n const k = indexStream[i] \u0026 codeMask;\r\n const curKey = ibCode \u003C\u003C 8 | k;\r\n const curCode = codeTable[curKey];\r\n\r\n if (curCode === undefined) {\r\n this.cur |= ibCode \u003C\u003C this.curShift;\r\n this.curShift \u002B= this.curCodeSize;\r\n\r\n while (this.curShift \u003E= 8) {\r\n this.buf[this.p\u002B\u002B] = this.cur \u0026 0xFF;\r\n this.cur \u003E\u003E= 8;\r\n this.curShift -= 8;\r\n\r\n if (this.p === this.curSubblock \u002B 256) {\r\n this.buf[this.curSubblock] = 255;\r\n this.curSubblock = this.p\u002B\u002B;\r\n }\r\n }\r\n\r\n if (nextCode === 4096) {\r\n this.emitCode(clearCode);\r\n nextCode = eoiCode \u002B 1;\r\n this.curCodeSize = minCodeSize \u002B 1;\r\n codeTable = {};\r\n }\r\n else {\r\n if (nextCode \u003E= (1 \u003C\u003C this.curCodeSize)) {\r\n \u002B\u002Bthis.curCodeSize;\r\n }\r\n\r\n codeTable[curKey] = nextCode\u002B\u002B;\r\n }\r\n\r\n ibCode = k;\r\n }\r\n else {\r\n ibCode = curCode;\r\n }\r\n }\r\n\r\n this.emitCode(ibCode);\r\n this.emitCode(eoiCode);\r\n this.emitBytesToBuffer(1);\r\n\r\n if (this.curSubblock \u002B 1 === this.p) {\r\n this.buf[this.curSubblock] = 0;\r\n }\r\n else {\r\n this.buf[this.curSubblock] = this.p - this.curSubblock - 1;\r\n this.buf[this.p\u002B\u002B] = 0;\r\n }\r\n\r\n return this.p;\r\n }\r\n\r\n static checkPaletteLength(palette) {\r\n const numColors = palette.length;\r\n if (numColors \u003C 2 || numColors \u003E 256 || numColors \u0026 (numColors - 1)) {\r\n throw new Error(\u0022Invalid code/color length, must be power of 2 and 2 .. 256.\u0022);\r\n }\r\n\r\n return palette;\r\n }\r\n\r\n static calculateMinCodeSize(numColors) {\r\n let minCodeSize = 0;\r\n while (numColors \u003E\u003E= 1) { \u002B\u002BminCodeSize; }\r\n\r\n return minCodeSize;\r\n }\r\n}\r\n\r\nclass GifWriter2 {\r\n constructor(buf, width, height, gopts = {}) {\r\n if (width \u003C= 0 || height \u003C= 0 || width \u003E 0XFFFF || height \u003E 0xFFFF) {\r\n throw new Error(\u0022Width/Height invalid.\u0022);\r\n }\r\n\r\n this.buf = buf;\r\n this.p = 0;\r\n this.globalPalette = gopts.palette ?? null;\r\n this.ended = false;\r\n const loopCount = gopts.loop ?? null;\r\n const gpNumColors = GifWriter.checkPaletteLength(this.globalPalette).length;\r\n const gpNumColorsPow2 = GifWriter.calculateMinCodeSize(gpNumColors);\r\n\r\n const background = (this.globalPalette \u0026\u0026 gopts.background) ?? null;\r\n if (background \u003E= gpNumColors) {\r\n throw new Error(\u0022Background index out of range.\u0022);\r\n }\r\n if (background === 0) {\r\n throw new Error(\u0022Background index explicitly passed as 0.\u0022);\r\n }\r\n\r\n this.buf[this.p\u002B\u002B] = 0x47;\r\n this.buf[this.p\u002B\u002B] = 0x49;\r\n this.buf[this.p\u002B\u002B] = 0x46;\r\n this.buf[this.p\u002B\u002B] = 0x38;\r\n this.buf[this.p\u002B\u002B] = 0x39;\r\n this.buf[this.p\u002B\u002B] = 0x61;\r\n this.buf[this.p\u002B\u002B] = width \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = width \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = height \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = height \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = !!this.globalPalette \u003C\u003C 7 | (gpNumColorsPow2 - 1);\r\n this.buf[this.p\u002B\u002B] = background;\r\n this.buf[this.p\u002B\u002B] = 0;\r\n\r\n if (this.globalPalette) {\r\n for (let i = 0, il = this.globalPalette.length; i \u003C il; \u002B\u002Bi) {\r\n const rgb = this.globalPalette[i];\r\n this.buf[this.p\u002B\u002B] = rgb \u003E\u003E 16 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = rgb \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = rgb \u0026 0xFF;\r\n }\r\n }\r\n\r\n if (loopCount !== null) {\r\n if (loopCount \u003C 0 || loopCount \u003E 0xFFFF) {\r\n throw new Error(\u0022Loop count invalid.\u0022);\r\n }\r\n\r\n this.buf[this.p\u002B\u002B] = 0x21;\r\n this.buf[this.p\u002B\u002B] = 0xFF;\r\n this.buf[this.p\u002B\u002B] = 0x0B;\r\n this.buf[this.p\u002B\u002B] = 0x4E;\r\n this.buf[this.p\u002B\u002B] = 0x45;\r\n this.buf[this.p\u002B\u002B] = 0x54;\r\n this.buf[this.p\u002B\u002B] = 0x53;\r\n this.buf[this.p\u002B\u002B] = 0x43;\r\n this.buf[this.p\u002B\u002B] = 0x41;\r\n this.buf[this.p\u002B\u002B] = 0x50;\r\n this.buf[this.p\u002B\u002B] = 0x45;\r\n this.buf[this.p\u002B\u002B] = 0x32;\r\n this.buf[this.p\u002B\u002B] = 0x2E;\r\n this.buf[this.p\u002B\u002B] = 0x30;\r\n this.buf[this.p\u002B\u002B] = 0x03;\r\n this.buf[this.p\u002B\u002B] = 0x01;\r\n this.buf[this.p\u002B\u002B] = loopCount \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = loopCount \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = 0x00;\r\n }\r\n }\r\n\r\n addFrame(x, y, w, h, indexedPixels, opts = {}) {\r\n if (this.ended) {\r\n --this.p;\r\n this.ended = false;\r\n }\r\n\r\n if (x \u003C 0 || y \u003C 0 || x \u003E 0xFFFF || y \u003E 0xFFFF) {\r\n throw new Error(\u0022x/y invalid.\u0022);\r\n }\r\n if (w \u003C= 0 || h \u003C= 0 || w \u003E 0xFFFF || h \u003E 0xFFFF) {\r\n throw new Error(\u0022Width/Height invalid.\u0022);\r\n }\r\n if (indexedPixels.length \u003C w * h) {\r\n throw new Error(\u0022Not enough pixels for the frame size.\u0022);\r\n }\r\n\r\n const usingLocalPalette = !!opts.palette;\r\n const palette = opts.palette ?? this.globalPalette;\r\n if (!palette) {\r\n throw new Error(\u0022Must supply either a local or global palette.\u0022);\r\n }\r\n\r\n const numColors = GifWriter.checkPaletteLength(palette).length;\r\n const minCodeSize = GifWriter.calculateMinCodeSize(numColors);\r\n\r\n const delay = opts.delay ?? 0;\r\n const disposal = opts.disposal ?? 0;\r\n\r\n if (disposal \u003C 0 || disposal \u003E 3) {\r\n throw new Error(\u0022Disposal out of range.\u0022);\r\n }\r\n\r\n const useTrancparency = !!opts.transparent;\r\n const transparentIndex = opts.transparent ?? 0;\r\n if (transparentIndex \u003C 0 || transparentIndex \u003E= numColors) {\r\n throw new Error(\u0022Transparent color index.\u0022);\r\n }\r\n\r\n if (disposal !== 0 || useTrancparency || delay !== 0) {\r\n this.buf[this.p\u002B\u002B] = 0x21;\r\n this.buf[this.p\u002B\u002B] = 0xF9;\r\n this.buf[this.p\u002B\u002B] = 4;\r\n this.buf[this.p\u002B\u002B] = disposal \u003C\u003C 2 | useTrancparency;\r\n this.buf[this.p\u002B\u002B] = delay \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = delay \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = transparentIndex;\r\n this.buf[this.p\u002B\u002B] = 0;\r\n }\r\n\r\n this.buf[this.p\u002B\u002B] = 0x2C;\r\n this.buf[this.p\u002B\u002B] = x \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = x \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = y \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = y \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = w \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = w \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = h \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = h \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = usingLocalPalette ? (0x80 | (minCodeSize - 1)) : 0;\r\n\r\n if (usingLocalPalette) {\r\n for (let i = 0, il = palette.length; i \u003C il; \u002B\u002Bi) {\r\n const rgb = palette[i];\r\n this.buf[this.p\u002B\u002B] = rgb \u003E\u003E 16 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = rgb \u003E\u003E 8 \u0026 0xFF;\r\n this.buf[this.p\u002B\u002B] = rgb \u0026 0xFF;\r\n }\r\n }\r\n\r\n // this.p = GifWriter.OutputLZWCodeStream(this.buf, this.p, minCodeSize \u003C 2 ? 2 : minCodeSize, indexedPixels);\r\n this.OutputLZWCodeStream(indexedPixels, minCodeSize \u003C 2 ? 2 : minCodeSize);\r\n\r\n return this.p;\r\n };\r\n\r\n end() {\r\n if (!this.ended) {\r\n this.buf[this.p\u002B\u002B] = 0x3B;\r\n this.ended = true;\r\n }\r\n\r\n return this.p;\r\n };\r\n getOutputBuffer() {\r\n return this.buf;\r\n };\r\n setOutputBuffer(v) {\r\n this.buf = v;\r\n };\r\n getOutputBufferPosition() {\r\n return this.p;\r\n };\r\n setOutputBufferPosition(v) {\r\n this.p = v;\r\n };\r\n\r\n emitBytesToBuffer(bitBlockSize) {\r\n while (this.curShift \u003E= bitBlockSize) {\r\n this.buf[this.p\u002B\u002B] = this.cur \u0026 0xFF;\r\n this.cur \u003E\u003E= 8;\r\n this.curShift -= 8;\r\n\r\n if (this.p === this.curSubblock \u002B 256) {\r\n this.buf[this.curSubblock] = 255;\r\n this.curSubblock = this.p\u002B\u002B;\r\n }\r\n }\r\n }\r\n\r\n emitCode(c) {\r\n this.cur |= c \u003C\u003C this.curShift;\r\n this.curShift \u002B= this.curCodeSize;\r\n this.emitBytesToBuffer(8);\r\n }\r\n\r\n OutputLZWCodeStream(indexStream, minCodeSize) {\r\n this.buf[this.p\u002B\u002B] = minCodeSize;\r\n const clearCode = 1 \u003C\u003C minCodeSize;\r\n const codeMask = clearCode - 1;\r\n const eoiCode = clearCode \u002B 1;\r\n this.curSubblock = this.p\u002B\u002B;\r\n this.curCodeSize = minCodeSize \u002B 1;\r\n this.curShift = 0;\r\n this.cur = 0;\r\n let nextCode = eoiCode \u002B 1;\r\n let ibCode = indexStream[0] \u0026 codeMask;\r\n let codeTable = {};\r\n\r\n this.emitCode(clearCode);\r\n\r\n for (let i = 1, il = indexStream.length; i \u003C il; \u002B\u002Bi) {\r\n const k = indexStream[i] \u0026 codeMask;\r\n const curKey = ibCode \u003C\u003C 8 | k;\r\n const curCode = codeTable[curKey];\r\n\r\n if (curCode === undefined) {\r\n this.emitCode(ibCode);\r\n\r\n if (nextCode === 4096) {\r\n this.emitCode(clearCode);\r\n nextCode = eoiCode \u002B 1;\r\n this.curCodeSize = minCodeSize \u002B 1;\r\n codeTable = {};\r\n }\r\n else {\r\n if (nextCode \u003E= (1 \u003C\u003C this.curCodeSize)) {\r\n \u002B\u002Bthis.curCodeSize;\r\n }\r\n\r\n codeTable[curKey] = nextCode\u002B\u002B;\r\n }\r\n\r\n ibCode = k;\r\n }\r\n else {\r\n ibCode = curCode;\r\n }\r\n }\r\n\r\n this.emitCode(ibCode);\r\n this.emitCode(eoiCode);\r\n this.emitBytesToBuffer(1);\r\n\r\n if (this.curSubblock \u002B 1 === this.p) {\r\n this.buf[this.curSubblock] = 0;\r\n }\r\n else {\r\n this.buf[this.curSubblock] = this.p - this.curSubblock - 1;\r\n this.buf[this.p\u002B\u002B] = 0;\r\n }\r\n\r\n return this.p;\r\n }\r\n\r\n static checkPaletteLength(palette) {\r\n const numColors = palette.length;\r\n if (numColors \u003C 2 || numColors \u003E 256 || numColors \u0026 (numColors - 1)) {\r\n throw new Error(\u0022Invalid code/color length, must be power of 2 and 2 .. 256.\u0022);\r\n }\r\n\r\n return palette;\r\n }\r\n\r\n static calculateMinCodeSize(numColors) {\r\n let minCodeSize = 0;\r\n while (numColors \u003E\u003E= 1) { \u002B\u002BminCodeSize; }\r\n\r\n return minCodeSize;\r\n }\r\n}\r\n\r\n\r\n\r\n\r\nfunction makeMapPalette(buffer, offset, size) {\r\n const paletteMap = new Map();\r\n for (let i = offset, limit = offset \u002B size * 3; i \u003C limit; i \u002B= 3) {\r\n const color = buffer[i] \u003C\u003C 16 | buffer[i \u002B 1] \u003C\u003C 8 | buffer[i \u002B 2];\r\n if (!paletteMap.has(color)) {\r\n paletteMap.set(color, paletteMap.size);\r\n }\r\n }\r\n\r\n return paletteMap;\r\n}\r\n\r\nfunction makeResizedPaletteFromMap(paletteMap) {\r\n const oldPaletteSize = paletteMap.size;\r\n let newPaletteSize = 2;\r\n while (newPaletteSize \u003C oldPaletteSize) newPaletteSize \u003C\u003C= 1;\r\n const palette = [...paletteMap.keys()];\r\n palette.length = newPaletteSize;\r\n // palette.fill(0, oldPaletteSize, newPaletteSize);\r\n\r\n return palette;\r\n}\r\n\r\nfunction colorDistance(c1, c2) {\r\n const r = (c1 \u0026 0xFF) - (c2 \u0026 0xFF);\r\n const g = (c1 \u003E\u003E 8 \u0026 0xFF) - (c2 \u003E\u003E 8 \u0026 0xFF);\r\n const b = (c1 \u003E\u003E 16 \u0026 0xFF) - (c2 \u003E\u003E 16 \u0026 0xFF);\r\n\r\n return r * r \u002B g * g \u002B b * b;\r\n}\r\n\r\nfunction h(srcCtx, destCtx) {\r\n const offset = (srcCtx.canvas.width - srcCtx.canvas.height) * 0.5;\r\n const srcX = offset \u003C 0 ? 0 : offset;\r\n const srcY = offset \u003E 0 ? 0 : -offset;\r\n const srcSize = srcCtx.canvas.width \u003C srcCtx.canvas.height ? srcCtx.canvas.width : srcCtx.canvas.height;\r\n const destSize = destCtx.canvas.width;\r\n destCtx.drawImage(srcCtx.canvas, srcX, srcY, srcSize, srcSize, 0, 0, destSize, destSize);\r\n}\r\n\r\nfunction calculateNewSizeAndPosition(x, y, width, height, gifWidth, gifHeight, newSize) {\r\n const size = gifWidth \u003C gifHeight ? gifWidth : gifHeight;\r\n const offset = (gifWidth - gifHeight) * 0.5;\r\n const offsetX = offset \u003C 0 ? 0 : offset;\r\n const offsetY = offset \u003E 0 ? 0 : -offset;\r\n\r\n const left = x;\r\n const right = x \u002B width;\r\n const top = y;\r\n const bottom = y \u002B height;\r\n\r\n const leftX = offsetX;\r\n const rightX = offsetX \u002B size;\r\n const leftY = offsetY;\r\n const rightY = offsetY \u002B size;\r\n\r\n const f0 = left \u003C leftX;\r\n const f1 = left \u003C rightX;\r\n const f2 = right \u003E leftX;\r\n const f3 = right \u003E rightX;\r\n const f4 = top \u003C leftY;\r\n const f5 = top \u003C rightY;\r\n const f6 = bottom \u003E leftY;\r\n const f7 = bottom \u003E rightY;\r\n\r\n const fsx = f0 | f1 \u003C\u003C 1 | f2 \u003C\u003C 2 | f3 \u003C\u003C 3;\r\n const fsy = f4 | f5 \u003C\u003C 1 | f6 \u003C\u003C 2 | f7 \u003C\u003C 3;\r\n\r\n\r\n let state;\r\n\r\n switch (fsx) {\r\n case 0b0110:\r\n case 0b0111:\r\n case 0b1110:\r\n case 0b1111:\r\n state |= 1;\r\n break;\r\n case 0b0011:\r\n case 0b1100:\r\n state |= 2;\r\n break;\r\n default:\r\n state |= 4;\r\n }\r\n\r\n switch (fsy) {\r\n case 0b0110:\r\n case 0b0111:\r\n case 0b1110:\r\n case 0b1111:\r\n state |= 1;\r\n break;\r\n case 0b0011:\r\n case 0b1100:\r\n state |= 2;\r\n break;\r\n default:\r\n state |= 4;\r\n }\r\n\r\n if (state \u003E\u003E 2) { throw new Error(\u0022Invalid state\u0022); }\r\n if (state \u003E\u003E 1) { return { cropX: -1, cropY: -1, cropWidth: 1, cropHeight: 1 }; }\r\n\r\n const cropX = x \u003E offsetX ? x - offsetX : 0;\r\n const cropWidth = Math.min(x \u002B width, offsetX \u002B size) - cropX - offsetX;\r\n const cropY = y \u003E offsetY ? y - offsetY : 0;\r\n const cropHeight = Math.min(y \u002B height, offsetY \u002B size) - cropY - offsetY;\r\n const scale = newSize / size;\r\n\r\n return {\r\n cropX: Math.round(cropX * scale),\r\n cropY: Math.round(cropY * scale),\r\n cropWidth: Math.round(cropWidth * scale),\r\n cropHeight: Math.round(cropHeight * scale),\r\n };\r\n}\r\n\r\nfunction processPixels(frameData, x, y, width, height, size, palette, paletteMap) {\r\n const pixels = new Uint8Array(width * height);\r\n\r\n if (x === -1) { pixels[0] = 0; return pixels; }\r\n\r\n for (let i = y, pixelIndex = 0; i \u003C y \u002B height; \u002B\u002Bi) {\r\n for (let j = x; j \u003C x \u002B width; \u002B\u002Bj, \u002B\u002BpixelIndex) {\r\n const index = (i * size \u002B j) * 4;\r\n const color = frameData[index] \u003C\u003C 16 | frameData[index \u002B 1] \u003C\u003C 8 | frameData[index \u002B 2];\r\n pixels[pixelIndex] = paletteMap.get(color) ?? palette.reduce((closest, currentColor, index) =\u003E {\r\n const dist = colorDistance(color, currentColor);\r\n return dist \u003C closest.dist ? { index, dist } : closest;\r\n }, { index: 0, dist: Infinity }).index;\r\n }\r\n }\r\n\r\n return pixels;\r\n}\r\n\r\nfunction f(imageURL) {\r\n if (imageURL === undefined) {\r\n imageURL = \u0022https://techolay.net/sosyal/data/avatars/o/6/6412.jpg?1724340482\u0022;\r\n }\r\n\r\n return fetch(imageURL)\r\n .then(response =\u003E response.arrayBuffer())\r\n .then(buffer =\u003E {\r\n console.time(\u0022gif\u0022);\r\n\r\n const bufArr = new Uint8Array(buffer);\r\n const gifReader = new GifReader(bufArr);\r\n const frameCount = gifReader.numFrames();\r\n\r\n const { palette_offset, palette_size } = gifReader.frameInfo(0);\r\n const paletteMap = makeMapPalette(bufArr, palette_offset, palette_size);\r\n const palette = makeResizedPaletteFromMap(paletteMap);\r\n\r\n const size = 192;\r\n const newWidth = size;\r\n const newHeight = size;\r\n\r\n const gifWriter = new GifWriter(\r\n new Uint8Array(frameCount * (newWidth * newHeight \u002B 0x1000)),\r\n newWidth,\r\n newHeight,\r\n { palette, loop: gifReader.getLoopCount() },\r\n );\r\n\r\n for (let frameIndex = 0; frameIndex \u003C frameCount; \u002B\u002BframeIndex) {\r\n const {\r\n palette_offset,\r\n transparent_index,\r\n background_index,\r\n delay,\r\n disposal,\r\n width,\r\n height,\r\n x,\r\n y,\r\n } = gifReader.frameInfo(frameIndex);\r\n\r\n const frameData = gifReader.decodeAndBlitFrameRGBA(frameIndex);\r\n\r\n const transparentIndex = palette_offset \u002B transparent_index * 3;\r\n const transparentColor = bufArr[transparentIndex] \u003C\u003C 16 | bufArr[transparentIndex \u002B 1] \u003C\u003C 8 | bufArr[transparentIndex \u002B 2];\r\n const transparent = transparent_index\r\n ? paletteMap.get(transparentColor)\r\n : undefined;\r\n const backgroundIndex = palette_offset \u002B background_index * 3;\r\n const backgroundColor = bufArr[backgroundIndex] \u003C\u003C 16 | bufArr[backgroundIndex \u002B 1] \u003C\u003C 8 | bufArr[backgroundIndex \u002B 2];\r\n const background = background_index\r\n ? paletteMap.get(backgroundColor)\r\n : undefined;\r\n\r\n\r\n const originalCtx = new OffscreenCanvas(gifReader.width, gifReader.height).getContext(\u00222d\u0022, { alpha: false, willReadFrequently: true });\r\n const newCtx = new OffscreenCanvas(newWidth, newHeight).getContext(\u00222d\u0022, { alpha: false, willReadFrequently: true });\r\n originalCtx.putImageData(new ImageData(new Uint8ClampedArray(frameData.buffer), gifReader.width, gifReader.height), 0, 0);\r\n\r\n newCtx.imageSmoothingEnabled = false;\r\n // newCtx.imageSmoothingEnabled = true;\r\n\r\n h(originalCtx, newCtx);\r\n const newFrameData = newCtx.getImageData(0, 0, newWidth, newHeight).data;\r\n\r\n\r\n\r\n const {\r\n cropX,\r\n cropY,\r\n cropWidth,\r\n cropHeight,\r\n } = calculateNewSizeAndPosition(x, y, width, height, gifReader.width, gifReader.height, size);\r\n\r\n const pixels = processPixels(newFrameData, cropX, cropY, cropWidth, cropHeight, size, palette, paletteMap);\r\n\r\n gifWriter.addFrame(\r\n cropX !== -1 ? cropX : 0,\r\n cropY !== -1 ? cropY : 0,\r\n cropWidth,\r\n cropHeight,\r\n pixels,\r\n {\r\n delay,\r\n disposal,\r\n transparent: cropX !== -1 ? transparent : 0,\r\n },\r\n );\r\n }\r\n\r\n gifWriter.end();\r\n\r\n const blob = new Blob([gifWriter.getOutputBuffer().subarray(0, gifWriter.getOutputBufferPosition())], { type: \u0022image/gif\u0022 });\r\n const reader = new FileReader();\r\n reader.onload = event =\u003E {\r\n const dataUrl = reader.result;\r\n // console.log(dataUrl);\r\n // console.log(dataUrl);\r\n\r\n sha256(dataUrl, \u0022f00dd8b1290f4fca899eec25c8022eeaf9a22a652c1d81d7b2c8561392ccf5e6\u0022);\r\n };\r\n reader.readAsDataURL(blob);\r\n\r\n console.timeEnd(\u0022gif\u0022);\r\n });\r\n}\r\n\r\nasync function sha256(message, sha) {\r\n // encode as UTF-8\r\n const msgBuffer = new TextEncoder().encode(message);\r\n\r\n // hash the message\r\n const hashBuffer = await crypto.subtle.digest(\u0027SHA-256\u0027, msgBuffer);\r\n\r\n // convert ArrayBuffer to Array\r\n const hashArray = Array.from(new Uint8Array(hashBuffer));\r\n\r\n // convert bytes to hex string \r\n const hashHex = hashArray.map(b =\u003E b.toString(16).padStart(2, \u00270\u0027)).join(\u0027\u0027);\r\n\r\n const isShaEqual = hashHex === sha;\r\n\r\n if (isShaEqual) {\r\n console.log(\u0060sha256: ${ isShaEqual }\u0060);\r\n // console.log(\u0060${ message }\u0060);\r\n }\r\n else {\r\n console.log(\u0060sha256: ${ hashHex }\u0060);\r\n console.log(\u0060${ message }\u0060);\r\n }\r\n}\r\n\r\n\r\nfunction g(imageURL) {\r\n if (imageURL === undefined) {\r\n imageURL = \u0022https://techolay.net/sosyal/data/avatars/o/6/6412.jpg?1724340482\u0022;\r\n }\r\n\r\n return fetch(imageURL)\r\n .then(response =\u003E response.arrayBuffer())\r\n .then(buffer =\u003E {\r\n console.time(\u0022gif\u0022);\r\n\r\n const bufArr = new Uint8Array(buffer);\r\n const gifReader = new GifReader(bufArr);\r\n const frameCount = gifReader.numFrames();\r\n\r\n const { palette_offset, palette_size } = gifReader.frameInfo(0);\r\n const paletteMap = makeMapPalette(bufArr, palette_offset, palette_size);\r\n const palette = makeResizedPaletteFromMap(paletteMap);\r\n\r\n const size = 192;\r\n const newWidth = size;\r\n const newHeight = size;\r\n\r\n const gifWriter = new GifWriter2(\r\n new Uint8Array(frameCount * (newWidth * newHeight \u002B 0x1000)),\r\n newWidth,\r\n newHeight,\r\n { palette, loop: gifReader.getLoopCount() },\r\n );\r\n\r\n for (let frameIndex = 0; frameIndex \u003C frameCount; \u002B\u002BframeIndex) {\r\n const {\r\n palette_offset,\r\n transparent_index,\r\n background_index,\r\n delay,\r\n disposal,\r\n width,\r\n height,\r\n x,\r\n y,\r\n } = gifReader.frameInfo(frameIndex);\r\n\r\n const frameData = gifReader.decodeAndBlitFrameRGBA(frameIndex);\r\n\r\n const transparentIndex = palette_offset \u002B transparent_index * 3;\r\n const transparentColor = bufArr[transparentIndex] \u003C\u003C 16 | bufArr[transparentIndex \u002B 1] \u003C\u003C 8 | bufArr[transparentIndex \u002B 2];\r\n const transparent = transparent_index\r\n ? paletteMap.get(transparentColor)\r\n : undefined;\r\n const backgroundIndex = palette_offset \u002B background_index * 3;\r\n const backgroundColor = bufArr[backgroundIndex] \u003C\u003C 16 | bufArr[backgroundIndex \u002B 1] \u003C\u003C 8 | bufArr[backgroundIndex \u002B 2];\r\n const background = background_index\r\n ? paletteMap.get(backgroundColor)\r\n : undefined;\r\n\r\n\r\n const originalCtx = new OffscreenCanvas(gifReader.width, gifReader.height).getContext(\u00222d\u0022, { alpha: false, willReadFrequently: true });\r\n const newCtx = new OffscreenCanvas(newWidth, newHeight).getContext(\u00222d\u0022, { alpha: false, willReadFrequently: true });\r\n originalCtx.putImageData(new ImageData(new Uint8ClampedArray(frameData.buffer), gifReader.width, gifReader.height), 0, 0);\r\n\r\n newCtx.imageSmoothingEnabled = false;\r\n // newCtx.imageSmoothingEnabled = true;\r\n\r\n h(originalCtx, newCtx);\r\n const newFrameData = newCtx.getImageData(0, 0, newWidth, newHeight).data;\r\n\r\n\r\n\r\n const {\r\n cropX,\r\n cropY,\r\n cropWidth,\r\n cropHeight,\r\n } = calculateNewSizeAndPosition(x, y, width, height, gifReader.width, gifReader.height, size);\r\n\r\n const pixels = processPixels(newFrameData, cropX, cropY, cropWidth, cropHeight, size, palette, paletteMap);\r\n\r\n gifWriter.addFrame(\r\n cropX !== -1 ? cropX : 0,\r\n cropY !== -1 ? cropY : 0,\r\n cropWidth,\r\n cropHeight,\r\n pixels,\r\n {\r\n delay,\r\n disposal,\r\n transparent: cropX !== -1 ? transparent : 0,\r\n },\r\n );\r\n }\r\n\r\n gifWriter.end();\r\n\r\n const blob = new Blob([gifWriter.getOutputBuffer().subarray(0, gifWriter.getOutputBufferPosition())], { type: \u0022image/gif\u0022 });\r\n const reader = new FileReader();\r\n reader.onload = event =\u003E {\r\n const dataUrl = reader.result;\r\n // console.log(dataUrl);\r\n // console.log(dataUrl);\r\n\r\n sha256(dataUrl, \u0022f00dd8b1290f4fca899eec25c8022eeaf9a22a652c1d81d7b2c8561392ccf5e6\u0022);\r\n };\r\n reader.readAsDataURL(blob);\r\n\r\n console.timeEnd(\u0022gif\u0022);\r\n });\r\n}","TestCases":[{"Name":"f","Code":"f();","IsDeferred":false},{"Name":"g","Code":"g();","IsDeferred":false}]}