├── .gitignore ├── demo ├── image.png ├── demo.html └── demo.js ├── .babelrc ├── demo.config.js ├── umd.min.config.js ├── esm.min.config.js ├── umd.config.js ├── esm.config.js ├── LICENSE ├── package.json ├── README.md ├── src ├── demo.js └── index.js └── dist ├── xBRjs.min.esm.js ├── xBRjs.min.umd.js ├── xBRjs.esm.js └── xBRjs.umd.js /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules 3 | -------------------------------------------------------------------------------- /demo/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joseprio/xBRjs/HEAD/demo/image.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "browsers": ["last 2 versions", "> 5% in BE"] 8 | }, 9 | "modules": false 10 | } 11 | ] 12 | ] 13 | } -------------------------------------------------------------------------------- /demo.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/demo.js', 5 | output: { 6 | filename: 'demo.js', 7 | path: path.resolve(__dirname, 'demo'), 8 | }, 9 | optimization: { 10 | minimize: false, 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /demo/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | xBR js demo 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 |
12 |
13 | Best results with cartoon or 8-bit images 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /umd.min.config.js: -------------------------------------------------------------------------------- 1 | const EsmWebpackPlugin = require('@purtuga/esm-webpack-plugin'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | mode: 'production', 6 | entry: './src/index.js', 7 | output: { 8 | library: 'xBRjs', 9 | libraryTarget: 'umd', 10 | filename: 'xBRjs.min.umd.js' 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.js$/, 16 | exclude: /(node_modules)/, 17 | use: { 18 | loader: 'babel-loader' 19 | } 20 | } 21 | ] 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /esm.min.config.js: -------------------------------------------------------------------------------- 1 | const EsmWebpackPlugin = require('@purtuga/esm-webpack-plugin'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | entry: './src/index.js', 6 | output: { 7 | library: 'xBRjs', 8 | libraryTarget: 'var', 9 | filename: 'xBRjs.min.esm.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.js$/, 15 | exclude: /node_modules/, 16 | use: { 17 | loader: 'babel-loader' 18 | } 19 | } 20 | ] 21 | }, 22 | plugins: [ 23 | new EsmWebpackPlugin() 24 | ] 25 | }; 26 | -------------------------------------------------------------------------------- /umd.config.js: -------------------------------------------------------------------------------- 1 | const EsmWebpackPlugin = require('@purtuga/esm-webpack-plugin'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | mode: 'production', 6 | entry: './src/index.js', 7 | output: { 8 | library: 'xBRjs', 9 | libraryTarget: 'umd', 10 | filename: 'xBRjs.umd.js' 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.js$/, 16 | exclude: /node_modules/, 17 | use: { 18 | loader: 'babel-loader' 19 | } 20 | } 21 | ] 22 | }, 23 | optimization: { 24 | minimize: false, 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /esm.config.js: -------------------------------------------------------------------------------- 1 | const EsmWebpackPlugin = require('@purtuga/esm-webpack-plugin'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | mode: 'production', 6 | entry: './src/index.js', 7 | output: { 8 | library: 'xBRjs', 9 | libraryTarget: 'var', 10 | filename: 'xBRjs.esm.js' 11 | }, 12 | optimization: { 13 | minimize: false, 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | use: { 21 | loader: 'babel-loader' 22 | } 23 | } 24 | ] 25 | }, 26 | plugins: [ 27 | new EsmWebpackPlugin() 28 | ] 29 | }; 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Josep del Rio 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xbr-js", 3 | "version": "2.0.1", 4 | "description": "xBRjs is a library to upscale images", 5 | "module": "src/index.js", 6 | "scripts": { 7 | "build": "webpack --config demo.config.js && webpack --config umd.config.js && webpack --config umd.min.config.js && webpack --config esm.config.js && webpack --config esm.min.config.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/joseprio/xBRjs.git" 12 | }, 13 | "keywords": [ 14 | "xbr", 15 | "image", 16 | "scale", 17 | "upscale", 18 | "resize", 19 | "enlarge" 20 | ], 21 | "author": "Josep del Rio", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/joseprio/xBRjs/issues" 25 | }, 26 | "homepage": "https://github.com/joseprio/xBRjs#readme", 27 | "devDependencies": { 28 | "@babel/core": "^7.7.7", 29 | "@babel/preset-env": "^7.7.7", 30 | "@purtuga/esm-webpack-plugin": "^1.2.1", 31 | "babel-loader": "^8.0.6", 32 | "webpack": "^4.41.5", 33 | "webpack-cli": "^3.3.10" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xBRjs 2 | 3 | [![NPM Version](https://img.shields.io/npm/v/xbr-js.svg)](https://www.npmjs.com/package/xbr-js) 4 | 5 | JS implementation of the xBR image scaling algorytm by Hyllian. 6 | 7 | ## Installation 8 | 9 | ```sh 10 | # npm 11 | npm install xbr-js --save 12 | 13 | # yarn 14 | yarn add xbr-js 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```js 20 | import {xbr2x, xbr3x, xbr4x} from 'xbr-js'; 21 | ``` 22 | 23 | ```js 24 | // if you have an , draw it on a canvas first 25 | const canvas = document.createElement('canvas'); 26 | const sourceWidth = canvas.width = img.width; 27 | const sourceHeight = canvas.height = img.height; 28 | const context = canvas.getContext('2d'); 29 | context.drawImage(img, 0, 0); 30 | 31 | // the following code will apply xbr2x to an existing canvas 32 | canvas.width = sourceWidth * 2; 33 | canvas.height = sourceHeight * 2; 34 | 35 | const originalImageData = context.getImageData(0, 0, sourceWidth, sourceHeight); 36 | const originalPixelView = new Uint32Array(originalImageData.data.buffer); 37 | const scaledPixelView = xbr2x(originalPixelView, sourceWidth, sourceHeight); 38 | const scaledImageData = context.createImageData(canvas.width, canvas.height); 39 | scaledImageData.data.set(new Uint8ClampedArray(scaledPixelView.buffer)); 40 | 41 | context.putImageData(scaledImageData, 0, 0); 42 | ``` 43 | 44 | 45 | ## API 46 | 47 | ### xbr2x([array], [width], [height], [options]) ⇒ `Uint32Array` 48 | Returns a typed array with the pixels that form the scaled image. 49 | 50 | | Param | Type | Description | 51 | |-------|------|-------------| 52 | | array | Uint32Array | The input pixels in ARGB format | 53 | | width | number | The width of the original image | 54 | | height | number | The height of the original image | 55 | | [options.blendColors] | boolean | Determines if new colors will be created. Defaults to true. | 56 | | [options.scaleAlpha] | boolean | Determines whether to upscale the alpha channel using the xBR algorythm. Defaults to false. | 57 | 58 | ## Demo 59 | 60 | Check it out [here](http://joseprio.github.io/xBRjs/demo/demo.html). 61 | -------------------------------------------------------------------------------- /src/demo.js: -------------------------------------------------------------------------------- 1 | import {xbr2x, xbr3x, xbr4x} from './index.js'; 2 | 3 | function readURL(input) { 4 | if (input.files && input.files[0]) { 5 | let reader = new FileReader(); 6 | reader.onload = function(e) { 7 | processURL(e.target.result); 8 | } 9 | 10 | reader.readAsDataURL(input.files[0]); 11 | } 12 | } 13 | 14 | export function applyXBR(image, factor) { 15 | const canvas = document.createElement('canvas'); 16 | const 17 | sourceWidth = image.width, 18 | sourceHeight = image.height; 19 | canvas.width = sourceWidth; 20 | canvas.height = sourceHeight; 21 | 22 | const context = canvas.getContext('2d'); 23 | context.drawImage(image, 0, 0); 24 | 25 | const 26 | scaledWidth = sourceWidth * factor, 27 | scaledHeight = sourceHeight * factor, 28 | originalImageData = context.getImageData( 29 | 0, 30 | 0, 31 | sourceWidth, 32 | sourceHeight); 33 | 34 | const originalPixelView = new Uint32Array(originalImageData.data.buffer); 35 | 36 | let scaledPixelView; 37 | switch (factor) { 38 | case 2: 39 | scaledPixelView = xbr2x(originalPixelView, sourceWidth, sourceHeight); 40 | break; 41 | case 3: 42 | scaledPixelView = xbr3x(originalPixelView, sourceWidth, sourceHeight); 43 | break; 44 | case 4: 45 | scaledPixelView = xbr4x(originalPixelView, sourceWidth, sourceHeight); 46 | break; 47 | } 48 | 49 | const scaledImageData = new ImageData(new Uint8ClampedArray(scaledPixelView.buffer), scaledWidth, scaledHeight); 50 | canvas.width = scaledWidth; 51 | canvas.height = scaledHeight; 52 | 53 | context.putImageData(scaledImageData, 0, 0); 54 | 55 | return canvas; 56 | } 57 | 58 | function processURL(url) { 59 | let image = new Image(); 60 | image.src=url; 61 | 62 | /*When image loads...*/ 63 | image.onload = function(e) { 64 | image.setAttribute('width', image.width); 65 | image.setAttribute('height', image.height); 66 | /*Apply 2xBR*/ 67 | let resultCanvas = applyXBR(image, 2); 68 | 69 | document.body.appendChild(resultCanvas); 70 | resultCanvas = applyXBR(image, 3); 71 | 72 | document.body.appendChild(resultCanvas); 73 | resultCanvas = applyXBR(image, 4); 74 | 75 | document.body.appendChild(resultCanvas); 76 | } 77 | 78 | document.body.appendChild(image); 79 | } 80 | 81 | window.onload = function() { 82 | var inputFile = document.getElementById('processImage'); 83 | inputFile.addEventListener('change', () => readURL(inputFile)); 84 | 85 | let original = document.getElementById("original"); 86 | processURL("image.png"); 87 | } 88 | 89 | -------------------------------------------------------------------------------- /dist/xBRjs.min.esm.js: -------------------------------------------------------------------------------- 1 | var xBRjs=function(r){var n={};function t(e){if(n[e])return n[e].exports;var u=n[e]={i:e,l:!1,exports:{}};return r[e].call(u.exports,u,u.exports,t),u.l=!0,u.exports}return t.m=r,t.c=n,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{enumerable:!0,get:e})},t.r=function(r){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})},t.t=function(r,n){if(1&n&&(r=t(r)),8&n)return r;if(4&n&&"object"==typeof r&&r&&r.__esModule)return r;var e=Object.create(null);if(t.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:r}),2&n&&"string"!=typeof r)for(var u in r)t.d(e,u,function(n){return r[n]}.bind(null,u));return e},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,"a",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p="",t(t.s=0)}([function(r,n,t){"use strict";function e(r,n){return function(r){if(Array.isArray(r))return r}(r)||function(r,n){if(!(Symbol.iterator in Object(r)||"[object Arguments]"===Object.prototype.toString.call(r)))return;var t=[],e=!0,u=!1,a=void 0;try{for(var o,i=r[Symbol.iterator]();!(e=(o=i.next()).done)&&(t.push(o.value),!n||t.length!==n);e=!0);}catch(r){u=!0,a=r}finally{try{e||null==i.return||i.return()}finally{if(u)throw a}}return t}(r,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}t.r(n),t.d(n,"xbr2x",(function(){return A})),t.d(n,"xbr3x",(function(){return m})),t.d(n,"xbr4x",(function(){return B}));function u(r){var n=255&r,t=(65280&r)>>8,e=(16711680&r)>>16;return[.299*n+.587*t+.114*e,-.168736*n+-.331264*t+.5*e,.5*n+-.418688*t+-.081312*e]}function a(r,n,t){var e=(4278190080&r)>>24&255,a=(4278190080&n)>>24&255;if(0===e&&0===a)return 0;if(!t&&(e<255||a<255))return 1e6;if(0===e||0===a)return 1e6;var o=u(r),i=u(n);return 48*Math.abs(o[0]-i[0])+7*Math.abs(o[1]-i[1])+6*Math.abs(o[2]-i[2])}function o(r,n,t){var e=(4278190080&r)>>24&255,a=(4278190080&n)>>24&255;if(0===e&&0===a)return!0;if(!t&&(e<255||a<255))return!1;if(0===e||0===a)return!1;var o=u(r),i=u(n);return!(Math.abs(o[0]-i[0])>48)&&(!(Math.abs(o[1]-i[1])>7)&&!(Math.abs(o[2]-i[2])>6))}function i(r,n,t,e){var u,a,o,i=(4278190080&r)>>24&255,f=(4278190080&n)>>24&255;return 0===i?(u=255&n,a=(65280&n)>>8,o=(16711680&n)>>16):0===f?(u=255&r,a=(65280&r)>>8,o=(16711680&r)>>16):(u=(e*(255&n)+t*(255&r))/(t+e),a=(e*((65280&n)>>8)+t*((65280&r)>>8))/(t+e),o=(e*((16711680&n)>>16)+t*((16711680&r)>>16))/(t+e)),~~u|~~a<<8|~~o<<16|~~((e*f+t*i)/(t+e))<<24}function f(r,n,t,e,u){var a=n-1;a<0&&(a=0);var o=n-2;o<0&&(o=0);var i=n+1;i>=e&&(i=e-1);var f=n+2;f>=e&&(f=e-1);var c=t-1;c<0&&(c=0);var l=t-2;l<0&&(l=0);var v=t+1;v>=u&&(v=u-1);var s=t+2;return s>=u&&(s=u-1),[r[a+l*e],r[n+l*e],r[i+l*e],r[o+c*e],r[a+c*e],r[n+c*e],r[i+c*e],r[f+c*e],r[o+t*e],r[a+t*e],r[n+t*e],r[i+t*e],r[f+t*e],r[o+v*e],r[a+v*e],r[n+v*e],r[i+v*e],r[f+v*e],r[a+s*e],r[n+s*e],r[i+s*e]]}function c(r,n,t,u,a,o,i,c,l,v,s){var x,b,d,p,j=e(f(r,n,t,u,a),21),h=j[0],_=j[1],A=j[2],m=j[3],B=j[4],M=j[5],R=j[6],g=j[7],O=j[8],S=j[9],w=j[10],$=j[11],C=j[12],P=j[13],T=j[14],U=j[15],E=j[16],I=j[17],k=j[18],q=j[19];x=b=d=p=w;var z=e(y(w,E,U,$,T,R,S,M,C,I,q,j[20],b,d,p,v,s),3);b=z[0],d=z[1];var D=e(y(w,R,$,M,E,B,U,S,_,A,C,g,x,p=z[2],b,v,s),3);x=D[0],p=D[1];var F=e(y(w,B,M,S,R,T,$,U,O,m,_,h,d,b=D[2],x,v,s),3);d=F[0],b=F[1];var G=e(y(w,T,S,U,B,E,M,$,q,k,O,P,p,x=F[2],d,v,s),3);p=G[0],x=G[1],d=G[2],o[i+c*l]=x,o[i+1+c*l]=b,o[i+(c+1)*l]=d,o[i+1+(c+1)*l]=p}function l(r,n,t,u,a,o,i,c,l,v,s){var x,b,d,p,y,h,_,A,m,B=e(f(r,n,t,u,a),21),M=B[0],R=B[1],g=B[2],O=B[3],S=B[4],w=B[5],$=B[6],C=B[7],P=B[8],T=B[9],U=B[10],E=B[11],I=B[12],k=B[13],q=B[14],z=B[15],D=B[16],F=B[17],G=B[18],H=B[19];x=b=d=p=y=h=_=A=m=U;var J=e(j(U,D,z,E,q,$,T,w,I,F,H,B[20],d,h,_,A,m,v,s),5);d=J[0],h=J[1],_=J[2],A=J[3];var K=e(j(U,$,E,w,D,S,z,T,R,g,I,C,x,b,m=J[4],h,d,v,s),5);x=K[0],b=K[1],m=K[2],h=K[3];var L=e(j(U,S,w,T,$,q,E,z,P,O,R,M,_,p,d=K[4],b,x,v,s),5);_=L[0],p=L[1],d=L[2],b=L[3];var N=e(j(U,q,T,z,S,D,w,E,H,G,P,k,m,A,x=L[4],p,_,v,s),5);m=N[0],A=N[1],x=N[2],p=N[3],_=N[4],o[i+c*l]=x,o[i+1+c*l]=b,o[i+2+c*l]=d,o[i+(c+1)*l]=p,o[i+1+(c+1)*l]=y,o[i+2+(c+1)*l]=h,o[i+(c+2)*l]=_,o[i+1+(c+2)*l]=A,o[i+2+(c+2)*l]=m}function v(r,n,t,u,a,o,i,c,l,v,s){var x,b,d,p,y,j,_,A,m,B,M,R,g,O,S,w,$=e(f(r,n,t,u,a),21),C=$[0],P=$[1],T=$[2],U=$[3],E=$[4],I=$[5],k=$[6],q=$[7],z=$[8],D=$[9],F=$[10],G=$[11],H=$[12],J=$[13],K=$[14],L=$[15],N=$[16],Q=$[17],V=$[18],W=$[19];x=b=d=p=y=j=_=A=m=B=M=R=g=O=S=w=F;var X=e(h(F,N,L,G,K,k,D,I,H,Q,W,$[20],w,S,R,p,A,M,O,g,v,s),8);w=X[0],S=X[1],R=X[2],p=X[3],A=X[4],M=X[5],O=X[6],g=X[7];var Y=e(h(F,k,G,I,N,E,L,D,P,T,H,q,p,A,d,x,b,_,R,w,v,s),8);p=Y[0],A=Y[1],d=Y[2],x=Y[3],b=Y[4],_=Y[5],R=Y[6],w=Y[7];var Z=e(h(F,E,I,D,k,K,G,L,z,U,P,C,x,b,y,g,m,j,d,p,v,s),8);x=Z[0],b=Z[1],y=Z[2],g=Z[3],m=Z[4],j=Z[5],d=Z[6],p=Z[7];var rr=e(h(F,K,D,L,E,N,I,G,W,V,z,J,g,m,O,w,S,B,y,x,v,s),8);g=rr[0],m=rr[1],O=rr[2],w=rr[3],S=rr[4],B=rr[5],y=rr[6],x=rr[7],o[i+c*l]=x,o[i+1+c*l]=b,o[i+2+c*l]=d,o[i+3+c*l]=p,o[i+(c+1)*l]=y,o[i+1+(c+1)*l]=j,o[i+2+(c+1)*l]=_,o[i+3+(c+1)*l]=A,o[i+(c+2)*l]=m,o[i+1+(c+2)*l]=B,o[i+2+(c+2)*l]=M,o[i+3+(c+2)*l]=R,o[i+(c+3)*l]=g,o[i+1+(c+3)*l]=O,o[i+2+(c+3)*l]=S,o[i+3+(c+3)*l]=w}function s(r,n,t){return t?i(r,n,7,1):r}function x(r,n,t){return t?i(r,n,3,1):r}function b(r,n,t){return t?i(r,n,1,1):r}function d(r,n,t){return t?i(r,n,1,3):n}function p(r,n,t){return t?i(r,n,1,7):n}function y(r,n,t,e,u,i,f,c,l,v,s,p,y,j,h,_,A){if(!(r!=t&&r!=e))return[y,j,h];var m=a(r,i,A)+a(r,u,A)+a(n,s,A)+a(n,l,A)+(a(t,e)<<2),B=a(t,f,A)+a(t,p,A)+a(e,v,A)+a(e,c,A)+(a(r,n,A)<<2),M=a(r,e,A)<=a(r,t,A)?e:t;if(m=g<<1&&O){if(R<<1<=g&&S){var w=function(r,n,t,e){return[d(r,t,e),x(n,t,e)]}(h,j,M,_);h=w[0],j=w[1]}if(R>=g<<1&&O){var $=function(r,n,t,e){return[d(r,t,e),x(n,t,e)]}(h,y,M,_);h=$[0],y=$[1]}}else h=function(r,n,t){return b(r,n,t)}(h,M,_)}else m<=B&&(h=x(h,M,_));return[y,j,h]}function j(r,n,t,u,i,f,c,l,v,y,j,h,_,A,m,B,M,R,g){if(!(r!=t&&r!=u))return[_,A,m,B,M];var O=a(r,f,g)+a(r,i,g)+a(n,j,g)+a(n,v,g)+(a(t,u,g)<<2),S=a(t,c,g)+a(t,h,g)+a(u,y,g)+a(u,l,g)+(a(r,n,g)<<2);if(O=$<<1&&C){var U=e(function(r,n,t,e,u,a,o){var i=d(r,a,o),f=x(t,a,o);return[i,i,f,f,a]}(B,0,m,0,0,T,R),5);B=U[0],A=U[1],m=U[2],_=U[3],M=U[4]}else if(w<<1<=$&&P){var E=e(function(r,n,t,e,u,a){return[d(r,u,a),x(n,u,a),x(t,u,a),u]}(B,A,m,0,T,R),4);B=E[0],A=E[1],m=E[2],M=E[3]}else if(w>=$<<1&&C){var I=e(function(r,n,t,e,u,a){return[d(r,u,a),x(n,u,a),x(t,u,a),u]}(A,B,_,0,T,R),4);A=I[0],B=I[1],_=I[2],M=I[3]}else{var k=e(function(r,n,t,e,u){return[p(r,e,u),s(n,e,u),s(t,e,u)]}(M,A,B,T,R),3);M=k[0],A=k[1],B=k[2]}}else O<=S&&(M=b(M,a(r,u,g)<=a(r,t,g)?u:t,R));return[_,A,m,B,M]}function h(r,n,t,u,i,f,c,l,v,s,p,y,j,h,_,A,m,B,M,R,g,O){if(!(r!=t&&r!=u))return[j,h,_,A,m,B,M,R];var S=a(r,f,O)+a(r,i,O)+a(n,p,O)+a(n,v,O)+(a(t,u,O)<<2),w=a(t,c,O)+a(t,y,O)+a(u,s,O)+a(u,l,O)+(a(r,n,O)<<2),$=a(r,u,O)<=a(r,t,O)?u:t;if(S=P<<1&&T){if(C<<1<=P&&U){var E=e(function(r,n,t,e,u,a,o,i){return[o,o,d(t,o,i),d(e,o,i),x(u,o,i),x(a,o,i)]}(0,0,_,M,R,B,$,g),6);j=E[0],h=E[1],_=E[2],M=E[3],R=E[4],B=E[5]}if(C>=P<<1&&T){var I=e(function(r,n,t,e,u,a,o,i){return[o,d(n,o,i),o,x(e,o,i),d(u,o,i),x(a,o,i)]}(0,h,0,A,m,B,$,g),6);j=I[0],h=I[1],_=I[2],A=I[3],m=I[4],B=I[5]}}else{var k=e(function(r,n,t,e,u){return[e,b(n,e,u),b(t,e,u)]}(0,h,_,$,g),3);j=k[0],h=k[1],_=k[2]}}else S<=w&&(j=b(j,$,g));return[j,h,_,A,m,B,M,R]}function _(r){var n=!0,t=!1;return r&&(!1===r.blendColors&&(n=!1),!0===r.scaleAlpha&&(t=!0)),{blendColors:n,scaleAlpha:t}}function A(r,n,t,e){for(var u=_(e),a=u.blendColors,o=u.scaleAlpha,i=new Uint32Array(n*t*4),f=0;f>8,e=(16711680&r)>>16;return[.299*n+.587*t+.114*e,-.168736*n+-.331264*t+.5*e,.5*n+-.418688*t+-.081312*e]}function o(r,n,t){var e=(4278190080&r)>>24&255,o=(4278190080&n)>>24&255;if(0===e&&0===o)return 0;if(!t&&(e<255||o<255))return 1e6;if(0===e||0===o)return 1e6;var a=u(r),i=u(n);return 48*Math.abs(a[0]-i[0])+7*Math.abs(a[1]-i[1])+6*Math.abs(a[2]-i[2])}function a(r,n,t){var e=(4278190080&r)>>24&255,o=(4278190080&n)>>24&255;if(0===e&&0===o)return!0;if(!t&&(e<255||o<255))return!1;if(0===e||0===o)return!1;var a=u(r),i=u(n);return!(Math.abs(a[0]-i[0])>48)&&(!(Math.abs(a[1]-i[1])>7)&&!(Math.abs(a[2]-i[2])>6))}function i(r,n,t,e){var u,o,a,i=(4278190080&r)>>24&255,f=(4278190080&n)>>24&255;return 0===i?(u=255&n,o=(65280&n)>>8,a=(16711680&n)>>16):0===f?(u=255&r,o=(65280&r)>>8,a=(16711680&r)>>16):(u=(e*(255&n)+t*(255&r))/(t+e),o=(e*((65280&n)>>8)+t*((65280&r)>>8))/(t+e),a=(e*((16711680&n)>>16)+t*((16711680&r)>>16))/(t+e)),~~u|~~o<<8|~~a<<16|~~((e*f+t*i)/(t+e))<<24}function f(r,n,t,e,u){var o=n-1;o<0&&(o=0);var a=n-2;a<0&&(a=0);var i=n+1;i>=e&&(i=e-1);var f=n+2;f>=e&&(f=e-1);var c=t-1;c<0&&(c=0);var l=t-2;l<0&&(l=0);var v=t+1;v>=u&&(v=u-1);var s=t+2;return s>=u&&(s=u-1),[r[o+l*e],r[n+l*e],r[i+l*e],r[a+c*e],r[o+c*e],r[n+c*e],r[i+c*e],r[f+c*e],r[a+t*e],r[o+t*e],r[n+t*e],r[i+t*e],r[f+t*e],r[a+v*e],r[o+v*e],r[n+v*e],r[i+v*e],r[f+v*e],r[o+s*e],r[n+s*e],r[i+s*e]]}function c(r,n,t,u,o,a,i,c,l,v,s){var b,d,p,y,h=e(f(r,n,t,u,o),21),j=h[0],m=h[1],A=h[2],M=h[3],g=h[4],w=h[5],O=h[6],S=h[7],_=h[8],C=h[9],P=h[10],T=h[11],U=h[12],B=h[13],R=h[14],E=h[15],I=h[16],k=h[17],q=h[18],z=h[19];b=d=p=y=P;var D=e(x(P,I,E,T,R,O,C,w,U,k,z,h[20],d,p,y,v,s),3);d=D[0],p=D[1];var F=e(x(P,O,T,w,I,g,E,C,m,A,U,S,b,y=D[2],d,v,s),3);b=F[0],y=F[1];var G=e(x(P,g,w,C,O,R,T,E,_,M,m,j,p,d=F[2],b,v,s),3);p=G[0],d=G[1];var H=e(x(P,R,C,E,g,I,w,T,z,q,_,B,y,b=G[2],p,v,s),3);y=H[0],b=H[1],p=H[2],a[i+c*l]=b,a[i+1+c*l]=d,a[i+(c+1)*l]=p,a[i+1+(c+1)*l]=y}function l(r,n,t,u,o,a,i,c,l,v,s){var b,d,p,y,x,j,m,A,M,g=e(f(r,n,t,u,o),21),w=g[0],O=g[1],S=g[2],_=g[3],C=g[4],P=g[5],T=g[6],U=g[7],B=g[8],R=g[9],E=g[10],I=g[11],k=g[12],q=g[13],z=g[14],D=g[15],F=g[16],G=g[17],H=g[18],J=g[19];b=d=p=y=x=j=m=A=M=E;var K=e(h(E,F,D,I,z,T,R,P,k,G,J,g[20],p,j,m,A,M,v,s),5);p=K[0],j=K[1],m=K[2],A=K[3];var L=e(h(E,T,I,P,F,C,D,R,O,S,k,U,b,d,M=K[4],j,p,v,s),5);b=L[0],d=L[1],M=L[2],j=L[3];var N=e(h(E,C,P,R,T,z,I,D,B,_,O,w,m,y,p=L[4],d,b,v,s),5);m=N[0],y=N[1],p=N[2],d=N[3];var Q=e(h(E,z,R,D,C,F,P,I,J,H,B,q,M,A,b=N[4],y,m,v,s),5);M=Q[0],A=Q[1],b=Q[2],y=Q[3],m=Q[4],a[i+c*l]=b,a[i+1+c*l]=d,a[i+2+c*l]=p,a[i+(c+1)*l]=y,a[i+1+(c+1)*l]=x,a[i+2+(c+1)*l]=j,a[i+(c+2)*l]=m,a[i+1+(c+2)*l]=A,a[i+2+(c+2)*l]=M}function v(r,n,t,u,o,a,i,c,l,v,s){var b,d,p,y,x,h,m,A,M,g,w,O,S,_,C,P,T=e(f(r,n,t,u,o),21),U=T[0],B=T[1],R=T[2],E=T[3],I=T[4],k=T[5],q=T[6],z=T[7],D=T[8],F=T[9],G=T[10],H=T[11],J=T[12],K=T[13],L=T[14],N=T[15],Q=T[16],V=T[17],W=T[18],X=T[19];b=d=p=y=x=h=m=A=M=g=w=O=S=_=C=P=G;var Y=e(j(G,Q,N,H,L,q,F,k,J,V,X,T[20],P,C,O,y,A,w,_,S,v,s),8);P=Y[0],C=Y[1],O=Y[2],y=Y[3],A=Y[4],w=Y[5],_=Y[6],S=Y[7];var Z=e(j(G,q,H,k,Q,I,N,F,B,R,J,z,y,A,p,b,d,m,O,P,v,s),8);y=Z[0],A=Z[1],p=Z[2],b=Z[3],d=Z[4],m=Z[5],O=Z[6],P=Z[7];var $=e(j(G,I,k,F,q,L,H,N,D,E,B,U,b,d,x,S,M,h,p,y,v,s),8);b=$[0],d=$[1],x=$[2],S=$[3],M=$[4],h=$[5],p=$[6],y=$[7];var rr=e(j(G,L,F,N,I,Q,k,H,X,W,D,K,S,M,_,P,C,g,x,b,v,s),8);S=rr[0],M=rr[1],_=rr[2],P=rr[3],C=rr[4],g=rr[5],x=rr[6],b=rr[7],a[i+c*l]=b,a[i+1+c*l]=d,a[i+2+c*l]=p,a[i+3+c*l]=y,a[i+(c+1)*l]=x,a[i+1+(c+1)*l]=h,a[i+2+(c+1)*l]=m,a[i+3+(c+1)*l]=A,a[i+(c+2)*l]=M,a[i+1+(c+2)*l]=g,a[i+2+(c+2)*l]=w,a[i+3+(c+2)*l]=O,a[i+(c+3)*l]=S,a[i+1+(c+3)*l]=_,a[i+2+(c+3)*l]=C,a[i+3+(c+3)*l]=P}function s(r,n,t){return t?i(r,n,7,1):r}function b(r,n,t){return t?i(r,n,3,1):r}function d(r,n,t){return t?i(r,n,1,1):r}function p(r,n,t){return t?i(r,n,1,3):n}function y(r,n,t){return t?i(r,n,1,7):n}function x(r,n,t,e,u,i,f,c,l,v,s,y,x,h,j,m,A){if(!(r!=t&&r!=e))return[x,h,j];var M=o(r,i,A)+o(r,u,A)+o(n,s,A)+o(n,l,A)+(o(t,e)<<2),g=o(t,f,A)+o(t,y,A)+o(e,v,A)+o(e,c,A)+(o(r,n,A)<<2),w=o(r,e,A)<=o(r,t,A)?e:t;if(M=S<<1&&_){if(O<<1<=S&&C){var P=function(r,n,t,e){return[p(r,t,e),b(n,t,e)]}(j,h,w,m);j=P[0],h=P[1]}if(O>=S<<1&&_){var T=function(r,n,t,e){return[p(r,t,e),b(n,t,e)]}(j,x,w,m);j=T[0],x=T[1]}}else j=function(r,n,t){return d(r,n,t)}(j,w,m)}else M<=g&&(j=b(j,w,m));return[x,h,j]}function h(r,n,t,u,i,f,c,l,v,x,h,j,m,A,M,g,w,O,S){if(!(r!=t&&r!=u))return[m,A,M,g,w];var _=o(r,f,S)+o(r,i,S)+o(n,h,S)+o(n,v,S)+(o(t,u,S)<<2),C=o(t,c,S)+o(t,j,S)+o(u,x,S)+o(u,l,S)+(o(r,n,S)<<2);if(_=T<<1&&U){var E=e(function(r,n,t,e,u,o,a){var i=p(r,o,a),f=b(t,o,a);return[i,i,f,f,o]}(g,0,M,0,0,R,O),5);g=E[0],A=E[1],M=E[2],m=E[3],w=E[4]}else if(P<<1<=T&&B){var I=e(function(r,n,t,e,u,o){return[p(r,u,o),b(n,u,o),b(t,u,o),u]}(g,A,M,0,R,O),4);g=I[0],A=I[1],M=I[2],w=I[3]}else if(P>=T<<1&&U){var k=e(function(r,n,t,e,u,o){return[p(r,u,o),b(n,u,o),b(t,u,o),u]}(A,g,m,0,R,O),4);A=k[0],g=k[1],m=k[2],w=k[3]}else{var q=e(function(r,n,t,e,u){return[y(r,e,u),s(n,e,u),s(t,e,u)]}(w,A,g,R,O),3);w=q[0],A=q[1],g=q[2]}}else _<=C&&(w=d(w,o(r,u,S)<=o(r,t,S)?u:t,O));return[m,A,M,g,w]}function j(r,n,t,u,i,f,c,l,v,s,y,x,h,j,m,A,M,g,w,O,S,_){if(!(r!=t&&r!=u))return[h,j,m,A,M,g,w,O];var C=o(r,f,_)+o(r,i,_)+o(n,y,_)+o(n,v,_)+(o(t,u,_)<<2),P=o(t,c,_)+o(t,x,_)+o(u,s,_)+o(u,l,_)+(o(r,n,_)<<2),T=o(r,u,_)<=o(r,t,_)?u:t;if(C=B<<1&&R){if(U<<1<=B&&E){var I=e(function(r,n,t,e,u,o,a,i){return[a,a,p(t,a,i),p(e,a,i),b(u,a,i),b(o,a,i)]}(0,0,m,w,O,g,T,S),6);h=I[0],j=I[1],m=I[2],w=I[3],O=I[4],g=I[5]}if(U>=B<<1&&R){var k=e(function(r,n,t,e,u,o,a,i){return[a,p(n,a,i),a,b(e,a,i),p(u,a,i),b(o,a,i)]}(0,j,0,A,M,g,T,S),6);h=k[0],j=k[1],m=k[2],A=k[3],M=k[4],g=k[5]}}else{var q=e(function(r,n,t,e,u){return[e,d(n,e,u),d(t,e,u)]}(0,j,m,T,S),3);h=q[0],j=q[1],m=q[2]}}else C<=P&&(h=d(h,T,S));return[h,j,m,A,M,g,w,O]}function m(r){var n=!0,t=!1;return r&&(!1===r.blendColors&&(n=!1),!0===r.scaleAlpha&&(t=!0)),{blendColors:n,scaleAlpha:t}}function A(r,n,t,e){for(var u=m(e),o=u.blendColors,a=u.scaleAlpha,i=new Uint32Array(n*t*4),f=0;f>0 6 | GREENMASK = 0x0000FF00, // &MASK >>8 7 | BLUEMASK = 0x00FF0000, // &MASK >>16 8 | ALPHAMASK = 0xFF000000, // &MASK >>24 9 | THRESHHOLD_Y = 48, 10 | THRESHHOLD_U = 7, 11 | THRESHHOLD_V = 6; 12 | 13 | // Convert an ARGB byte to YUV 14 | function getYuv(p) { 15 | const 16 | r = (p & REDMASK), 17 | g = (p & GREENMASK) >> 8, 18 | b = (p & BLUEMASK) >> 16, 19 | y = r * .299000 + g * .587000 + b * .114000, 20 | u = r * - .168736 + g * - .331264 + b * .500000, 21 | v = r * .500000 + g * - .418688 + b * - .081312; 22 | return [y, u, v]; 23 | } 24 | 25 | function yuvDifference(A, B, scaleAlpha) { 26 | const 27 | alphaA = ((A & ALPHAMASK) >> 24) & 0xff, 28 | alphaB = ((B & ALPHAMASK) >> 24) & 0xff; 29 | 30 | if (alphaA === 0 && alphaB === 0) { 31 | return 0; 32 | } 33 | 34 | if (!scaleAlpha && (alphaA < 255 || alphaB < 255)) { 35 | // Very large value not attainable by the thresholds 36 | return 1000000; 37 | } 38 | 39 | if (alphaA === 0 || alphaB === 0) { 40 | // Very large value not attainable by the thresholds 41 | return 1000000; 42 | } 43 | 44 | const 45 | yuvA = getYuv(A), 46 | yuvB = getYuv(B); 47 | 48 | /*Add HQx filters threshold & return*/ 49 | return Math.abs(yuvA[0] - yuvB[0]) * THRESHHOLD_Y 50 | + Math.abs(yuvA[1] - yuvB[1]) * THRESHHOLD_U 51 | + Math.abs(yuvA[2] - yuvB[2]) * THRESHHOLD_V; 52 | } 53 | 54 | function isEqual(A, B, scaleAlpha) { 55 | const 56 | alphaA = ((A & ALPHAMASK) >> 24) & 0xff, 57 | alphaB = ((B & ALPHAMASK) >> 24) & 0xff; 58 | 59 | if (alphaA === 0 && alphaB === 0) { 60 | return true; 61 | } 62 | 63 | if (!scaleAlpha && (alphaA < 255 || alphaB < 255)) { 64 | return false; 65 | } 66 | 67 | if (alphaA === 0 || alphaB === 0) { 68 | return false; 69 | } 70 | 71 | const 72 | yuvA = getYuv(A), 73 | yuvB = getYuv(B); 74 | 75 | if (Math.abs(yuvA[0] - yuvB[0]) > THRESHHOLD_Y) { 76 | return false; 77 | } 78 | if (Math.abs(yuvA[1] - yuvB[1]) > THRESHHOLD_U) { 79 | return false; 80 | } 81 | if (Math.abs(yuvA[2] - yuvB[2]) > THRESHHOLD_V) { 82 | return false; 83 | } 84 | 85 | return true; 86 | } 87 | 88 | function pixelInterpolate(A, B, q1, q2) { 89 | const 90 | alphaA = ((A & ALPHAMASK) >> 24) & 0xff, 91 | alphaB = ((B & ALPHAMASK) >> 24) & 0xff; 92 | 93 | /*Extract each value from 32bit Uint & blend colors together*/ 94 | let r, g, b, a; 95 | 96 | if (alphaA === 0) { 97 | r = B & REDMASK; 98 | g = (B & GREENMASK) >> 8; 99 | b = (B & BLUEMASK) >> 16; 100 | } else if (alphaB === 0) { 101 | r = A & REDMASK; 102 | g = (A & GREENMASK) >> 8; 103 | b = (A & BLUEMASK) >> 16; 104 | } else { 105 | r = (q2 * (B & REDMASK) + q1 * (A & REDMASK)) / (q1 + q2); 106 | g = (q2 * ((B & GREENMASK) >> 8) + q1 * ((A & GREENMASK) >> 8)) / (q1 + q2); 107 | b = (q2 * ((B & BLUEMASK) >> 16) + q1 * ((A & BLUEMASK) >> 16)) / (q1 + q2); 108 | } 109 | a = (q2 * alphaB + q1 * alphaA) / (q1 + q2); 110 | /*The bit hack '~~' is used to floor the values like Math.floor, but faster*/ 111 | return ((~~r) | ((~~g) << 8) | ((~~b) << 16) | ((~~a) << 24)); 112 | } 113 | 114 | function getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH) { 115 | let xm1 = oriX - 1; 116 | if (xm1 < 0) { 117 | xm1 = 0; 118 | } 119 | let xm2 = oriX - 2; 120 | if (xm2 < 0) { 121 | xm2 = 0; 122 | } 123 | let xp1 = oriX + 1; 124 | if (xp1 >= oriW) { 125 | xp1 = oriW - 1; 126 | } 127 | let xp2 = oriX + 2; 128 | if (xp2 >= oriW) { 129 | xp2 = oriW - 1; 130 | } 131 | let ym1 = oriY - 1; 132 | if (ym1 < 0) { 133 | ym1 = 0; 134 | } 135 | let ym2 = oriY - 2; 136 | if (ym2 < 0) { 137 | ym2 = 0; 138 | } 139 | let yp1 = oriY + 1; 140 | if (yp1 >= oriH) { 141 | yp1 = oriH - 1; 142 | } 143 | let yp2 = oriY + 2; 144 | if (yp2 >= oriH) { 145 | yp2 = oriH - 1; 146 | } 147 | 148 | return [ 149 | oriPixelView[xm1 + ym2 * oriW], /* a1 */ 150 | oriPixelView[oriX + ym2 * oriW], /* b1 */ 151 | oriPixelView[xp1 + ym2 * oriW], /* c1 */ 152 | 153 | oriPixelView[xm2 + ym1 * oriW], /* a0 */ 154 | oriPixelView[xm1 + ym1 * oriW], /* pa */ 155 | oriPixelView[oriX + ym1 * oriW], /* pb */ 156 | oriPixelView[xp1 + ym1 * oriW], /* pc */ 157 | oriPixelView[xp2 + ym1 * oriW], /* c4 */ 158 | 159 | oriPixelView[xm2 + oriY * oriW], /* d0 */ 160 | oriPixelView[xm1 + oriY * oriW], /* pd */ 161 | oriPixelView[oriX + oriY * oriW],/* pe */ 162 | oriPixelView[xp1 + oriY * oriW], /* pf */ 163 | oriPixelView[xp2 + oriY * oriW], /* f4 */ 164 | 165 | oriPixelView[xm2 + yp1 * oriW], /* g0 */ 166 | oriPixelView[xm1 + yp1 * oriW], /* pg */ 167 | oriPixelView[oriX + yp1 * oriW], /* ph */ 168 | oriPixelView[xp1 + yp1 * oriW], /* pi */ 169 | oriPixelView[xp2 + yp1 * oriW], /* i4 */ 170 | 171 | oriPixelView[xm1 + yp2 * oriW], /* g5 */ 172 | oriPixelView[oriX + yp2 * oriW], /* h5 */ 173 | oriPixelView[xp1 + yp2 * oriW] /* i5 */ 174 | ]; 175 | } 176 | 177 | // This is the XBR2x by Hyllian (see http://board.byuu.org/viewtopic.php?f=10&t=2248) 178 | function computeXbr2x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 179 | const relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 180 | const 181 | [a1, 182 | b1, 183 | c1, 184 | a0, 185 | pa, 186 | pb, 187 | pc, 188 | c4, 189 | d0, 190 | pd, 191 | pe, 192 | pf, 193 | f4, 194 | g0, 195 | pg, 196 | ph, 197 | pi, 198 | i4, 199 | g5, 200 | h5, 201 | i5] = relatedPoints; 202 | let e0, e1, e2, e3; 203 | e0 = e1 = e2 = e3 = pe; 204 | 205 | [e1, e2, e3] = kernel2Xv5(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, e1, e2, e3, blendColors, scaleAlpha); 206 | [e0, e3, e1] = kernel2Xv5(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e0, e3, e1, blendColors, scaleAlpha); 207 | [e2, e1, e0] = kernel2Xv5(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e2, e1, e0, blendColors, scaleAlpha); 208 | [e3, e0, e2] = kernel2Xv5(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, e3, e0, e2, blendColors, scaleAlpha); 209 | 210 | dstPixelView[dstX + dstY * dstW] = e0; 211 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 212 | dstPixelView[dstX + (dstY + 1) * dstW] = e2; 213 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e3; 214 | } 215 | 216 | function computeXbr3x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 217 | const relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 218 | const 219 | [a1, 220 | b1, 221 | c1, 222 | a0, 223 | pa, 224 | pb, 225 | pc, 226 | c4, 227 | d0, 228 | pd, 229 | pe, 230 | pf, 231 | f4, 232 | g0, 233 | pg, 234 | ph, 235 | pi, 236 | i4, 237 | g5, 238 | h5, 239 | i5] = relatedPoints; 240 | let e0, e1, e2, e3, e4, e5, e6, e7, e8; 241 | e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = pe; 242 | 243 | [e2, e5, e6, e7, e8] = kernel3X(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, e2, e5, e6, e7, e8, blendColors, scaleAlpha); 244 | [e0, e1, e8, e5, e2] = kernel3X(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e0, e1, e8, e5, e2, blendColors, scaleAlpha); 245 | [e6, e3, e2, e1, e0] = kernel3X(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e6, e3, e2, e1, e0, blendColors, scaleAlpha); 246 | [e8, e7, e0, e3, e6] = kernel3X(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, e8, e7, e0, e3, e6, blendColors, scaleAlpha); 247 | 248 | dstPixelView[dstX + dstY * dstW] = e0; 249 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 250 | dstPixelView[dstX + 2 + dstY * dstW] = e2; 251 | dstPixelView[dstX + (dstY + 1) * dstW] = e3; 252 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e4; 253 | dstPixelView[dstX + 2 + (dstY + 1) * dstW] = e5; 254 | dstPixelView[dstX + (dstY + 2) * dstW] = e6; 255 | dstPixelView[dstX + 1 + (dstY + 2) * dstW] = e7; 256 | dstPixelView[dstX + 2 + (dstY + 2) * dstW] = e8; 257 | } 258 | 259 | 260 | function computeXbr4x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 261 | const relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 262 | const 263 | [a1, 264 | b1, 265 | c1, 266 | a0, 267 | pa, 268 | pb, 269 | pc, 270 | c4, 271 | d0, 272 | pd, 273 | pe, 274 | pf, 275 | f4, 276 | g0, 277 | pg, 278 | ph, 279 | pi, 280 | i4, 281 | g5, 282 | h5, 283 | i5] = relatedPoints; 284 | let e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef; 285 | e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = e9 = ea = eb = ec = ed = ee = ef = pe; 286 | 287 | [ef, ee, eb, e3, e7, ea, ed, ec] = kernel4Xv2(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, ef, ee, eb, e3, e7, ea, ed, ec, blendColors, scaleAlpha); 288 | [e3, e7, e2, e0, e1, e6, eb, ef] = kernel4Xv2(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e3, e7, e2, e0, e1, e6, eb, ef, blendColors, scaleAlpha); 289 | [e0, e1, e4, ec, e8, e5, e2, e3] = kernel4Xv2(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e0, e1, e4, ec, e8, e5, e2, e3, blendColors, scaleAlpha); 290 | [ec, e8, ed, ef, ee, e9, e4, e0] = kernel4Xv2(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, ec, e8, ed, ef, ee, e9, e4, e0, blendColors, scaleAlpha); 291 | 292 | dstPixelView[dstX + dstY * dstW] = e0; 293 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 294 | dstPixelView[dstX + 2 + dstY * dstW] = e2; 295 | dstPixelView[dstX + 3 + dstY * dstW] = e3; 296 | dstPixelView[dstX + (dstY + 1) * dstW] = e4; 297 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e5; 298 | dstPixelView[dstX + 2 + (dstY + 1) * dstW] = e6; 299 | dstPixelView[dstX + 3 + (dstY + 1) * dstW] = e7; 300 | dstPixelView[dstX + (dstY + 2) * dstW] = e8; 301 | dstPixelView[dstX + 1 + (dstY + 2) * dstW] = e9; 302 | dstPixelView[dstX + 2 + (dstY + 2) * dstW] = ea; 303 | dstPixelView[dstX + 3 + (dstY + 2) * dstW] = eb; 304 | dstPixelView[dstX + (dstY + 3) * dstW] = ec; 305 | dstPixelView[dstX + 1 + (dstY + 3) * dstW] = ed; 306 | dstPixelView[dstX + 2 + (dstY + 3) * dstW] = ee; 307 | dstPixelView[dstX + 3 + (dstY + 3) * dstW] = ef; 308 | } 309 | 310 | function alphaBlend32W(dst, src, blendColors) { 311 | if (blendColors) { 312 | return pixelInterpolate(dst, src, 7, 1); 313 | } 314 | 315 | return dst; 316 | } 317 | 318 | function alphaBlend64W(dst, src, blendColors) { 319 | if (blendColors) { 320 | return pixelInterpolate(dst, src, 3, 1); 321 | } 322 | return dst; 323 | } 324 | 325 | function alphaBlend128W(dst, src, blendColors) { 326 | if (blendColors) { 327 | return pixelInterpolate(dst, src, 1, 1); 328 | } 329 | return dst; 330 | } 331 | 332 | function alphaBlend192W(dst, src, blendColors) { 333 | if (blendColors) { 334 | return pixelInterpolate(dst, src, 1, 3); 335 | } 336 | return src; 337 | } 338 | 339 | function alphaBlend224W(dst, src, blendColors) { 340 | if (blendColors) { 341 | return pixelInterpolate(dst, src, 1, 7); 342 | } 343 | return src; 344 | } 345 | 346 | function leftUp2_2X(n3, n2, pixel, blendColors) { 347 | const blendedN2 = alphaBlend64W(n2, pixel, blendColors); 348 | return [ 349 | alphaBlend224W(n3, pixel, blendColors), 350 | blendedN2, 351 | blendedN2 352 | ]; 353 | } 354 | 355 | function left2_2X(n3, n2, pixel, blendColors) { 356 | return [ 357 | alphaBlend192W(n3, pixel, blendColors), 358 | alphaBlend64W(n2, pixel, blendColors) 359 | ]; 360 | } 361 | 362 | function up2_2X(n3, n1, pixel, blendColors) { 363 | return [ 364 | alphaBlend192W(n3, pixel, blendColors), 365 | alphaBlend64W(n1, pixel, blendColors) 366 | ]; 367 | } 368 | 369 | function dia_2X(n3, pixel, blendColors) { 370 | return alphaBlend128W(n3, pixel, blendColors); 371 | } 372 | 373 | function kernel2Xv5(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n1, n2, n3, blendColors, scaleAlpha) { 374 | let ex = (pe != ph && pe != pf); 375 | if (!ex) { 376 | return [n1, n2, n3]; 377 | } 378 | let 379 | e = (yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha)) + (yuvDifference(ph, pf) << 2), 380 | i = (yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha)) + (yuvDifference(pe, pi, scaleAlpha) << 2), 381 | px = (yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha)) ? pf : ph; 382 | 383 | if ((e < i) && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))) { 384 | let 385 | ke = yuvDifference(pf, pg, scaleAlpha), 386 | ki = yuvDifference(ph, pc, scaleAlpha), 387 | ex2 = (pe != pc && pb != pc), 388 | ex3 = (pe != pg && pd != pg); 389 | if (((ke << 1) <= ki) && ex3 || (ke >= (ki << 1)) && ex2) { 390 | if (((ke << 1) <= ki) && ex3) { 391 | let leftOut = left2_2X(n3, n2, px, blendColors); 392 | n3 = leftOut[0]; 393 | n2 = leftOut[1]; 394 | } 395 | if ((ke >= (ki << 1)) && ex2) { 396 | let upOut = up2_2X(n3, n1, px, blendColors); 397 | n3 = upOut[0]; 398 | n1 = upOut[1]; 399 | } 400 | } else { 401 | n3 = dia_2X(n3, px, blendColors); 402 | } 403 | 404 | } else if (e <= i) { 405 | n3 = alphaBlend64W(n3, px, blendColors); 406 | } 407 | return [n1, n2, n3]; 408 | } 409 | 410 | function leftUp2_3X(n7, n5, n6, n2, n8, pixel, blendColors) { 411 | const 412 | blendedN7 = alphaBlend192W(n7, pixel, blendColors), 413 | blendedN6 = alphaBlend64W(n6, pixel, blendColors); 414 | return [ 415 | blendedN7, 416 | blendedN7, 417 | blendedN6, 418 | blendedN6, 419 | pixel 420 | ]; 421 | } 422 | 423 | function left2_3X(n7, n5, n6, n8, pixel, blendColors) { 424 | return [ 425 | alphaBlend192W(n7, pixel, blendColors), 426 | alphaBlend64W(n5, pixel, blendColors), 427 | alphaBlend64W(n6, pixel, blendColors), 428 | pixel 429 | ]; 430 | } 431 | 432 | function up2_3X(n5, n7, n2, n8, pixel, blendColors) { 433 | return [ 434 | alphaBlend192W(n5, pixel, blendColors), 435 | alphaBlend64W(n7, pixel, blendColors), 436 | alphaBlend64W(n2, pixel, blendColors), 437 | pixel 438 | ]; 439 | } 440 | 441 | function dia_3X(n8, n5, n7, pixel, blendColors) { 442 | return [ 443 | alphaBlend224W(n8, pixel, blendColors), 444 | alphaBlend32W(n5, pixel, blendColors), 445 | alphaBlend32W(n7, pixel, blendColors) 446 | ]; 447 | } 448 | 449 | function kernel3X(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n2, n5, n6, n7, n8, blendColors, scaleAlpha) { 450 | const ex = (pe != ph && pe != pf); 451 | if (!ex) { 452 | return [n2, n5, n6, n7, n8]; 453 | } 454 | 455 | const 456 | e = (yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha)) + (yuvDifference(ph, pf, scaleAlpha) << 2), 457 | i = (yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha)) + (yuvDifference(pe, pi, scaleAlpha) << 2); 458 | 459 | let state; 460 | if (USE_3X_ORIGINAL_IMPLEMENTATION) { 461 | state = ((e < i) && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))); 462 | } else { 463 | state = ((e < i) && (!isEqual(pf, pb, scaleAlpha) && !isEqual(pf, pc, scaleAlpha) || !isEqual(ph, pd, scaleAlpha) && !isEqual(ph, pg, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, f4, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) || !isEqual(ph, h5, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))); 464 | } 465 | 466 | if (state) { 467 | const 468 | ke = yuvDifference(pf, pg, scaleAlpha), 469 | ki = yuvDifference(ph, pc, scaleAlpha), 470 | ex2 = (pe != pc && pb != pc), 471 | ex3 = (pe != pg && pd != pg), 472 | px = (yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha)) ? pf : ph; 473 | if (((ke << 1) <= ki) && ex3 && (ke >= (ki << 1)) && ex2) { 474 | [n7, n5, n6, n2, n8] = leftUp2_3X(n7, n5, n6, n2, n8, px, blendColors); 475 | } else if (((ke << 1) <= ki) && ex3) { 476 | [n7, n5, n6, n8] = left2_3X(n7, n5, n6, n8, px, blendColors); 477 | } else if ((ke >= (ki << 1)) && ex2) { 478 | [n5, n7, n2, n8] = up2_3X(n5, n7, n2, n8, px, blendColors); 479 | } else { 480 | [n8, n5, n7] = dia_3X(n8, n5, n7, px, blendColors); 481 | } 482 | } else if (e <= i) { 483 | n8 = alphaBlend128W(n8, ((yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha)) ? pf : ph), blendColors); 484 | } 485 | return [n2, n5, n6, n7, n8]; 486 | } 487 | 488 | // 4xBR 489 | function leftUp2(n15, n14, n11, n13, n12, n10, n7, n3, pixel, blendColors) { 490 | const 491 | blendedN13 = alphaBlend192W(n13, pixel, blendColors), 492 | blendedN12 = alphaBlend64W(n12, pixel, blendColors); 493 | 494 | return [pixel, pixel, pixel, blendedN12, blendedN12, blendedN12, blendedN13, n3]; 495 | } 496 | 497 | function left2(n15, n14, n11, n13, n12, n10, pixel, blendColors) { 498 | return [ 499 | pixel, 500 | pixel, 501 | alphaBlend192W(n11, pixel, blendColors), 502 | alphaBlend192W(n13, pixel, blendColors), 503 | alphaBlend64W(n12, pixel, blendColors), 504 | alphaBlend64W(n10, pixel, blendColors) 505 | ]; 506 | } 507 | 508 | function up2(n15, n14, n11, n3, n7, n10, pixel, blendColors) { 509 | return [ 510 | pixel, 511 | alphaBlend192W(n14, pixel, blendColors), 512 | pixel, 513 | alphaBlend64W(n3, pixel, blendColors), 514 | alphaBlend192W(n7, pixel, blendColors), 515 | alphaBlend64W(n10, pixel, blendColors) 516 | ]; 517 | } 518 | 519 | function dia(n15, n14, n11, pixel, blendColors) { 520 | return [ 521 | pixel, 522 | alphaBlend128W(n14, pixel, blendColors), 523 | alphaBlend128W(n11, pixel, blendColors) 524 | ]; 525 | } 526 | 527 | function kernel4Xv2(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n15, n14, n11, n3, n7, n10, n13, n12, blendColors, scaleAlpha) { 528 | var ex = (pe != ph && pe != pf); 529 | if (!ex) { 530 | return [n15, n14, n11, n3, n7, n10, n13, n12]; 531 | } 532 | const 533 | e = (yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha)) + (yuvDifference(ph, pf, scaleAlpha) << 2), 534 | i = (yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha)) + (yuvDifference(pe, pi, scaleAlpha) << 2), 535 | px = (yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha)) ? pf : ph; 536 | if ((e < i) && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))) { 537 | const 538 | ke = yuvDifference(pf, pg, scaleAlpha), 539 | ki = yuvDifference(ph, pc, scaleAlpha), 540 | ex2 = (pe != pc && pb != pc), 541 | ex3 = (pe != pg && pd != pg); 542 | if (((ke << 1) <= ki) && ex3 || (ke >= (ki << 1)) && ex2) { 543 | if (((ke << 1) <= ki) && ex3) { 544 | [n15, n14, n11, n13, n12, n10] = left2(n15, n14, n11, n13, n12, n10, px, blendColors); 545 | } 546 | if ((ke >= (ki << 1)) && ex2) { 547 | [n15, n14, n11, n3, n7, n10] = up2(n15, n14, n11, n3, n7, n10, px, blendColors); 548 | } 549 | } else { 550 | [n15, n14, n11] = dia(n15, n14, n11, px, blendColors); 551 | } 552 | 553 | } else if (e <= i) { 554 | n15 = alphaBlend128W(n15, px, blendColors); 555 | } 556 | 557 | return [n15, n14, n11, n3, n7, n10, n13, n12]; 558 | } 559 | 560 | function parseOptions(rawOpts) { 561 | let 562 | blendColors = true, 563 | scaleAlpha = false; 564 | 565 | if (rawOpts) { 566 | if (rawOpts.blendColors === false) { 567 | blendColors = false; 568 | } 569 | 570 | if (rawOpts.scaleAlpha === true) { 571 | scaleAlpha = true; 572 | } 573 | } 574 | 575 | return {blendColors, scaleAlpha}; 576 | } 577 | 578 | export function xbr2x(pixelArray, width, height, options) { 579 | const {blendColors, scaleAlpha} = parseOptions(options); 580 | const scaledPixelArray = new Uint32Array(width * height * 4); 581 | for (let c = 0; c < width; c++) { 582 | for (let d = 0; d < height; d++) { 583 | computeXbr2x(pixelArray, c, d, width, height, scaledPixelArray, c * 2, d * 2, width * 2, blendColors, scaleAlpha); 584 | } 585 | } 586 | return scaledPixelArray; 587 | } 588 | 589 | export function xbr3x(pixelArray, width, height, options) { 590 | const {blendColors, scaleAlpha} = parseOptions(options); 591 | const scaledPixelArray = new Uint32Array(width * height * 9); 592 | for (let c = 0; c < width; c++) { 593 | for (let d = 0; d < height; d++) { 594 | computeXbr3x(pixelArray, c, d, width, height, scaledPixelArray, c * 3, d * 3, width * 3, blendColors, scaleAlpha); 595 | } 596 | } 597 | return scaledPixelArray; 598 | } 599 | 600 | export function xbr4x(pixelArray, width, height, options) { 601 | const {blendColors, scaleAlpha} = parseOptions(options); 602 | const scaledPixelArray = new Uint32Array(width * height * 16); 603 | for (let c = 0; c < width; c++) { 604 | for (let d = 0; d < height; d++) { 605 | computeXbr4x(pixelArray, c, d, width, height, scaledPixelArray, c * 4, d * 4, width * 4, blendColors, scaleAlpha); 606 | } 607 | } 608 | return scaledPixelArray; 609 | } -------------------------------------------------------------------------------- /demo/demo.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 | /******/ } 41 | /******/ }; 42 | /******/ 43 | /******/ // define __esModule on exports 44 | /******/ __webpack_require__.r = function(exports) { 45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 | /******/ } 48 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 | /******/ }; 50 | /******/ 51 | /******/ // create a fake namespace object 52 | /******/ // mode & 1: value is a module id, require it 53 | /******/ // mode & 2: merge all properties of value into the ns 54 | /******/ // mode & 4: return value when already ns object 55 | /******/ // mode & 8|1: behave like require 56 | /******/ __webpack_require__.t = function(value, mode) { 57 | /******/ if(mode & 1) value = __webpack_require__(value); 58 | /******/ if(mode & 8) return value; 59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 | /******/ var ns = Object.create(null); 61 | /******/ __webpack_require__.r(ns); 62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 | /******/ return ns; 65 | /******/ }; 66 | /******/ 67 | /******/ // getDefaultExport function for compatibility with non-harmony modules 68 | /******/ __webpack_require__.n = function(module) { 69 | /******/ var getter = module && module.__esModule ? 70 | /******/ function getDefault() { return module['default']; } : 71 | /******/ function getModuleExports() { return module; }; 72 | /******/ __webpack_require__.d(getter, 'a', getter); 73 | /******/ return getter; 74 | /******/ }; 75 | /******/ 76 | /******/ // Object.prototype.hasOwnProperty.call 77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 | /******/ 79 | /******/ // __webpack_public_path__ 80 | /******/ __webpack_require__.p = ""; 81 | /******/ 82 | /******/ 83 | /******/ // Load entry module and return exports 84 | /******/ return __webpack_require__(__webpack_require__.s = 0); 85 | /******/ }) 86 | /************************************************************************/ 87 | /******/ ([ 88 | /* 0 */ 89 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 90 | 91 | "use strict"; 92 | __webpack_require__.r(__webpack_exports__); 93 | 94 | // CONCATENATED MODULE: ./src/index.js 95 | // Options 96 | const USE_3X_ORIGINAL_IMPLEMENTATION = false; 97 | 98 | const 99 | REDMASK = 0x000000FF, // &MASK >>0 100 | GREENMASK = 0x0000FF00, // &MASK >>8 101 | BLUEMASK = 0x00FF0000, // &MASK >>16 102 | ALPHAMASK = 0xFF000000, // &MASK >>24 103 | THRESHHOLD_Y = 48, 104 | THRESHHOLD_U = 7, 105 | THRESHHOLD_V = 6; 106 | 107 | // Convert an ARGB byte to YUV 108 | function getYuv(p) { 109 | const 110 | r = (p & REDMASK), 111 | g = (p & GREENMASK) >> 8, 112 | b = (p & BLUEMASK) >> 16, 113 | y = r * .299000 + g * .587000 + b * .114000, 114 | u = r * - .168736 + g * - .331264 + b * .500000, 115 | v = r * .500000 + g * - .418688 + b * - .081312; 116 | return [y, u, v]; 117 | } 118 | 119 | function yuvDifference(A, B, scaleAlpha) { 120 | const 121 | alphaA = ((A & ALPHAMASK) >> 24) & 0xff, 122 | alphaB = ((B & ALPHAMASK) >> 24) & 0xff; 123 | 124 | if (alphaA === 0 && alphaB === 0) { 125 | return 0; 126 | } 127 | 128 | if (!scaleAlpha && (alphaA < 255 || alphaB < 255)) { 129 | // Very large value not attainable by the thresholds 130 | return 1000000; 131 | } 132 | 133 | if (alphaA === 0 || alphaB === 0) { 134 | // Very large value not attainable by the thresholds 135 | return 1000000; 136 | } 137 | 138 | const 139 | yuvA = getYuv(A), 140 | yuvB = getYuv(B); 141 | 142 | /*Add HQx filters threshold & return*/ 143 | return Math.abs(yuvA[0] - yuvB[0]) * THRESHHOLD_Y 144 | + Math.abs(yuvA[1] - yuvB[1]) * THRESHHOLD_U 145 | + Math.abs(yuvA[2] - yuvB[2]) * THRESHHOLD_V; 146 | } 147 | 148 | function isEqual(A, B, scaleAlpha) { 149 | const 150 | alphaA = ((A & ALPHAMASK) >> 24) & 0xff, 151 | alphaB = ((B & ALPHAMASK) >> 24) & 0xff; 152 | 153 | if (alphaA === 0 && alphaB === 0) { 154 | return true; 155 | } 156 | 157 | if (!scaleAlpha && (alphaA < 255 || alphaB < 255)) { 158 | return false; 159 | } 160 | 161 | if (alphaA === 0 || alphaB === 0) { 162 | return false; 163 | } 164 | 165 | const 166 | yuvA = getYuv(A), 167 | yuvB = getYuv(B); 168 | 169 | if (Math.abs(yuvA[0] - yuvB[0]) > THRESHHOLD_Y) { 170 | return false; 171 | } 172 | if (Math.abs(yuvA[1] - yuvB[1]) > THRESHHOLD_U) { 173 | return false; 174 | } 175 | if (Math.abs(yuvA[2] - yuvB[2]) > THRESHHOLD_V) { 176 | return false; 177 | } 178 | 179 | return true; 180 | } 181 | 182 | function pixelInterpolate(A, B, q1, q2) { 183 | const 184 | alphaA = ((A & ALPHAMASK) >> 24) & 0xff, 185 | alphaB = ((B & ALPHAMASK) >> 24) & 0xff; 186 | 187 | /*Extract each value from 32bit Uint & blend colors together*/ 188 | let r, g, b, a; 189 | 190 | if (alphaA === 0) { 191 | r = B & REDMASK; 192 | g = (B & GREENMASK) >> 8; 193 | b = (B & BLUEMASK) >> 16; 194 | } else if (alphaB === 0) { 195 | r = A & REDMASK; 196 | g = (A & GREENMASK) >> 8; 197 | b = (A & BLUEMASK) >> 16; 198 | } else { 199 | r = (q2 * (B & REDMASK) + q1 * (A & REDMASK)) / (q1 + q2); 200 | g = (q2 * ((B & GREENMASK) >> 8) + q1 * ((A & GREENMASK) >> 8)) / (q1 + q2); 201 | b = (q2 * ((B & BLUEMASK) >> 16) + q1 * ((A & BLUEMASK) >> 16)) / (q1 + q2); 202 | } 203 | a = (q2 * alphaB + q1 * alphaA) / (q1 + q2); 204 | /*The bit hack '~~' is used to floor the values like Math.floor, but faster*/ 205 | return ((~~r) | ((~~g) << 8) | ((~~b) << 16) | ((~~a) << 24)); 206 | } 207 | 208 | function getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH) { 209 | let xm1 = oriX - 1; 210 | if (xm1 < 0) { 211 | xm1 = 0; 212 | } 213 | let xm2 = oriX - 2; 214 | if (xm2 < 0) { 215 | xm2 = 0; 216 | } 217 | let xp1 = oriX + 1; 218 | if (xp1 >= oriW) { 219 | xp1 = oriW - 1; 220 | } 221 | let xp2 = oriX + 2; 222 | if (xp2 >= oriW) { 223 | xp2 = oriW - 1; 224 | } 225 | let ym1 = oriY - 1; 226 | if (ym1 < 0) { 227 | ym1 = 0; 228 | } 229 | let ym2 = oriY - 2; 230 | if (ym2 < 0) { 231 | ym2 = 0; 232 | } 233 | let yp1 = oriY + 1; 234 | if (yp1 >= oriH) { 235 | yp1 = oriH - 1; 236 | } 237 | let yp2 = oriY + 2; 238 | if (yp2 >= oriH) { 239 | yp2 = oriH - 1; 240 | } 241 | 242 | return [ 243 | oriPixelView[xm1 + ym2 * oriW], /* a1 */ 244 | oriPixelView[oriX + ym2 * oriW], /* b1 */ 245 | oriPixelView[xp1 + ym2 * oriW], /* c1 */ 246 | 247 | oriPixelView[xm2 + ym1 * oriW], /* a0 */ 248 | oriPixelView[xm1 + ym1 * oriW], /* pa */ 249 | oriPixelView[oriX + ym1 * oriW], /* pb */ 250 | oriPixelView[xp1 + ym1 * oriW], /* pc */ 251 | oriPixelView[xp2 + ym1 * oriW], /* c4 */ 252 | 253 | oriPixelView[xm2 + oriY * oriW], /* d0 */ 254 | oriPixelView[xm1 + oriY * oriW], /* pd */ 255 | oriPixelView[oriX + oriY * oriW],/* pe */ 256 | oriPixelView[xp1 + oriY * oriW], /* pf */ 257 | oriPixelView[xp2 + oriY * oriW], /* f4 */ 258 | 259 | oriPixelView[xm2 + yp1 * oriW], /* g0 */ 260 | oriPixelView[xm1 + yp1 * oriW], /* pg */ 261 | oriPixelView[oriX + yp1 * oriW], /* ph */ 262 | oriPixelView[xp1 + yp1 * oriW], /* pi */ 263 | oriPixelView[xp2 + yp1 * oriW], /* i4 */ 264 | 265 | oriPixelView[xm1 + yp2 * oriW], /* g5 */ 266 | oriPixelView[oriX + yp2 * oriW], /* h5 */ 267 | oriPixelView[xp1 + yp2 * oriW] /* i5 */ 268 | ]; 269 | } 270 | 271 | // This is the XBR2x by Hyllian (see http://board.byuu.org/viewtopic.php?f=10&t=2248) 272 | function computeXbr2x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 273 | const relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 274 | const 275 | [a1, 276 | b1, 277 | c1, 278 | a0, 279 | pa, 280 | pb, 281 | pc, 282 | c4, 283 | d0, 284 | pd, 285 | pe, 286 | pf, 287 | f4, 288 | g0, 289 | pg, 290 | ph, 291 | pi, 292 | i4, 293 | g5, 294 | h5, 295 | i5] = relatedPoints; 296 | let e0, e1, e2, e3; 297 | e0 = e1 = e2 = e3 = pe; 298 | 299 | [e1, e2, e3] = kernel2Xv5(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, e1, e2, e3, blendColors, scaleAlpha); 300 | [e0, e3, e1] = kernel2Xv5(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e0, e3, e1, blendColors, scaleAlpha); 301 | [e2, e1, e0] = kernel2Xv5(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e2, e1, e0, blendColors, scaleAlpha); 302 | [e3, e0, e2] = kernel2Xv5(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, e3, e0, e2, blendColors, scaleAlpha); 303 | 304 | dstPixelView[dstX + dstY * dstW] = e0; 305 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 306 | dstPixelView[dstX + (dstY + 1) * dstW] = e2; 307 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e3; 308 | } 309 | 310 | function computeXbr3x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 311 | const relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 312 | const 313 | [a1, 314 | b1, 315 | c1, 316 | a0, 317 | pa, 318 | pb, 319 | pc, 320 | c4, 321 | d0, 322 | pd, 323 | pe, 324 | pf, 325 | f4, 326 | g0, 327 | pg, 328 | ph, 329 | pi, 330 | i4, 331 | g5, 332 | h5, 333 | i5] = relatedPoints; 334 | let e0, e1, e2, e3, e4, e5, e6, e7, e8; 335 | e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = pe; 336 | 337 | [e2, e5, e6, e7, e8] = kernel3X(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, e2, e5, e6, e7, e8, blendColors, scaleAlpha); 338 | [e0, e1, e8, e5, e2] = kernel3X(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e0, e1, e8, e5, e2, blendColors, scaleAlpha); 339 | [e6, e3, e2, e1, e0] = kernel3X(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e6, e3, e2, e1, e0, blendColors, scaleAlpha); 340 | [e8, e7, e0, e3, e6] = kernel3X(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, e8, e7, e0, e3, e6, blendColors, scaleAlpha); 341 | 342 | dstPixelView[dstX + dstY * dstW] = e0; 343 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 344 | dstPixelView[dstX + 2 + dstY * dstW] = e2; 345 | dstPixelView[dstX + (dstY + 1) * dstW] = e3; 346 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e4; 347 | dstPixelView[dstX + 2 + (dstY + 1) * dstW] = e5; 348 | dstPixelView[dstX + (dstY + 2) * dstW] = e6; 349 | dstPixelView[dstX + 1 + (dstY + 2) * dstW] = e7; 350 | dstPixelView[dstX + 2 + (dstY + 2) * dstW] = e8; 351 | } 352 | 353 | 354 | function computeXbr4x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 355 | const relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 356 | const 357 | [a1, 358 | b1, 359 | c1, 360 | a0, 361 | pa, 362 | pb, 363 | pc, 364 | c4, 365 | d0, 366 | pd, 367 | pe, 368 | pf, 369 | f4, 370 | g0, 371 | pg, 372 | ph, 373 | pi, 374 | i4, 375 | g5, 376 | h5, 377 | i5] = relatedPoints; 378 | let e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef; 379 | e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = e9 = ea = eb = ec = ed = ee = ef = pe; 380 | 381 | [ef, ee, eb, e3, e7, ea, ed, ec] = kernel4Xv2(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, ef, ee, eb, e3, e7, ea, ed, ec, blendColors, scaleAlpha); 382 | [e3, e7, e2, e0, e1, e6, eb, ef] = kernel4Xv2(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e3, e7, e2, e0, e1, e6, eb, ef, blendColors, scaleAlpha); 383 | [e0, e1, e4, ec, e8, e5, e2, e3] = kernel4Xv2(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e0, e1, e4, ec, e8, e5, e2, e3, blendColors, scaleAlpha); 384 | [ec, e8, ed, ef, ee, e9, e4, e0] = kernel4Xv2(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, ec, e8, ed, ef, ee, e9, e4, e0, blendColors, scaleAlpha); 385 | 386 | dstPixelView[dstX + dstY * dstW] = e0; 387 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 388 | dstPixelView[dstX + 2 + dstY * dstW] = e2; 389 | dstPixelView[dstX + 3 + dstY * dstW] = e3; 390 | dstPixelView[dstX + (dstY + 1) * dstW] = e4; 391 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e5; 392 | dstPixelView[dstX + 2 + (dstY + 1) * dstW] = e6; 393 | dstPixelView[dstX + 3 + (dstY + 1) * dstW] = e7; 394 | dstPixelView[dstX + (dstY + 2) * dstW] = e8; 395 | dstPixelView[dstX + 1 + (dstY + 2) * dstW] = e9; 396 | dstPixelView[dstX + 2 + (dstY + 2) * dstW] = ea; 397 | dstPixelView[dstX + 3 + (dstY + 2) * dstW] = eb; 398 | dstPixelView[dstX + (dstY + 3) * dstW] = ec; 399 | dstPixelView[dstX + 1 + (dstY + 3) * dstW] = ed; 400 | dstPixelView[dstX + 2 + (dstY + 3) * dstW] = ee; 401 | dstPixelView[dstX + 3 + (dstY + 3) * dstW] = ef; 402 | } 403 | 404 | function alphaBlend32W(dst, src, blendColors) { 405 | if (blendColors) { 406 | return pixelInterpolate(dst, src, 7, 1); 407 | } 408 | 409 | return dst; 410 | } 411 | 412 | function alphaBlend64W(dst, src, blendColors) { 413 | if (blendColors) { 414 | return pixelInterpolate(dst, src, 3, 1); 415 | } 416 | return dst; 417 | } 418 | 419 | function alphaBlend128W(dst, src, blendColors) { 420 | if (blendColors) { 421 | return pixelInterpolate(dst, src, 1, 1); 422 | } 423 | return dst; 424 | } 425 | 426 | function alphaBlend192W(dst, src, blendColors) { 427 | if (blendColors) { 428 | return pixelInterpolate(dst, src, 1, 3); 429 | } 430 | return src; 431 | } 432 | 433 | function alphaBlend224W(dst, src, blendColors) { 434 | if (blendColors) { 435 | return pixelInterpolate(dst, src, 1, 7); 436 | } 437 | return src; 438 | } 439 | 440 | function leftUp2_2X(n3, n2, pixel, blendColors) { 441 | const blendedN2 = alphaBlend64W(n2, pixel, blendColors); 442 | return [ 443 | alphaBlend224W(n3, pixel, blendColors), 444 | blendedN2, 445 | blendedN2 446 | ]; 447 | } 448 | 449 | function left2_2X(n3, n2, pixel, blendColors) { 450 | return [ 451 | alphaBlend192W(n3, pixel, blendColors), 452 | alphaBlend64W(n2, pixel, blendColors) 453 | ]; 454 | } 455 | 456 | function up2_2X(n3, n1, pixel, blendColors) { 457 | return [ 458 | alphaBlend192W(n3, pixel, blendColors), 459 | alphaBlend64W(n1, pixel, blendColors) 460 | ]; 461 | } 462 | 463 | function dia_2X(n3, pixel, blendColors) { 464 | return alphaBlend128W(n3, pixel, blendColors); 465 | } 466 | 467 | function kernel2Xv5(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n1, n2, n3, blendColors, scaleAlpha) { 468 | let ex = (pe != ph && pe != pf); 469 | if (!ex) { 470 | return [n1, n2, n3]; 471 | } 472 | let 473 | e = (yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha)) + (yuvDifference(ph, pf) << 2), 474 | i = (yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha)) + (yuvDifference(pe, pi, scaleAlpha) << 2), 475 | px = (yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha)) ? pf : ph; 476 | 477 | if ((e < i) && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))) { 478 | let 479 | ke = yuvDifference(pf, pg, scaleAlpha), 480 | ki = yuvDifference(ph, pc, scaleAlpha), 481 | ex2 = (pe != pc && pb != pc), 482 | ex3 = (pe != pg && pd != pg); 483 | if (((ke << 1) <= ki) && ex3 || (ke >= (ki << 1)) && ex2) { 484 | if (((ke << 1) <= ki) && ex3) { 485 | let leftOut = left2_2X(n3, n2, px, blendColors); 486 | n3 = leftOut[0]; 487 | n2 = leftOut[1]; 488 | } 489 | if ((ke >= (ki << 1)) && ex2) { 490 | let upOut = up2_2X(n3, n1, px, blendColors); 491 | n3 = upOut[0]; 492 | n1 = upOut[1]; 493 | } 494 | } else { 495 | n3 = dia_2X(n3, px, blendColors); 496 | } 497 | 498 | } else if (e <= i) { 499 | n3 = alphaBlend64W(n3, px, blendColors); 500 | } 501 | return [n1, n2, n3]; 502 | } 503 | 504 | function leftUp2_3X(n7, n5, n6, n2, n8, pixel, blendColors) { 505 | const 506 | blendedN7 = alphaBlend192W(n7, pixel, blendColors), 507 | blendedN6 = alphaBlend64W(n6, pixel, blendColors); 508 | return [ 509 | blendedN7, 510 | blendedN7, 511 | blendedN6, 512 | blendedN6, 513 | pixel 514 | ]; 515 | } 516 | 517 | function left2_3X(n7, n5, n6, n8, pixel, blendColors) { 518 | return [ 519 | alphaBlend192W(n7, pixel, blendColors), 520 | alphaBlend64W(n5, pixel, blendColors), 521 | alphaBlend64W(n6, pixel, blendColors), 522 | pixel 523 | ]; 524 | } 525 | 526 | function up2_3X(n5, n7, n2, n8, pixel, blendColors) { 527 | return [ 528 | alphaBlend192W(n5, pixel, blendColors), 529 | alphaBlend64W(n7, pixel, blendColors), 530 | alphaBlend64W(n2, pixel, blendColors), 531 | pixel 532 | ]; 533 | } 534 | 535 | function dia_3X(n8, n5, n7, pixel, blendColors) { 536 | return [ 537 | alphaBlend224W(n8, pixel, blendColors), 538 | alphaBlend32W(n5, pixel, blendColors), 539 | alphaBlend32W(n7, pixel, blendColors) 540 | ]; 541 | } 542 | 543 | function kernel3X(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n2, n5, n6, n7, n8, blendColors, scaleAlpha) { 544 | const ex = (pe != ph && pe != pf); 545 | if (!ex) { 546 | return [n2, n5, n6, n7, n8]; 547 | } 548 | 549 | const 550 | e = (yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha)) + (yuvDifference(ph, pf, scaleAlpha) << 2), 551 | i = (yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha)) + (yuvDifference(pe, pi, scaleAlpha) << 2); 552 | 553 | let state; 554 | if (USE_3X_ORIGINAL_IMPLEMENTATION) { 555 | state = ((e < i) && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))); 556 | } else { 557 | state = ((e < i) && (!isEqual(pf, pb, scaleAlpha) && !isEqual(pf, pc, scaleAlpha) || !isEqual(ph, pd, scaleAlpha) && !isEqual(ph, pg, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, f4, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) || !isEqual(ph, h5, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))); 558 | } 559 | 560 | if (state) { 561 | const 562 | ke = yuvDifference(pf, pg, scaleAlpha), 563 | ki = yuvDifference(ph, pc, scaleAlpha), 564 | ex2 = (pe != pc && pb != pc), 565 | ex3 = (pe != pg && pd != pg), 566 | px = (yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha)) ? pf : ph; 567 | if (((ke << 1) <= ki) && ex3 && (ke >= (ki << 1)) && ex2) { 568 | [n7, n5, n6, n2, n8] = leftUp2_3X(n7, n5, n6, n2, n8, px, blendColors); 569 | } else if (((ke << 1) <= ki) && ex3) { 570 | [n7, n5, n6, n8] = left2_3X(n7, n5, n6, n8, px, blendColors); 571 | } else if ((ke >= (ki << 1)) && ex2) { 572 | [n5, n7, n2, n8] = up2_3X(n5, n7, n2, n8, px, blendColors); 573 | } else { 574 | [n8, n5, n7] = dia_3X(n8, n5, n7, px, blendColors); 575 | } 576 | } else if (e <= i) { 577 | n8 = alphaBlend128W(n8, ((yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha)) ? pf : ph), blendColors); 578 | } 579 | return [n2, n5, n6, n7, n8]; 580 | } 581 | 582 | // 4xBR 583 | function leftUp2(n15, n14, n11, n13, n12, n10, n7, n3, pixel, blendColors) { 584 | const 585 | blendedN13 = alphaBlend192W(n13, pixel, blendColors), 586 | blendedN12 = alphaBlend64W(n12, pixel, blendColors); 587 | 588 | return [pixel, pixel, pixel, blendedN12, blendedN12, blendedN12, blendedN13, n3]; 589 | } 590 | 591 | function left2(n15, n14, n11, n13, n12, n10, pixel, blendColors) { 592 | return [ 593 | pixel, 594 | pixel, 595 | alphaBlend192W(n11, pixel, blendColors), 596 | alphaBlend192W(n13, pixel, blendColors), 597 | alphaBlend64W(n12, pixel, blendColors), 598 | alphaBlend64W(n10, pixel, blendColors) 599 | ]; 600 | } 601 | 602 | function up2(n15, n14, n11, n3, n7, n10, pixel, blendColors) { 603 | return [ 604 | pixel, 605 | alphaBlend192W(n14, pixel, blendColors), 606 | pixel, 607 | alphaBlend64W(n3, pixel, blendColors), 608 | alphaBlend192W(n7, pixel, blendColors), 609 | alphaBlend64W(n10, pixel, blendColors) 610 | ]; 611 | } 612 | 613 | function dia(n15, n14, n11, pixel, blendColors) { 614 | return [ 615 | pixel, 616 | alphaBlend128W(n14, pixel, blendColors), 617 | alphaBlend128W(n11, pixel, blendColors) 618 | ]; 619 | } 620 | 621 | function kernel4Xv2(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n15, n14, n11, n3, n7, n10, n13, n12, blendColors, scaleAlpha) { 622 | var ex = (pe != ph && pe != pf); 623 | if (!ex) { 624 | return [n15, n14, n11, n3, n7, n10, n13, n12]; 625 | } 626 | const 627 | e = (yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha)) + (yuvDifference(ph, pf, scaleAlpha) << 2), 628 | i = (yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha)) + (yuvDifference(pe, pi, scaleAlpha) << 2), 629 | px = (yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha)) ? pf : ph; 630 | if ((e < i) && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))) { 631 | const 632 | ke = yuvDifference(pf, pg, scaleAlpha), 633 | ki = yuvDifference(ph, pc, scaleAlpha), 634 | ex2 = (pe != pc && pb != pc), 635 | ex3 = (pe != pg && pd != pg); 636 | if (((ke << 1) <= ki) && ex3 || (ke >= (ki << 1)) && ex2) { 637 | if (((ke << 1) <= ki) && ex3) { 638 | [n15, n14, n11, n13, n12, n10] = left2(n15, n14, n11, n13, n12, n10, px, blendColors); 639 | } 640 | if ((ke >= (ki << 1)) && ex2) { 641 | [n15, n14, n11, n3, n7, n10] = up2(n15, n14, n11, n3, n7, n10, px, blendColors); 642 | } 643 | } else { 644 | [n15, n14, n11] = dia(n15, n14, n11, px, blendColors); 645 | } 646 | 647 | } else if (e <= i) { 648 | n15 = alphaBlend128W(n15, px, blendColors); 649 | } 650 | 651 | return [n15, n14, n11, n3, n7, n10, n13, n12]; 652 | } 653 | 654 | function parseOptions(rawOpts) { 655 | let 656 | blendColors = true, 657 | scaleAlpha = false; 658 | 659 | if (rawOpts) { 660 | if (rawOpts.blendColors === false) { 661 | blendColors = false; 662 | } 663 | 664 | if (rawOpts.scaleAlpha === true) { 665 | scaleAlpha = true; 666 | } 667 | } 668 | 669 | return {blendColors, scaleAlpha}; 670 | } 671 | 672 | function xbr2x(pixelArray, width, height, options) { 673 | const {blendColors, scaleAlpha} = parseOptions(options); 674 | const scaledPixelArray = new Uint32Array(width * height * 4); 675 | for (let c = 0; c < width; c++) { 676 | for (let d = 0; d < height; d++) { 677 | computeXbr2x(pixelArray, c, d, width, height, scaledPixelArray, c * 2, d * 2, width * 2, blendColors, scaleAlpha); 678 | } 679 | } 680 | return scaledPixelArray; 681 | } 682 | 683 | function xbr3x(pixelArray, width, height, options) { 684 | const {blendColors, scaleAlpha} = parseOptions(options); 685 | const scaledPixelArray = new Uint32Array(width * height * 9); 686 | for (let c = 0; c < width; c++) { 687 | for (let d = 0; d < height; d++) { 688 | computeXbr3x(pixelArray, c, d, width, height, scaledPixelArray, c * 3, d * 3, width * 3, blendColors, scaleAlpha); 689 | } 690 | } 691 | return scaledPixelArray; 692 | } 693 | 694 | function xbr4x(pixelArray, width, height, options) { 695 | const {blendColors, scaleAlpha} = parseOptions(options); 696 | const scaledPixelArray = new Uint32Array(width * height * 16); 697 | for (let c = 0; c < width; c++) { 698 | for (let d = 0; d < height; d++) { 699 | computeXbr4x(pixelArray, c, d, width, height, scaledPixelArray, c * 4, d * 4, width * 4, blendColors, scaleAlpha); 700 | } 701 | } 702 | return scaledPixelArray; 703 | } 704 | // CONCATENATED MODULE: ./src/demo.js 705 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyXBR", function() { return applyXBR; }); 706 | 707 | 708 | function readURL(input) { 709 | if (input.files && input.files[0]) { 710 | let reader = new FileReader(); 711 | reader.onload = function(e) { 712 | processURL(e.target.result); 713 | } 714 | 715 | reader.readAsDataURL(input.files[0]); 716 | } 717 | } 718 | 719 | function applyXBR(image, factor) { 720 | const canvas = document.createElement('canvas'); 721 | const 722 | sourceWidth = image.width, 723 | sourceHeight = image.height; 724 | canvas.width = sourceWidth; 725 | canvas.height = sourceHeight; 726 | 727 | const context = canvas.getContext('2d'); 728 | context.drawImage(image, 0, 0); 729 | 730 | const 731 | scaledWidth = sourceWidth * factor, 732 | scaledHeight = sourceHeight * factor, 733 | originalImageData = context.getImageData( 734 | 0, 735 | 0, 736 | sourceWidth, 737 | sourceHeight); 738 | 739 | const originalPixelView = new Uint32Array(originalImageData.data.buffer); 740 | 741 | let scaledPixelView; 742 | switch (factor) { 743 | case 2: 744 | scaledPixelView = xbr2x(originalPixelView, sourceWidth, sourceHeight); 745 | break; 746 | case 3: 747 | scaledPixelView = xbr3x(originalPixelView, sourceWidth, sourceHeight); 748 | break; 749 | case 4: 750 | scaledPixelView = xbr4x(originalPixelView, sourceWidth, sourceHeight); 751 | break; 752 | } 753 | 754 | const scaledImageData = new ImageData(new Uint8ClampedArray(scaledPixelView.buffer), scaledWidth, scaledHeight); 755 | canvas.width = scaledWidth; 756 | canvas.height = scaledHeight; 757 | 758 | context.putImageData(scaledImageData, 0, 0); 759 | 760 | return canvas; 761 | } 762 | 763 | function processURL(url) { 764 | let image = new Image(); 765 | image.src=url; 766 | 767 | /*When image loads...*/ 768 | image.onload = function(e) { 769 | image.setAttribute('width', image.width); 770 | image.setAttribute('height', image.height); 771 | /*Apply 2xBR*/ 772 | let resultCanvas = applyXBR(image, 2); 773 | 774 | document.body.appendChild(resultCanvas); 775 | resultCanvas = applyXBR(image, 3); 776 | 777 | document.body.appendChild(resultCanvas); 778 | resultCanvas = applyXBR(image, 4); 779 | 780 | document.body.appendChild(resultCanvas); 781 | } 782 | 783 | document.body.appendChild(image); 784 | } 785 | 786 | window.onload = function() { 787 | var inputFile = document.getElementById('processImage'); 788 | inputFile.addEventListener('change', () => readURL(inputFile)); 789 | 790 | let original = document.getElementById("original"); 791 | processURL("image.png"); 792 | } 793 | 794 | 795 | 796 | /***/ }) 797 | /******/ ]); -------------------------------------------------------------------------------- /dist/xBRjs.esm.js: -------------------------------------------------------------------------------- 1 | var xBRjs = 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | /******/ 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | /******/ 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) { 11 | /******/ return installedModules[moduleId].exports; 12 | /******/ } 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ i: moduleId, 16 | /******/ l: false, 17 | /******/ exports: {} 18 | /******/ }; 19 | /******/ 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | /******/ 23 | /******/ // Flag the module as loaded 24 | /******/ module.l = true; 25 | /******/ 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | /******/ 30 | /******/ 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | /******/ 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | /******/ 37 | /******/ // define getter function for harmony exports 38 | /******/ __webpack_require__.d = function(exports, name, getter) { 39 | /******/ if(!__webpack_require__.o(exports, name)) { 40 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 41 | /******/ } 42 | /******/ }; 43 | /******/ 44 | /******/ // define __esModule on exports 45 | /******/ __webpack_require__.r = function(exports) { 46 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 47 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 48 | /******/ } 49 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 50 | /******/ }; 51 | /******/ 52 | /******/ // create a fake namespace object 53 | /******/ // mode & 1: value is a module id, require it 54 | /******/ // mode & 2: merge all properties of value into the ns 55 | /******/ // mode & 4: return value when already ns object 56 | /******/ // mode & 8|1: behave like require 57 | /******/ __webpack_require__.t = function(value, mode) { 58 | /******/ if(mode & 1) value = __webpack_require__(value); 59 | /******/ if(mode & 8) return value; 60 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 61 | /******/ var ns = Object.create(null); 62 | /******/ __webpack_require__.r(ns); 63 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 64 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 65 | /******/ return ns; 66 | /******/ }; 67 | /******/ 68 | /******/ // getDefaultExport function for compatibility with non-harmony modules 69 | /******/ __webpack_require__.n = function(module) { 70 | /******/ var getter = module && module.__esModule ? 71 | /******/ function getDefault() { return module['default']; } : 72 | /******/ function getModuleExports() { return module; }; 73 | /******/ __webpack_require__.d(getter, 'a', getter); 74 | /******/ return getter; 75 | /******/ }; 76 | /******/ 77 | /******/ // Object.prototype.hasOwnProperty.call 78 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 79 | /******/ 80 | /******/ // __webpack_public_path__ 81 | /******/ __webpack_require__.p = ""; 82 | /******/ 83 | /******/ 84 | /******/ // Load entry module and return exports 85 | /******/ return __webpack_require__(__webpack_require__.s = 0); 86 | /******/ }) 87 | /************************************************************************/ 88 | /******/ ([ 89 | /* 0 */ 90 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 91 | 92 | "use strict"; 93 | __webpack_require__.r(__webpack_exports__); 94 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "xbr2x", function() { return xbr2x; }); 95 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "xbr3x", function() { return xbr3x; }); 96 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "xbr4x", function() { return xbr4x; }); 97 | function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } 98 | 99 | function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } 100 | 101 | function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } 102 | 103 | function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } 104 | 105 | // Options 106 | var USE_3X_ORIGINAL_IMPLEMENTATION = false; 107 | var REDMASK = 0x000000FF, 108 | // &MASK >>0 109 | GREENMASK = 0x0000FF00, 110 | // &MASK >>8 111 | BLUEMASK = 0x00FF0000, 112 | // &MASK >>16 113 | ALPHAMASK = 0xFF000000, 114 | // &MASK >>24 115 | THRESHHOLD_Y = 48, 116 | THRESHHOLD_U = 7, 117 | THRESHHOLD_V = 6; // Convert an ARGB byte to YUV 118 | 119 | function getYuv(p) { 120 | var r = p & REDMASK, 121 | g = (p & GREENMASK) >> 8, 122 | b = (p & BLUEMASK) >> 16, 123 | y = r * .299000 + g * .587000 + b * .114000, 124 | u = r * -.168736 + g * -.331264 + b * .500000, 125 | v = r * .500000 + g * -.418688 + b * -.081312; 126 | return [y, u, v]; 127 | } 128 | 129 | function yuvDifference(A, B, scaleAlpha) { 130 | var alphaA = (A & ALPHAMASK) >> 24 & 0xff, 131 | alphaB = (B & ALPHAMASK) >> 24 & 0xff; 132 | 133 | if (alphaA === 0 && alphaB === 0) { 134 | return 0; 135 | } 136 | 137 | if (!scaleAlpha && (alphaA < 255 || alphaB < 255)) { 138 | // Very large value not attainable by the thresholds 139 | return 1000000; 140 | } 141 | 142 | if (alphaA === 0 || alphaB === 0) { 143 | // Very large value not attainable by the thresholds 144 | return 1000000; 145 | } 146 | 147 | var yuvA = getYuv(A), 148 | yuvB = getYuv(B); 149 | /*Add HQx filters threshold & return*/ 150 | 151 | return Math.abs(yuvA[0] - yuvB[0]) * THRESHHOLD_Y + Math.abs(yuvA[1] - yuvB[1]) * THRESHHOLD_U + Math.abs(yuvA[2] - yuvB[2]) * THRESHHOLD_V; 152 | } 153 | 154 | function isEqual(A, B, scaleAlpha) { 155 | var alphaA = (A & ALPHAMASK) >> 24 & 0xff, 156 | alphaB = (B & ALPHAMASK) >> 24 & 0xff; 157 | 158 | if (alphaA === 0 && alphaB === 0) { 159 | return true; 160 | } 161 | 162 | if (!scaleAlpha && (alphaA < 255 || alphaB < 255)) { 163 | return false; 164 | } 165 | 166 | if (alphaA === 0 || alphaB === 0) { 167 | return false; 168 | } 169 | 170 | var yuvA = getYuv(A), 171 | yuvB = getYuv(B); 172 | 173 | if (Math.abs(yuvA[0] - yuvB[0]) > THRESHHOLD_Y) { 174 | return false; 175 | } 176 | 177 | if (Math.abs(yuvA[1] - yuvB[1]) > THRESHHOLD_U) { 178 | return false; 179 | } 180 | 181 | if (Math.abs(yuvA[2] - yuvB[2]) > THRESHHOLD_V) { 182 | return false; 183 | } 184 | 185 | return true; 186 | } 187 | 188 | function pixelInterpolate(A, B, q1, q2) { 189 | var alphaA = (A & ALPHAMASK) >> 24 & 0xff, 190 | alphaB = (B & ALPHAMASK) >> 24 & 0xff; 191 | /*Extract each value from 32bit Uint & blend colors together*/ 192 | 193 | var r, g, b, a; 194 | 195 | if (alphaA === 0) { 196 | r = B & REDMASK; 197 | g = (B & GREENMASK) >> 8; 198 | b = (B & BLUEMASK) >> 16; 199 | } else if (alphaB === 0) { 200 | r = A & REDMASK; 201 | g = (A & GREENMASK) >> 8; 202 | b = (A & BLUEMASK) >> 16; 203 | } else { 204 | r = (q2 * (B & REDMASK) + q1 * (A & REDMASK)) / (q1 + q2); 205 | g = (q2 * ((B & GREENMASK) >> 8) + q1 * ((A & GREENMASK) >> 8)) / (q1 + q2); 206 | b = (q2 * ((B & BLUEMASK) >> 16) + q1 * ((A & BLUEMASK) >> 16)) / (q1 + q2); 207 | } 208 | 209 | a = (q2 * alphaB + q1 * alphaA) / (q1 + q2); 210 | /*The bit hack '~~' is used to floor the values like Math.floor, but faster*/ 211 | 212 | return ~~r | ~~g << 8 | ~~b << 16 | ~~a << 24; 213 | } 214 | 215 | function getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH) { 216 | var xm1 = oriX - 1; 217 | 218 | if (xm1 < 0) { 219 | xm1 = 0; 220 | } 221 | 222 | var xm2 = oriX - 2; 223 | 224 | if (xm2 < 0) { 225 | xm2 = 0; 226 | } 227 | 228 | var xp1 = oriX + 1; 229 | 230 | if (xp1 >= oriW) { 231 | xp1 = oriW - 1; 232 | } 233 | 234 | var xp2 = oriX + 2; 235 | 236 | if (xp2 >= oriW) { 237 | xp2 = oriW - 1; 238 | } 239 | 240 | var ym1 = oriY - 1; 241 | 242 | if (ym1 < 0) { 243 | ym1 = 0; 244 | } 245 | 246 | var ym2 = oriY - 2; 247 | 248 | if (ym2 < 0) { 249 | ym2 = 0; 250 | } 251 | 252 | var yp1 = oriY + 1; 253 | 254 | if (yp1 >= oriH) { 255 | yp1 = oriH - 1; 256 | } 257 | 258 | var yp2 = oriY + 2; 259 | 260 | if (yp2 >= oriH) { 261 | yp2 = oriH - 1; 262 | } 263 | 264 | return [oriPixelView[xm1 + ym2 * oriW], 265 | /* a1 */ 266 | oriPixelView[oriX + ym2 * oriW], 267 | /* b1 */ 268 | oriPixelView[xp1 + ym2 * oriW], 269 | /* c1 */ 270 | oriPixelView[xm2 + ym1 * oriW], 271 | /* a0 */ 272 | oriPixelView[xm1 + ym1 * oriW], 273 | /* pa */ 274 | oriPixelView[oriX + ym1 * oriW], 275 | /* pb */ 276 | oriPixelView[xp1 + ym1 * oriW], 277 | /* pc */ 278 | oriPixelView[xp2 + ym1 * oriW], 279 | /* c4 */ 280 | oriPixelView[xm2 + oriY * oriW], 281 | /* d0 */ 282 | oriPixelView[xm1 + oriY * oriW], 283 | /* pd */ 284 | oriPixelView[oriX + oriY * oriW], 285 | /* pe */ 286 | oriPixelView[xp1 + oriY * oriW], 287 | /* pf */ 288 | oriPixelView[xp2 + oriY * oriW], 289 | /* f4 */ 290 | oriPixelView[xm2 + yp1 * oriW], 291 | /* g0 */ 292 | oriPixelView[xm1 + yp1 * oriW], 293 | /* pg */ 294 | oriPixelView[oriX + yp1 * oriW], 295 | /* ph */ 296 | oriPixelView[xp1 + yp1 * oriW], 297 | /* pi */ 298 | oriPixelView[xp2 + yp1 * oriW], 299 | /* i4 */ 300 | oriPixelView[xm1 + yp2 * oriW], 301 | /* g5 */ 302 | oriPixelView[oriX + yp2 * oriW], 303 | /* h5 */ 304 | oriPixelView[xp1 + yp2 * oriW] 305 | /* i5 */ 306 | ]; 307 | } // This is the XBR2x by Hyllian (see http://board.byuu.org/viewtopic.php?f=10&t=2248) 308 | 309 | 310 | function computeXbr2x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 311 | var relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 312 | 313 | var _relatedPoints = _slicedToArray(relatedPoints, 21), 314 | a1 = _relatedPoints[0], 315 | b1 = _relatedPoints[1], 316 | c1 = _relatedPoints[2], 317 | a0 = _relatedPoints[3], 318 | pa = _relatedPoints[4], 319 | pb = _relatedPoints[5], 320 | pc = _relatedPoints[6], 321 | c4 = _relatedPoints[7], 322 | d0 = _relatedPoints[8], 323 | pd = _relatedPoints[9], 324 | pe = _relatedPoints[10], 325 | pf = _relatedPoints[11], 326 | f4 = _relatedPoints[12], 327 | g0 = _relatedPoints[13], 328 | pg = _relatedPoints[14], 329 | ph = _relatedPoints[15], 330 | pi = _relatedPoints[16], 331 | i4 = _relatedPoints[17], 332 | g5 = _relatedPoints[18], 333 | h5 = _relatedPoints[19], 334 | i5 = _relatedPoints[20]; 335 | 336 | var e0, e1, e2, e3; 337 | e0 = e1 = e2 = e3 = pe; 338 | 339 | var _kernel2Xv = kernel2Xv5(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, e1, e2, e3, blendColors, scaleAlpha); 340 | 341 | var _kernel2Xv2 = _slicedToArray(_kernel2Xv, 3); 342 | 343 | e1 = _kernel2Xv2[0]; 344 | e2 = _kernel2Xv2[1]; 345 | e3 = _kernel2Xv2[2]; 346 | 347 | var _kernel2Xv3 = kernel2Xv5(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e0, e3, e1, blendColors, scaleAlpha); 348 | 349 | var _kernel2Xv4 = _slicedToArray(_kernel2Xv3, 3); 350 | 351 | e0 = _kernel2Xv4[0]; 352 | e3 = _kernel2Xv4[1]; 353 | e1 = _kernel2Xv4[2]; 354 | 355 | var _kernel2Xv5 = kernel2Xv5(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e2, e1, e0, blendColors, scaleAlpha); 356 | 357 | var _kernel2Xv6 = _slicedToArray(_kernel2Xv5, 3); 358 | 359 | e2 = _kernel2Xv6[0]; 360 | e1 = _kernel2Xv6[1]; 361 | e0 = _kernel2Xv6[2]; 362 | 363 | var _kernel2Xv7 = kernel2Xv5(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, e3, e0, e2, blendColors, scaleAlpha); 364 | 365 | var _kernel2Xv8 = _slicedToArray(_kernel2Xv7, 3); 366 | 367 | e3 = _kernel2Xv8[0]; 368 | e0 = _kernel2Xv8[1]; 369 | e2 = _kernel2Xv8[2]; 370 | dstPixelView[dstX + dstY * dstW] = e0; 371 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 372 | dstPixelView[dstX + (dstY + 1) * dstW] = e2; 373 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e3; 374 | } 375 | 376 | function computeXbr3x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 377 | var relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 378 | 379 | var _relatedPoints2 = _slicedToArray(relatedPoints, 21), 380 | a1 = _relatedPoints2[0], 381 | b1 = _relatedPoints2[1], 382 | c1 = _relatedPoints2[2], 383 | a0 = _relatedPoints2[3], 384 | pa = _relatedPoints2[4], 385 | pb = _relatedPoints2[5], 386 | pc = _relatedPoints2[6], 387 | c4 = _relatedPoints2[7], 388 | d0 = _relatedPoints2[8], 389 | pd = _relatedPoints2[9], 390 | pe = _relatedPoints2[10], 391 | pf = _relatedPoints2[11], 392 | f4 = _relatedPoints2[12], 393 | g0 = _relatedPoints2[13], 394 | pg = _relatedPoints2[14], 395 | ph = _relatedPoints2[15], 396 | pi = _relatedPoints2[16], 397 | i4 = _relatedPoints2[17], 398 | g5 = _relatedPoints2[18], 399 | h5 = _relatedPoints2[19], 400 | i5 = _relatedPoints2[20]; 401 | 402 | var e0, e1, e2, e3, e4, e5, e6, e7, e8; 403 | e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = pe; 404 | 405 | var _kernel3X = kernel3X(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, e2, e5, e6, e7, e8, blendColors, scaleAlpha); 406 | 407 | var _kernel3X2 = _slicedToArray(_kernel3X, 5); 408 | 409 | e2 = _kernel3X2[0]; 410 | e5 = _kernel3X2[1]; 411 | e6 = _kernel3X2[2]; 412 | e7 = _kernel3X2[3]; 413 | e8 = _kernel3X2[4]; 414 | 415 | var _kernel3X3 = kernel3X(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e0, e1, e8, e5, e2, blendColors, scaleAlpha); 416 | 417 | var _kernel3X4 = _slicedToArray(_kernel3X3, 5); 418 | 419 | e0 = _kernel3X4[0]; 420 | e1 = _kernel3X4[1]; 421 | e8 = _kernel3X4[2]; 422 | e5 = _kernel3X4[3]; 423 | e2 = _kernel3X4[4]; 424 | 425 | var _kernel3X5 = kernel3X(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e6, e3, e2, e1, e0, blendColors, scaleAlpha); 426 | 427 | var _kernel3X6 = _slicedToArray(_kernel3X5, 5); 428 | 429 | e6 = _kernel3X6[0]; 430 | e3 = _kernel3X6[1]; 431 | e2 = _kernel3X6[2]; 432 | e1 = _kernel3X6[3]; 433 | e0 = _kernel3X6[4]; 434 | 435 | var _kernel3X7 = kernel3X(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, e8, e7, e0, e3, e6, blendColors, scaleAlpha); 436 | 437 | var _kernel3X8 = _slicedToArray(_kernel3X7, 5); 438 | 439 | e8 = _kernel3X8[0]; 440 | e7 = _kernel3X8[1]; 441 | e0 = _kernel3X8[2]; 442 | e3 = _kernel3X8[3]; 443 | e6 = _kernel3X8[4]; 444 | dstPixelView[dstX + dstY * dstW] = e0; 445 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 446 | dstPixelView[dstX + 2 + dstY * dstW] = e2; 447 | dstPixelView[dstX + (dstY + 1) * dstW] = e3; 448 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e4; 449 | dstPixelView[dstX + 2 + (dstY + 1) * dstW] = e5; 450 | dstPixelView[dstX + (dstY + 2) * dstW] = e6; 451 | dstPixelView[dstX + 1 + (dstY + 2) * dstW] = e7; 452 | dstPixelView[dstX + 2 + (dstY + 2) * dstW] = e8; 453 | } 454 | 455 | function computeXbr4x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 456 | var relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 457 | 458 | var _relatedPoints3 = _slicedToArray(relatedPoints, 21), 459 | a1 = _relatedPoints3[0], 460 | b1 = _relatedPoints3[1], 461 | c1 = _relatedPoints3[2], 462 | a0 = _relatedPoints3[3], 463 | pa = _relatedPoints3[4], 464 | pb = _relatedPoints3[5], 465 | pc = _relatedPoints3[6], 466 | c4 = _relatedPoints3[7], 467 | d0 = _relatedPoints3[8], 468 | pd = _relatedPoints3[9], 469 | pe = _relatedPoints3[10], 470 | pf = _relatedPoints3[11], 471 | f4 = _relatedPoints3[12], 472 | g0 = _relatedPoints3[13], 473 | pg = _relatedPoints3[14], 474 | ph = _relatedPoints3[15], 475 | pi = _relatedPoints3[16], 476 | i4 = _relatedPoints3[17], 477 | g5 = _relatedPoints3[18], 478 | h5 = _relatedPoints3[19], 479 | i5 = _relatedPoints3[20]; 480 | 481 | var e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef; 482 | e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = e9 = ea = eb = ec = ed = ee = ef = pe; 483 | 484 | var _kernel4Xv = kernel4Xv2(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, ef, ee, eb, e3, e7, ea, ed, ec, blendColors, scaleAlpha); 485 | 486 | var _kernel4Xv2 = _slicedToArray(_kernel4Xv, 8); 487 | 488 | ef = _kernel4Xv2[0]; 489 | ee = _kernel4Xv2[1]; 490 | eb = _kernel4Xv2[2]; 491 | e3 = _kernel4Xv2[3]; 492 | e7 = _kernel4Xv2[4]; 493 | ea = _kernel4Xv2[5]; 494 | ed = _kernel4Xv2[6]; 495 | ec = _kernel4Xv2[7]; 496 | 497 | var _kernel4Xv3 = kernel4Xv2(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e3, e7, e2, e0, e1, e6, eb, ef, blendColors, scaleAlpha); 498 | 499 | var _kernel4Xv4 = _slicedToArray(_kernel4Xv3, 8); 500 | 501 | e3 = _kernel4Xv4[0]; 502 | e7 = _kernel4Xv4[1]; 503 | e2 = _kernel4Xv4[2]; 504 | e0 = _kernel4Xv4[3]; 505 | e1 = _kernel4Xv4[4]; 506 | e6 = _kernel4Xv4[5]; 507 | eb = _kernel4Xv4[6]; 508 | ef = _kernel4Xv4[7]; 509 | 510 | var _kernel4Xv5 = kernel4Xv2(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e0, e1, e4, ec, e8, e5, e2, e3, blendColors, scaleAlpha); 511 | 512 | var _kernel4Xv6 = _slicedToArray(_kernel4Xv5, 8); 513 | 514 | e0 = _kernel4Xv6[0]; 515 | e1 = _kernel4Xv6[1]; 516 | e4 = _kernel4Xv6[2]; 517 | ec = _kernel4Xv6[3]; 518 | e8 = _kernel4Xv6[4]; 519 | e5 = _kernel4Xv6[5]; 520 | e2 = _kernel4Xv6[6]; 521 | e3 = _kernel4Xv6[7]; 522 | 523 | var _kernel4Xv7 = kernel4Xv2(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, ec, e8, ed, ef, ee, e9, e4, e0, blendColors, scaleAlpha); 524 | 525 | var _kernel4Xv8 = _slicedToArray(_kernel4Xv7, 8); 526 | 527 | ec = _kernel4Xv8[0]; 528 | e8 = _kernel4Xv8[1]; 529 | ed = _kernel4Xv8[2]; 530 | ef = _kernel4Xv8[3]; 531 | ee = _kernel4Xv8[4]; 532 | e9 = _kernel4Xv8[5]; 533 | e4 = _kernel4Xv8[6]; 534 | e0 = _kernel4Xv8[7]; 535 | dstPixelView[dstX + dstY * dstW] = e0; 536 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 537 | dstPixelView[dstX + 2 + dstY * dstW] = e2; 538 | dstPixelView[dstX + 3 + dstY * dstW] = e3; 539 | dstPixelView[dstX + (dstY + 1) * dstW] = e4; 540 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e5; 541 | dstPixelView[dstX + 2 + (dstY + 1) * dstW] = e6; 542 | dstPixelView[dstX + 3 + (dstY + 1) * dstW] = e7; 543 | dstPixelView[dstX + (dstY + 2) * dstW] = e8; 544 | dstPixelView[dstX + 1 + (dstY + 2) * dstW] = e9; 545 | dstPixelView[dstX + 2 + (dstY + 2) * dstW] = ea; 546 | dstPixelView[dstX + 3 + (dstY + 2) * dstW] = eb; 547 | dstPixelView[dstX + (dstY + 3) * dstW] = ec; 548 | dstPixelView[dstX + 1 + (dstY + 3) * dstW] = ed; 549 | dstPixelView[dstX + 2 + (dstY + 3) * dstW] = ee; 550 | dstPixelView[dstX + 3 + (dstY + 3) * dstW] = ef; 551 | } 552 | 553 | function alphaBlend32W(dst, src, blendColors) { 554 | if (blendColors) { 555 | return pixelInterpolate(dst, src, 7, 1); 556 | } 557 | 558 | return dst; 559 | } 560 | 561 | function alphaBlend64W(dst, src, blendColors) { 562 | if (blendColors) { 563 | return pixelInterpolate(dst, src, 3, 1); 564 | } 565 | 566 | return dst; 567 | } 568 | 569 | function alphaBlend128W(dst, src, blendColors) { 570 | if (blendColors) { 571 | return pixelInterpolate(dst, src, 1, 1); 572 | } 573 | 574 | return dst; 575 | } 576 | 577 | function alphaBlend192W(dst, src, blendColors) { 578 | if (blendColors) { 579 | return pixelInterpolate(dst, src, 1, 3); 580 | } 581 | 582 | return src; 583 | } 584 | 585 | function alphaBlend224W(dst, src, blendColors) { 586 | if (blendColors) { 587 | return pixelInterpolate(dst, src, 1, 7); 588 | } 589 | 590 | return src; 591 | } 592 | 593 | function leftUp2_2X(n3, n2, pixel, blendColors) { 594 | var blendedN2 = alphaBlend64W(n2, pixel, blendColors); 595 | return [alphaBlend224W(n3, pixel, blendColors), blendedN2, blendedN2]; 596 | } 597 | 598 | function left2_2X(n3, n2, pixel, blendColors) { 599 | return [alphaBlend192W(n3, pixel, blendColors), alphaBlend64W(n2, pixel, blendColors)]; 600 | } 601 | 602 | function up2_2X(n3, n1, pixel, blendColors) { 603 | return [alphaBlend192W(n3, pixel, blendColors), alphaBlend64W(n1, pixel, blendColors)]; 604 | } 605 | 606 | function dia_2X(n3, pixel, blendColors) { 607 | return alphaBlend128W(n3, pixel, blendColors); 608 | } 609 | 610 | function kernel2Xv5(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n1, n2, n3, blendColors, scaleAlpha) { 611 | var ex = pe != ph && pe != pf; 612 | 613 | if (!ex) { 614 | return [n1, n2, n3]; 615 | } 616 | 617 | var e = yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha) + (yuvDifference(ph, pf) << 2), 618 | i = yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha) + (yuvDifference(pe, pi, scaleAlpha) << 2), 619 | px = yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha) ? pf : ph; 620 | 621 | if (e < i && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))) { 622 | var ke = yuvDifference(pf, pg, scaleAlpha), 623 | ki = yuvDifference(ph, pc, scaleAlpha), 624 | ex2 = pe != pc && pb != pc, 625 | ex3 = pe != pg && pd != pg; 626 | 627 | if (ke << 1 <= ki && ex3 || ke >= ki << 1 && ex2) { 628 | if (ke << 1 <= ki && ex3) { 629 | var leftOut = left2_2X(n3, n2, px, blendColors); 630 | n3 = leftOut[0]; 631 | n2 = leftOut[1]; 632 | } 633 | 634 | if (ke >= ki << 1 && ex2) { 635 | var upOut = up2_2X(n3, n1, px, blendColors); 636 | n3 = upOut[0]; 637 | n1 = upOut[1]; 638 | } 639 | } else { 640 | n3 = dia_2X(n3, px, blendColors); 641 | } 642 | } else if (e <= i) { 643 | n3 = alphaBlend64W(n3, px, blendColors); 644 | } 645 | 646 | return [n1, n2, n3]; 647 | } 648 | 649 | function leftUp2_3X(n7, n5, n6, n2, n8, pixel, blendColors) { 650 | var blendedN7 = alphaBlend192W(n7, pixel, blendColors), 651 | blendedN6 = alphaBlend64W(n6, pixel, blendColors); 652 | return [blendedN7, blendedN7, blendedN6, blendedN6, pixel]; 653 | } 654 | 655 | function left2_3X(n7, n5, n6, n8, pixel, blendColors) { 656 | return [alphaBlend192W(n7, pixel, blendColors), alphaBlend64W(n5, pixel, blendColors), alphaBlend64W(n6, pixel, blendColors), pixel]; 657 | } 658 | 659 | function up2_3X(n5, n7, n2, n8, pixel, blendColors) { 660 | return [alphaBlend192W(n5, pixel, blendColors), alphaBlend64W(n7, pixel, blendColors), alphaBlend64W(n2, pixel, blendColors), pixel]; 661 | } 662 | 663 | function dia_3X(n8, n5, n7, pixel, blendColors) { 664 | return [alphaBlend224W(n8, pixel, blendColors), alphaBlend32W(n5, pixel, blendColors), alphaBlend32W(n7, pixel, blendColors)]; 665 | } 666 | 667 | function kernel3X(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n2, n5, n6, n7, n8, blendColors, scaleAlpha) { 668 | var ex = pe != ph && pe != pf; 669 | 670 | if (!ex) { 671 | return [n2, n5, n6, n7, n8]; 672 | } 673 | 674 | var e = yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha) + (yuvDifference(ph, pf, scaleAlpha) << 2), 675 | i = yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha) + (yuvDifference(pe, pi, scaleAlpha) << 2); 676 | var state; 677 | 678 | if (USE_3X_ORIGINAL_IMPLEMENTATION) { 679 | state = e < i && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha)); 680 | } else { 681 | state = e < i && (!isEqual(pf, pb, scaleAlpha) && !isEqual(pf, pc, scaleAlpha) || !isEqual(ph, pd, scaleAlpha) && !isEqual(ph, pg, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, f4, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) || !isEqual(ph, h5, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha)); 682 | } 683 | 684 | if (state) { 685 | var ke = yuvDifference(pf, pg, scaleAlpha), 686 | ki = yuvDifference(ph, pc, scaleAlpha), 687 | ex2 = pe != pc && pb != pc, 688 | ex3 = pe != pg && pd != pg, 689 | px = yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha) ? pf : ph; 690 | 691 | if (ke << 1 <= ki && ex3 && ke >= ki << 1 && ex2) { 692 | var _leftUp2_3X = leftUp2_3X(n7, n5, n6, n2, n8, px, blendColors); 693 | 694 | var _leftUp2_3X2 = _slicedToArray(_leftUp2_3X, 5); 695 | 696 | n7 = _leftUp2_3X2[0]; 697 | n5 = _leftUp2_3X2[1]; 698 | n6 = _leftUp2_3X2[2]; 699 | n2 = _leftUp2_3X2[3]; 700 | n8 = _leftUp2_3X2[4]; 701 | } else if (ke << 1 <= ki && ex3) { 702 | var _left2_3X = left2_3X(n7, n5, n6, n8, px, blendColors); 703 | 704 | var _left2_3X2 = _slicedToArray(_left2_3X, 4); 705 | 706 | n7 = _left2_3X2[0]; 707 | n5 = _left2_3X2[1]; 708 | n6 = _left2_3X2[2]; 709 | n8 = _left2_3X2[3]; 710 | } else if (ke >= ki << 1 && ex2) { 711 | var _up2_3X = up2_3X(n5, n7, n2, n8, px, blendColors); 712 | 713 | var _up2_3X2 = _slicedToArray(_up2_3X, 4); 714 | 715 | n5 = _up2_3X2[0]; 716 | n7 = _up2_3X2[1]; 717 | n2 = _up2_3X2[2]; 718 | n8 = _up2_3X2[3]; 719 | } else { 720 | var _dia_3X = dia_3X(n8, n5, n7, px, blendColors); 721 | 722 | var _dia_3X2 = _slicedToArray(_dia_3X, 3); 723 | 724 | n8 = _dia_3X2[0]; 725 | n5 = _dia_3X2[1]; 726 | n7 = _dia_3X2[2]; 727 | } 728 | } else if (e <= i) { 729 | n8 = alphaBlend128W(n8, yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha) ? pf : ph, blendColors); 730 | } 731 | 732 | return [n2, n5, n6, n7, n8]; 733 | } // 4xBR 734 | 735 | 736 | function leftUp2(n15, n14, n11, n13, n12, n10, n7, n3, pixel, blendColors) { 737 | var blendedN13 = alphaBlend192W(n13, pixel, blendColors), 738 | blendedN12 = alphaBlend64W(n12, pixel, blendColors); 739 | return [pixel, pixel, pixel, blendedN12, blendedN12, blendedN12, blendedN13, n3]; 740 | } 741 | 742 | function left2(n15, n14, n11, n13, n12, n10, pixel, blendColors) { 743 | return [pixel, pixel, alphaBlend192W(n11, pixel, blendColors), alphaBlend192W(n13, pixel, blendColors), alphaBlend64W(n12, pixel, blendColors), alphaBlend64W(n10, pixel, blendColors)]; 744 | } 745 | 746 | function up2(n15, n14, n11, n3, n7, n10, pixel, blendColors) { 747 | return [pixel, alphaBlend192W(n14, pixel, blendColors), pixel, alphaBlend64W(n3, pixel, blendColors), alphaBlend192W(n7, pixel, blendColors), alphaBlend64W(n10, pixel, blendColors)]; 748 | } 749 | 750 | function dia(n15, n14, n11, pixel, blendColors) { 751 | return [pixel, alphaBlend128W(n14, pixel, blendColors), alphaBlend128W(n11, pixel, blendColors)]; 752 | } 753 | 754 | function kernel4Xv2(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n15, n14, n11, n3, n7, n10, n13, n12, blendColors, scaleAlpha) { 755 | var ex = pe != ph && pe != pf; 756 | 757 | if (!ex) { 758 | return [n15, n14, n11, n3, n7, n10, n13, n12]; 759 | } 760 | 761 | var e = yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha) + (yuvDifference(ph, pf, scaleAlpha) << 2), 762 | i = yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha) + (yuvDifference(pe, pi, scaleAlpha) << 2), 763 | px = yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha) ? pf : ph; 764 | 765 | if (e < i && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))) { 766 | var ke = yuvDifference(pf, pg, scaleAlpha), 767 | ki = yuvDifference(ph, pc, scaleAlpha), 768 | ex2 = pe != pc && pb != pc, 769 | ex3 = pe != pg && pd != pg; 770 | 771 | if (ke << 1 <= ki && ex3 || ke >= ki << 1 && ex2) { 772 | if (ke << 1 <= ki && ex3) { 773 | var _left = left2(n15, n14, n11, n13, n12, n10, px, blendColors); 774 | 775 | var _left2 = _slicedToArray(_left, 6); 776 | 777 | n15 = _left2[0]; 778 | n14 = _left2[1]; 779 | n11 = _left2[2]; 780 | n13 = _left2[3]; 781 | n12 = _left2[4]; 782 | n10 = _left2[5]; 783 | } 784 | 785 | if (ke >= ki << 1 && ex2) { 786 | var _up = up2(n15, n14, n11, n3, n7, n10, px, blendColors); 787 | 788 | var _up2 = _slicedToArray(_up, 6); 789 | 790 | n15 = _up2[0]; 791 | n14 = _up2[1]; 792 | n11 = _up2[2]; 793 | n3 = _up2[3]; 794 | n7 = _up2[4]; 795 | n10 = _up2[5]; 796 | } 797 | } else { 798 | var _dia = dia(n15, n14, n11, px, blendColors); 799 | 800 | var _dia2 = _slicedToArray(_dia, 3); 801 | 802 | n15 = _dia2[0]; 803 | n14 = _dia2[1]; 804 | n11 = _dia2[2]; 805 | } 806 | } else if (e <= i) { 807 | n15 = alphaBlend128W(n15, px, blendColors); 808 | } 809 | 810 | return [n15, n14, n11, n3, n7, n10, n13, n12]; 811 | } 812 | 813 | function parseOptions(rawOpts) { 814 | var blendColors = true, 815 | scaleAlpha = false; 816 | 817 | if (rawOpts) { 818 | if (rawOpts.blendColors === false) { 819 | blendColors = false; 820 | } 821 | 822 | if (rawOpts.scaleAlpha === true) { 823 | scaleAlpha = true; 824 | } 825 | } 826 | 827 | return { 828 | blendColors: blendColors, 829 | scaleAlpha: scaleAlpha 830 | }; 831 | } 832 | 833 | function xbr2x(pixelArray, width, height, options) { 834 | var _parseOptions = parseOptions(options), 835 | blendColors = _parseOptions.blendColors, 836 | scaleAlpha = _parseOptions.scaleAlpha; 837 | 838 | var scaledPixelArray = new Uint32Array(width * height * 4); 839 | 840 | for (var c = 0; c < width; c++) { 841 | for (var d = 0; d < height; d++) { 842 | computeXbr2x(pixelArray, c, d, width, height, scaledPixelArray, c * 2, d * 2, width * 2, blendColors, scaleAlpha); 843 | } 844 | } 845 | 846 | return scaledPixelArray; 847 | } 848 | function xbr3x(pixelArray, width, height, options) { 849 | var _parseOptions2 = parseOptions(options), 850 | blendColors = _parseOptions2.blendColors, 851 | scaleAlpha = _parseOptions2.scaleAlpha; 852 | 853 | var scaledPixelArray = new Uint32Array(width * height * 9); 854 | 855 | for (var c = 0; c < width; c++) { 856 | for (var d = 0; d < height; d++) { 857 | computeXbr3x(pixelArray, c, d, width, height, scaledPixelArray, c * 3, d * 3, width * 3, blendColors, scaleAlpha); 858 | } 859 | } 860 | 861 | return scaledPixelArray; 862 | } 863 | function xbr4x(pixelArray, width, height, options) { 864 | var _parseOptions3 = parseOptions(options), 865 | blendColors = _parseOptions3.blendColors, 866 | scaleAlpha = _parseOptions3.scaleAlpha; 867 | 868 | var scaledPixelArray = new Uint32Array(width * height * 16); 869 | 870 | for (var c = 0; c < width; c++) { 871 | for (var d = 0; d < height; d++) { 872 | computeXbr4x(pixelArray, c, d, width, height, scaledPixelArray, c * 4, d * 4, width * 4, blendColors, scaleAlpha); 873 | } 874 | } 875 | 876 | return scaledPixelArray; 877 | } 878 | 879 | /***/ }) 880 | /******/ ]); 881 | 882 | 883 | const _xBRjs$xbr2x = xBRjs['xbr2x']; 884 | const _xBRjs$xbr3x = xBRjs['xbr3x']; 885 | const _xBRjs$xbr4x = xBRjs['xbr4x']; 886 | 887 | export { 888 | _xBRjs$xbr2x as xbr2x, 889 | _xBRjs$xbr3x as xbr3x, 890 | _xBRjs$xbr4x as xbr4x 891 | } -------------------------------------------------------------------------------- /dist/xBRjs.umd.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(); 4 | else if(typeof define === 'function' && define.amd) 5 | define([], factory); 6 | else if(typeof exports === 'object') 7 | exports["xBRjs"] = factory(); 8 | else 9 | root["xBRjs"] = factory(); 10 | })(window, function() { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | /******/ 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | /******/ 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) { 20 | /******/ return installedModules[moduleId].exports; 21 | /******/ } 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ i: moduleId, 25 | /******/ l: false, 26 | /******/ exports: {} 27 | /******/ }; 28 | /******/ 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | /******/ 32 | /******/ // Flag the module as loaded 33 | /******/ module.l = true; 34 | /******/ 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | /******/ 39 | /******/ 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | /******/ 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | /******/ 46 | /******/ // define getter function for harmony exports 47 | /******/ __webpack_require__.d = function(exports, name, getter) { 48 | /******/ if(!__webpack_require__.o(exports, name)) { 49 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 50 | /******/ } 51 | /******/ }; 52 | /******/ 53 | /******/ // define __esModule on exports 54 | /******/ __webpack_require__.r = function(exports) { 55 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 56 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 57 | /******/ } 58 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 59 | /******/ }; 60 | /******/ 61 | /******/ // create a fake namespace object 62 | /******/ // mode & 1: value is a module id, require it 63 | /******/ // mode & 2: merge all properties of value into the ns 64 | /******/ // mode & 4: return value when already ns object 65 | /******/ // mode & 8|1: behave like require 66 | /******/ __webpack_require__.t = function(value, mode) { 67 | /******/ if(mode & 1) value = __webpack_require__(value); 68 | /******/ if(mode & 8) return value; 69 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 70 | /******/ var ns = Object.create(null); 71 | /******/ __webpack_require__.r(ns); 72 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 73 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 74 | /******/ return ns; 75 | /******/ }; 76 | /******/ 77 | /******/ // getDefaultExport function for compatibility with non-harmony modules 78 | /******/ __webpack_require__.n = function(module) { 79 | /******/ var getter = module && module.__esModule ? 80 | /******/ function getDefault() { return module['default']; } : 81 | /******/ function getModuleExports() { return module; }; 82 | /******/ __webpack_require__.d(getter, 'a', getter); 83 | /******/ return getter; 84 | /******/ }; 85 | /******/ 86 | /******/ // Object.prototype.hasOwnProperty.call 87 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 88 | /******/ 89 | /******/ // __webpack_public_path__ 90 | /******/ __webpack_require__.p = ""; 91 | /******/ 92 | /******/ 93 | /******/ // Load entry module and return exports 94 | /******/ return __webpack_require__(__webpack_require__.s = 0); 95 | /******/ }) 96 | /************************************************************************/ 97 | /******/ ([ 98 | /* 0 */ 99 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 100 | 101 | "use strict"; 102 | __webpack_require__.r(__webpack_exports__); 103 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "xbr2x", function() { return xbr2x; }); 104 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "xbr3x", function() { return xbr3x; }); 105 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "xbr4x", function() { return xbr4x; }); 106 | function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } 107 | 108 | function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } 109 | 110 | function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } 111 | 112 | function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } 113 | 114 | // Options 115 | var USE_3X_ORIGINAL_IMPLEMENTATION = false; 116 | var REDMASK = 0x000000FF, 117 | // &MASK >>0 118 | GREENMASK = 0x0000FF00, 119 | // &MASK >>8 120 | BLUEMASK = 0x00FF0000, 121 | // &MASK >>16 122 | ALPHAMASK = 0xFF000000, 123 | // &MASK >>24 124 | THRESHHOLD_Y = 48, 125 | THRESHHOLD_U = 7, 126 | THRESHHOLD_V = 6; // Convert an ARGB byte to YUV 127 | 128 | function getYuv(p) { 129 | var r = p & REDMASK, 130 | g = (p & GREENMASK) >> 8, 131 | b = (p & BLUEMASK) >> 16, 132 | y = r * .299000 + g * .587000 + b * .114000, 133 | u = r * -.168736 + g * -.331264 + b * .500000, 134 | v = r * .500000 + g * -.418688 + b * -.081312; 135 | return [y, u, v]; 136 | } 137 | 138 | function yuvDifference(A, B, scaleAlpha) { 139 | var alphaA = (A & ALPHAMASK) >> 24 & 0xff, 140 | alphaB = (B & ALPHAMASK) >> 24 & 0xff; 141 | 142 | if (alphaA === 0 && alphaB === 0) { 143 | return 0; 144 | } 145 | 146 | if (!scaleAlpha && (alphaA < 255 || alphaB < 255)) { 147 | // Very large value not attainable by the thresholds 148 | return 1000000; 149 | } 150 | 151 | if (alphaA === 0 || alphaB === 0) { 152 | // Very large value not attainable by the thresholds 153 | return 1000000; 154 | } 155 | 156 | var yuvA = getYuv(A), 157 | yuvB = getYuv(B); 158 | /*Add HQx filters threshold & return*/ 159 | 160 | return Math.abs(yuvA[0] - yuvB[0]) * THRESHHOLD_Y + Math.abs(yuvA[1] - yuvB[1]) * THRESHHOLD_U + Math.abs(yuvA[2] - yuvB[2]) * THRESHHOLD_V; 161 | } 162 | 163 | function isEqual(A, B, scaleAlpha) { 164 | var alphaA = (A & ALPHAMASK) >> 24 & 0xff, 165 | alphaB = (B & ALPHAMASK) >> 24 & 0xff; 166 | 167 | if (alphaA === 0 && alphaB === 0) { 168 | return true; 169 | } 170 | 171 | if (!scaleAlpha && (alphaA < 255 || alphaB < 255)) { 172 | return false; 173 | } 174 | 175 | if (alphaA === 0 || alphaB === 0) { 176 | return false; 177 | } 178 | 179 | var yuvA = getYuv(A), 180 | yuvB = getYuv(B); 181 | 182 | if (Math.abs(yuvA[0] - yuvB[0]) > THRESHHOLD_Y) { 183 | return false; 184 | } 185 | 186 | if (Math.abs(yuvA[1] - yuvB[1]) > THRESHHOLD_U) { 187 | return false; 188 | } 189 | 190 | if (Math.abs(yuvA[2] - yuvB[2]) > THRESHHOLD_V) { 191 | return false; 192 | } 193 | 194 | return true; 195 | } 196 | 197 | function pixelInterpolate(A, B, q1, q2) { 198 | var alphaA = (A & ALPHAMASK) >> 24 & 0xff, 199 | alphaB = (B & ALPHAMASK) >> 24 & 0xff; 200 | /*Extract each value from 32bit Uint & blend colors together*/ 201 | 202 | var r, g, b, a; 203 | 204 | if (alphaA === 0) { 205 | r = B & REDMASK; 206 | g = (B & GREENMASK) >> 8; 207 | b = (B & BLUEMASK) >> 16; 208 | } else if (alphaB === 0) { 209 | r = A & REDMASK; 210 | g = (A & GREENMASK) >> 8; 211 | b = (A & BLUEMASK) >> 16; 212 | } else { 213 | r = (q2 * (B & REDMASK) + q1 * (A & REDMASK)) / (q1 + q2); 214 | g = (q2 * ((B & GREENMASK) >> 8) + q1 * ((A & GREENMASK) >> 8)) / (q1 + q2); 215 | b = (q2 * ((B & BLUEMASK) >> 16) + q1 * ((A & BLUEMASK) >> 16)) / (q1 + q2); 216 | } 217 | 218 | a = (q2 * alphaB + q1 * alphaA) / (q1 + q2); 219 | /*The bit hack '~~' is used to floor the values like Math.floor, but faster*/ 220 | 221 | return ~~r | ~~g << 8 | ~~b << 16 | ~~a << 24; 222 | } 223 | 224 | function getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH) { 225 | var xm1 = oriX - 1; 226 | 227 | if (xm1 < 0) { 228 | xm1 = 0; 229 | } 230 | 231 | var xm2 = oriX - 2; 232 | 233 | if (xm2 < 0) { 234 | xm2 = 0; 235 | } 236 | 237 | var xp1 = oriX + 1; 238 | 239 | if (xp1 >= oriW) { 240 | xp1 = oriW - 1; 241 | } 242 | 243 | var xp2 = oriX + 2; 244 | 245 | if (xp2 >= oriW) { 246 | xp2 = oriW - 1; 247 | } 248 | 249 | var ym1 = oriY - 1; 250 | 251 | if (ym1 < 0) { 252 | ym1 = 0; 253 | } 254 | 255 | var ym2 = oriY - 2; 256 | 257 | if (ym2 < 0) { 258 | ym2 = 0; 259 | } 260 | 261 | var yp1 = oriY + 1; 262 | 263 | if (yp1 >= oriH) { 264 | yp1 = oriH - 1; 265 | } 266 | 267 | var yp2 = oriY + 2; 268 | 269 | if (yp2 >= oriH) { 270 | yp2 = oriH - 1; 271 | } 272 | 273 | return [oriPixelView[xm1 + ym2 * oriW], 274 | /* a1 */ 275 | oriPixelView[oriX + ym2 * oriW], 276 | /* b1 */ 277 | oriPixelView[xp1 + ym2 * oriW], 278 | /* c1 */ 279 | oriPixelView[xm2 + ym1 * oriW], 280 | /* a0 */ 281 | oriPixelView[xm1 + ym1 * oriW], 282 | /* pa */ 283 | oriPixelView[oriX + ym1 * oriW], 284 | /* pb */ 285 | oriPixelView[xp1 + ym1 * oriW], 286 | /* pc */ 287 | oriPixelView[xp2 + ym1 * oriW], 288 | /* c4 */ 289 | oriPixelView[xm2 + oriY * oriW], 290 | /* d0 */ 291 | oriPixelView[xm1 + oriY * oriW], 292 | /* pd */ 293 | oriPixelView[oriX + oriY * oriW], 294 | /* pe */ 295 | oriPixelView[xp1 + oriY * oriW], 296 | /* pf */ 297 | oriPixelView[xp2 + oriY * oriW], 298 | /* f4 */ 299 | oriPixelView[xm2 + yp1 * oriW], 300 | /* g0 */ 301 | oriPixelView[xm1 + yp1 * oriW], 302 | /* pg */ 303 | oriPixelView[oriX + yp1 * oriW], 304 | /* ph */ 305 | oriPixelView[xp1 + yp1 * oriW], 306 | /* pi */ 307 | oriPixelView[xp2 + yp1 * oriW], 308 | /* i4 */ 309 | oriPixelView[xm1 + yp2 * oriW], 310 | /* g5 */ 311 | oriPixelView[oriX + yp2 * oriW], 312 | /* h5 */ 313 | oriPixelView[xp1 + yp2 * oriW] 314 | /* i5 */ 315 | ]; 316 | } // This is the XBR2x by Hyllian (see http://board.byuu.org/viewtopic.php?f=10&t=2248) 317 | 318 | 319 | function computeXbr2x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 320 | var relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 321 | 322 | var _relatedPoints = _slicedToArray(relatedPoints, 21), 323 | a1 = _relatedPoints[0], 324 | b1 = _relatedPoints[1], 325 | c1 = _relatedPoints[2], 326 | a0 = _relatedPoints[3], 327 | pa = _relatedPoints[4], 328 | pb = _relatedPoints[5], 329 | pc = _relatedPoints[6], 330 | c4 = _relatedPoints[7], 331 | d0 = _relatedPoints[8], 332 | pd = _relatedPoints[9], 333 | pe = _relatedPoints[10], 334 | pf = _relatedPoints[11], 335 | f4 = _relatedPoints[12], 336 | g0 = _relatedPoints[13], 337 | pg = _relatedPoints[14], 338 | ph = _relatedPoints[15], 339 | pi = _relatedPoints[16], 340 | i4 = _relatedPoints[17], 341 | g5 = _relatedPoints[18], 342 | h5 = _relatedPoints[19], 343 | i5 = _relatedPoints[20]; 344 | 345 | var e0, e1, e2, e3; 346 | e0 = e1 = e2 = e3 = pe; 347 | 348 | var _kernel2Xv = kernel2Xv5(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, e1, e2, e3, blendColors, scaleAlpha); 349 | 350 | var _kernel2Xv2 = _slicedToArray(_kernel2Xv, 3); 351 | 352 | e1 = _kernel2Xv2[0]; 353 | e2 = _kernel2Xv2[1]; 354 | e3 = _kernel2Xv2[2]; 355 | 356 | var _kernel2Xv3 = kernel2Xv5(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e0, e3, e1, blendColors, scaleAlpha); 357 | 358 | var _kernel2Xv4 = _slicedToArray(_kernel2Xv3, 3); 359 | 360 | e0 = _kernel2Xv4[0]; 361 | e3 = _kernel2Xv4[1]; 362 | e1 = _kernel2Xv4[2]; 363 | 364 | var _kernel2Xv5 = kernel2Xv5(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e2, e1, e0, blendColors, scaleAlpha); 365 | 366 | var _kernel2Xv6 = _slicedToArray(_kernel2Xv5, 3); 367 | 368 | e2 = _kernel2Xv6[0]; 369 | e1 = _kernel2Xv6[1]; 370 | e0 = _kernel2Xv6[2]; 371 | 372 | var _kernel2Xv7 = kernel2Xv5(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, e3, e0, e2, blendColors, scaleAlpha); 373 | 374 | var _kernel2Xv8 = _slicedToArray(_kernel2Xv7, 3); 375 | 376 | e3 = _kernel2Xv8[0]; 377 | e0 = _kernel2Xv8[1]; 378 | e2 = _kernel2Xv8[2]; 379 | dstPixelView[dstX + dstY * dstW] = e0; 380 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 381 | dstPixelView[dstX + (dstY + 1) * dstW] = e2; 382 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e3; 383 | } 384 | 385 | function computeXbr3x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 386 | var relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 387 | 388 | var _relatedPoints2 = _slicedToArray(relatedPoints, 21), 389 | a1 = _relatedPoints2[0], 390 | b1 = _relatedPoints2[1], 391 | c1 = _relatedPoints2[2], 392 | a0 = _relatedPoints2[3], 393 | pa = _relatedPoints2[4], 394 | pb = _relatedPoints2[5], 395 | pc = _relatedPoints2[6], 396 | c4 = _relatedPoints2[7], 397 | d0 = _relatedPoints2[8], 398 | pd = _relatedPoints2[9], 399 | pe = _relatedPoints2[10], 400 | pf = _relatedPoints2[11], 401 | f4 = _relatedPoints2[12], 402 | g0 = _relatedPoints2[13], 403 | pg = _relatedPoints2[14], 404 | ph = _relatedPoints2[15], 405 | pi = _relatedPoints2[16], 406 | i4 = _relatedPoints2[17], 407 | g5 = _relatedPoints2[18], 408 | h5 = _relatedPoints2[19], 409 | i5 = _relatedPoints2[20]; 410 | 411 | var e0, e1, e2, e3, e4, e5, e6, e7, e8; 412 | e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = pe; 413 | 414 | var _kernel3X = kernel3X(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, e2, e5, e6, e7, e8, blendColors, scaleAlpha); 415 | 416 | var _kernel3X2 = _slicedToArray(_kernel3X, 5); 417 | 418 | e2 = _kernel3X2[0]; 419 | e5 = _kernel3X2[1]; 420 | e6 = _kernel3X2[2]; 421 | e7 = _kernel3X2[3]; 422 | e8 = _kernel3X2[4]; 423 | 424 | var _kernel3X3 = kernel3X(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e0, e1, e8, e5, e2, blendColors, scaleAlpha); 425 | 426 | var _kernel3X4 = _slicedToArray(_kernel3X3, 5); 427 | 428 | e0 = _kernel3X4[0]; 429 | e1 = _kernel3X4[1]; 430 | e8 = _kernel3X4[2]; 431 | e5 = _kernel3X4[3]; 432 | e2 = _kernel3X4[4]; 433 | 434 | var _kernel3X5 = kernel3X(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e6, e3, e2, e1, e0, blendColors, scaleAlpha); 435 | 436 | var _kernel3X6 = _slicedToArray(_kernel3X5, 5); 437 | 438 | e6 = _kernel3X6[0]; 439 | e3 = _kernel3X6[1]; 440 | e2 = _kernel3X6[2]; 441 | e1 = _kernel3X6[3]; 442 | e0 = _kernel3X6[4]; 443 | 444 | var _kernel3X7 = kernel3X(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, e8, e7, e0, e3, e6, blendColors, scaleAlpha); 445 | 446 | var _kernel3X8 = _slicedToArray(_kernel3X7, 5); 447 | 448 | e8 = _kernel3X8[0]; 449 | e7 = _kernel3X8[1]; 450 | e0 = _kernel3X8[2]; 451 | e3 = _kernel3X8[3]; 452 | e6 = _kernel3X8[4]; 453 | dstPixelView[dstX + dstY * dstW] = e0; 454 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 455 | dstPixelView[dstX + 2 + dstY * dstW] = e2; 456 | dstPixelView[dstX + (dstY + 1) * dstW] = e3; 457 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e4; 458 | dstPixelView[dstX + 2 + (dstY + 1) * dstW] = e5; 459 | dstPixelView[dstX + (dstY + 2) * dstW] = e6; 460 | dstPixelView[dstX + 1 + (dstY + 2) * dstW] = e7; 461 | dstPixelView[dstX + 2 + (dstY + 2) * dstW] = e8; 462 | } 463 | 464 | function computeXbr4x(oriPixelView, oriX, oriY, oriW, oriH, dstPixelView, dstX, dstY, dstW, blendColors, scaleAlpha) { 465 | var relatedPoints = getRelatedPoints(oriPixelView, oriX, oriY, oriW, oriH); 466 | 467 | var _relatedPoints3 = _slicedToArray(relatedPoints, 21), 468 | a1 = _relatedPoints3[0], 469 | b1 = _relatedPoints3[1], 470 | c1 = _relatedPoints3[2], 471 | a0 = _relatedPoints3[3], 472 | pa = _relatedPoints3[4], 473 | pb = _relatedPoints3[5], 474 | pc = _relatedPoints3[6], 475 | c4 = _relatedPoints3[7], 476 | d0 = _relatedPoints3[8], 477 | pd = _relatedPoints3[9], 478 | pe = _relatedPoints3[10], 479 | pf = _relatedPoints3[11], 480 | f4 = _relatedPoints3[12], 481 | g0 = _relatedPoints3[13], 482 | pg = _relatedPoints3[14], 483 | ph = _relatedPoints3[15], 484 | pi = _relatedPoints3[16], 485 | i4 = _relatedPoints3[17], 486 | g5 = _relatedPoints3[18], 487 | h5 = _relatedPoints3[19], 488 | i5 = _relatedPoints3[20]; 489 | 490 | var e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef; 491 | e0 = e1 = e2 = e3 = e4 = e5 = e6 = e7 = e8 = e9 = ea = eb = ec = ed = ee = ef = pe; 492 | 493 | var _kernel4Xv = kernel4Xv2(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, ef, ee, eb, e3, e7, ea, ed, ec, blendColors, scaleAlpha); 494 | 495 | var _kernel4Xv2 = _slicedToArray(_kernel4Xv, 8); 496 | 497 | ef = _kernel4Xv2[0]; 498 | ee = _kernel4Xv2[1]; 499 | eb = _kernel4Xv2[2]; 500 | e3 = _kernel4Xv2[3]; 501 | e7 = _kernel4Xv2[4]; 502 | ea = _kernel4Xv2[5]; 503 | ed = _kernel4Xv2[6]; 504 | ec = _kernel4Xv2[7]; 505 | 506 | var _kernel4Xv3 = kernel4Xv2(pe, pc, pf, pb, pi, pa, ph, pd, b1, c1, f4, c4, e3, e7, e2, e0, e1, e6, eb, ef, blendColors, scaleAlpha); 507 | 508 | var _kernel4Xv4 = _slicedToArray(_kernel4Xv3, 8); 509 | 510 | e3 = _kernel4Xv4[0]; 511 | e7 = _kernel4Xv4[1]; 512 | e2 = _kernel4Xv4[2]; 513 | e0 = _kernel4Xv4[3]; 514 | e1 = _kernel4Xv4[4]; 515 | e6 = _kernel4Xv4[5]; 516 | eb = _kernel4Xv4[6]; 517 | ef = _kernel4Xv4[7]; 518 | 519 | var _kernel4Xv5 = kernel4Xv2(pe, pa, pb, pd, pc, pg, pf, ph, d0, a0, b1, a1, e0, e1, e4, ec, e8, e5, e2, e3, blendColors, scaleAlpha); 520 | 521 | var _kernel4Xv6 = _slicedToArray(_kernel4Xv5, 8); 522 | 523 | e0 = _kernel4Xv6[0]; 524 | e1 = _kernel4Xv6[1]; 525 | e4 = _kernel4Xv6[2]; 526 | ec = _kernel4Xv6[3]; 527 | e8 = _kernel4Xv6[4]; 528 | e5 = _kernel4Xv6[5]; 529 | e2 = _kernel4Xv6[6]; 530 | e3 = _kernel4Xv6[7]; 531 | 532 | var _kernel4Xv7 = kernel4Xv2(pe, pg, pd, ph, pa, pi, pb, pf, h5, g5, d0, g0, ec, e8, ed, ef, ee, e9, e4, e0, blendColors, scaleAlpha); 533 | 534 | var _kernel4Xv8 = _slicedToArray(_kernel4Xv7, 8); 535 | 536 | ec = _kernel4Xv8[0]; 537 | e8 = _kernel4Xv8[1]; 538 | ed = _kernel4Xv8[2]; 539 | ef = _kernel4Xv8[3]; 540 | ee = _kernel4Xv8[4]; 541 | e9 = _kernel4Xv8[5]; 542 | e4 = _kernel4Xv8[6]; 543 | e0 = _kernel4Xv8[7]; 544 | dstPixelView[dstX + dstY * dstW] = e0; 545 | dstPixelView[dstX + 1 + dstY * dstW] = e1; 546 | dstPixelView[dstX + 2 + dstY * dstW] = e2; 547 | dstPixelView[dstX + 3 + dstY * dstW] = e3; 548 | dstPixelView[dstX + (dstY + 1) * dstW] = e4; 549 | dstPixelView[dstX + 1 + (dstY + 1) * dstW] = e5; 550 | dstPixelView[dstX + 2 + (dstY + 1) * dstW] = e6; 551 | dstPixelView[dstX + 3 + (dstY + 1) * dstW] = e7; 552 | dstPixelView[dstX + (dstY + 2) * dstW] = e8; 553 | dstPixelView[dstX + 1 + (dstY + 2) * dstW] = e9; 554 | dstPixelView[dstX + 2 + (dstY + 2) * dstW] = ea; 555 | dstPixelView[dstX + 3 + (dstY + 2) * dstW] = eb; 556 | dstPixelView[dstX + (dstY + 3) * dstW] = ec; 557 | dstPixelView[dstX + 1 + (dstY + 3) * dstW] = ed; 558 | dstPixelView[dstX + 2 + (dstY + 3) * dstW] = ee; 559 | dstPixelView[dstX + 3 + (dstY + 3) * dstW] = ef; 560 | } 561 | 562 | function alphaBlend32W(dst, src, blendColors) { 563 | if (blendColors) { 564 | return pixelInterpolate(dst, src, 7, 1); 565 | } 566 | 567 | return dst; 568 | } 569 | 570 | function alphaBlend64W(dst, src, blendColors) { 571 | if (blendColors) { 572 | return pixelInterpolate(dst, src, 3, 1); 573 | } 574 | 575 | return dst; 576 | } 577 | 578 | function alphaBlend128W(dst, src, blendColors) { 579 | if (blendColors) { 580 | return pixelInterpolate(dst, src, 1, 1); 581 | } 582 | 583 | return dst; 584 | } 585 | 586 | function alphaBlend192W(dst, src, blendColors) { 587 | if (blendColors) { 588 | return pixelInterpolate(dst, src, 1, 3); 589 | } 590 | 591 | return src; 592 | } 593 | 594 | function alphaBlend224W(dst, src, blendColors) { 595 | if (blendColors) { 596 | return pixelInterpolate(dst, src, 1, 7); 597 | } 598 | 599 | return src; 600 | } 601 | 602 | function leftUp2_2X(n3, n2, pixel, blendColors) { 603 | var blendedN2 = alphaBlend64W(n2, pixel, blendColors); 604 | return [alphaBlend224W(n3, pixel, blendColors), blendedN2, blendedN2]; 605 | } 606 | 607 | function left2_2X(n3, n2, pixel, blendColors) { 608 | return [alphaBlend192W(n3, pixel, blendColors), alphaBlend64W(n2, pixel, blendColors)]; 609 | } 610 | 611 | function up2_2X(n3, n1, pixel, blendColors) { 612 | return [alphaBlend192W(n3, pixel, blendColors), alphaBlend64W(n1, pixel, blendColors)]; 613 | } 614 | 615 | function dia_2X(n3, pixel, blendColors) { 616 | return alphaBlend128W(n3, pixel, blendColors); 617 | } 618 | 619 | function kernel2Xv5(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n1, n2, n3, blendColors, scaleAlpha) { 620 | var ex = pe != ph && pe != pf; 621 | 622 | if (!ex) { 623 | return [n1, n2, n3]; 624 | } 625 | 626 | var e = yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha) + (yuvDifference(ph, pf) << 2), 627 | i = yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha) + (yuvDifference(pe, pi, scaleAlpha) << 2), 628 | px = yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha) ? pf : ph; 629 | 630 | if (e < i && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))) { 631 | var ke = yuvDifference(pf, pg, scaleAlpha), 632 | ki = yuvDifference(ph, pc, scaleAlpha), 633 | ex2 = pe != pc && pb != pc, 634 | ex3 = pe != pg && pd != pg; 635 | 636 | if (ke << 1 <= ki && ex3 || ke >= ki << 1 && ex2) { 637 | if (ke << 1 <= ki && ex3) { 638 | var leftOut = left2_2X(n3, n2, px, blendColors); 639 | n3 = leftOut[0]; 640 | n2 = leftOut[1]; 641 | } 642 | 643 | if (ke >= ki << 1 && ex2) { 644 | var upOut = up2_2X(n3, n1, px, blendColors); 645 | n3 = upOut[0]; 646 | n1 = upOut[1]; 647 | } 648 | } else { 649 | n3 = dia_2X(n3, px, blendColors); 650 | } 651 | } else if (e <= i) { 652 | n3 = alphaBlend64W(n3, px, blendColors); 653 | } 654 | 655 | return [n1, n2, n3]; 656 | } 657 | 658 | function leftUp2_3X(n7, n5, n6, n2, n8, pixel, blendColors) { 659 | var blendedN7 = alphaBlend192W(n7, pixel, blendColors), 660 | blendedN6 = alphaBlend64W(n6, pixel, blendColors); 661 | return [blendedN7, blendedN7, blendedN6, blendedN6, pixel]; 662 | } 663 | 664 | function left2_3X(n7, n5, n6, n8, pixel, blendColors) { 665 | return [alphaBlend192W(n7, pixel, blendColors), alphaBlend64W(n5, pixel, blendColors), alphaBlend64W(n6, pixel, blendColors), pixel]; 666 | } 667 | 668 | function up2_3X(n5, n7, n2, n8, pixel, blendColors) { 669 | return [alphaBlend192W(n5, pixel, blendColors), alphaBlend64W(n7, pixel, blendColors), alphaBlend64W(n2, pixel, blendColors), pixel]; 670 | } 671 | 672 | function dia_3X(n8, n5, n7, pixel, blendColors) { 673 | return [alphaBlend224W(n8, pixel, blendColors), alphaBlend32W(n5, pixel, blendColors), alphaBlend32W(n7, pixel, blendColors)]; 674 | } 675 | 676 | function kernel3X(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n2, n5, n6, n7, n8, blendColors, scaleAlpha) { 677 | var ex = pe != ph && pe != pf; 678 | 679 | if (!ex) { 680 | return [n2, n5, n6, n7, n8]; 681 | } 682 | 683 | var e = yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha) + (yuvDifference(ph, pf, scaleAlpha) << 2), 684 | i = yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha) + (yuvDifference(pe, pi, scaleAlpha) << 2); 685 | var state; 686 | 687 | if (USE_3X_ORIGINAL_IMPLEMENTATION) { 688 | state = e < i && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha)); 689 | } else { 690 | state = e < i && (!isEqual(pf, pb, scaleAlpha) && !isEqual(pf, pc, scaleAlpha) || !isEqual(ph, pd, scaleAlpha) && !isEqual(ph, pg, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && (!isEqual(pf, f4, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) || !isEqual(ph, h5, scaleAlpha) && !isEqual(ph, i5, scaleAlpha)) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha)); 691 | } 692 | 693 | if (state) { 694 | var ke = yuvDifference(pf, pg, scaleAlpha), 695 | ki = yuvDifference(ph, pc, scaleAlpha), 696 | ex2 = pe != pc && pb != pc, 697 | ex3 = pe != pg && pd != pg, 698 | px = yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha) ? pf : ph; 699 | 700 | if (ke << 1 <= ki && ex3 && ke >= ki << 1 && ex2) { 701 | var _leftUp2_3X = leftUp2_3X(n7, n5, n6, n2, n8, px, blendColors); 702 | 703 | var _leftUp2_3X2 = _slicedToArray(_leftUp2_3X, 5); 704 | 705 | n7 = _leftUp2_3X2[0]; 706 | n5 = _leftUp2_3X2[1]; 707 | n6 = _leftUp2_3X2[2]; 708 | n2 = _leftUp2_3X2[3]; 709 | n8 = _leftUp2_3X2[4]; 710 | } else if (ke << 1 <= ki && ex3) { 711 | var _left2_3X = left2_3X(n7, n5, n6, n8, px, blendColors); 712 | 713 | var _left2_3X2 = _slicedToArray(_left2_3X, 4); 714 | 715 | n7 = _left2_3X2[0]; 716 | n5 = _left2_3X2[1]; 717 | n6 = _left2_3X2[2]; 718 | n8 = _left2_3X2[3]; 719 | } else if (ke >= ki << 1 && ex2) { 720 | var _up2_3X = up2_3X(n5, n7, n2, n8, px, blendColors); 721 | 722 | var _up2_3X2 = _slicedToArray(_up2_3X, 4); 723 | 724 | n5 = _up2_3X2[0]; 725 | n7 = _up2_3X2[1]; 726 | n2 = _up2_3X2[2]; 727 | n8 = _up2_3X2[3]; 728 | } else { 729 | var _dia_3X = dia_3X(n8, n5, n7, px, blendColors); 730 | 731 | var _dia_3X2 = _slicedToArray(_dia_3X, 3); 732 | 733 | n8 = _dia_3X2[0]; 734 | n5 = _dia_3X2[1]; 735 | n7 = _dia_3X2[2]; 736 | } 737 | } else if (e <= i) { 738 | n8 = alphaBlend128W(n8, yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha) ? pf : ph, blendColors); 739 | } 740 | 741 | return [n2, n5, n6, n7, n8]; 742 | } // 4xBR 743 | 744 | 745 | function leftUp2(n15, n14, n11, n13, n12, n10, n7, n3, pixel, blendColors) { 746 | var blendedN13 = alphaBlend192W(n13, pixel, blendColors), 747 | blendedN12 = alphaBlend64W(n12, pixel, blendColors); 748 | return [pixel, pixel, pixel, blendedN12, blendedN12, blendedN12, blendedN13, n3]; 749 | } 750 | 751 | function left2(n15, n14, n11, n13, n12, n10, pixel, blendColors) { 752 | return [pixel, pixel, alphaBlend192W(n11, pixel, blendColors), alphaBlend192W(n13, pixel, blendColors), alphaBlend64W(n12, pixel, blendColors), alphaBlend64W(n10, pixel, blendColors)]; 753 | } 754 | 755 | function up2(n15, n14, n11, n3, n7, n10, pixel, blendColors) { 756 | return [pixel, alphaBlend192W(n14, pixel, blendColors), pixel, alphaBlend64W(n3, pixel, blendColors), alphaBlend192W(n7, pixel, blendColors), alphaBlend64W(n10, pixel, blendColors)]; 757 | } 758 | 759 | function dia(n15, n14, n11, pixel, blendColors) { 760 | return [pixel, alphaBlend128W(n14, pixel, blendColors), alphaBlend128W(n11, pixel, blendColors)]; 761 | } 762 | 763 | function kernel4Xv2(pe, pi, ph, pf, pg, pc, pd, pb, f4, i4, h5, i5, n15, n14, n11, n3, n7, n10, n13, n12, blendColors, scaleAlpha) { 764 | var ex = pe != ph && pe != pf; 765 | 766 | if (!ex) { 767 | return [n15, n14, n11, n3, n7, n10, n13, n12]; 768 | } 769 | 770 | var e = yuvDifference(pe, pc, scaleAlpha) + yuvDifference(pe, pg, scaleAlpha) + yuvDifference(pi, h5, scaleAlpha) + yuvDifference(pi, f4, scaleAlpha) + (yuvDifference(ph, pf, scaleAlpha) << 2), 771 | i = yuvDifference(ph, pd, scaleAlpha) + yuvDifference(ph, i5, scaleAlpha) + yuvDifference(pf, i4, scaleAlpha) + yuvDifference(pf, pb, scaleAlpha) + (yuvDifference(pe, pi, scaleAlpha) << 2), 772 | px = yuvDifference(pe, pf, scaleAlpha) <= yuvDifference(pe, ph, scaleAlpha) ? pf : ph; 773 | 774 | if (e < i && (!isEqual(pf, pb, scaleAlpha) && !isEqual(ph, pd, scaleAlpha) || isEqual(pe, pi, scaleAlpha) && !isEqual(pf, i4, scaleAlpha) && !isEqual(ph, i5, scaleAlpha) || isEqual(pe, pg, scaleAlpha) || isEqual(pe, pc, scaleAlpha))) { 775 | var ke = yuvDifference(pf, pg, scaleAlpha), 776 | ki = yuvDifference(ph, pc, scaleAlpha), 777 | ex2 = pe != pc && pb != pc, 778 | ex3 = pe != pg && pd != pg; 779 | 780 | if (ke << 1 <= ki && ex3 || ke >= ki << 1 && ex2) { 781 | if (ke << 1 <= ki && ex3) { 782 | var _left = left2(n15, n14, n11, n13, n12, n10, px, blendColors); 783 | 784 | var _left2 = _slicedToArray(_left, 6); 785 | 786 | n15 = _left2[0]; 787 | n14 = _left2[1]; 788 | n11 = _left2[2]; 789 | n13 = _left2[3]; 790 | n12 = _left2[4]; 791 | n10 = _left2[5]; 792 | } 793 | 794 | if (ke >= ki << 1 && ex2) { 795 | var _up = up2(n15, n14, n11, n3, n7, n10, px, blendColors); 796 | 797 | var _up2 = _slicedToArray(_up, 6); 798 | 799 | n15 = _up2[0]; 800 | n14 = _up2[1]; 801 | n11 = _up2[2]; 802 | n3 = _up2[3]; 803 | n7 = _up2[4]; 804 | n10 = _up2[5]; 805 | } 806 | } else { 807 | var _dia = dia(n15, n14, n11, px, blendColors); 808 | 809 | var _dia2 = _slicedToArray(_dia, 3); 810 | 811 | n15 = _dia2[0]; 812 | n14 = _dia2[1]; 813 | n11 = _dia2[2]; 814 | } 815 | } else if (e <= i) { 816 | n15 = alphaBlend128W(n15, px, blendColors); 817 | } 818 | 819 | return [n15, n14, n11, n3, n7, n10, n13, n12]; 820 | } 821 | 822 | function parseOptions(rawOpts) { 823 | var blendColors = true, 824 | scaleAlpha = false; 825 | 826 | if (rawOpts) { 827 | if (rawOpts.blendColors === false) { 828 | blendColors = false; 829 | } 830 | 831 | if (rawOpts.scaleAlpha === true) { 832 | scaleAlpha = true; 833 | } 834 | } 835 | 836 | return { 837 | blendColors: blendColors, 838 | scaleAlpha: scaleAlpha 839 | }; 840 | } 841 | 842 | function xbr2x(pixelArray, width, height, options) { 843 | var _parseOptions = parseOptions(options), 844 | blendColors = _parseOptions.blendColors, 845 | scaleAlpha = _parseOptions.scaleAlpha; 846 | 847 | var scaledPixelArray = new Uint32Array(width * height * 4); 848 | 849 | for (var c = 0; c < width; c++) { 850 | for (var d = 0; d < height; d++) { 851 | computeXbr2x(pixelArray, c, d, width, height, scaledPixelArray, c * 2, d * 2, width * 2, blendColors, scaleAlpha); 852 | } 853 | } 854 | 855 | return scaledPixelArray; 856 | } 857 | function xbr3x(pixelArray, width, height, options) { 858 | var _parseOptions2 = parseOptions(options), 859 | blendColors = _parseOptions2.blendColors, 860 | scaleAlpha = _parseOptions2.scaleAlpha; 861 | 862 | var scaledPixelArray = new Uint32Array(width * height * 9); 863 | 864 | for (var c = 0; c < width; c++) { 865 | for (var d = 0; d < height; d++) { 866 | computeXbr3x(pixelArray, c, d, width, height, scaledPixelArray, c * 3, d * 3, width * 3, blendColors, scaleAlpha); 867 | } 868 | } 869 | 870 | return scaledPixelArray; 871 | } 872 | function xbr4x(pixelArray, width, height, options) { 873 | var _parseOptions3 = parseOptions(options), 874 | blendColors = _parseOptions3.blendColors, 875 | scaleAlpha = _parseOptions3.scaleAlpha; 876 | 877 | var scaledPixelArray = new Uint32Array(width * height * 16); 878 | 879 | for (var c = 0; c < width; c++) { 880 | for (var d = 0; d < height; d++) { 881 | computeXbr4x(pixelArray, c, d, width, height, scaledPixelArray, c * 4, d * 4, width * 4, blendColors, scaleAlpha); 882 | } 883 | } 884 | 885 | return scaledPixelArray; 886 | } 887 | 888 | /***/ }) 889 | /******/ ]); 890 | }); --------------------------------------------------------------------------------