aboutsummaryrefslogtreecommitdiff
path: root/tools/crunch-worker.js
blob: 5c48d009ac0b9cf65ee28b40bdf0ddc5c9268ea6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// From Brandon Jones' awesome WebGL texture utils,
// https://github.com/toji/webgl-texture-utils
// which in turn based off of Evan Parker's cool work,
// http://www-cs-students.stanford.edu/~eparker/files/crunch/decode_test.html
//
// This combines crunch-worker.js and crn_decomp.js. Minor changes
// to make it work that way, and to return all levels in one array

    /*
     * Copyright (c) 2012 Brandon Jones
     *
     * This software is provided 'as-is', without any express or implied
     * warranty. In no event will the authors be held liable for any damages
     * arising from the use of this software.
     *
     * Permission is granted to anyone to use this software for any purpose,
     * including commercial applications, and to alter it and redistribute it
     * freely, subject to the following restrictions:
     *
     *    1. The origin of this software must not be misrepresented; you must not
     *    claim that you wrote the original software. If you use this software
     *    in a product, an acknowledgment in the product documentation would be
     *    appreciated but is not required.
     *
     *    2. Altered source versions must be plainly marked as such, and must not
     *    be misrepresented as being the original software.
     *
     *    3. This notice may not be removed or altered from any source
     *    distribution.
     */

    // Taken from crnlib.h
    var cCRNFmtInvalid = -1;

    var cCRNFmtDXT1 = 0;
    var cCRNFmtDXT3 = 1;
    var cCRNFmtDXT5 = 2;

    // Various DXT5 derivatives
    var cCRNFmtDXT5_CCxY = 3;    // Luma-chroma
    var cCRNFmtDXT5_xGxR = 4;    // Swizzled 2-component
    var cCRNFmtDXT5_xGBR = 5;    // Swizzled 3-component
    var cCRNFmtDXT5_AGBR = 6;    // Swizzled 4-component

    // ATI 3DC and X360 DXN
    var cCRNFmtDXN_XY = 7;
    var cCRNFmtDXN_YX = 8;

    // DXT5 alpha blocks only
    var cCRNFmtDXT5A = 9;

    function arrayBufferCopy(src, dst, dstByteOffset, numBytes) {
        dst.set(src.subarray(0, numBytes), dstByteOffset);
    }

    function deCrunch(bytes, filename) {
        var srcSize = bytes.length;
        var src = Module._malloc(srcSize),
            format, internalFormat, dst, dstSize,
            width, height, levels, dxtData, rgb565Data, i;
        
        arrayBufferCopy(bytes, Module.HEAPU8, src, srcSize);

        format = Module._crn_get_dxt_format(src, srcSize);
        
        if(format != cCRNFmtDXT1 && format != cCRNFmtDXT3 && format != cCRNFmtDXT5) {
            throw "Unsupported image format " + format + " for " + filename;
        }
        width = Module._crn_get_width(src, srcSize);
        height = Module._crn_get_height(src, srcSize);
        levels = Module._crn_get_levels(src, srcSize);
        dstSize = Module._crn_get_uncompressed_size(src, srcSize, 0);
        dst = Module._malloc(dstSize);

        var totalSize = 0;
        var bytesPerPixel = format == cCRNFmtDXT1 ? 0.5 : 1;
        for(i = 0; i < levels; ++i) {
            totalSize += width * height * bytesPerPixel;
            width *= 0.5;
            height *= 0.5;
            width = Math.max(width, 4);
            height = Math.max(height, 4);
        }

        width = Module._crn_get_width(src, srcSize);
        height = Module._crn_get_height(src, srcSize);

        var ret = new Uint8Array(totalSize);
        var retIndex = 0;

        for(i = 0; i < levels; ++i) {
            if(i) {
                dstSize = Module._crn_get_uncompressed_size(src, srcSize, i);
            }
            Module._crn_decompress(src, srcSize, dst, dstSize, i);
            ret.set(Module.HEAPU8.subarray(dst, dst+dstSize), retIndex);
            retIndex += dstSize;

            width *= 0.5;
            height *= 0.5;
        }
        
        Module._free(src);
        Module._free(dst);

        return ret;
    }

    //===
function a(b){throw b}var aa=void 0,l=!0,pa=null,n=!1,za=[],Da="object"===typeof process,Ea="object"===typeof window,Fa="function"===typeof importScripts,Ja=!Ea&&!Da&&!Fa;if(Da){print=(function(b){process.stdout.write(b+"\n")});printErr=(function(b){process.stderr.write(b+"\n")});var Ma=require("fs");read=(function(b){var c=Ma.readFileSync(b).toString();!c&&"/"!=b[0]&&(b=__dirname.split("/").slice(0,-1).join("/")+"/src/"+b,c=Ma.readFileSync(b).toString());return c});load=(function(b){Na(read(b))});za=process.argv.slice(2)}else{Ja?(this.read||(this.read=(function(b){snarf(b)})),"undefined"!=typeof scriptArgs?za=scriptArgs:"undefined"!=typeof arguments&&(za=arguments)):Ea?(this.print=printErr=(function(b){console.log(b)}),this.read=(function(b){var c=new XMLHttpRequest;c.open("GET",b,n);c.send(pa);return c.responseText}),this.arguments&&(za=arguments)):Fa?this.load=importScripts:a("Unknown runtime environment. Where are we?")}function Na(b){eval.call(pa,b)}"undefined"==typeof load&&"undefined"!=typeof read&&(this.load=(function(b){Na(read(b))}));"undefined"===typeof printErr&&(this.printErr=(function(){}));"undefined"===typeof print&&(this.print=printErr);try{this.Module=Module}catch(Qa){this.Module=Module={}}Module.arguments||(Module.arguments=za);Module.print&&(print=Module.print);function Wa(b){if(Xa==1){return 1}var c={"%i1":1,"%i8":1,"%i16":2,"%i32":4,"%i64":8,"%float":4,"%double":8}["%"+b];if(!c){if(b[b.length-1]=="*"){c=Xa}else{if(b[0]=="i"){b=parseInt(b.substr(1));Ya(b%8==0);c=b/8}}}return c}function cb(b){var c=q;q=q+b;q=q+3>>2<<2;return c}function db(b){var c=eb;eb=eb+b;eb=eb+3>>2<<2;if(eb>=fb){for(;fb<=eb;){fb=2*fb+4095>>12<<12}var b=v,d=new ArrayBuffer(fb);v=new Int8Array(d);gb=new Int16Array(d);y=new Int32Array(d);z=new Uint8Array(d);A=new Uint16Array(d);C=new Uint32Array(d);lb=new Float32Array(d);mb=new Float64Array(d);v.set(b)}return c}var Xa=4,ub={},vb;function wb(b){print(b+":\n"+Error().stack);a("Assertion: "+b)}function Ya(b,c){b||wb("Assertion failed: "+c)}var Mb=this;Module.ccall=(function(b,c,d,e){try{var g=eval("_"+b)}catch(h){try{g=Mb.Module["_"+b]}catch(j){}}Ya(g,"Cannot call unknown function "+b+" (perhaps LLVM optimizations or closure removed it?)");var i=0,b=e?e.map((function(b){if(d[i++]=="string"){var c=q;cb(b.length+1);Nb(b,c);b=c}return b})):[];return(function(b,c){return c=="string"?Vb(b):b})(g.apply(pa,b),c)});function Wb(b,c,d){d=d||"i8";d[d.length-1]==="*"&&(d="i32");switch(d){case"i1":v[b]=c;break;case"i8":v[b]=c;break;case"i16":gb[b>>1]=c;break;case"i32":y[b>>2]=c;break;case"i64":y[b>>2]=c;break;case"float":lb[b>>2]=c;break;case"double":Yb[0]=c;y[b>>2]=Zb[0];y[b+4>>2]=Zb[1];break;default:wb("invalid type for setValue: "+d)}}Module.setValue=Wb;Module.getValue=(function(b,c){c=c||"i8";c[c.length-1]==="*"&&(c="i32");switch(c){case"i1":return v[b];case"i8":return v[b];case"i16":return gb[b>>1];case"i32":return y[b>>2];case"i64":return y[b>>2];case"float":return lb[b>>2];case"double":return Zb[0]=y[b>>2],Zb[1]=y[b+4>>2],Yb[0];default:wb("invalid type for setValue: "+c)}return pa});var $b=1,D=2;Module.ALLOC_NORMAL=0;Module.ALLOC_STACK=$b;Module.ALLOC_STATIC=D;function