1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/canvas/test/webgl-conformance/conformance/resources/pnglib.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,207 @@ 1.4 +/** 1.5 +* A handy class to calculate color values. 1.6 +* 1.7 +* @version 1.0 1.8 +* @author Robert Eisele <robert@xarg.org> 1.9 +* @copyright Copyright (c) 2010, Robert Eisele 1.10 +* @link http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/ 1.11 +* @license http://www.opensource.org/licenses/bsd-license.php BSD License 1.12 +* 1.13 +*/ 1.14 + 1.15 +(function() { 1.16 + 1.17 + // helper functions for that ctx 1.18 + function write(buffer, offs) { 1.19 + for (var i = 2; i < arguments.length; i++) { 1.20 + for (var j = 0; j < arguments[i].length; j++) { 1.21 + buffer[offs++] = arguments[i].charAt(j); 1.22 + } 1.23 + } 1.24 + } 1.25 + 1.26 + function byte2(w) { 1.27 + return String.fromCharCode((w >> 8) & 255, w & 255); 1.28 + } 1.29 + 1.30 + function byte4(w) { 1.31 + return String.fromCharCode((w >> 24) & 255, (w >> 16) & 255, (w >> 8) & 255, w & 255); 1.32 + } 1.33 + 1.34 + function byte2lsb(w) { 1.35 + return String.fromCharCode(w & 255, (w >> 8) & 255); 1.36 + } 1.37 + 1.38 + window.PNGlib = function(width,height,depth) { 1.39 + 1.40 + this.width = width; 1.41 + this.height = height; 1.42 + this.depth = depth; 1.43 + 1.44 + // pixel data and row filter identifier size 1.45 + this.pix_size = height * (width + 1); 1.46 + 1.47 + // deflate header, pix_size, block headers, adler32 checksum 1.48 + this.data_size = 2 + this.pix_size + 5 * Math.floor((0xfffe + this.pix_size) / 0xffff) + 4; 1.49 + 1.50 + // offsets and sizes of Png chunks 1.51 + this.ihdr_offs = 0; // IHDR offset and size 1.52 + this.ihdr_size = 4 + 4 + 13 + 4; 1.53 + this.plte_offs = this.ihdr_offs + this.ihdr_size; // PLTE offset and size 1.54 + this.plte_size = 4 + 4 + 3 * depth + 4; 1.55 + this.trns_offs = this.plte_offs + this.plte_size; // tRNS offset and size 1.56 + this.trns_size = 4 + 4 + depth + 4; 1.57 + this.idat_offs = this.trns_offs + this.trns_size; // IDAT offset and size 1.58 + this.idat_size = 4 + 4 + this.data_size + 4; 1.59 + this.iend_offs = this.idat_offs + this.idat_size; // IEND offset and size 1.60 + this.iend_size = 4 + 4 + 4; 1.61 + this.buffer_size = this.iend_offs + this.iend_size; // total PNG size 1.62 + 1.63 + this.buffer = new Array(); 1.64 + this.palette = new Object(); 1.65 + this.pindex = 0; 1.66 + 1.67 + var _crc32 = new Array(); 1.68 + 1.69 + // initialize buffer with zero bytes 1.70 + for (var i = 0; i < this.buffer_size; i++) { 1.71 + this.buffer[i] = "\x00"; 1.72 + } 1.73 + 1.74 + // initialize non-zero elements 1.75 + write(this.buffer, this.ihdr_offs, byte4(this.ihdr_size - 12), 'IHDR', byte4(width), byte4(height), "\x08\x03"); 1.76 + write(this.buffer, this.plte_offs, byte4(this.plte_size - 12), 'PLTE'); 1.77 + write(this.buffer, this.trns_offs, byte4(this.trns_size - 12), 'tRNS'); 1.78 + write(this.buffer, this.idat_offs, byte4(this.idat_size - 12), 'IDAT'); 1.79 + write(this.buffer, this.iend_offs, byte4(this.iend_size - 12), 'IEND'); 1.80 + 1.81 + // initialize deflate header 1.82 + var header = ((8 + (7 << 4)) << 8) | (3 << 6); 1.83 + header+= 31 - (header % 31); 1.84 + 1.85 + write(this.buffer, this.idat_offs + 8, byte2(header)); 1.86 + 1.87 + // initialize deflate block headers 1.88 + for (var i = 0; (i << 16) - 1 < this.pix_size; i++) { 1.89 + var size, bits; 1.90 + if (i + 0xffff < this.pix_size) { 1.91 + size = 0xffff; 1.92 + bits = "\x00"; 1.93 + } else { 1.94 + size = this.pix_size - (i << 16) - i; 1.95 + bits = "\x01"; 1.96 + } 1.97 + write(this.buffer, this.idat_offs + 8 + 2 + (i << 16) + (i << 2), bits, byte2lsb(size), byte2lsb(~size)); 1.98 + } 1.99 + 1.100 + /* Create crc32 lookup table */ 1.101 + for (var i = 0; i < 256; i++) { 1.102 + var c = i; 1.103 + for (var j = 0; j < 8; j++) { 1.104 + if (c & 1) { 1.105 + c = -306674912 ^ ((c >> 1) & 0x7fffffff); 1.106 + } else { 1.107 + c = (c >> 1) & 0x7fffffff; 1.108 + } 1.109 + } 1.110 + _crc32[i] = c; 1.111 + } 1.112 + 1.113 + // compute the index into a png for a given pixel 1.114 + this.index = function(x,y) { 1.115 + var i = y * (this.width + 1) + x + 1; 1.116 + var j = this.idat_offs + 8 + 2 + 5 * Math.floor((i / 0xffff) + 1) + i; 1.117 + return j; 1.118 + } 1.119 + 1.120 + // convert a color and build up the palette 1.121 + this.color = function(red, green, blue, alpha) { 1.122 + 1.123 + alpha = alpha >= 0 ? alpha : 255; 1.124 + var color = (((((alpha << 8) | red) << 8) | green) << 8) | blue; 1.125 + 1.126 + if (typeof this.palette[color] == "undefined") { 1.127 + if (this.pindex == this.depth) return "\x00"; 1.128 + 1.129 + var ndx = this.plte_offs + 8 + 3 * this.pindex; 1.130 + 1.131 + this.buffer[ndx + 0] = String.fromCharCode(red); 1.132 + this.buffer[ndx + 1] = String.fromCharCode(green); 1.133 + this.buffer[ndx + 2] = String.fromCharCode(blue); 1.134 + this.buffer[this.trns_offs+8+this.pindex] = String.fromCharCode(alpha); 1.135 + 1.136 + this.palette[color] = String.fromCharCode(this.pindex++); 1.137 + } 1.138 + return this.palette[color]; 1.139 + } 1.140 + 1.141 + // output a PNG string, Base64 encoded 1.142 + this.getBase64 = function() { 1.143 + 1.144 + var s = this.getDump(); 1.145 + 1.146 + var ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 1.147 + var c1, c2, c3, e1, e2, e3, e4; 1.148 + var l = s.length; 1.149 + var i = 0; 1.150 + var r = ""; 1.151 + 1.152 + do { 1.153 + c1 = s.charCodeAt(i); 1.154 + e1 = c1 >> 2; 1.155 + c2 = s.charCodeAt(i+1); 1.156 + e2 = ((c1 & 3) << 4) | (c2 >> 4); 1.157 + c3 = s.charCodeAt(i+2); 1.158 + if (l < i+2) { e3 = 64; } else { e3 = ((c2 & 0xf) << 2) | (c3 >> 6); } 1.159 + if (l < i+3) { e4 = 64; } else { e4 = c3 & 0x3f; } 1.160 + r+= ch.charAt(e1) + ch.charAt(e2) + ch.charAt(e3) + ch.charAt(e4); 1.161 + } while ((i+= 3) < l); 1.162 + return r; 1.163 + } 1.164 + 1.165 + // output a PNG string 1.166 + this.getDump = function() { 1.167 + 1.168 + // compute adler32 of output pixels + row filter bytes 1.169 + var BASE = 65521; /* largest prime smaller than 65536 */ 1.170 + var NMAX = 5552; /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ 1.171 + var s1 = 1; 1.172 + var s2 = 0; 1.173 + var n = NMAX; 1.174 + 1.175 + for (var y = 0; y < this.height; y++) { 1.176 + for (var x = -1; x < this.width; x++) { 1.177 + s1+= this.buffer[this.index(x, y)].charCodeAt(0); 1.178 + s2+= s1; 1.179 + if ((n-= 1) == 0) { 1.180 + s1%= BASE; 1.181 + s2%= BASE; 1.182 + n = NMAX; 1.183 + } 1.184 + } 1.185 + } 1.186 + s1%= BASE; 1.187 + s2%= BASE; 1.188 + write(this.buffer, this.idat_offs + this.idat_size - 8, byte4((s2 << 16) | s1)); 1.189 + 1.190 + // compute crc32 of the PNG chunks 1.191 + function crc32(png, offs, size) { 1.192 + var crc = -1; 1.193 + for (var i = 4; i < size-4; i += 1) { 1.194 + crc = _crc32[(crc ^ png[offs+i].charCodeAt(0)) & 0xff] ^ ((crc >> 8) & 0x00ffffff); 1.195 + } 1.196 + write(png, offs+size-4, byte4(crc ^ -1)); 1.197 + } 1.198 + 1.199 + crc32(this.buffer, this.ihdr_offs, this.ihdr_size); 1.200 + crc32(this.buffer, this.plte_offs, this.plte_size); 1.201 + crc32(this.buffer, this.trns_offs, this.trns_size); 1.202 + crc32(this.buffer, this.idat_offs, this.idat_size); 1.203 + crc32(this.buffer, this.iend_offs, this.iend_size); 1.204 + 1.205 + // convert PNG to string 1.206 + return "\211PNG\r\n\032\n"+this.buffer.join(''); 1.207 + } 1.208 + } 1.209 + 1.210 +})();