Showing
7 changed files
with
8 additions
and
243 deletions
This diff is collapsed. Click to expand it.
| ... | @@ -19,6 +19,8 @@ | ... | @@ -19,6 +19,8 @@ |
| 19 | "webpack-cli": "^4.6.0" | 19 | "webpack-cli": "^4.6.0" |
| 20 | }, | 20 | }, |
| 21 | "dependencies": { | 21 | "dependencies": { |
| 22 | - "@babel/plugin-proposal-class-properties": "^7.13.0" | 22 | + "@babel/plugin-proposal-class-properties": "^7.13.0", |
| 23 | + "gifencoder": "^2.0.1", | ||
| 24 | + "stream": "0.0.2" | ||
| 23 | } | 25 | } |
| 24 | } | 26 | } | ... | ... |
| 1 | -import GIF from "./lib/GIFEncoder"; | 1 | +import GIF from "gifencoder"; |
| 2 | 2 | ||
| 3 | class GifGenerator { | 3 | class GifGenerator { |
| 4 | constructor(canvas) { | 4 | constructor(canvas) { |
| ... | @@ -7,32 +7,22 @@ class GifGenerator { | ... | @@ -7,32 +7,22 @@ class GifGenerator { |
| 7 | this.height = canvas.getHeight(); | 7 | this.height = canvas.getHeight(); |
| 8 | this.gif = new GIF(this.width, this.height); | 8 | this.gif = new GIF(this.width, this.height); |
| 9 | 9 | ||
| 10 | - this.gif.writeHeader(); | 10 | + this.gif.start(); |
| 11 | this.gif.setTransparent(null); | 11 | this.gif.setTransparent(null); |
| 12 | this.gif.setRepeat(0); | 12 | this.gif.setRepeat(0); |
| 13 | this.gif.setQuality(10); | 13 | this.gif.setQuality(10); |
| 14 | - this.gif.setDither(false); | ||
| 15 | - this.gif.setGlobalPalette(false); | ||
| 16 | } | 14 | } |
| 17 | 15 | ||
| 18 | addFrame(delay = 0) { | 16 | addFrame(delay = 0) { |
| 19 | this.gif.setDelay(delay); | 17 | this.gif.setDelay(delay); |
| 20 | - this.gif.addFrame( | 18 | + this.gif.addFrame(this.canvas.getContext()); |
| 21 | - this.canvas.getContext().getImageData(0, 0, this.width, this.height).data | ||
| 22 | - ); | ||
| 23 | } | 19 | } |
| 24 | 20 | ||
| 25 | render() { | 21 | render() { |
| 26 | this.gif.finish(); | 22 | this.gif.finish(); |
| 27 | - const stream = this.gif.stream(); | 23 | + const byte = new Uint8Array(this.gif.out.data); |
| 28 | 24 | ||
| 29 | - let bytes = []; | 25 | + return new Blob([byte], { type: "image/gif" }); |
| 30 | - stream.pages.map((page) => { | ||
| 31 | - bytes = bytes.concat([...page]); | ||
| 32 | - }); | ||
| 33 | - bytes = new Uint8Array(bytes); | ||
| 34 | - | ||
| 35 | - return new Blob([bytes], { type: "image/gif" }); | ||
| 36 | } | 26 | } |
| 37 | } | 27 | } |
| 38 | 28 | ... | ... |
gif-generator/src/lib/GIFEncoder.js
deleted
100644 → 0
This diff is collapsed. Click to expand it.
gif-generator/src/lib/LZWEncoder.js
deleted
100644 → 0
| 1 | -/* | ||
| 2 | - LZWEncoder.js | ||
| 3 | - | ||
| 4 | - Authors | ||
| 5 | - Kevin Weiner (original Java version - kweiner@fmsware.com) | ||
| 6 | - Thibault Imbert (AS3 version - bytearray.org) | ||
| 7 | - Johan Nordberg (JS version - code@johan-nordberg.com) | ||
| 8 | - | ||
| 9 | - Acknowledgements | ||
| 10 | - GIFCOMPR.C - GIF Image compression routines | ||
| 11 | - Lempel-Ziv compression based on 'compress'. GIF modifications by | ||
| 12 | - David Rowley (mgardi@watdcsu.waterloo.edu) | ||
| 13 | - GIF Image compression - modified 'compress' | ||
| 14 | - Based on: compress.c - File compression ala IEEE Computer, June 1984. | ||
| 15 | - By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) | ||
| 16 | - Jim McKie (decvax!mcvax!jim) | ||
| 17 | - Steve Davies (decvax!vax135!petsd!peora!srd) | ||
| 18 | - Ken Turkowski (decvax!decwrl!turtlevax!ken) | ||
| 19 | - James A. Woods (decvax!ihnp4!ames!jaw) | ||
| 20 | - Joe Orost (decvax!vax135!petsd!joe) | ||
| 21 | -*/ | ||
| 22 | - | ||
| 23 | -var EOF = -1; | ||
| 24 | -var BITS = 12; | ||
| 25 | -var HSIZE = 5003; // 80% occupancy | ||
| 26 | -var masks = [ | ||
| 27 | - 0x0000, | ||
| 28 | - 0x0001, | ||
| 29 | - 0x0003, | ||
| 30 | - 0x0007, | ||
| 31 | - 0x000f, | ||
| 32 | - 0x001f, | ||
| 33 | - 0x003f, | ||
| 34 | - 0x007f, | ||
| 35 | - 0x00ff, | ||
| 36 | - 0x01ff, | ||
| 37 | - 0x03ff, | ||
| 38 | - 0x07ff, | ||
| 39 | - 0x0fff, | ||
| 40 | - 0x1fff, | ||
| 41 | - 0x3fff, | ||
| 42 | - 0x7fff, | ||
| 43 | - 0xffff, | ||
| 44 | -]; | ||
| 45 | - | ||
| 46 | -function LZWEncoder(width, height, pixels, colorDepth) { | ||
| 47 | - var initCodeSize = Math.max(2, colorDepth); | ||
| 48 | - | ||
| 49 | - var accum = new Uint8Array(256); | ||
| 50 | - var htab = new Int32Array(HSIZE); | ||
| 51 | - var codetab = new Int32Array(HSIZE); | ||
| 52 | - | ||
| 53 | - var cur_accum, | ||
| 54 | - cur_bits = 0; | ||
| 55 | - var a_count; | ||
| 56 | - var free_ent = 0; // first unused entry | ||
| 57 | - var maxcode; | ||
| 58 | - | ||
| 59 | - // block compression parameters -- after all codes are used up, | ||
| 60 | - // and compression rate changes, start over. | ||
| 61 | - var clear_flg = false; | ||
| 62 | - | ||
| 63 | - // Algorithm: use open addressing double hashing (no chaining) on the | ||
| 64 | - // prefix code / next character combination. We do a variant of Knuth's | ||
| 65 | - // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime | ||
| 66 | - // secondary probe. Here, the modular division first probe is gives way | ||
| 67 | - // to a faster exclusive-or manipulation. Also do block compression with | ||
| 68 | - // an adaptive reset, whereby the code table is cleared when the compression | ||
| 69 | - // ratio decreases, but after the table fills. The variable-length output | ||
| 70 | - // codes are re-sized at this point, and a special CLEAR code is generated | ||
| 71 | - // for the decompressor. Late addition: construct the table according to | ||
| 72 | - // file size for noticeable speed improvement on small files. Please direct | ||
| 73 | - // questions about this implementation to ames!jaw. | ||
| 74 | - var g_init_bits, ClearCode, EOFCode; | ||
| 75 | - | ||
| 76 | - // Add a character to the end of the current packet, and if it is 254 | ||
| 77 | - // characters, flush the packet to disk. | ||
| 78 | - function char_out(c, outs) { | ||
| 79 | - accum[a_count++] = c; | ||
| 80 | - if (a_count >= 254) flush_char(outs); | ||
| 81 | - } | ||
| 82 | - | ||
| 83 | - // Clear out the hash table | ||
| 84 | - // table clear for block compress | ||
| 85 | - function cl_block(outs) { | ||
| 86 | - cl_hash(HSIZE); | ||
| 87 | - free_ent = ClearCode + 2; | ||
| 88 | - clear_flg = true; | ||
| 89 | - output(ClearCode, outs); | ||
| 90 | - } | ||
| 91 | - | ||
| 92 | - // Reset code table | ||
| 93 | - function cl_hash(hsize) { | ||
| 94 | - for (var i = 0; i < hsize; ++i) htab[i] = -1; | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | - function compress(init_bits, outs) { | ||
| 98 | - var fcode, c, i, ent, disp, hsize_reg, hshift; | ||
| 99 | - | ||
| 100 | - // Set up the globals: g_init_bits - initial number of bits | ||
| 101 | - g_init_bits = init_bits; | ||
| 102 | - | ||
| 103 | - // Set up the necessary values | ||
| 104 | - clear_flg = false; | ||
| 105 | - n_bits = g_init_bits; | ||
| 106 | - maxcode = MAXCODE(n_bits); | ||
| 107 | - | ||
| 108 | - ClearCode = 1 << (init_bits - 1); | ||
| 109 | - EOFCode = ClearCode + 1; | ||
| 110 | - free_ent = ClearCode + 2; | ||
| 111 | - | ||
| 112 | - a_count = 0; // clear packet | ||
| 113 | - | ||
| 114 | - ent = nextPixel(); | ||
| 115 | - | ||
| 116 | - hshift = 0; | ||
| 117 | - for (fcode = HSIZE; fcode < 65536; fcode *= 2) ++hshift; | ||
| 118 | - hshift = 8 - hshift; // set hash code range bound | ||
| 119 | - hsize_reg = HSIZE; | ||
| 120 | - cl_hash(hsize_reg); // clear hash table | ||
| 121 | - | ||
| 122 | - output(ClearCode, outs); | ||
| 123 | - | ||
| 124 | - outer_loop: while ((c = nextPixel()) != EOF) { | ||
| 125 | - fcode = (c << BITS) + ent; | ||
| 126 | - i = (c << hshift) ^ ent; // xor hashing | ||
| 127 | - if (htab[i] === fcode) { | ||
| 128 | - ent = codetab[i]; | ||
| 129 | - continue; | ||
| 130 | - } else if (htab[i] >= 0) { | ||
| 131 | - // non-empty slot | ||
| 132 | - disp = hsize_reg - i; // secondary hash (after G. Knott) | ||
| 133 | - if (i === 0) disp = 1; | ||
| 134 | - do { | ||
| 135 | - if ((i -= disp) < 0) i += hsize_reg; | ||
| 136 | - if (htab[i] === fcode) { | ||
| 137 | - ent = codetab[i]; | ||
| 138 | - continue outer_loop; | ||
| 139 | - } | ||
| 140 | - } while (htab[i] >= 0); | ||
| 141 | - } | ||
| 142 | - output(ent, outs); | ||
| 143 | - ent = c; | ||
| 144 | - if (free_ent < 1 << BITS) { | ||
| 145 | - codetab[i] = free_ent++; // code -> hashtable | ||
| 146 | - htab[i] = fcode; | ||
| 147 | - } else { | ||
| 148 | - cl_block(outs); | ||
| 149 | - } | ||
| 150 | - } | ||
| 151 | - | ||
| 152 | - // Put out the final code. | ||
| 153 | - output(ent, outs); | ||
| 154 | - output(EOFCode, outs); | ||
| 155 | - } | ||
| 156 | - | ||
| 157 | - function encode(outs) { | ||
| 158 | - outs.writeByte(initCodeSize); // write "initial code size" byte | ||
| 159 | - remaining = width * height; // reset navigation variables | ||
| 160 | - curPixel = 0; | ||
| 161 | - compress(initCodeSize + 1, outs); // compress and write the pixel data | ||
| 162 | - outs.writeByte(0); // write block terminator | ||
| 163 | - } | ||
| 164 | - | ||
| 165 | - // Flush the packet to disk, and reset the accumulator | ||
| 166 | - function flush_char(outs) { | ||
| 167 | - if (a_count > 0) { | ||
| 168 | - outs.writeByte(a_count); | ||
| 169 | - outs.writeBytes(accum, 0, a_count); | ||
| 170 | - a_count = 0; | ||
| 171 | - } | ||
| 172 | - } | ||
| 173 | - | ||
| 174 | - function MAXCODE(n_bits) { | ||
| 175 | - return (1 << n_bits) - 1; | ||
| 176 | - } | ||
| 177 | - | ||
| 178 | - // Return the next pixel from the image | ||
| 179 | - function nextPixel() { | ||
| 180 | - if (remaining === 0) return EOF; | ||
| 181 | - --remaining; | ||
| 182 | - var pix = pixels[curPixel++]; | ||
| 183 | - return pix & 0xff; | ||
| 184 | - } | ||
| 185 | - | ||
| 186 | - function output(code, outs) { | ||
| 187 | - cur_accum &= masks[cur_bits]; | ||
| 188 | - | ||
| 189 | - if (cur_bits > 0) cur_accum |= code << cur_bits; | ||
| 190 | - else cur_accum = code; | ||
| 191 | - | ||
| 192 | - cur_bits += n_bits; | ||
| 193 | - | ||
| 194 | - while (cur_bits >= 8) { | ||
| 195 | - char_out(cur_accum & 0xff, outs); | ||
| 196 | - cur_accum >>= 8; | ||
| 197 | - cur_bits -= 8; | ||
| 198 | - } | ||
| 199 | - | ||
| 200 | - // If the next entry is going to be too big for the code size, | ||
| 201 | - // then increase it, if possible. | ||
| 202 | - if (free_ent > maxcode || clear_flg) { | ||
| 203 | - if (clear_flg) { | ||
| 204 | - maxcode = MAXCODE((n_bits = g_init_bits)); | ||
| 205 | - clear_flg = false; | ||
| 206 | - } else { | ||
| 207 | - ++n_bits; | ||
| 208 | - if (n_bits == BITS) maxcode = 1 << BITS; | ||
| 209 | - else maxcode = MAXCODE(n_bits); | ||
| 210 | - } | ||
| 211 | - } | ||
| 212 | - | ||
| 213 | - if (code == EOFCode) { | ||
| 214 | - // At EOF, write the rest of the buffer. | ||
| 215 | - while (cur_bits > 0) { | ||
| 216 | - char_out(cur_accum & 0xff, outs); | ||
| 217 | - cur_accum >>= 8; | ||
| 218 | - cur_bits -= 8; | ||
| 219 | - } | ||
| 220 | - flush_char(outs); | ||
| 221 | - } | ||
| 222 | - } | ||
| 223 | - | ||
| 224 | - this.encode = encode; | ||
| 225 | -} | ||
| 226 | - | ||
| 227 | -module.exports = LZWEncoder; |
gif-generator/src/lib/NeuQuant.js
deleted
100644 → 0
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment