├── .gitignore ├── .gitmodules ├── README.md ├── bower.json ├── dist ├── jpx.js └── jpx.min.js ├── gruntfile.js ├── package.json ├── src └── index.html └── test ├── data ├── 000000.dcm ├── 000000.raw ├── 860AE501.dcm ├── 860AE501.dcm.jp2 ├── 860AE501.dcm.raw ├── cameraman.10.jp2 ├── cameraman.10.raw ├── cameraman.lossless.jp2 ├── cameraman.lossless.raw ├── lossyhdr.dcm ├── lossyhdr.dcm.jp2 ├── lossyhdr.dcm.raw ├── navimage.jp2 ├── navimage.raw ├── peppers.10.jp2 ├── peppers.10.raw ├── peppers.lossless.jp2 ├── peppers.lossless.raw ├── saturn.jpc ├── saturn.raw ├── subsampling_1.jp2 ├── subsampling_1.raw ├── subsampling_2.jp2 ├── subsampling_2.raw ├── unexpectedEOF.jp2 └── unexpectedEOF.raw ├── dcm_test.js ├── imcompare.m ├── img2raw.m ├── jp2_16bit_test.js ├── jp2_U16bit_test.js ├── jp2_test.js └── jpc_test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | test/out_* 3 | dist/ 4 | !dist/jpx.js 5 | !dist/jpx.min.js 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/pdf.js"] 2 | path = ext/pdf.js 3 | url = https://github.com/OHIF/pdf.js.git 4 | branch = jpx-medical 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # image-JPEG2000 2 | 3 | Support repository for a fork of Mozilla's PDF.js that adds support for 16 bit signed grayscale JPEG2000 images. 4 | 5 | ## Build 6 | 7 | ``` 8 | git submodule init 9 | git submodule update 10 | npm install 11 | grunt 12 | ``` 13 | 14 | ## Usage 15 | 16 | See src/index.html 17 | 18 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "image-jpeg2000", 3 | "version": "0.3.1", 4 | "authors": [ 5 | "Jean-Francois Pambrun " 6 | ], 7 | "description": "JPEG2000 decoder suitable for medical images inspired by mozilla's PDF.js.", 8 | "main": "dist/jpx.js", 9 | "keywords": [ 10 | "JPEG2000", 11 | "Medical", 12 | "Imaging" 13 | ], 14 | "license": "Apache Version 2", 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /dist/jpx.min.js: -------------------------------------------------------------------------------- 1 | /*! image-JPEG2000 - v0.3.1 - 2015-08-26 | https://github.com/OHIF/image-JPEG2000 */ 2 | "use strict";function info(a){PDFJS.verbosity>=PDFJS.VERBOSITY_LEVELS.infos&&console.log("Info: "+a)}function warn(a){PDFJS.verbosity>=PDFJS.VERBOSITY_LEVELS.warnings&&console.log("Warning: "+a)}function error(a){if(arguments.length>1){var b=["Error:"];b.push.apply(b,arguments),console.log.apply(console,b),a=[].join.call(arguments," ")}else console.log("Error: "+a);throw console.log(backtrace()),UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown),new Error(a)}function backtrace(){try{throw new Error}catch(a){return a.stack?a.stack.split("\n").slice(2).join("\n"):""}}function assert(a,b){a||error(b)}function combineUrl(a,b){if(!b)return a;if(/^[a-z][a-z0-9+\-.]*:/i.test(b))return b;var c;if("/"===b.charAt(0))return c=a.indexOf("://"),"/"===b.charAt(1)?++c:c=a.indexOf("/",c+3),a.substring(0,c)+b;var d=a.length;c=a.lastIndexOf("#"),d=c>=0?c:d,c=a.lastIndexOf("?",d),d=c>=0?c:d;var e=a.lastIndexOf("/",d);return a.substring(0,e+1)+b}function isValidUrl(a,b){if(!a)return!1;var c=/^[a-z][a-z0-9+\-.]*(?=:)/i.exec(a);if(!c)return b;switch(c=c[0].toLowerCase()){case"http":case"https":case"ftp":case"mailto":case"tel":return!0;default:return!1}}function shadow(a,b,c){return Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!1}),c}function bytesToString(a){assert(null!==a&&"object"==typeof a&&void 0!==a.length,"Invalid argument for bytesToString");var b=a.length,c=8192;if(c>b)return String.fromCharCode.apply(null,a);for(var d=[],e=0;b>e;e+=c){var f=Math.min(e+c,b),g=a.subarray(e,f);d.push(String.fromCharCode.apply(null,g))}return d.join("")}function stringToBytes(a){assert("string"==typeof a,"Invalid argument for stringToBytes");for(var b=a.length,c=new Uint8Array(b),d=0;b>d;++d)c[d]=255&a.charCodeAt(d);return c}function string32(a){return String.fromCharCode(a>>24&255,a>>16&255,a>>8&255,255&a)}function log2(a){for(var b=1,c=0;a>b;)b<<=1,c++;return c}function readInt8(a,b){return a[b]<<24>>24}function readUint16(a,b){return a[b]<<8|a[b+1]}function readUint32(a,b){return(a[b]<<24|a[b+1]<<16|a[b+2]<<8|a[b+3])>>>0}function isLittleEndian(){var a=new Uint8Array(2);a[0]=1;var b=new Uint16Array(a.buffer);return 1===b[0]}function hasCanvasTypedArrays(){var a=document.createElement("canvas");a.width=a.height=1;var b=a.getContext("2d"),c=b.createImageData(1,1);return"undefined"!=typeof c.data.buffer}function stringToPDFString(a){var b,c=a.length,d=[];if("þ"===a[0]&&"ÿ"===a[1])for(b=2;c>b;b+=2)d.push(String.fromCharCode(a.charCodeAt(b)<<8|a.charCodeAt(b+1)));else for(b=0;c>b;++b){var e=PDFStringTranslateTable[a.charCodeAt(b)];d.push(e?String.fromCharCode(e):a.charAt(b))}return d.join("")}function stringToUTF8String(a){return decodeURIComponent(escape(a))}function isEmptyObj(a){for(var b in a)return!1;return!0}function isBool(a){return"boolean"==typeof a}function isInt(a){return"number"==typeof a&&(0|a)===a}function isNum(a){return"number"==typeof a}function isString(a){return"string"==typeof a}function isNull(a){return null===a}function isName(a){return a instanceof Name}function isCmd(a,b){return a instanceof Cmd&&(void 0===b||a.cmd===b)}function isDict(a,b){if(!(a instanceof Dict))return!1;if(!b)return!0;var c=a.get("Type");return isName(c)&&c.name===b}function isArray(a){return a instanceof Array}function isStream(a){return"object"==typeof a&&null!==a&&void 0!==a.getBytes}function isArrayBuffer(a){return"object"==typeof a&&null!==a&&void 0!==a.byteLength}function isRef(a){return a instanceof Ref}function createPromiseCapability(){var a={};return a.promise=new Promise(function(b,c){a.resolve=b,a.reject=c}),a}function MessageHandler(a,b){this.name=a,this.comObj=b,this.callbackIndex=1,this.postMessageTransfers=!0;var c=this.callbacksCapabilities={},d=this.actionHandler={};d.console_log=[function(a){console.log.apply(console,a)}],d.console_error=[function(a){console.error.apply(console,a)}],d._unsupported_feature=[function(a){UnsupportedManager.notify(a)}],b.onmessage=function(a){var e=a.data;if(e.isReply){var f=e.callbackId;if(e.callbackId in c){var g=c[f];delete c[f],"error"in e?g.reject(e.error):g.resolve(e.data)}else error("Cannot resolve callback "+f)}else if(e.action in d){var h=d[e.action];e.callbackId?Promise.resolve().then(function(){return h[0].call(h[1],e.data)}).then(function(a){b.postMessage({isReply:!0,callbackId:e.callbackId,data:a})},function(a){b.postMessage({isReply:!0,callbackId:e.callbackId,error:a})}):h[0].call(h[1],e.data)}else error("Unknown action from worker: "+e.action)}}function loadJpegStream(a,b,c){var d=new Image;d.onload=function(){c.resolve(a,d)},d.onerror=function(){c.resolve(a,null),warn("Error during JPEG image loading")},d.src=b}var JpxImage=function(){function a(){this.failOnCorruptedImage=!1}function b(a,b){a.x0=Math.ceil(b.XOsiz/a.XRsiz),a.x1=Math.ceil(b.Xsiz/a.XRsiz),a.y0=Math.ceil(b.YOsiz/a.YRsiz),a.y1=Math.ceil(b.Ysiz/a.YRsiz),a.width=a.x1-a.x0,a.height=a.y1-a.y0}function c(a,b){for(var c,d=a.SIZ,e=[],f=Math.ceil((d.Xsiz-d.XTOsiz)/d.XTsiz),g=Math.ceil((d.Ysiz-d.YTOsiz)/d.YTsiz),h=0;g>h;h++)for(var i=0;f>i;i++)c={},c.tx0=Math.max(d.XTOsiz+i*d.XTsiz,d.XOsiz),c.ty0=Math.max(d.YTOsiz+h*d.YTsiz,d.YOsiz),c.tx1=Math.min(d.XTOsiz+(i+1)*d.XTsiz,d.Xsiz),c.ty1=Math.min(d.YTOsiz+(h+1)*d.YTsiz,d.Ysiz),c.width=c.tx1-c.tx0,c.height=c.ty1-c.ty0,c.components=[],e.push(c);a.tiles=e;for(var j=d.Csiz,k=0,l=j;l>k;k++)for(var m=b[k],n=0,o=e.length;o>n;n++){var p={};c=e[n],p.tcx0=Math.ceil(c.tx0/m.XRsiz),p.tcy0=Math.ceil(c.ty0/m.YRsiz),p.tcx1=Math.ceil(c.tx1/m.XRsiz),p.tcy1=Math.ceil(c.ty1/m.YRsiz),p.width=p.tcx1-p.tcx0,p.height=p.tcy1-p.tcy0,c.components[k]=p}}function d(a,b,c){var d=b.codingStyleParameters,e={};return d.entropyCoderWithCustomPrecincts?(e.PPx=d.precinctsSizes[c].PPx,e.PPy=d.precinctsSizes[c].PPy):(e.PPx=15,e.PPy=15),e.xcb_=c>0?Math.min(d.xcb,e.PPx-1):Math.min(d.xcb,e.PPx),e.ycb_=c>0?Math.min(d.ycb,e.PPy-1):Math.min(d.ycb,e.PPy),e}function e(a,b,c){var d=1<b.trx0?Math.ceil(b.trx1/d)-Math.floor(b.trx0/d):0,j=b.try1>b.try0?Math.ceil(b.try1/e)-Math.floor(b.try0/e):0,k=i*j;b.precinctParameters={precinctWidth:d,precinctHeight:e,numprecinctswide:i,numprecinctshigh:j,numprecincts:k,precinctWidthInSubband:g,precinctHeightInSubband:h}}function f(a,b,c){var d,e,f,g,h=c.xcb_,i=c.ycb_,j=1<>h,m=b.tby0>>i,n=b.tbx1+j-1>>h,o=b.tby1+k-1>>i,p=b.resolution.precinctParameters,q=[],r=[];for(e=m;o>e;e++)for(d=l;n>d;d++){f={cbx:d,cby:e,tbx0:j*d,tby0:k*e,tbx1:j*(d+1),tby1:k*(e+1)},f.tbx0_=Math.max(b.tbx0,f.tbx0),f.tby0_=Math.max(b.tby0,f.tby0),f.tbx1_=Math.min(b.tbx1,f.tbx1),f.tby1_=Math.min(b.tby1,f.tby1);var s=Math.floor((f.tbx0_-b.tbx0)/p.precinctWidthInSubband),t=Math.floor((f.tby0_-b.tby0)/p.precinctHeightInSubband);if(g=s+t*p.numprecinctswide,f.precinctNumber=g,f.subbandType=b.type,f.Lblock=3,!(f.tbx1_<=f.tbx0_||f.tby1_<=f.tby0_)){q.push(f);var u=r[g];void 0!==u?(du.cbxMax&&(u.cbxMax=d),eu.cbyMax&&(u.cbyMax=e)):r[g]=u={cbxMin:d,cbyMin:e,cbxMax:d,cbyMax:e},f.precinct=u}}b.codeblockParameters={codeblockWidth:h,codeblockHeight:i,numcodeblockwide:n-l+1,numcodeblockhigh:o-m+1},b.codeblocks=q,b.precincts=r}function g(a,b,c){for(var d=[],e=a.subbands,f=0,g=e.length;g>f;f++)for(var h=e[f],i=h.codeblocks,j=0,k=i.length;k>j;j++){var l=i[j];l.precinctNumber===b&&d.push(l)}return{layerNumber:c,codeblocks:d}}function h(a){for(var b=a.SIZ,c=a.currentTile.index,d=a.tiles[c],e=d.codingStyleDefaultParameters.layersCount,f=b.Csiz,h=0,i=0;f>i;i++)h=Math.max(h,d.components[i].codingStyleParameters.decompositionLevelsCount);var j=0,k=0,l=0,m=0;this.nextPacket=function(){for(;e>j;j++){for(;h>=k;k++){for(;f>l;l++){var a=d.components[l];if(!(k>a.codingStyleParameters.decompositionLevelsCount)){for(var b=a.resolutions[k],c=b.precinctParameters.numprecincts;c>m;){var i=g(b,m,j);return m++,i}m=0}}l=0}k=0}}}function i(a){for(var b=a.SIZ,c=a.currentTile.index,d=a.tiles[c],e=d.codingStyleDefaultParameters.layersCount,f=b.Csiz,h=0,i=0;f>i;i++)h=Math.max(h,d.components[i].codingStyleParameters.decompositionLevelsCount);var j=0,k=0,l=0,m=0;this.nextPacket=function(){for(;h>=j;j++){for(;e>k;k++){for(;f>l;l++){var a=d.components[l];if(!(j>a.codingStyleParameters.decompositionLevelsCount)){for(var b=a.resolutions[j],c=b.precinctParameters.numprecincts;c>m;){var i=g(b,m,k);return m++,i}m=0}}l=0}k=0}}}function j(a){var b,c,d,e,f=a.SIZ,h=a.currentTile.index,i=a.tiles[h],j=i.codingStyleDefaultParameters.layersCount,k=f.Csiz,l=0;for(d=0;k>d;d++){var m=i.components[d];l=Math.max(l,m.codingStyleParameters.decompositionLevelsCount)}var n=new Int32Array(l+1);for(c=0;l>=c;++c){var o=0;for(d=0;k>d;++d){var p=i.components[d].resolutions;c=c;c++){for(;ed;d++){var a=i.components[d];if(!(c>a.codingStyleParameters.decompositionLevelsCount)){var f=a.resolutions[c],h=f.precinctParameters.numprecincts;if(!(e>=h)){for(;j>b;){var m=g(f,e,b);return b++,m}b=0}}}d=0}e=0}}}function k(a){var b=a.SIZ,c=a.currentTile.index,d=a.tiles[c],e=d.codingStyleDefaultParameters.layersCount,f=b.Csiz,h=n(d),i=h,j=0,k=0,l=0,o=0,p=0;this.nextPacket=function(){for(;pl;l++){for(var a=d.components[l],b=a.codingStyleParameters.decompositionLevelsCount;b>=k;k++){var c=a.resolutions[k],n=h.components[l].resolutions[k],q=m(o,p,n,i,c);if(null!==q){for(;e>j;){var r=g(c,q,j);return j++,r}j=0}}k=0}l=0}o=0}}}function l(a){var b=a.SIZ,c=a.currentTile.index,d=a.tiles[c],e=d.codingStyleDefaultParameters.layersCount,f=b.Csiz,h=n(d),i=0,j=0,k=0,l=0,o=0;this.nextPacket=function(){for(;f>k;++k){for(var a=d.components[k],b=h.components[k],c=a.codingStyleParameters.decompositionLevelsCount;o=j;j++){var n=a.resolutions[j],p=b.resolutions[j],q=m(l,o,p,b,n);if(null!==q){for(;e>i;){var r=g(n,q,i);return i++,r}i=0}}j=0}l=0}o=0}}}function m(a,b,c,d,e){var f=a*d.minWidth,g=b*d.minHeight;if(f%c.width!==0||g%c.height!==0)return null;var h=g/c.width*e.precinctParameters.numprecinctswide;return f/c.height+h}function n(a){for(var b=a.components.length,c=Number.MAX_VALUE,d=Number.MAX_VALUE,e=0,f=0,g=new Array(b),h=0;b>h;h++){for(var i=a.components[h],j=i.codingStyleParameters.decompositionLevelsCount,k=new Array(j+1),l=Number.MAX_VALUE,m=Number.MAX_VALUE,n=0,o=0,p=1,q=j;q>=0;--q){var r=i.resolutions[q],s=p*r.precinctParameters.precinctWidth,t=p*r.precinctParameters.precinctHeight;l=Math.min(l,s),m=Math.min(m,t),n=Math.max(n,r.precinctParameters.numprecinctswide),o=Math.max(o,r.precinctParameters.numprecinctshigh),k[q]={width:s,height:t},p<<=1}c=Math.min(c,l),d=Math.min(d,m),e=Math.max(e,n),f=Math.max(f,o),g[h]={resolutions:k,minWidth:l,minHeight:m,maxNumWide:n,maxNumHigh:o}}return{components:g,minWidth:c,minHeight:d,maxNumWide:e,maxNumHigh:f}}function o(a){for(var b=a.SIZ,c=a.currentTile.index,g=a.tiles[c],m=b.Csiz,n=0;m>n;n++){for(var o=g.components[n],p=o.codingStyleParameters.decompositionLevelsCount,q=[],r=[],s=0;p>=s;s++){var t=d(a,o,s),u={},v=1<l;){if(c+k>=b.length)throw new Error("Unexpected EOF");var d=b[c+k];k++,m?(j=j<<7|d,l+=7,m=!1):(j=j<<8|d,l+=8),255===d&&(m=!0)}return l-=a,j>>>l&(1<a?a+3:(a=e(5),31>a?a+6:(a=e(7),a+37))}for(var j,k=0,l=0,m=!1,n=a.currentTile.index,o=a.tiles[n],p=a.COD.sopMarkerUsed,q=a.COD.ephMarkerUsed,r=o.packetsIterator;d>k;)try{h(),p&&f(145)&&g(4);var s=r.nextPacket();if(void 0===s)return;if(!e(1))continue;for(var t,u=s.layerNumber,x=[],y=0,z=s.codeblocks.length;z>y;y++){t=s.codeblocks[y];var A,B=t.precinct,C=t.cbx-B.cbxMin,D=t.cby-B.cbyMin,E=!1,F=!1;if(void 0!==t.included)E=!!e(1);else{B=t.precinct;var G,H;if(void 0!==B.inclusionTree)G=B.inclusionTree;else{var I=B.cbxMax-B.cbxMin+1,J=B.cbyMax-B.cbyMin+1;G=new w(I,J),H=new v(I,J),B.inclusionTree=G,B.zeroBitPlanesTree=H}for(G.reset(C,D,u);;){if(k>=b.length)return;if(G.isAboveThreshold())break;if(G.isKnown())G.nextLevel();else if(e(1)){if(G.setKnown(),G.isLeaf()){t.included=!0,E=F=!0;break}G.nextLevel()}else G.incrementValue()}}if(E){if(F){for(H=B.zeroBitPlanesTree,H.reset(C,D);;){if(k>=b.length)return;if(e(1)){if(A=!H.nextLevel())break}else H.incrementValue()}t.zeroBitPlanes=H.value}for(var K=i();e(1);)t.Lblock++;var L=log2(K),M=(1<K?L-1:L)+t.Lblock,N=e(M);x.push({codeblock:t,codingpasses:K,dataLength:N})}}for(h(),q&&f(146);x.length>0;){var O=x.shift();t=O.codeblock,void 0===t.data&&(t.data=[]),t.data.push({data:b,start:c+k,end:c+k+O.dataLength,codingpasses:O.codingpasses}),k+=O.dataLength}}catch(P){return}return k}function q(a,b,c,d,e,f,g,h){for(var i=d.tbx0,j=d.tby0,k=d.tbx1-d.tbx0,l=d.codeblocks,m="H"===d.type.charAt(0)?1:0,n="H"===d.type.charAt(1)?b:0,o=0,p=l.length;p>o;++o){var q=l[o],r=q.tbx1_-q.tbx0_,s=q.tby1_-q.tby0_;if(0!==r&&0!==s&&void 0!==q.data){var t,u;t=new x(r,s,q.subbandType,q.zeroBitPlanes,f),u=2;var v,w,y,z=q.data,A=0,B=0;for(v=0,w=z.length;w>v;v++)y=z[v],A+=y.end-y.start,B+=y.codingpasses;var C=new Int16Array(A),D=0;for(v=0,w=z.length;w>v;v++){y=z[v];var E=y.data.subarray(y.start,y.end);C.set(E,D),D+=E.length}var F=new ArithmeticDecoder(C,0,A);for(t.setDecoder(F),v=0;B>v;v++){switch(u){case 0:t.runSignificancePropogationPass();break;case 1:t.runMagnitudeRefinementPass();break;case 2:t.runCleanupPass(),h&&t.checkSegmentationSymbol()}u=(u+1)%3}var G,H,I,J=q.tbx0_-i+(q.tby0_-j)*k,K=t.coefficentsSign,L=t.coefficentsMagnitude,M=t.bitsDecoded,N=g?0:.5;D=0;var O="LL"!==d.type;for(v=0;s>v;v++){var P=J/k|0,Q=2*P*(b-k)+m+n;for(G=0;r>G;G++){if(H=L[D],0!==H){H=(H+N)*e,0!==K[D]&&(H=-H),I=M[D];var R=O?Q+(J<<1):J;g&&I>=f?a[R]=H:a[R]=H*(1<=r;r++){for(var s=d.resolutions[r],t=s.trx1-s.trx0,v=s.try1-s.try0,w=new Float32Array(t*v),x=0,y=s.subbands.length;y>x;x++){var B,C;i?(B=h[p].mu,C=h[p].epsilon,p++):(B=h[0].mu,C=h[0].epsilon+(r>0?1-r:0));var D=s.subbands[x],E=u[D.type],F=m?1:Math.pow(2,l+E-C)*(1+B/2048),G=j+C-1;q(w,t,v,D,F,G,m,k)}o.push({width:t,height:v,items:w})}var H=n.calculate(o,d.tcx0,d.tcy0);return{left:d.tcx0,top:d.tcy0,width:H.width,height:H.height,items:H.items}}function s(a){for(var b=a.SIZ,c=a.components,d=b.Csiz,e=[],f=0,g=a.tiles.length;g>f;f++){var h,i=a.tiles[f],j=[];for(h=0;d>h;h++)j[h]=r(a,i,h);var k=j[0],l=c[0].isSigned;if(l)var m=new Int16Array(k.items.length*d);else var m=new Uint16Array(k.items.length*d);var n,o,p,q,s,t,u,v,w,x,y,z,A,B,C,D={left:k.left,top:k.top,width:k.width,height:k.height,items:m},E=0;if(i.codingStyleDefaultParameters.multipleComponentTransform){var F=4===d,G=j[0].items,H=j[1].items,I=j[2].items,J=F?j[3].items:null;n=c[0].precision-8,o=(128<t;t++,E+=L)v=G[t]+o,w=H[t],x=I[t],z=v-(x+w>>2),y=z+x,A=z+w,m[E++]=0>=y?0:y>=p?255:y>>n,m[E++]=0>=z?0:z>=p?255:z>>n,m[E++]=0>=A?0:A>=p?255:A>>n;else for(t=0;u>t;t++,E+=L)v=G[t]+o,w=H[t],x=I[t],y=v+1.402*x,z=v-.34413*w-.71414*x,A=v+1.772*w,m[E++]=0>=y?0:y>=p?255:y>>n,m[E++]=0>=z?0:z>=p?255:z>>n,m[E++]=0>=A?0:A>=p?255:A>>n;if(F)for(t=0,E=3;u>t;t++,E+=4)B=J[t],m[E]=q>=B?0:B>=s?255:B+o>>n}else for(h=0;d>h;h++)if(8===c[h].precision){var M=j[h].items;for(n=c[h].precision-8,o=(128<t;t++)C=M[t],m[E]=q>=C?0:C>=p?255:C+o>>n,E+=d}else{var l=c[h].isSigned,M=j[h].items;if(l)for(E=h,t=0,u=M.length;u>t;t++)m[E]=M[t],E+=d;else{n=c[h].precision-8,o=(128<t;t++)C=M[t],m[E]=Math.max(Math.min(C+o,N),0),E+=d}}e.push(D)}return e}function t(a,b){for(var c=a.SIZ,d=c.Csiz,e=a.tiles[b],f=0;d>f;f++){var g=e.components[f],h=void 0!==a.currentTile.QCC[f]?a.currentTile.QCC[f]:a.currentTile.QCD;g.quantizationParameters=h;var i=void 0!==a.currentTile.COC[f]?a.currentTile.COC[f]:a.currentTile.COD;g.codingStyleParameters=i}e.codingStyleDefaultParameters=a.currentTile.COD}var u={LL:0,LH:1,HL:1,HH:2};a.prototype={parse:function(a){var b=readUint16(a,0);if(65359===b)return void this.parseCodestream(a,0,a.length);for(var c=0,d=a.length;d>c;){var e=8,f=readUint32(a,c),g=readUint32(a,c+4);if(c+=e,1===f&&(f=4294967296*readUint32(a,c)+readUint32(a,c+4),c+=8,e+=8),0===f&&(f=d-c+e),e>f)throw new Error("JPX Error: Invalid box field size");var h=f-e,i=!0;switch(g){case 1785737832:i=!1;break;case 1668246642:var j=a[c];a[c+1],a[c+2];if(1===j){var k=readUint32(a,c+3);switch(k){case 16:case 17:case 18:break;default:warn("Unknown colorspace "+k)}}else 2===j&&info("ICC profile not supported");break;case 1785737827:this.parseCodestream(a,c,c+h);break;case 1783636e3:218793738!==readUint32(a,c)&&warn("Invalid JP2 signature");break;case 1783634458:case 1718909296:case 1920099697:case 1919251232:case 1768449138:break;default:var l=String.fromCharCode(g>>24&255,g>>16&255,g>>8&255,255&g);warn("Unsupported header type "+g+" ("+l+")")}i&&(c+=h)}},parseImageProperties:function(a){for(var b=a.getByte();b>=0;){var c=b;b=a.getByte();var d=c<<8|b;if(65361===d){a.skip(4);var e=a.getInt32()>>>0,f=a.getInt32()>>>0,g=a.getInt32()>>>0,h=a.getInt32()>>>0;a.skip(16);var i=a.getUint16();return this.width=e-g,this.height=f-h,this.componentsCount=i,void(this.bitsPerComponent=8)}}throw new Error("JPX Error: No size marker found in JPX stream")},parseCodestream:function(a,d,e){var f={};try{for(var g=!1,h=d;e>h+1;){var i=readUint16(a,h);h+=2;var j,k,l,m,n,q,r=0;switch(i){case 65359:f.mainHeader=!0;break;case 65497:break;case 65361:r=readUint16(a,h);var u={};u.Xsiz=readUint32(a,h+4),u.Ysiz=readUint32(a,h+8),u.XOsiz=readUint32(a,h+12),u.YOsiz=readUint32(a,h+16),u.XTsiz=readUint32(a,h+20),u.YTsiz=readUint32(a,h+24),u.XTOsiz=readUint32(a,h+28),u.YTOsiz=readUint32(a,h+32);var v=readUint16(a,h+36);u.Csiz=v;var w=[];j=h+38;for(var x=0;v>x;x++){var y={precision:(127&a[j])+1,isSigned:!!(128&a[j]),XRsiz:a[j+1],YRsiz:a[j+1]};b(y,u),w.push(y)}f.SIZ=u,f.components=w,c(f,w),f.QCC=[],f.COC=[];break;case 65372:r=readUint16(a,h);var z={};switch(j=h+2,k=a[j++],31&k){case 0:m=8,n=!0;break;case 1:m=16,n=!1;break;case 2:m=16,n=!0;break;default:throw new Error("JPX Error: Invalid SQcd value "+k)}for(z.noQuantization=8===m,z.scalarExpounded=n,z.guardBits=k>>5,l=[];r+h>j;){var A={};8===m?(A.epsilon=a[j++]>>3,A.mu=0):(A.epsilon=a[j]>>3,A.mu=(7&a[j])<<8|a[j+1],j+=2),l.push(A)}z.SPqcds=l,f.mainHeader?f.QCD=z:(f.currentTile.QCD=z,f.currentTile.QCC=[]);break;case 65373:r=readUint16(a,h);var B={};j=h+2;var C;switch(f.SIZ.Csiz<257?C=a[j++]:(C=readUint16(a,j),j+=2),k=a[j++],31&k){case 0:m=8,n=!0;break;case 1:m=16,n=!1;break;case 2:m=16,n=!0;break;default:throw new Error("JPX Error: Invalid SQcd value "+k)}for(B.noQuantization=8===m,B.scalarExpounded=n,B.guardBits=k>>5,l=[];r+h>j;)A={},8===m?(A.epsilon=a[j++]>>3,A.mu=0):(A.epsilon=a[j]>>3,A.mu=(7&a[j])<<8|a[j+1],j+=2),l.push(A);B.SPqcds=l,f.mainHeader?f.QCC[C]=B:f.currentTile.QCC[C]=B;break;case 65362:r=readUint16(a,h);var D={};j=h+2;var E=a[j++];D.entropyCoderWithCustomPrecincts=!!(1&E),D.sopMarkerUsed=!!(2&E),D.ephMarkerUsed=!!(4&E),D.progressionOrder=a[j++],D.layersCount=readUint16(a,j),j+=2,D.multipleComponentTransform=a[j++],D.decompositionLevelsCount=a[j++],D.xcb=(15&a[j++])+2,D.ycb=(15&a[j++])+2;var F=a[j++];if(D.selectiveArithmeticCodingBypass=!!(1&F),D.resetContextProbabilities=!!(2&F),D.terminationOnEachCodingPass=!!(4&F),D.verticalyStripe=!!(8&F),D.predictableTermination=!!(16&F),D.segmentationSymbolUsed=!!(32&F),D.reversibleTransformation=a[j++],D.entropyCoderWithCustomPrecincts){for(var G=[];r+h>j;){var H=a[j++];G.push({PPx:15&H,PPy:H>>4})}D.precinctsSizes=G}var I=[];if(D.selectiveArithmeticCodingBypass&&I.push("selectiveArithmeticCodingBypass"),D.resetContextProbabilities&&I.push("resetContextProbabilities"),D.terminationOnEachCodingPass&&I.push("terminationOnEachCodingPass"),D.verticalyStripe&&I.push("verticalyStripe"),D.predictableTermination&&I.push("predictableTermination"),I.length>0)throw g=!0,new Error("JPX Error: Unsupported COD options ("+I.join(", ")+")");f.mainHeader?f.COD=D:(f.currentTile.COD=D,f.currentTile.COC=[]);break;case 65424:r=readUint16(a,h),q={},q.index=readUint16(a,h+2),q.length=readUint32(a,h+4),q.dataEnd=q.length+h-2,q.partIndex=a[h+8],q.partsCount=a[h+9],f.mainHeader=!1,0===q.partIndex&&(q.COD=f.COD,q.COC=f.COC.slice(0),q.QCD=f.QCD,q.QCC=f.QCC.slice(0)),f.currentTile=q;break;case 65427:q=f.currentTile,0===q.partIndex&&(t(f,q.index),o(f)),r=q.dataEnd-h,p(f,a,h,r);break;case 65365:case 65367:case 65368:case 65380:r=readUint16(a,h);break;case 65363:throw new Error("JPX Error: Codestream code 0xFF53 (COC) is not implemented");default:throw new Error("JPX Error: Unknown codestream code: "+i.toString(16))}h+=r}}catch(J){if(g||this.failOnCorruptedImage)throw J;warn("Trying to recover from "+J.message)}this.tiles=s(f),this.width=f.SIZ.Xsiz-f.SIZ.XOsiz,this.height=f.SIZ.Ysiz-f.SIZ.YOsiz,this.componentsCount=f.SIZ.Csiz}};var v=function(){function a(a,b){var c=log2(Math.max(a,b))+1;this.levels=[];for(var d=0;c>d;d++){var e={width:a,height:b,items:[]};this.levels.push(e),a=Math.ceil(a/2),b=Math.ceil(b/2)}}return a.prototype={reset:function(a,b){for(var c,d=0,e=0;d>=1,b>>=1,d++}d--,c=this.levels[d],c.items[c.index]=e,this.currentLevel=d,delete this.value},incrementValue:function(){var a=this.levels[this.currentLevel];a.items[a.index]++},nextLevel:function(){var a=this.currentLevel,b=this.levels[a],c=b.items[b.index];return a--,0>a?(this.value=c,!1):(this.currentLevel=a,b=this.levels[a],b.items[b.index]=c,!0)}},a}(),w=function(){function a(a,b){var c=log2(Math.max(a,b))+1;this.levels=[];for(var d=0;c>d;d++){for(var e=new Uint8Array(a*b),f=new Uint8Array(a*b),g=0,h=e.length;h>g;g++)e[g]=0,f[g]=0;var i={width:a,height:b,items:e,status:f};this.levels.push(i),a=Math.ceil(a/2),b=Math.ceil(b/2)}}return a.prototype={reset:function(a,b,c){this.currentStopValue=c;for(var d=0;d>=1,b>>=1,d++}this.currentLevel=this.levels.length-1,this.minValue=this.levels[this.currentLevel].items[0]},incrementValue:function(){var a=this.levels[this.currentLevel];a.items[a.index]=a.items[a.index]+1,a.items[a.index]>this.minValue&&(this.minValue=a.items[a.index])},nextLevel:function(){var a=this.currentLevel;if(a--,0>a)return!1;this.currentLevel=a;var b=this.levels[a];return b.items[b.index]this.minValue&&(this.minValue=b.items[b.index]),!0},isLeaf:function(){return 0===this.currentLevel},isAboveThreshold:function(){var a=this.currentLevel,b=this.levels[a];return b.items[b.index]>this.currentStopValue},isKnown:function(){var a=this.currentLevel,b=this.levels[a];return b.status[b.index]>0},setKnown:function(){var a=this.currentLevel,b=this.levels[a];b.status[b.index]=1}},a}(),x=function(){function a(a,b,c,g,h){this.width=a,this.height=b,this.contextLabelTable="HH"===c?f:"HL"===c?e:d;var i=a*b;this.neighborsSignificance=new Uint8Array(i),this.coefficentsSign=new Uint8Array(i),this.coefficentsMagnitude=h>14?new Uint32Array(i):h>6?new Uint16Array(i):new Uint8Array(i),this.processingFlags=new Uint8Array(i);var j=new Uint8Array(i);if(0!==g)for(var k=0;i>k;k++)j[k]=g;this.bitsDecoded=j,this.reset()}var b=17,c=18,d=new Uint8Array([0,5,8,0,3,7,8,0,4,7,8,0,0,0,0,0,1,6,8,0,3,7,8,0,4,7,8,0,0,0,0,0,2,6,8,0,3,7,8,0,4,7,8,0,0,0,0,0,2,6,8,0,3,7,8,0,4,7,8,0,0,0,0,0,2,6,8,0,3,7,8,0,4,7,8]),e=new Uint8Array([0,3,4,0,5,7,7,0,8,8,8,0,0,0,0,0,1,3,4,0,6,7,7,0,8,8,8,0,0,0,0,0,2,3,4,0,6,7,7,0,8,8,8,0,0,0,0,0,2,3,4,0,6,7,7,0,8,8,8,0,0,0,0,0,2,3,4,0,6,7,7,0,8,8,8]),f=new Uint8Array([0,1,2,0,1,2,2,0,2,2,2,0,0,0,0,0,3,4,5,0,4,5,5,0,5,5,5,0,0,0,0,0,6,7,7,0,7,7,7,0,7,7,7,0,0,0,0,0,8,8,8,0,8,8,8,0,8,8,8,0,0,0,0,0,8,8,8,0,8,8,8,0,8,8,8]);return a.prototype={setDecoder:function(a){this.decoder=a},reset:function(){this.contexts=new Int8Array(19),this.contexts[0]=8,this.contexts[b]=92,this.contexts[c]=6},setNeighborsSignificance:function(a,b,c){var d,e=this.neighborsSignificance,f=this.width,g=this.height,h=b>0,i=f>b+1;a>0&&(d=c-f,h&&(e[d-1]+=16),i&&(e[d+1]+=16),e[d]+=4),g>a+1&&(d=c+f,h&&(e[d-1]+=16),i&&(e[d+1]+=16),e[d]+=4),h&&(e[c-1]+=1),i&&(e[c+1]+=1),e[c]|=128},runSignificancePropogationPass:function(){for(var a=this.decoder,b=this.width,c=this.height,d=this.coefficentsMagnitude,e=this.coefficentsSign,f=this.neighborsSignificance,g=this.processingFlags,h=this.contexts,i=this.contextLabelTable,j=this.bitsDecoded,k=-2,l=1,m=2,n=0;c>n;n+=4)for(var o=0;b>o;o++)for(var p=n*b+o,q=0;4>q;q++,p+=b){var r=n+q;if(r>=c)break;if(g[p]&=k,!d[p]&&f[p]){var s=i[f[p]],t=a.readBit(h,s);if(t){var u=this.decodeSignBit(r,o,p);e[p]=u,d[p]=1,this.setNeighborsSignificance(r,o,p),g[p]|=m}j[p]++,g[p]|=l}}},decodeSignBit:function(a,b,c){var d,e,f,g,h,i,j=this.width,k=this.height,l=this.coefficentsMagnitude,m=this.coefficentsSign;g=b>0&&0!==l[c-1],j>b+1&&0!==l[c+1]?(f=m[c+1],g?(e=m[c-1],d=1-f-e):d=1-f-f):g?(e=m[c-1],d=1-e-e):d=0;var n=3*d;return g=a>0&&0!==l[c-j],k>a+1&&0!==l[c+j]?(f=m[c+j],g?(e=m[c-j],d=1-f-e+n):d=1-f-f+n):g?(e=m[c-j],d=1-e-e+n):d=n,d>=0?(h=9+d,i=this.decoder.readBit(this.contexts,h)):(h=9-d,i=1^this.decoder.readBit(this.contexts,h)),i},runMagnitudeRefinementPass:function(){for(var a,b=this.decoder,c=this.width,d=this.height,e=this.coefficentsMagnitude,f=this.neighborsSignificance,g=this.contexts,h=this.bitsDecoded,i=this.processingFlags,j=1,k=2,l=c*d,m=4*c,n=0;l>n;n=a){a=Math.min(l,n+m);for(var o=0;c>o;o++)for(var p=n+o;a>p;p+=c)if(e[p]&&0===(i[p]&j)){var q=16;if(0!==(i[p]&k)){i[p]^=k;var r=127&f[p];q=0===r?15:14}var s=b.readBit(g,q);e[p]=e[p]<<1|s,h[p]++,i[p]|=j}}},runCleanupPass:function(){for(var a,d=this.decoder,e=this.width,f=this.height,g=this.neighborsSignificance,h=this.coefficentsMagnitude,i=this.coefficentsSign,j=this.contexts,k=this.contextLabelTable,l=this.bitsDecoded,m=this.processingFlags,n=1,o=2,p=e,q=2*e,r=3*e,s=0;f>s;s=a){a=Math.min(s+4,f);for(var t=s*e,u=f>s+3,v=0;e>v;v++){var w,x=t+v,y=u&&0===m[x]&&0===m[x+p]&&0===m[x+q]&&0===m[x+r]&&0===g[x]&&0===g[x+p]&&0===g[x+q]&&0===g[x+r],z=0,A=x,B=s;if(y){var C=d.readBit(j,c);if(!C){l[x]++,l[x+p]++,l[x+q]++,l[x+r]++;continue}z=d.readBit(j,b)<<1|d.readBit(j,b),0!==z&&(B=s+z,A+=z*e),w=this.decodeSignBit(B,v,A),i[A]=w,h[A]=1,this.setNeighborsSignificance(B,v,A),m[A]|=o,A=x;for(var D=s;B>=D;D++,A+=e)l[A]++;z++}for(B=s+z;a>B;B++,A+=e)if(!h[A]&&0===(m[A]&n)){var E=k[g[A]],F=d.readBit(j,E);1===F&&(w=this.decodeSignBit(B,v,A),i[A]=w,h[A]=1,this.setNeighborsSignificance(B,v,A),m[A]|=o),l[A]++}}}},checkSegmentationSymbol:function(){var a=this.decoder,c=this.contexts,d=a.readBit(c,b)<<3|a.readBit(c,b)<<2|a.readBit(c,b)<<1|a.readBit(c,b);if(10!==d)throw new Error("JPX Error: Invalid segmentation symbol")}},a}(),y=function(){function a(){}return a.prototype.calculate=function(a,b,c){for(var d=a[0],e=1,f=a.length;f>e;e++)d=this.iterate(d,a[e],b,c);return d},a.prototype.extend=function(a,b,c){var d=b-1,e=b+1,f=b+c-2,g=b+c;a[d--]=a[e++],a[g++]=a[f--],a[d--]=a[e++],a[g++]=a[f--],a[d--]=a[e++],a[g++]=a[f--],a[d]=a[e],a[g]=a[f]},a.prototype.iterate=function(a,b,c,d){var e,f,g,h,i,j,k=a.width,l=a.height,m=a.items,n=b.width,o=b.height,p=b.items;for(g=0,e=0;l>e;e++)for(h=2*e*n,f=0;k>f;f++,g++,h+=2)p[h]=m[g];m=a.items=null;var q=4,r=new Float32Array(n+2*q);if(1===n){if(0!==(1&c))for(j=0,g=0;o>j;j++,g+=n)p[g]*=.5}else for(j=0,g=0;o>j;j++,g+=n)r.set(p.subarray(g,g+n),q),this.extend(r,q,n),this.filter(r,q,n),p.set(r.subarray(q,q+n),g);var s=16,t=[];for(e=0;s>e;e++)t.push(new Float32Array(o+2*q));var u,v=0;if(a=q+o,1===o){if(0!==(1&d))for(i=0;n>i;i++)p[i]*=.5}else for(i=0;n>i;i++){if(0===v){for(s=Math.min(n-i,s),g=i,h=q;a>h;g+=n,h++)for(u=0;s>u;u++)t[u][h]=p[g+u];v=s}v--;var w=t[v];if(this.extend(w,q,o),this.filter(w,q,o),0===v)for(g=i-s+1,h=q;a>h;g+=n,h++)for(u=0;s>u;u++)p[g+u]=t[u][h]}return{width:n,height:o,items:p}},a}(),z=function(){function a(){y.call(this)}return a.prototype=Object.create(y.prototype),a.prototype.filter=function(a,b,c){var d=c>>1;b=0|b;var e,f,g,h,i=-1.586134342059924,j=-.052980118572961,k=.882911075530934,l=.443506852043971,m=1.230174104914001,n=1/m;for(e=b-3,f=d+4;f--;e+=2)a[e]*=n;for(e=b-2,g=l*a[e-1],f=d+3;f--&&(h=l*a[e+1],a[e]=m*a[e]-g-h,f--);e+=2)e+=2,g=l*a[e+1],a[e]=m*a[e]-g-h;for(e=b-1,g=k*a[e-1],f=d+2;f--&&(h=k*a[e+1],a[e]-=g+h,f--);e+=2)e+=2,g=k*a[e+1],a[e]-=g+h;for(e=b,g=j*a[e-1],f=d+1;f--&&(h=j*a[e+1],a[e]-=g+h,f--);e+=2)e+=2,g=j*a[e+1],a[e]-=g+h;if(0!==d)for(e=b+1,g=i*a[e-1],f=d;f--&&(h=i*a[e+1],a[e]-=g+h,f--);e+=2)e+=2,g=i*a[e+1],a[e]-=g+h},a}(),A=function(){function a(){y.call(this)}return a.prototype=Object.create(y.prototype),a.prototype.filter=function(a,b,c){var d=c>>1;b=0|b;var e,f;for(e=b,f=d+1;f--;e+=2)a[e]-=a[e-1]+a[e+1]+2>>2;for(e=b+1,f=d;f--;e+=2)a[e]+=a[e-1]+a[e+1]>>1},a}();return a}(),ArithmeticDecoder=function(){function a(a,b,c){this.data=a,this.bp=b,this.dataEnd=c,this.chigh=a[b],this.clow=0,this.byteIn(),this.chigh=this.chigh<<7&65535|this.clow>>9&127,this.clow=this.clow<<7&65535,this.ct-=7,this.a=32768}var b=[{qe:22017,nmps:1,nlps:1,switchFlag:1},{qe:13313,nmps:2,nlps:6,switchFlag:0},{qe:6145,nmps:3,nlps:9,switchFlag:0},{qe:2753,nmps:4,nlps:12,switchFlag:0},{qe:1313,nmps:5,nlps:29,switchFlag:0},{qe:545,nmps:38,nlps:33,switchFlag:0},{qe:22017,nmps:7,nlps:6,switchFlag:1},{qe:21505,nmps:8,nlps:14,switchFlag:0},{qe:18433,nmps:9,nlps:14,switchFlag:0},{qe:14337,nmps:10,nlps:14,switchFlag:0},{qe:12289,nmps:11,nlps:17,switchFlag:0},{qe:9217,nmps:12,nlps:18,switchFlag:0},{qe:7169,nmps:13,nlps:20,switchFlag:0},{qe:5633,nmps:29,nlps:21,switchFlag:0},{qe:22017,nmps:15,nlps:14,switchFlag:1},{qe:21505,nmps:16,nlps:14,switchFlag:0},{qe:20737,nmps:17,nlps:15,switchFlag:0},{qe:18433,nmps:18,nlps:16,switchFlag:0},{qe:14337,nmps:19,nlps:17,switchFlag:0},{qe:13313,nmps:20,nlps:18,switchFlag:0},{qe:12289,nmps:21,nlps:19,switchFlag:0},{qe:10241,nmps:22,nlps:19,switchFlag:0},{qe:9217,nmps:23,nlps:20,switchFlag:0},{qe:8705,nmps:24,nlps:21,switchFlag:0},{qe:7169,nmps:25,nlps:22,switchFlag:0},{qe:6145,nmps:26,nlps:23,switchFlag:0},{qe:5633,nmps:27,nlps:24,switchFlag:0},{ 3 | qe:5121,nmps:28,nlps:25,switchFlag:0},{qe:4609,nmps:29,nlps:26,switchFlag:0},{qe:4353,nmps:30,nlps:27,switchFlag:0},{qe:2753,nmps:31,nlps:28,switchFlag:0},{qe:2497,nmps:32,nlps:29,switchFlag:0},{qe:2209,nmps:33,nlps:30,switchFlag:0},{qe:1313,nmps:34,nlps:31,switchFlag:0},{qe:1089,nmps:35,nlps:32,switchFlag:0},{qe:673,nmps:36,nlps:33,switchFlag:0},{qe:545,nmps:37,nlps:34,switchFlag:0},{qe:321,nmps:38,nlps:35,switchFlag:0},{qe:273,nmps:39,nlps:36,switchFlag:0},{qe:133,nmps:40,nlps:37,switchFlag:0},{qe:73,nmps:41,nlps:38,switchFlag:0},{qe:37,nmps:42,nlps:39,switchFlag:0},{qe:21,nmps:43,nlps:40,switchFlag:0},{qe:9,nmps:44,nlps:41,switchFlag:0},{qe:5,nmps:45,nlps:42,switchFlag:0},{qe:1,nmps:45,nlps:43,switchFlag:0},{qe:22017,nmps:46,nlps:46,switchFlag:0}];return a.prototype={byteIn:function(){var a=this.data,b=this.bp;if(255===a[b]){var c=a[b+1];c>143?(this.clow+=65280,this.ct=8):(b++,this.clow+=a[b]<<9,this.ct=7,this.bp=b)}else b++,this.clow+=b65535&&(this.chigh+=this.clow>>16,this.clow&=65535)},readBit:function(a,c){var d,e=a[c]>>1,f=1&a[c],g=b[e],h=g.qe,i=this.a-h;if(this.chighi?(i=h,d=f,e=g.nmps):(i=h,d=1^f,1===g.switchFlag&&(f=d),e=g.nlps);else{if(this.chigh-=h,0!==(32768&i))return this.a=i,f;h>i?(d=1^f,1===g.switchFlag&&(f=d),e=g.nlps):(d=f,e=g.nmps)}do 0===this.ct&&this.byteIn(),i<<=1,this.chigh=this.chigh<<1&65535|this.clow>>15&1,this.clow=this.clow<<1&65535,this.ct--;while(0===(32768&i));return this.a=i,a[c]=e<<1|f,d}},a}(),globalScope="undefined"==typeof window?this:window,isWorker="undefined"==typeof window,FONT_IDENTITY_MATRIX=[.001,0,0,.001,0,0],TextRenderingMode={FILL:0,STROKE:1,FILL_STROKE:2,INVISIBLE:3,FILL_ADD_TO_PATH:4,STROKE_ADD_TO_PATH:5,FILL_STROKE_ADD_TO_PATH:6,ADD_TO_PATH:7,FILL_STROKE_MASK:3,ADD_TO_PATH_FLAG:4},ImageKind={GRAYSCALE_1BPP:1,RGB_24BPP:2,RGBA_32BPP:3},AnnotationType={WIDGET:1,TEXT:2,LINK:3},StreamType={UNKNOWN:0,FLATE:1,LZW:2,DCT:3,JPX:4,JBIG:5,A85:6,AHX:7,CCF:8,RL:9},FontType={UNKNOWN:0,TYPE1:1,TYPE1C:2,CIDFONTTYPE0:3,CIDFONTTYPE0C:4,TRUETYPE:5,CIDFONTTYPE2:6,TYPE3:7,OPENTYPE:8,TYPE0:9,MMTYPE1:10};globalScope.PDFJS||(globalScope.PDFJS={}),globalScope.PDFJS.pdfBug=!1,PDFJS.VERBOSITY_LEVELS={errors:0,warnings:1,infos:5};var OPS=PDFJS.OPS={dependency:1,setLineWidth:2,setLineCap:3,setLineJoin:4,setMiterLimit:5,setDash:6,setRenderingIntent:7,setFlatness:8,setGState:9,save:10,restore:11,transform:12,moveTo:13,lineTo:14,curveTo:15,curveTo2:16,curveTo3:17,closePath:18,rectangle:19,stroke:20,closeStroke:21,fill:22,eoFill:23,fillStroke:24,eoFillStroke:25,closeFillStroke:26,closeEOFillStroke:27,endPath:28,clip:29,eoClip:30,beginText:31,endText:32,setCharSpacing:33,setWordSpacing:34,setHScale:35,setLeading:36,setFont:37,setTextRenderingMode:38,setTextRise:39,moveText:40,setLeadingMoveText:41,setTextMatrix:42,nextLine:43,showText:44,showSpacedText:45,nextLineShowText:46,nextLineSetSpacingShowText:47,setCharWidth:48,setCharWidthAndBounds:49,setStrokeColorSpace:50,setFillColorSpace:51,setStrokeColor:52,setStrokeColorN:53,setFillColor:54,setFillColorN:55,setStrokeGray:56,setFillGray:57,setStrokeRGBColor:58,setFillRGBColor:59,setStrokeCMYKColor:60,setFillCMYKColor:61,shadingFill:62,beginInlineImage:63,beginImageData:64,endInlineImage:65,paintXObject:66,markPoint:67,markPointProps:68,beginMarkedContent:69,beginMarkedContentProps:70,endMarkedContent:71,beginCompat:72,endCompat:73,paintFormXObjectBegin:74,paintFormXObjectEnd:75,beginGroup:76,endGroup:77,beginAnnotations:78,endAnnotations:79,beginAnnotation:80,endAnnotation:81,paintJpegXObject:82,paintImageMaskXObject:83,paintImageMaskXObjectGroup:84,paintImageXObject:85,paintInlineImageXObject:86,paintInlineImageXObjectGroup:87,paintImageXObjectRepeat:88,paintImageMaskXObjectRepeat:89,paintSolidColorImageMask:90,constructPath:91},UNSUPPORTED_FEATURES=PDFJS.UNSUPPORTED_FEATURES={unknown:"unknown",forms:"forms",javaScript:"javaScript",smask:"smask",shadingPattern:"shadingPattern",font:"font"},UnsupportedManager=PDFJS.UnsupportedManager=function(){var a=[];return{listen:function(b){a.push(b)},notify:function(b){warn('Unsupported feature "'+b+'"');for(var c=0,d=a.length;d>c;c++)a[c](b)}}}();PDFJS.isValidUrl=isValidUrl,PDFJS.shadow=shadow;var PasswordResponses=PDFJS.PasswordResponses={NEED_PASSWORD:1,INCORRECT_PASSWORD:2},PasswordException=function(){function a(a,b){this.name="PasswordException",this.message=a,this.code=b}return a.prototype=new Error,a.constructor=a,a}();PDFJS.PasswordException=PasswordException;var UnknownErrorException=function(){function a(a,b){this.name="UnknownErrorException",this.message=a,this.details=b}return a.prototype=new Error,a.constructor=a,a}();PDFJS.UnknownErrorException=UnknownErrorException;var InvalidPDFException=function(){function a(a){this.name="InvalidPDFException",this.message=a}return a.prototype=new Error,a.constructor=a,a}();PDFJS.InvalidPDFException=InvalidPDFException;var MissingPDFException=function(){function a(a){this.name="MissingPDFException",this.message=a}return a.prototype=new Error,a.constructor=a,a}();PDFJS.MissingPDFException=MissingPDFException;var UnexpectedResponseException=function(){function a(a,b){this.name="UnexpectedResponseException",this.message=a,this.status=b}return a.prototype=new Error,a.constructor=a,a}();PDFJS.UnexpectedResponseException=UnexpectedResponseException;var NotImplementedException=function(){function a(a){this.message=a}return a.prototype=new Error,a.prototype.name="NotImplementedException",a.constructor=a,a}(),MissingDataException=function(){function a(a,b){this.begin=a,this.end=b,this.message="Missing data ["+a+", "+b+")"}return a.prototype=new Error,a.prototype.name="MissingDataException",a.constructor=a,a}(),XRefParseException=function(){function a(a){this.message=a}return a.prototype=new Error,a.prototype.name="XRefParseException",a.constructor=a,a}();Object.defineProperty(PDFJS,"isLittleEndian",{configurable:!0,get:function(){return shadow(PDFJS,"isLittleEndian",isLittleEndian())}}),Object.defineProperty(PDFJS,"hasCanvasTypedArrays",{configurable:!0,get:function(){return shadow(PDFJS,"hasCanvasTypedArrays",hasCanvasTypedArrays())}});var Uint32ArrayView=function(){function a(a,b){this.buffer=a,this.byteLength=a.length,this.length=void 0===b?this.byteLength>>2:b,c(this.length)}function b(a){return{get:function(){var b=this.buffer,c=a<<2;return(b[c]|b[c+1]<<8|b[c+2]<<16|b[c+3]<<24)>>>0},set:function(b){var c=this.buffer,d=a<<2;c[d]=255&b,c[d+1]=b>>8&255,c[d+2]=b>>16&255,c[d+3]=b>>>24&255}}}function c(c){for(;c>d;)Object.defineProperty(a.prototype,d,b(d)),d++}a.prototype=Object.create(null);var d=0;return a}(),IDENTITY_MATRIX=[1,0,0,1,0,0],Util=PDFJS.Util=function(){function a(){}var b=["rgb(",0,",",0,",",0,")"];return a.makeCssRgb=function(a,c,d){return b[1]=a,b[3]=c,b[5]=d,b.join("")},a.transform=function(a,b){return[a[0]*b[0]+a[2]*b[1],a[1]*b[0]+a[3]*b[1],a[0]*b[2]+a[2]*b[3],a[1]*b[2]+a[3]*b[3],a[0]*b[4]+a[2]*b[5]+a[4],a[1]*b[4]+a[3]*b[5]+a[5]]},a.applyTransform=function(a,b){var c=a[0]*b[0]+a[1]*b[2]+b[4],d=a[0]*b[1]+a[1]*b[3]+b[5];return[c,d]},a.applyInverseTransform=function(a,b){var c=b[0]*b[3]-b[1]*b[2],d=(a[0]*b[3]-a[1]*b[2]+b[2]*b[5]-b[4]*b[3])/c,e=(-a[0]*b[1]+a[1]*b[0]+b[4]*b[1]-b[5]*b[0])/c;return[d,e]},a.getAxialAlignedBoundingBox=function(b,c){var d=a.applyTransform(b,c),e=a.applyTransform(b.slice(2,4),c),f=a.applyTransform([b[0],b[3]],c),g=a.applyTransform([b[2],b[1]],c);return[Math.min(d[0],e[0],f[0],g[0]),Math.min(d[1],e[1],f[1],g[1]),Math.max(d[0],e[0],f[0],g[0]),Math.max(d[1],e[1],f[1],g[1])]},a.inverseTransform=function(a){var b=a[0]*a[3]-a[1]*a[2];return[a[3]/b,-a[1]/b,-a[2]/b,a[0]/b,(a[2]*a[5]-a[4]*a[3])/b,(a[4]*a[1]-a[5]*a[0])/b]},a.apply3dTransform=function(a,b){return[a[0]*b[0]+a[1]*b[1]+a[2]*b[2],a[3]*b[0]+a[4]*b[1]+a[5]*b[2],a[6]*b[0]+a[7]*b[1]+a[8]*b[2]]},a.singularValueDecompose2dScale=function(a){var b=[a[0],a[2],a[1],a[3]],c=a[0]*b[0]+a[1]*b[2],d=a[0]*b[1]+a[1]*b[3],e=a[2]*b[0]+a[3]*b[2],f=a[2]*b[1]+a[3]*b[3],g=(c+f)/2,h=Math.sqrt((c+f)*(c+f)-4*(c*f-e*d))/2,i=g+h||1,j=g-h||1;return[Math.sqrt(i),Math.sqrt(j)]},a.normalizeRect=function(a){var b=a.slice(0);return a[0]>a[2]&&(b[0]=a[2],b[2]=a[0]),a[1]>a[3]&&(b[1]=a[3],b[3]=a[1]),b},a.intersect=function(b,c){function d(a,b){return a-b}var e=[b[0],b[2],c[0],c[2]].sort(d),f=[b[1],b[3],c[1],c[3]].sort(d),g=[];return b=a.normalizeRect(b),c=a.normalizeRect(c),e[0]===b[0]&&e[1]===c[0]||e[0]===c[0]&&e[1]===b[0]?(g[0]=e[1],g[2]=e[2],f[0]===b[1]&&f[1]===c[1]||f[0]===c[1]&&f[1]===b[1]?(g[1]=f[1],g[3]=f[2],g):!1):!1},a.sign=function(a){return 0>a?-1:1},a.appendToArray=function(a,b){Array.prototype.push.apply(a,b)},a.prependToArray=function(a,b){Array.prototype.unshift.apply(a,b)},a.extendObj=function(a,b){for(var c in b)a[c]=b[c]},a.getInheritableProperty=function(a,b){for(;a&&!a.has(b);)a=a.get("Parent");return a?a.get(b):null},a.inherit=function(a,b,c){a.prototype=Object.create(b.prototype),a.prototype.constructor=a;for(var d in c)a.prototype[d]=c[d]},a.loadScript=function(a,b){var c=document.createElement("script"),d=!1;c.setAttribute("src",a),b&&(c.onload=function(){d||b(),d=!0}),document.getElementsByTagName("head")[0].appendChild(c)},a}(),PageViewport=PDFJS.PageViewport=function(){function a(a,b,c,d,e,f){this.viewBox=a,this.scale=b,this.rotation=c,this.offsetX=d,this.offsetY=e;var g,h,i,j,k=(a[2]+a[0])/2,l=(a[3]+a[1])/2;switch(c%=360,c=0>c?c+360:c){case 180:g=-1,h=0,i=0,j=1;break;case 90:g=0,h=1,i=1,j=0;break;case 270:g=0,h=-1,i=-1,j=0;break;default:g=1,h=0,i=0,j=-1}f&&(i=-i,j=-j);var m,n,o,p;0===g?(m=Math.abs(l-a[1])*b+d,n=Math.abs(k-a[0])*b+e,o=Math.abs(a[3]-a[1])*b,p=Math.abs(a[2]-a[0])*b):(m=Math.abs(k-a[0])*b+d,n=Math.abs(l-a[1])*b+e,o=Math.abs(a[2]-a[0])*b,p=Math.abs(a[3]-a[1])*b),this.transform=[g*b,h*b,i*b,j*b,m-g*b*k-i*b*l,n-h*b*k-j*b*l],this.width=o,this.height=p,this.fontScale=b}return a.prototype={clone:function(b){b=b||{};var c="scale"in b?b.scale:this.scale,d="rotation"in b?b.rotation:this.rotation;return new a(this.viewBox.slice(),c,d,this.offsetX,this.offsetY,b.dontFlip)},convertToViewportPoint:function(a,b){return Util.applyTransform([a,b],this.transform)},convertToViewportRectangle:function(a){var b=Util.applyTransform([a[0],a[1]],this.transform),c=Util.applyTransform([a[2],a[3]],this.transform);return[b[0],b[1],c[0],c[1]]},convertToPdfPoint:function(a,b){return Util.applyInverseTransform([a,b],this.transform)}},a}(),PDFStringTranslateTable=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,728,711,710,729,733,731,730,732,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8226,8224,8225,8230,8212,8211,402,8260,8249,8250,8722,8240,8222,8220,8221,8216,8217,8218,8482,64257,64258,321,338,352,376,381,305,322,339,353,382,0,8364];PDFJS.createPromiseCapability=createPromiseCapability,function(){function a(a){this._status=b,this._handlers=[];try{a.call(this,this._resolve.bind(this),this._reject.bind(this))}catch(c){this._reject(c)}}if(globalScope.Promise)return"function"!=typeof globalScope.Promise.all&&(globalScope.Promise.all=function(a){var b,c,d=0,e=[],f=new globalScope.Promise(function(a,d){b=a,c=d});return a.forEach(function(a,f){d++,a.then(function(a){e[f]=a,d--,0===d&&b(e)},c)}),0===d&&b(e),f}),"function"!=typeof globalScope.Promise.resolve&&(globalScope.Promise.resolve=function(a){return new globalScope.Promise(function(b){b(a)})}),"function"!=typeof globalScope.Promise.reject&&(globalScope.Promise.reject=function(a){return new globalScope.Promise(function(b,c){c(a)})}),void("function"!=typeof globalScope.Promise.prototype["catch"]&&(globalScope.Promise.prototype["catch"]=function(a){return globalScope.Promise.prototype.then(void 0,a)}));var b=0,c=1,d=2,e=500,f={handlers:[],running:!1,unhandledRejections:[],pendingRejectionCheck:!1,scheduleHandlers:function(a){a._status!==b&&(this.handlers=this.handlers.concat(a._handlers),a._handlers=[],this.running||(this.running=!0,setTimeout(this.runHandlers.bind(this),0)))},runHandlers:function(){for(var a=1,b=Date.now()+a;this.handlers.length>0;){var e=this.handlers.shift(),f=e.thisPromise._status,g=e.thisPromise._value;try{f===c?"function"==typeof e.onResolve&&(g=e.onResolve(g)):"function"==typeof e.onReject&&(g=e.onReject(g),f=c,e.thisPromise._unhandledRejection&&this.removeUnhandeledRejection(e.thisPromise))}catch(h){f=d,g=h}if(e.nextPromise._updateStatus(f,g),Date.now()>=b)break}return this.handlers.length>0?void setTimeout(this.runHandlers.bind(this),0):void(this.running=!1)},addUnhandledRejection:function(a){this.unhandledRejections.push({promise:a,time:Date.now()}),this.scheduleRejectionCheck()},removeUnhandeledRejection:function(a){a._unhandledRejection=!1;for(var b=0;be){var c=this.unhandledRejections[b].promise._value,d="Unhandled rejection: "+c;c.stack&&(d+="\n"+c.stack),warn(d),this.unhandledRejections.splice(b),b--}this.unhandledRejections.length&&this.scheduleRejectionCheck()}.bind(this),e))}};a.all=function(b){function c(a){g._status!==d&&(i=[],f(a))}var e,f,g=new a(function(a,b){e=a,f=b}),h=b.length,i=[];if(0===h)return e(i),g;for(var j=0,k=b.length;k>j;++j){var l=b[j],m=function(a){return function(b){g._status!==d&&(i[a]=b,h--,0===h&&e(i))}}(j);a.isPromise(l)?l.then(m,c):m(l)}return g},a.isPromise=function(a){return a&&"function"==typeof a.then},a.resolve=function(b){return new a(function(a){a(b)})},a.reject=function(b){return new a(function(a,c){c(b)})},a.prototype={_status:null,_value:null,_handlers:null,_unhandledRejection:null,_updateStatus:function(b,e){if(this._status!==c&&this._status!==d){if(b===c&&a.isPromise(e))return void e.then(this._updateStatus.bind(this,c),this._updateStatus.bind(this,d));this._status=b,this._value=e,b===d&&0===this._handlers.length&&(this._unhandledRejection=!0,f.addUnhandledRejection(this)),f.scheduleHandlers(this)}},_resolve:function(a){this._updateStatus(c,a)},_reject:function(a){this._updateStatus(d,a)},then:function(b,c){var d=new a(function(a,b){this.resolve=a,this.reject=b});return this._handlers.push({thisPromise:this,onResolve:b,onReject:c,nextPromise:d}),f.scheduleHandlers(this),d},"catch":function(a){return this.then(void 0,a)}},globalScope.Promise=a}();var StatTimer=function(){function a(a,b,c){for(;a.lengthb;++b){var g=d[b].name;g.length>f&&(f=g.length)}for(b=0,c=d.length;c>b;++b){var h=d[b],i=h.end-h.start;e+=a(h.name," ",f)+" "+i+"ms\n"}return e}},b}();PDFJS.createBlob=function(a,b){if("undefined"!=typeof Blob)return new Blob([a],{type:b});var c=new MozBlobBuilder;return c.append(a),c.getBlob(b)},PDFJS.createObjectURL=function(){var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return function(b,c){if(!PDFJS.disableCreateObjectURL&&"undefined"!=typeof URL&&URL.createObjectURL){var d=PDFJS.createBlob(b,c);return URL.createObjectURL(d)}for(var e="data:"+c+";base64,",f=0,g=b.length;g>f;f+=3){var h=255&b[f],i=255&b[f+1],j=255&b[f+2],k=h>>2,l=(3&h)<<4|i>>4,m=g>f+1?(15&i)<<2|j>>6:64,n=g>f+2?63&j:64;e+=a[k]+a[l]+a[m]+a[n]}return e}}(),MessageHandler.prototype={on:function(a,b,c){var d=this.actionHandler;d[a]&&error('There is already an actionName called "'+a+'"'),d[a]=[b,c]},send:function(a,b,c){var d={action:a,data:b};this.postMessage(d,c)},sendWithPromise:function(a,b,c){var d=this.callbackIndex++,e={action:a,data:b,callbackId:d},f=createPromiseCapability();this.callbacksCapabilities[d]=f;try{this.postMessage(e,c)}catch(g){f.reject(g)}return f.promise},postMessage:function(a,b){b&&this.postMessageTransfers?this.comObj.postMessage(a,b):this.comObj.postMessage(a)}}; -------------------------------------------------------------------------------- /gruntfile.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2015, Jean-Francois Pambrun 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 23 | 24 | module.exports = function (grunt) { 25 | grunt.initConfig({ 26 | pkg: grunt.file.readJSON('package.json'), 27 | 28 | clean: ['dist'], 29 | 30 | version: { 31 | // options: {}, 32 | defaults: { 33 | src: ['bower.json'] 34 | } 35 | }, 36 | 37 | jsbeautifier: { 38 | "default": { 39 | src: ['gruntfile.js', 'test/**/*.js'], 40 | options: { 41 | js: { 42 | jslintHappy: true 43 | } 44 | } 45 | }, 46 | }, 47 | 48 | jshint: { 49 | options: { 50 | '-W097': true, 51 | browser: true, // define globals exposed by modern browsers? 52 | devel: true, 53 | nonstandard: true, 54 | worker: true, 55 | reporter: require('jshint-stylish') // use jshint-stylish to make our errors look and read good 56 | }, 57 | 58 | // when this task is run, lint the Gruntfile and all js files in src 59 | dev: ['Grunfile.js', 'ext/core/jpx.js'] 60 | }, 61 | 62 | uglify: { 63 | options: { 64 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + 65 | '<%= grunt.template.today("yyyy-mm-dd") %> ' + 66 | '| https://github.com/OHIF/image-JPEG2000 */\n' 67 | }, 68 | prod: { 69 | files: { 70 | 'dist/jpx.min.js': ['ext/pdf.js/src/core/jpx.js', 'ext/pdf.js/src/core/arithmetic_decoder.js', 'ext/pdf.js/src/shared/util.js'] 71 | } 72 | } 73 | }, 74 | 75 | concat: { 76 | dev: { 77 | options: { 78 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + 79 | '<%= grunt.template.today("yyyy-mm-dd") %> ' + 80 | '| https://github.com/OHIF/image-JPEG2000 */\n' 81 | }, 82 | src: ['ext/pdf.js/src/core/jpx.js', 'ext/pdf.js/src/core/arithmetic_decoder.js', 'ext/pdf.js/src/shared/util.js'], 83 | dest: 'dist/jpx.js' 84 | } 85 | }, 86 | 87 | nodeunit: { 88 | all: ['test/*_test.js'], 89 | options: { 90 | reporter: 'grunt', 91 | } 92 | }, 93 | 94 | watch: { 95 | serv: { 96 | files: ['src/**/*', 'ext/pdf.js/src/core/*'], 97 | tasks: ['dev'] 98 | } 99 | }, 100 | 101 | connect: { 102 | serv: { 103 | options: { 104 | port: 8000, 105 | hostname: 'localhost', 106 | base: 'dist' 107 | }, 108 | } 109 | }, 110 | 111 | copy: { 112 | dev: { 113 | files: [{ 114 | expand: true, 115 | flatten: true, 116 | src: ['src/*.html'], 117 | dest: 'dist/', 118 | filter: 'isFile' 119 | }, { 120 | expand: true, 121 | flatten: true, 122 | src: ['ext/pdf.js/src/core/jpx.js', 'ext/pdf.js/src/core/arithmetic_decoder.js', 'ext/pdf.js/src/shared/util.js'], 123 | dest: 'dist/js', 124 | filter: 'isFile' 125 | }, { 126 | expand: true, 127 | flatten: true, 128 | src: ['test/data/*.jp2'], 129 | dest: 'dist/test', 130 | filter: 'isFile' 131 | }] 132 | } 133 | } 134 | }); 135 | 136 | grunt.registerTask('dev', ['jshint:dev', 'copy:dev', 'concat:dev']); 137 | grunt.registerTask('prod', ['uglify:prod']); 138 | grunt.registerTask('beautify', ['jsbeautifier']); 139 | grunt.registerTask('serv', ['dev', 'connect:serv', 'watch:serv']); 140 | grunt.registerTask('default', ['jsbeautifier', 'dev', 'prod']); 141 | grunt.registerTask('test', ['nodeunit']); 142 | 143 | grunt.loadNpmTasks('grunt-contrib-jshint'); 144 | grunt.loadNpmTasks('grunt-contrib-clean'); 145 | grunt.loadNpmTasks('grunt-contrib-concat'); 146 | grunt.loadNpmTasks('grunt-contrib-watch'); 147 | grunt.loadNpmTasks('grunt-contrib-copy'); 148 | grunt.loadNpmTasks('grunt-contrib-connect'); 149 | grunt.loadNpmTasks('grunt-contrib-uglify'); 150 | grunt.loadNpmTasks("grunt-jsbeautifier"); 151 | grunt.loadNpmTasks('grunt-version'); 152 | grunt.loadNpmTasks('grunt-contrib-nodeunit'); 153 | 154 | }; 155 | 156 | // Release process: 157 | // 1) Update version numbers in package.json and bower.json 158 | // grunt version 159 | // 2) do a build (needed to update dist versions with correct build number) 160 | // 3) commit changes 161 | // git commit -am "Changes...." 162 | // 4) tag the commit 163 | // git tag -a 0.1.0 -m "Version 0.1.0" 164 | // 5) push to github 165 | // git push origin master --tags 166 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "image-JPEG2000", 3 | "version": "0.3.1", 4 | "private": true, 5 | "devDependencies": { 6 | "dicom-parser": "^0.8.3", 7 | "grunt": "^0.4.5", 8 | "grunt-contrib-clean": "^0.6.0", 9 | "grunt-contrib-concat": "^0.3.0", 10 | "grunt-contrib-connect": "^0.11.2", 11 | "grunt-contrib-copy": "^0.8.1", 12 | "grunt-contrib-jshint": "^0.10.0", 13 | "grunt-contrib-nodeunit": "^0.4.1", 14 | "grunt-contrib-uglify": "^0.6.0", 15 | "grunt-contrib-watch": "^0.6.1", 16 | "grunt-jsbeautifier": "^0.2.8", 17 | "grunt-version": "^1.0.0", 18 | "jshint-stylish": "^1.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | sample 6 | 7 | 8 | 9 | 10 | 11 | 12 | 55 | 56 | 57 | 58 |

Hello world! This is HTML5 Boilerplate.

59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /test/data/000000.dcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/000000.dcm -------------------------------------------------------------------------------- /test/data/000000.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/000000.raw -------------------------------------------------------------------------------- /test/data/860AE501.dcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/860AE501.dcm -------------------------------------------------------------------------------- /test/data/860AE501.dcm.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/860AE501.dcm.jp2 -------------------------------------------------------------------------------- /test/data/860AE501.dcm.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/860AE501.dcm.raw -------------------------------------------------------------------------------- /test/data/cameraman.10.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/cameraman.10.jp2 -------------------------------------------------------------------------------- /test/data/cameraman.10.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/cameraman.10.raw -------------------------------------------------------------------------------- /test/data/cameraman.lossless.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/cameraman.lossless.jp2 -------------------------------------------------------------------------------- /test/data/cameraman.lossless.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/cameraman.lossless.raw -------------------------------------------------------------------------------- /test/data/lossyhdr.dcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/lossyhdr.dcm -------------------------------------------------------------------------------- /test/data/lossyhdr.dcm.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/lossyhdr.dcm.jp2 -------------------------------------------------------------------------------- /test/data/lossyhdr.dcm.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/lossyhdr.dcm.raw -------------------------------------------------------------------------------- /test/data/navimage.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/navimage.jp2 -------------------------------------------------------------------------------- /test/data/navimage.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/navimage.raw -------------------------------------------------------------------------------- /test/data/peppers.10.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/peppers.10.jp2 -------------------------------------------------------------------------------- /test/data/peppers.10.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/peppers.10.raw -------------------------------------------------------------------------------- /test/data/peppers.lossless.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/peppers.lossless.jp2 -------------------------------------------------------------------------------- /test/data/peppers.lossless.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/peppers.lossless.raw -------------------------------------------------------------------------------- /test/data/saturn.jpc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/saturn.jpc -------------------------------------------------------------------------------- /test/data/saturn.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/saturn.raw -------------------------------------------------------------------------------- /test/data/subsampling_1.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/subsampling_1.jp2 -------------------------------------------------------------------------------- /test/data/subsampling_1.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/subsampling_1.raw -------------------------------------------------------------------------------- /test/data/subsampling_2.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/subsampling_2.jp2 -------------------------------------------------------------------------------- /test/data/subsampling_2.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/subsampling_2.raw -------------------------------------------------------------------------------- /test/data/unexpectedEOF.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/unexpectedEOF.jp2 -------------------------------------------------------------------------------- /test/data/unexpectedEOF.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHIF/image-JPEG2000/ed628f6ef0c505377179ce5c952cd7265c87e065/test/data/unexpectedEOF.raw -------------------------------------------------------------------------------- /test/dcm_test.js: -------------------------------------------------------------------------------- 1 | // load modules 2 | global.PDFJS = {}; 3 | var fs = require('fs'); 4 | var vm = require('vm'); 5 | var dicomParser = require('../node_modules/dicom-parser/dist/dicomParser'); 6 | vm.runInThisContext(fs.readFileSync('./dist/jpx.js', 'utf8') + ''); 7 | 8 | function testDcmDecode(filename, test, lossless) { 9 | //load dicom file using 10 | var dicomFileAsBuffer = fs.readFileSync('./test/data/' + filename + '.dcm'); 11 | var dicomFileAsByteArray = new Uint8Array(dicomFileAsBuffer); 12 | var dataSet = dicomParser.parseDicom(dicomFileAsByteArray); 13 | var patientName = dataSet.string('x00100010'); 14 | 15 | 16 | //Extract embedded JPEG2000 stream 17 | var imageBaseOffset = dataSet.elements.x7fe00010.dataOffset + 16; 18 | var layer1 = dataSet.uint32('x00691012'); 19 | var layer2 = dataSet.uint32('x00691013'); 20 | var layer3 = dataSet.uint32('x00691014'); 21 | var jpxData = dicomFileAsByteArray.subarray(imageBaseOffset, layer3); 22 | 23 | //decode JPEG2000 steam 24 | var jpxImage = new global.JpxImage(); 25 | var startTime = Date.now(); 26 | jpxImage.parse(jpxData); 27 | var endTime = Date.now(); 28 | var componentsCount = jpxImage.componentsCount; 29 | var tileCount = jpxImage.tiles.length; 30 | var tileComponents = jpxImage.tiles[0]; 31 | var decodedPixelData = tileComponents.items; 32 | var height = jpxImage.height; 33 | var width = jpxImage.width; 34 | var j2kDecodeTime = (endTime - startTime); 35 | 36 | //load reference raw file 37 | var referenceFileAsBuffer = fs.readFileSync('./test/data/' + filename + '.raw'); 38 | 39 | //compare pixel by pixel 40 | var numDiff = 0; 41 | var cumDiff = 0; 42 | var maxErr = 0; 43 | for (var i = 0; i < height * width; i++) { 44 | referenceValue = referenceFileAsBuffer.readInt16LE(i * 2); 45 | if (Math.abs(referenceValue - decodedPixelData[i]) > 0) { 46 | numDiff++; 47 | cumDiff += Math.pow(referenceValue - decodedPixelData[i], 2); 48 | if (Math.abs(referenceValue - decodedPixelData[i]) > maxErr) { 49 | maxErr = Math.abs(referenceValue - decodedPixelData[i]); 50 | } 51 | } 52 | } 53 | 54 | if ((lossless ? maxErr === 0 : maxErr <= 1)) { 55 | var buf = new Buffer(height * width * 2); 56 | for (var i = 0; i < height * width; i++) { 57 | buf.writeInt16LE(decodedPixelData[i], i * 2); 58 | } 59 | fs.writeFileSync('./test/out_' + filename + '.raw', buf); 60 | } 61 | 62 | var numSamples = (height * width * componentsCount); 63 | 64 | test.ok((lossless ? maxErr === 0 : maxErr <= 1), numDiff + ' / ' + numSamples + ' degraded pixels, MSE=' + cumDiff / numSamples + ' Max err= ' + maxErr); 65 | return { 66 | numDiff: numDiff, 67 | cumDiff: cumDiff, 68 | decodeTime: (endTime - startTime), 69 | numSamples: numSamples, 70 | } 71 | } 72 | 73 | exports.dcm_00000 = function (test) { 74 | var result = testDcmDecode('000000', test, true) 75 | test.done(); 76 | }; 77 | -------------------------------------------------------------------------------- /test/imcompare.m: -------------------------------------------------------------------------------- 1 | function [] = imcompare(i1name, i2name, size, precision) 2 | % ex: 3 | % imcompare('data/000000.raw', '/test/out_000000.raw', [512 512 1], 'int16'); 4 | % imcompare('data/cameraman.10.raw', '/out_cameraman.10.raw', [256 256 1], 'uint8') 5 | % imcompare('data/saturn.raw', 'out_saturn.raw', [1500 1200 1], 'uint8') 6 | % imcompare('data/Uint16FDR_lossless.raw', 'out_Uint16FDR_lossless.raw', [1292 2648 1], 'uint16') 7 | % imcompare('data/lossyhdr.dcm.raw', 'out_lossyhdr.dcm.raw', [1238 1614 1], 'uint16') 8 | 9 | I1 =multibandread(i1name, size, precision, 0, 'bip', 'ieee-le'); 10 | I2 =multibandread(i2name, size, precision, 0, 'bip', 'ieee-le'); 11 | imshow(abs(I1-I2), []) 12 | figure;imshow([I1; I2], []) 13 | figure;imshow([I2], []) 14 | 15 | end 16 | -------------------------------------------------------------------------------- /test/img2raw.m: -------------------------------------------------------------------------------- 1 | function [] = img2raw(inname, outname) 2 | [pathstr,name,ext] = fileparts(inname); 3 | if (strcmp(ext, '.dcm')) 4 | I = dicomread(inname); 5 | else 6 | I = imread(inname); 7 | end 8 | 9 | multibandwrite(I, outname, 'bip'); 10 | end 11 | -------------------------------------------------------------------------------- /test/jp2_16bit_test.js: -------------------------------------------------------------------------------- 1 | // load modules 2 | global.PDFJS = {}; 3 | var fs = require('fs'); 4 | var vm = require('vm'); 5 | vm.runInThisContext(fs.readFileSync('./dist/jpx.js', 'utf8') + ''); 6 | 7 | function testJp2Decode(filename, test, lossless) { 8 | //load jp2 file using 9 | var jp2FileAsBuffer = fs.readFileSync('./test/data/' + filename + '.jp2'); 10 | var jp2FileAsByteArray = new Uint8Array(jp2FileAsBuffer); 11 | 12 | //decode JPEG2000 steam 13 | var jpxImage = new global.JpxImage(); 14 | var startTime = Date.now(); 15 | jpxImage.parse(jp2FileAsByteArray); 16 | var endTime = Date.now(); 17 | var componentsCount = jpxImage.componentsCount; 18 | var tileCount = jpxImage.tiles.length; 19 | var tileComponents = jpxImage.tiles[0]; 20 | var decodedPixelData = tileComponents.items; 21 | var height = jpxImage.height; 22 | var width = jpxImage.width; 23 | 24 | //load reference raw file 25 | var referenceFileAsBuffer = fs.readFileSync('./test/data/' + filename + '.raw'); 26 | 27 | 28 | //compare pixel by pixel 29 | var numDiff = 0; 30 | var cumDiff = 0; 31 | var maxErr = 0; 32 | for (var i = 0; i < height * width; i++) { 33 | referenceValue = referenceFileAsBuffer.readInt16LE(i * 2); 34 | if (Math.abs(referenceValue - decodedPixelData[i]) > 0) { 35 | numDiff++; 36 | cumDiff += Math.pow(referenceValue - decodedPixelData[i], 2); 37 | if (Math.abs(referenceValue - decodedPixelData[i]) > maxErr) { 38 | maxErr = Math.abs(referenceValue - decodedPixelData[i]); 39 | } 40 | } 41 | } 42 | 43 | //write output 44 | var buf = new Buffer(height * width * 2); 45 | for (var i = 0; i < height * width; i++) { 46 | buf.writeInt16LE(decodedPixelData[i], i * 2); 47 | } 48 | fs.writeFileSync('./test/out_' + filename + '.raw', buf); 49 | 50 | var numSamples = (height * width * componentsCount); 51 | 52 | test.ok((lossless ? maxErr === 0 : maxErr <= 1), numDiff + ' / ' + numSamples + ' degraded pixels, MSE=' + cumDiff / numSamples + ' Max err= ' + maxErr); 53 | return { 54 | numDiff: numDiff, 55 | cumDiff: cumDiff, 56 | decodeTime: (endTime - startTime), 57 | numSamples: numSamples, 58 | } 59 | } 60 | 61 | exports.navimage = function (test) { 62 | var result = testJp2Decode('navimage', test, false) 63 | test.done(); 64 | }; 65 | -------------------------------------------------------------------------------- /test/jp2_U16bit_test.js: -------------------------------------------------------------------------------- 1 | // load modules 2 | global.PDFJS = {}; 3 | var fs = require('fs'); 4 | var vm = require('vm'); 5 | vm.runInThisContext(fs.readFileSync('./dist/jpx.js', 'utf8') + ''); 6 | 7 | function testJp2Decode(filename, test, lossless) { 8 | //load jp2 file using 9 | var jp2FileAsBuffer = fs.readFileSync('./test/data/' + filename + '.jp2'); 10 | var jp2FileAsByteArray = new Uint8Array(jp2FileAsBuffer); 11 | 12 | //decode JPEG2000 steam 13 | var jpxImage = new global.JpxImage(); 14 | var startTime = Date.now(); 15 | jpxImage.parse(jp2FileAsByteArray); 16 | var endTime = Date.now(); 17 | var componentsCount = jpxImage.componentsCount; 18 | var tileCount = jpxImage.tiles.length; 19 | var tileComponents = jpxImage.tiles[0]; 20 | var decodedPixelData = tileComponents.items; 21 | var height = jpxImage.height; 22 | var width = jpxImage.width; 23 | 24 | //load reference raw file 25 | var referenceFileAsBuffer = fs.readFileSync('./test/data/' + filename + '.raw'); 26 | 27 | 28 | //compare pixel by pixel 29 | var numDiff = 0; 30 | var cumDiff = 0; 31 | var maxErr = 0; 32 | for (var i = 0; i < height * width; i++) { 33 | referenceValue = referenceFileAsBuffer.readUInt16LE(i * 2); 34 | if (Math.abs(referenceValue - decodedPixelData[i]) > 0) { 35 | numDiff++; 36 | cumDiff += Math.pow(referenceValue - decodedPixelData[i], 2); 37 | if (Math.abs(referenceValue - decodedPixelData[i]) > maxErr) { 38 | maxErr = Math.abs(referenceValue - decodedPixelData[i]); 39 | } 40 | } 41 | } 42 | 43 | //write output 44 | var buf = new Buffer(height * width * 2); 45 | for (var i = 0; i < height * width; i++) { 46 | buf.writeUInt16LE(decodedPixelData[i], i * 2); 47 | } 48 | fs.writeFileSync('./test/out_' + filename + '.raw', buf); 49 | 50 | var numSamples = (height * width * componentsCount); 51 | 52 | test.ok((lossless ? maxErr === 0 : maxErr <= 1), numDiff + ' / ' + numSamples + ' degraded pixels, MSE=' + cumDiff / numSamples + ' Max err= ' + maxErr); 53 | return { 54 | numDiff: numDiff, 55 | cumDiff: cumDiff, 56 | decodeTime: (endTime - startTime), 57 | numSamples: numSamples, 58 | } 59 | } 60 | 61 | exports.file_860AE501 = function (test) { 62 | var result = testJp2Decode('860AE501.dcm', test, true) 63 | test.done(); 64 | }; 65 | 66 | exports.file_unexpectedEOF = function (test) { 67 | var result = testJp2Decode('unexpectedEOF', test, true) 68 | test.done(); 69 | }; 70 | 71 | exports.file_lossyhdr = function (test) { 72 | var result = testJp2Decode('lossyhdr.dcm', test, false) 73 | test.done(); 74 | }; 75 | -------------------------------------------------------------------------------- /test/jp2_test.js: -------------------------------------------------------------------------------- 1 | // load modules 2 | global.PDFJS = {}; 3 | var fs = require('fs'); 4 | var vm = require('vm'); 5 | vm.runInThisContext(fs.readFileSync('./dist/jpx.js', 'utf8') + ''); 6 | 7 | function testJp2Decode(filename, test, lossless) { 8 | //load jp2 file using 9 | var jp2FileAsBuffer = fs.readFileSync('./test/data/' + filename + '.jp2'); 10 | var jp2FileAsByteArray = new Uint8Array(jp2FileAsBuffer); 11 | 12 | //decode JPEG2000 steam 13 | var jpxImage = new global.JpxImage(); 14 | var startTime = Date.now(); 15 | jpxImage.parse(jp2FileAsByteArray); 16 | var endTime = Date.now(); 17 | var componentsCount = jpxImage.componentsCount; 18 | var tileCount = jpxImage.tiles.length; 19 | var tileComponents = jpxImage.tiles[0]; 20 | var decodedPixelData = tileComponents.items; 21 | var height = jpxImage.height; 22 | var width = jpxImage.width; 23 | 24 | //load reference raw file 25 | var referenceFileAsBuffer = fs.readFileSync('./test/data/' + filename + '.raw'); 26 | var referenceFileAsByteArray = new Uint8Array(referenceFileAsBuffer); 27 | 28 | //compare pixel by pixel 29 | var numDiff = 0; 30 | var cumDiff = 0; 31 | var maxErr = 0; 32 | for (var i = 0; i < height * width; i++) { 33 | if (Math.abs(referenceFileAsByteArray[i] - decodedPixelData[i]) > 0) { 34 | numDiff++; 35 | cumDiff += Math.pow(referenceFileAsByteArray[i] - decodedPixelData[i], 2); 36 | if (Math.abs(referenceFileAsByteArray[i] - decodedPixelData[i]) > maxErr) { 37 | maxErr = Math.abs(referenceFileAsByteArray[i] - decodedPixelData[i]); 38 | } 39 | } 40 | } 41 | 42 | if ((lossless ? maxErr === 0 : maxErr <= 1)) { 43 | fs.writeFileSync('./test/out_' + filename + '.raw', new Buffer(decodedPixelData)); 44 | } 45 | 46 | var numSamples = (height * width * componentsCount); 47 | test.ok((lossless ? maxErr === 0 : maxErr <= 1), numDiff + ' / ' + numSamples + ' degraded pixels, MSE=' + cumDiff / numSamples + ' Max err= ' + maxErr); 48 | 49 | return { 50 | numDiff: numDiff, 51 | cumDiff: cumDiff, 52 | maxErr: maxErr, 53 | decodeTime: (endTime - startTime), 54 | numSamples: numSamples, 55 | } 56 | 57 | } 58 | 59 | exports.peppers_lossless = function (test) { 60 | var result = testJp2Decode('peppers.lossless', test, true) 61 | test.done(); 62 | }; 63 | 64 | exports.peppers_10 = function (test) { 65 | var result = testJp2Decode('peppers.10', test, false) 66 | test.done(); 67 | }; 68 | 69 | exports.cameraman_lossless = function (test) { 70 | var result = testJp2Decode('cameraman.lossless', test, true) 71 | test.done(); 72 | }; 73 | 74 | exports.cameraman_10 = function (test) { 75 | var result = testJp2Decode('cameraman.10', test, false) 76 | test.done(); 77 | }; 78 | 79 | 80 | exports.subsampling_1 = function (test) { 81 | var result = testJp2Decode('subsampling_1', test, false) 82 | test.done(); 83 | }; 84 | 85 | exports.subsampling_2 = function (test) { 86 | var result = testJp2Decode('subsampling_2', test, false) 87 | test.done(); 88 | }; 89 | -------------------------------------------------------------------------------- /test/jpc_test.js: -------------------------------------------------------------------------------- 1 | // load modules 2 | global.PDFJS = {}; 3 | var fs = require('fs'); 4 | var vm = require('vm'); 5 | vm.runInThisContext(fs.readFileSync('./dist/jpx.js', 'utf8') + ''); 6 | 7 | function testJp2Decode(filename, test, lossless) { 8 | //load jp2 file using 9 | var jp2FileAsBuffer = fs.readFileSync('./test/data/' + filename + '.jpc'); 10 | var jp2FileAsByteArray = new Uint8Array(jp2FileAsBuffer); 11 | 12 | //decode JPEG2000 steam 13 | var jpxImage = new global.JpxImage(); 14 | var startTime = Date.now(); 15 | jpxImage.parse(jp2FileAsByteArray); 16 | var endTime = Date.now(); 17 | var componentsCount = jpxImage.componentsCount; 18 | var tileCount = jpxImage.tiles.length; 19 | var tileComponents = jpxImage.tiles[0]; 20 | var decodedPixelData = tileComponents.items; 21 | var height = jpxImage.height; 22 | var width = jpxImage.width; 23 | 24 | //load reference raw file 25 | var referenceFileAsBuffer = fs.readFileSync('./test/data/' + filename + '.raw'); 26 | var referenceFileAsByteArray = new Uint8Array(referenceFileAsBuffer); 27 | 28 | //compare pixel by pixel 29 | var numDiff = 0; 30 | var cumDiff = 0; 31 | var maxErr = 0; 32 | for (var i = 0; i < height * width; i++) { 33 | if (Math.abs(referenceFileAsByteArray[i] - decodedPixelData[i]) > 0) { 34 | numDiff++; 35 | cumDiff += Math.pow(referenceFileAsByteArray[i] - decodedPixelData[i], 2); 36 | if (Math.abs(referenceFileAsByteArray[i] - decodedPixelData[i]) > maxErr) { 37 | maxErr = Math.abs(referenceFileAsByteArray[i] - decodedPixelData[i]); 38 | } 39 | } 40 | } 41 | 42 | if ((lossless ? maxErr === 0 : maxErr <= 1)) { 43 | fs.writeFileSync('./test/out_' + filename + '.raw', new Buffer(decodedPixelData)); 44 | } 45 | 46 | var numSamples = (height * width * componentsCount); 47 | test.ok((lossless ? maxErr === 0 : maxErr <= 1), numDiff + ' / ' + numSamples + ' degraded pixels, MSE=' + cumDiff / numSamples + ' Max err= ' + maxErr); 48 | 49 | return { 50 | numDiff: numDiff, 51 | cumDiff: cumDiff, 52 | maxErr: maxErr, 53 | decodeTime: (endTime - startTime), 54 | numSamples: numSamples, 55 | } 56 | 57 | } 58 | 59 | exports.saturn = function (test) { 60 | var result = testJp2Decode('saturn', test, true) 61 | test.done(); 62 | }; 63 | --------------------------------------------------------------------------------