lzw-encoder

LZWEncoder from jsgif

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/428485/1028790/lzw-encoder.js

  1. /**
  2. * This class handles LZW encoding
  3. * Adapted from Jef Poskanzer's Java port by way of J. M. G. Elliott.
  4. * @author Kevin Weiner (original Java version - kweiner@fmsware.com)
  5. * @author Thibault Imbert (AS3 version - bytearray.org)
  6. * @author Kevin Kwok (JavaScript version - https://github.com/antimatter15/jsgif)
  7. * @version 0.1 AS3 implementation
  8. */
  9.  
  10. LZWEncoder = function() {
  11.  
  12. var exports = {};
  13. var EOF = -1;
  14. var imgW;
  15. var imgH;
  16. var pixAry;
  17. var initCodeSize;
  18. var remaining;
  19. var curPixel;
  20.  
  21. // GIFCOMPR.C - GIF Image compression routines
  22. // Lempel-Ziv compression based on 'compress'. GIF modifications by
  23. // David Rowley (mgardi@watdcsu.waterloo.edu)
  24. // General DEFINEs
  25.  
  26. var BITS = 12;
  27. var HSIZE = 5003; // 80% occupancy
  28.  
  29. // GIF Image compression - modified 'compress'
  30. // Based on: compress.c - File compression ala IEEE Computer, June 1984.
  31. // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
  32. // Jim McKie (decvax!mcvax!jim)
  33. // Steve Davies (decvax!vax135!petsd!peora!srd)
  34. // Ken Turkowski (decvax!decwrl!turtlevax!ken)
  35. // James A. Woods (decvax!ihnp4!ames!jaw)
  36. // Joe Orost (decvax!vax135!petsd!joe)
  37.  
  38. var n_bits; // number of bits/code
  39. var maxbits = BITS; // user settable max # bits/code
  40. var maxcode; // maximum code, given n_bits
  41. var maxmaxcode = 1 << BITS; // should NEVER generate this code
  42. var htab = [];
  43. var codetab = [];
  44. var hsize = HSIZE; // for dynamic table sizing
  45. var free_ent = 0; // first unused entry
  46.  
  47. // block compression parameters -- after all codes are used up,
  48. // and compression rate changes, start over.
  49.  
  50. var clear_flg = false;
  51.  
  52. // Algorithm: use open addressing double hashing (no chaining) on the
  53. // prefix code / next character combination. We do a variant of Knuth's
  54. // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  55. // secondary probe. Here, the modular division first probe is gives way
  56. // to a faster exclusive-or manipulation. Also do block compression with
  57. // an adaptive reset, whereby the code table is cleared when the compression
  58. // ratio decreases, but after the table fills. The variable-length output
  59. // codes are re-sized at this point, and a special CLEAR code is generated
  60. // for the decompressor. Late addition: construct the table according to
  61. // file size for noticeable speed improvement on small files. Please direct
  62. // questions about this implementation to ames!jaw.
  63.  
  64. var g_init_bits;
  65. var ClearCode;
  66. var EOFCode;
  67.  
  68. // output
  69. // Output the given code.
  70. // Inputs:
  71. // code: A n_bits-bit integer. If == -1, then EOF. This assumes
  72. // that n_bits =< wordsize - 1.
  73. // Outputs:
  74. // Outputs code to the file.
  75. // Assumptions:
  76. // Chars are 8 bits long.
  77. // Algorithm:
  78. // Maintain a BITS character long buffer (so that 8 codes will
  79. // fit in it exactly). Use the VAX insv instruction to insert each
  80. // code in turn. When the buffer fills up empty it and start over.
  81.  
  82. var cur_accum = 0;
  83. var cur_bits = 0;
  84. var masks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF];
  85.  
  86. // Number of characters so far in this 'packet'
  87. var a_count;
  88.  
  89. // Define the storage for the packet accumulator
  90. var accum = [];
  91.  
  92. var LZWEncoder = exports.LZWEncoder = function LZWEncoder(width, height, pixels, color_depth) {
  93. imgW = width;
  94. imgH = height;
  95. pixAry = pixels;
  96. initCodeSize = Math.max(2, color_depth);
  97. };
  98.  
  99. // Add a character to the end of the current packet, and if it is 254
  100. // characters, flush the packet to disk.
  101. var char_out = function char_out(c, outs) {
  102. accum[a_count++] = c;
  103. if (a_count >= 254) flush_char(outs);
  104. };
  105.  
  106. // Clear out the hash table
  107. // table clear for block compress
  108.  
  109. var cl_block = function cl_block(outs) {
  110. cl_hash(hsize);
  111. free_ent = ClearCode + 2;
  112. clear_flg = true;
  113. output(ClearCode, outs);
  114. };
  115.  
  116. // reset code table
  117. var cl_hash = function cl_hash(hsize) {
  118. for (var i = 0; i < hsize; ++i) htab[i] = -1;
  119. };
  120.  
  121. var compress = exports.compress = function compress(init_bits, outs) {
  122.  
  123. var fcode;
  124. var i; /* = 0 */
  125. var c;
  126. var ent;
  127. var disp;
  128. var hsize_reg;
  129. var hshift;
  130.  
  131. // Set up the globals: g_init_bits - initial number of bits
  132. g_init_bits = init_bits;
  133.  
  134. // Set up the necessary values
  135. clear_flg = false;
  136. n_bits = g_init_bits;
  137. maxcode = MAXCODE(n_bits);
  138.  
  139. ClearCode = 1 << (init_bits - 1);
  140. EOFCode = ClearCode + 1;
  141. free_ent = ClearCode + 2;
  142.  
  143. a_count = 0; // clear packet
  144.  
  145. ent = nextPixel();
  146.  
  147. hshift = 0;
  148. for (fcode = hsize; fcode < 65536; fcode *= 2)
  149. ++hshift;
  150. hshift = 8 - hshift; // set hash code range bound
  151.  
  152. hsize_reg = hsize;
  153. cl_hash(hsize_reg); // clear hash table
  154.  
  155. output(ClearCode, outs);
  156.  
  157. outer_loop: while ((c = nextPixel()) != EOF) {
  158. fcode = (c << maxbits) + ent;
  159. i = (c << hshift) ^ ent; // xor hashing
  160.  
  161. if (htab[i] == fcode) {
  162. ent = codetab[i];
  163. continue;
  164. }
  165.  
  166. else if (htab[i] >= 0) { // non-empty slot
  167.  
  168. disp = hsize_reg - i; // secondary hash (after G. Knott)
  169. if (i === 0) disp = 1;
  170.  
  171. do {
  172. if ((i -= disp) < 0)
  173. i += hsize_reg;
  174.  
  175. if (htab[i] == fcode) {
  176. ent = codetab[i];
  177. continue outer_loop;
  178. }
  179. } while (htab[i] >= 0);
  180. }
  181.  
  182. output(ent, outs);
  183. ent = c;
  184. if (free_ent < maxmaxcode) {
  185. codetab[i] = free_ent++; // code -> hashtable
  186. htab[i] = fcode;
  187. }
  188. else cl_block(outs);
  189. }
  190.  
  191. // Put out the final code.
  192. output(ent, outs);
  193. output(EOFCode, outs);
  194. };
  195.  
  196. // ----------------------------------------------------------------------------
  197. var encode = exports.encode = function encode(os) {
  198. os.writeByte(initCodeSize); // write "initial code size" byte
  199. remaining = imgW * imgH; // reset navigation variables
  200. curPixel = 0;
  201. compress(initCodeSize + 1, os); // compress and write the pixel data
  202. os.writeByte(0); // write block terminator
  203. };
  204.  
  205. // Flush the packet to disk, and reset the accumulator
  206. var flush_char = function flush_char(outs) {
  207. if (a_count > 0) {
  208. outs.writeByte(a_count);
  209. outs.writeBytes(accum, 0, a_count);
  210. a_count = 0;
  211. }
  212. };
  213.  
  214. var MAXCODE = function MAXCODE(n_bits) {
  215. return (1 << n_bits) - 1;
  216. };
  217.  
  218. // ----------------------------------------------------------------------------
  219. // Return the next pixel from the image
  220. // ----------------------------------------------------------------------------
  221.  
  222. var nextPixel = function nextPixel() {
  223. if (remaining === 0) return EOF;
  224. --remaining;
  225. var pix = pixAry[curPixel++];
  226. return pix & 0xff;
  227. };
  228.  
  229. var output = function output(code, outs) {
  230.  
  231. cur_accum &= masks[cur_bits];
  232.  
  233. if (cur_bits > 0) cur_accum |= (code << cur_bits);
  234. else cur_accum = code;
  235.  
  236. cur_bits += n_bits;
  237.  
  238. while (cur_bits >= 8) {
  239. char_out((cur_accum & 0xff), outs);
  240. cur_accum >>= 8;
  241. cur_bits -= 8;
  242. }
  243.  
  244. // If the next entry is going to be too big for the code size,
  245. // then increase it, if possible.
  246.  
  247. if (free_ent > maxcode || clear_flg) {
  248.  
  249. if (clear_flg) {
  250.  
  251. maxcode = MAXCODE(n_bits = g_init_bits);
  252. clear_flg = false;
  253.  
  254. } else {
  255.  
  256. ++n_bits;
  257. if (n_bits == maxbits) maxcode = maxmaxcode;
  258. else maxcode = MAXCODE(n_bits);
  259. }
  260. }
  261.  
  262. if (code == EOFCode) {
  263.  
  264. // At EOF, write the rest of the buffer.
  265. while (cur_bits > 0) {
  266. char_out((cur_accum & 0xff), outs);
  267. cur_accum >>= 8;
  268. cur_bits -= 8;
  269. }
  270.  
  271. flush_char(outs);
  272. }
  273. };
  274.  
  275. LZWEncoder.apply(this, arguments);
  276. return exports;
  277. };

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址