5 Commits

Author SHA1 Message Date
xororz
f81d2dd793 update tfjs to fix error on chrome 131 2024-11-19 15:22:30 +08:00
xororz
b8a81864ea Update example 2024-11-05 20:49:21 +08:00
xororz
efc8e5b3c8 Update README.md 2024-11-01 21:40:45 +08:00
xororz
76f23dade3 supports img smaller than tile size 2024-10-19 21:52:38 +08:00
xororz
37036998d3 clean up; models to release 2024-10-16 23:06:08 +08:00
7 changed files with 183 additions and 115 deletions

2
.gitignore vendored
View File

@@ -32,3 +32,5 @@ coverage
*.sw?
*.tsbuildinfo
realesrgan
realcugan

View File

@@ -1,6 +1,6 @@
# web-realesrgan
Run Real-ESRGAN in the browser with tensorflow.js
Run Real-ESRGAN/Real-CUGAN in the browser with tensorflow.js
## Usage
@@ -21,6 +21,16 @@ Sure, PNG with alpha channel is supported.
All models are quantized to FP16, which reduces the size of the model download and has no noticeable difference in performance compared to FP32 models. However, currently, the computation speed of FP16 is the same as FP32. Future updates from the TensorFlow.js team are expected to improve FP16 computation performance on WebGPU.
### 🚀️ Advantages
**Accessible Anywhere**: The tool can be conveniently run on any device, such as a mobile phone📱, without needing to download or install any software. This makes it possible to upscale images anytime, anywhere, directly in your browser.
### ⚠️️ Limitations
**Performance Gap**: Even with WebGPU enabled, the performance of running models in the browser is slower than running them locally. WebGPUs speed is approximately half of the speed youd achieve with local execution. On local devices, FP16 computation provides significant acceleration, whereas in tfjs-webgpu for now, FP16 and FP32 run at the same speed.
If you need to upscale a lot of images, it is recommended to download and use the official Real-ESRGAN and Real-CUGAN repositories for local execution.
### Development
```bash
@@ -28,6 +38,10 @@ npm install
npm run dev
```
WebGPU cannot be used over HTTP. If you're developing this project locally, you can use OpenSSL to self-sign a certificate.
See https://developer.chrome.com/docs/web-platform/webgpu/troubleshooting-tips
## Models
The first run will download the models and cache them in the browser indexedDB. No need to download them again.

186
package-lock.json generated
View File

@@ -8,8 +8,9 @@
"name": "canvastest",
"version": "0.0.0",
"dependencies": {
"@tensorflow/tfjs": "^4.17.0",
"@tensorflow/tfjs-backend-webgpu": "^4.17.0",
"@tensorflow/tfjs": "^4.22.0",
"@tensorflow/tfjs-backend-webgpu": "^4.22.0",
"@tensorflow/tfjs-core": "^4.22.0",
"vue": "^3.4.21"
},
"devDependencies": {
@@ -603,16 +604,17 @@
]
},
"node_modules/@tensorflow/tfjs": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-4.21.0.tgz",
"integrity": "sha512-7D/+H150ptvt+POMbsME3WlIvLiuBR2rCC2Z0hOKKb/5Ygkj7xsp/K2HzOvUj0g0yjk+utkU45QEYhnhjnbHRA==",
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-4.22.0.tgz",
"integrity": "sha512-0TrIrXs6/b7FLhLVNmfh8Sah6JgjBPH4mZ8JGb7NU6WW+cx00qK5BcAZxw7NCzxj6N8MRAIfHq+oNbPUNG5VAg==",
"license": "Apache-2.0",
"dependencies": {
"@tensorflow/tfjs-backend-cpu": "4.21.0",
"@tensorflow/tfjs-backend-webgl": "4.21.0",
"@tensorflow/tfjs-converter": "4.21.0",
"@tensorflow/tfjs-core": "4.21.0",
"@tensorflow/tfjs-data": "4.21.0",
"@tensorflow/tfjs-layers": "4.21.0",
"@tensorflow/tfjs-backend-cpu": "4.22.0",
"@tensorflow/tfjs-backend-webgl": "4.22.0",
"@tensorflow/tfjs-converter": "4.22.0",
"@tensorflow/tfjs-core": "4.22.0",
"@tensorflow/tfjs-data": "4.22.0",
"@tensorflow/tfjs-layers": "4.22.0",
"argparse": "^1.0.10",
"chalk": "^4.1.0",
"core-js": "3.29.1",
@@ -624,9 +626,10 @@
}
},
"node_modules/@tensorflow/tfjs-backend-cpu": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.17.0.tgz",
"integrity": "sha512-2VSCHnX9qhYTjw9HiVwTBSnRVlntKXeBlK7aSVsmZfHGwWE2faErTtO7bWmqNqw0U7gyznJbVAjlow/p+0RNGw==",
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.22.0.tgz",
"integrity": "sha512-1u0FmuLGuRAi8D2c3cocHTASGXOmHc/4OvoVDENJayjYkS119fcTcQf4iHrtLthWyDIPy3JiPhRrZQC9EwnhLw==",
"license": "Apache-2.0",
"dependencies": {
"@types/seedrandom": "^2.4.28",
"seedrandom": "^3.0.5"
@@ -635,25 +638,53 @@
"yarn": ">= 1.3.2"
},
"peerDependencies": {
"@tensorflow/tfjs-core": "4.17.0"
"@tensorflow/tfjs-core": "4.22.0"
}
},
"node_modules/@tensorflow/tfjs-backend-webgl": {
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.22.0.tgz",
"integrity": "sha512-H535XtZWnWgNwSzv538czjVlbJebDl5QTMOth4RXr2p/kJ1qSIXE0vZvEtO+5EC9b00SvhplECny2yDewQb/Yg==",
"license": "Apache-2.0",
"dependencies": {
"@tensorflow/tfjs-backend-cpu": "4.22.0",
"@types/offscreencanvas": "~2019.3.0",
"@types/seedrandom": "^2.4.28",
"seedrandom": "^3.0.5"
},
"engines": {
"yarn": ">= 1.3.2"
},
"peerDependencies": {
"@tensorflow/tfjs-core": "4.22.0"
}
},
"node_modules/@tensorflow/tfjs-backend-webgpu": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgpu/-/tfjs-backend-webgpu-4.17.0.tgz",
"integrity": "sha512-LUEUU9ZT3/LTEzV3ht/i7QaQbe9ferrefVttL/2DS9NbgzgTa/lggMo4R8Mr49/PTKrvL1ou+61/rHn1virahg==",
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgpu/-/tfjs-backend-webgpu-4.22.0.tgz",
"integrity": "sha512-lvIc7Af4Tl2BCdYp43iQmSCRq3asaKT0q2xaErphXiUZ+jqeB0bQa0ZvQys1Xatvto0U4/c90DVsHPfvkn5ftg==",
"license": "Apache-2.0",
"dependencies": {
"@tensorflow/tfjs-backend-cpu": "4.17.0"
"@tensorflow/tfjs-backend-cpu": "4.22.0"
},
"peerDependencies": {
"@tensorflow/tfjs-core": "4.17.0"
"@tensorflow/tfjs-core": "4.22.0"
}
},
"node_modules/@tensorflow/tfjs-converter": {
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.22.0.tgz",
"integrity": "sha512-PT43MGlnzIo+YfbsjM79Lxk9lOq6uUwZuCc8rrp0hfpLjF6Jv8jS84u2jFb+WpUeuF4K33ZDNx8CjiYrGQ2trQ==",
"license": "Apache-2.0",
"peerDependencies": {
"@tensorflow/tfjs-core": "4.22.0"
}
},
"node_modules/@tensorflow/tfjs-core": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-4.17.0.tgz",
"integrity": "sha512-v9Q5430EnRpyhWNd9LVgXadciKvxLiq+sTrLKRowh26BHyAsams4tZIgX3lFKjB7b90p+FYifVMcqLTTHgjGpQ==",
"peer": true,
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-4.22.0.tgz",
"integrity": "sha512-LEkOyzbknKFoWUwfkr59vSB68DMJ4cjwwHgicXN0DUi3a0Vh1Er3JQqCI1Hl86GGZQvY8ezVrtDIvqR1ZFW55A==",
"license": "Apache-2.0",
"dependencies": {
"@types/long": "^4.0.1",
"@types/offscreencanvas": "~2019.7.0",
@@ -668,93 +699,32 @@
}
},
"node_modules/@tensorflow/tfjs-core/node_modules/@types/offscreencanvas": {
"version": "2019.7.3",
"resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz",
"integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==",
"peer": true
},
"node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-backend-cpu": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.21.0.tgz",
"integrity": "sha512-yS9Oisg4L48N7ML6677ilv1eP5Jt59S74skSU1cCsM4yBAtH4DAn9b89/JtqBISh6JadanfX26b4HCWQvMvqFg==",
"dependencies": {
"@types/seedrandom": "^2.4.28",
"seedrandom": "^3.0.5"
},
"engines": {
"yarn": ">= 1.3.2"
},
"peerDependencies": {
"@tensorflow/tfjs-core": "4.21.0"
}
},
"node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-backend-webgl": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.21.0.tgz",
"integrity": "sha512-7k6mb7dd0uF9jI51iunF3rhEXjvR/a613kjWZ0Rj3o1COFrneyku2C7cRMZERWPhbgXZ+dF+j9MdpGIpgtShIQ==",
"dependencies": {
"@tensorflow/tfjs-backend-cpu": "4.21.0",
"@types/offscreencanvas": "~2019.3.0",
"@types/seedrandom": "^2.4.28",
"seedrandom": "^3.0.5"
},
"engines": {
"yarn": ">= 1.3.2"
},
"peerDependencies": {
"@tensorflow/tfjs-core": "4.21.0"
}
},
"node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-converter": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.21.0.tgz",
"integrity": "sha512-cUhU+F1lGx2qnKk/gRy8odBh0PZlFz0Dl71TG8LVnj0/g352DqiNrKXlKO/po9aWzP8x0KUGC3gNMSMJW+T0DA==",
"peerDependencies": {
"@tensorflow/tfjs-core": "4.21.0"
}
},
"node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-core": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-4.21.0.tgz",
"integrity": "sha512-ZbECwXps5wb9XXcGq4ZXvZDVjr5okc3I0+i/vU6bpQ+nVApyIrMiyEudP8f6vracVTvNmnlN62vUXoEsQb2F8g==",
"dependencies": {
"@types/long": "^4.0.1",
"@types/offscreencanvas": "~2019.7.0",
"@types/seedrandom": "^2.4.28",
"@webgpu/types": "0.1.38",
"long": "4.0.0",
"node-fetch": "~2.6.1",
"seedrandom": "^3.0.5"
},
"engines": {
"yarn": ">= 1.3.2"
}
},
"node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-core/node_modules/@types/offscreencanvas": {
"version": "2019.7.3",
"resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz",
"integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A=="
},
"node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-data": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-4.21.0.tgz",
"integrity": "sha512-LpJ/vyQMwYHkcVCqIRg7IVVw13VBY7rNAiuhmKP9S5NP/2ye4KA8BJ4XwDIDgjCVQM7glK9L8bMav++xCDf7xA==",
"node_modules/@tensorflow/tfjs-data": {
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-4.22.0.tgz",
"integrity": "sha512-dYmF3LihQIGvtgJrt382hSRH4S0QuAp2w1hXJI2+kOaEqo5HnUPG0k5KA6va+S1yUhx7UBToUKCBHeLHFQRV4w==",
"license": "Apache-2.0",
"dependencies": {
"@types/node-fetch": "^2.1.2",
"node-fetch": "~2.6.1",
"string_decoder": "^1.3.0"
},
"peerDependencies": {
"@tensorflow/tfjs-core": "4.21.0",
"@tensorflow/tfjs-core": "4.22.0",
"seedrandom": "^3.0.5"
}
},
"node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-layers": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-4.21.0.tgz",
"integrity": "sha512-a8KaMYlY3+llvE9079nvASKpaaf8xpCMdOjbgn+eGhdOGOcY7QuFUkd/2odvnXDG8fK/jffE1LoNOlfYoBHC4w==",
"node_modules/@tensorflow/tfjs-layers": {
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-4.22.0.tgz",
"integrity": "sha512-lybPj4ZNj9iIAPUj7a8ZW1hg8KQGfqWLlCZDi9eM/oNKCCAgchiyzx8OrYoWmRrB+AM6VNEeIT+2gZKg5ReihA==",
"license": "Apache-2.0 AND MIT",
"peerDependencies": {
"@tensorflow/tfjs-core": "4.21.0"
"@tensorflow/tfjs-core": "4.22.0"
}
},
"node_modules/@tsconfig/node20": {
@@ -783,9 +753,10 @@
}
},
"node_modules/@types/node-fetch": {
"version": "2.6.11",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz",
"integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==",
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
"license": "MIT",
"dependencies": {
"@types/node": "*",
"form-data": "^4.0.0"
@@ -794,7 +765,8 @@
"node_modules/@types/offscreencanvas": {
"version": "2019.3.0",
"resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz",
"integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q=="
"integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==",
"license": "MIT"
},
"node_modules/@types/seedrandom": {
"version": "2.4.34",
@@ -997,7 +969,8 @@
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/balanced-match": {
"version": "1.0.2",
@@ -1073,6 +1046,7 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
@@ -1125,6 +1099,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
@@ -1200,6 +1175,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -1312,6 +1288,7 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -1320,6 +1297,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
@@ -1554,7 +1532,8 @@
"type": "consulting",
"url": "https://feross.org/support"
}
]
],
"license": "MIT"
},
"node_modules/seedrandom": {
"version": "3.0.5",
@@ -1623,6 +1602,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
}

View File

@@ -11,8 +11,9 @@
"type-check": "vue-tsc --build --force"
},
"dependencies": {
"@tensorflow/tfjs": "^4.17.0",
"@tensorflow/tfjs-backend-webgpu": "^4.17.0",
"@tensorflow/tfjs": "^4.22.0",
"@tensorflow/tfjs-backend-webgpu": "^4.22.0",
"@tensorflow/tfjs-core": "^4.22.0",
"vue": "^3.4.21"
},
"devDependencies": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 145 KiB

View File

@@ -20,15 +20,76 @@ export default class Image {
x2: number,
y2: number
) {
for (let j = y1; j < y2; j++) {
for (let i = x1; i < x2; i++) {
let index = (y + j - y1) * this.width * 4 + (x + i - x1) * 4;
let imageIndex = j * image.width * 4 + i * 4;
this.data[index] = image.data[imageIndex];
this.data[index + 1] = image.data[imageIndex + 1];
this.data[index + 2] = image.data[imageIndex + 2];
this.data[index + 3] = image.data[imageIndex + 3];
}
const width = x2 - x1;
for (let j = 0; j < y2 - y1; j++) {
const destIndex = (y + j) * this.width * 4 + x * 4;
const srcIndex = (y1 + j) * image.width * 4 + x1 * 4;
this.data.set(
image.data.subarray(srcIndex, srcIndex + width * 4),
destIndex
);
}
}
padToTileSize(tileSize: number) {
let newWidth = this.width;
let newHeight = this.height;
if (this.width < tileSize) {
newWidth = tileSize;
}
if (this.height < tileSize) {
newHeight = tileSize;
}
if (newWidth === this.width && newHeight === this.height) {
return;
}
const newData = new Uint8Array(newWidth * newHeight * 4);
for (let y = 0; y < this.height; y++) {
const srcStart = y * this.width * 4;
const destStart = y * newWidth * 4;
newData.set(
this.data.subarray(srcStart, srcStart + this.width * 4),
destStart
);
}
if (newWidth > this.width) {
const rightColumnIndex = (this.width - 1) * 4;
for (let y = 0; y < this.height; y++) {
const destRowStart = y * newWidth * 4;
const srcPixelIndex = y * this.width * 4 + rightColumnIndex;
const padPixel = this.data.subarray(srcPixelIndex, srcPixelIndex + 4);
for (let x = this.width; x < newWidth; x++) {
const destPixelIndex = destRowStart + x * 4;
newData.set(padPixel, destPixelIndex);
}
}
}
if (newHeight > this.height) {
const bottomRowStart = (this.height - 1) * newWidth * 4;
const bottomRow = newData.subarray(
bottomRowStart,
bottomRowStart + newWidth * 4
);
for (let y = this.height; y < newHeight; y++) {
const destRowStart = y * newWidth * 4;
newData.set(bottomRow, destRowStart);
}
}
this.width = newWidth;
this.height = newHeight;
this.data = newData;
}
cropToOriginalSize(width: number, height: number) {
const newData = new Uint8Array(width * height * 4);
for (let y = 0; y < height; y++) {
const srcStart = y * this.width * 4;
const destStart = y * width * 4;
newData.set(
this.data.subarray(srcStart, srcStart + width * 4),
destStart
);
}
this.width = width;
this.height = height;
this.data = newData;
}
}

View File

@@ -37,6 +37,13 @@ self.addEventListener("message", async (e) => {
return;
}
const input = new Img(data.width, data.height, new Uint8Array(data.input));
const width_ori = input.width;
const height_ori = input.height;
input.padToTileSize(data?.tile_size || 64);
let withPadding = false;
if (input.width !== width_ori || input.height !== height_ori) {
withPadding = true;
}
let hasAlpha = data.hasAlpha;
function sendprogress(progress) {
if (hasAlpha) {
@@ -223,6 +230,9 @@ self.addEventListener("message", async (e) => {
} catch (e) {
postMessage({ alertmsg: e.toString() });
}
if (withPadding) {
output.cropToOriginalSize(width_ori * factor, height_ori * factor);
}
const end = Date.now();
console.log("Time:", end - start);
await new Promise((resolve) => setTimeout(resolve, 10));