├── README.md ├── flower.png ├── index.html ├── resize.js └── resizeWorker.js /README.md: -------------------------------------------------------------------------------- 1 | # JS-Image-Resizer 2 | A javascript based solution for image scaling outside of html5 canvas. 3 | 4 | ##Troubleshoot 5 | When running index.html on Chrome, only first picture loads, due to Uncaught SecurityError on line 14: 6 |
`Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.` 7 | 8 | **Solution**: 9 | + Running on a server instead (eg localhost) 10 | 11 | -------------------------------------------------------------------------------- /flower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taisel/JS-Image-Resizer/d6bf3862951344ad75a026ea5d95afc9114f9421/flower.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Resize.js Demo 5 | 6 | 79 | 80 | 81 |

Original Image:

82 | 83 |
84 |

Downscaling With Context2d:

85 | 86 | 87 |
88 |

Downscaling With Resize.js:

89 | 90 | 91 |
92 |

Upscaling With Context2d:

93 | 94 |
95 |

Upscaling With Resize.js:

96 | 97 |
98 |

Upscaling With Resize.js (Crisp):

99 | 100 |
101 | 102 | -------------------------------------------------------------------------------- /resize.js: -------------------------------------------------------------------------------- 1 | //JavaScript Image Resizer (c) 2012 - Grant Galitz 2 | var scripts = document.getElementsByTagName("script"); 3 | var sourceOfWorker = scripts[scripts.length-1].src; 4 | function Resize(widthOriginal, heightOriginal, targetWidth, targetHeight, blendAlpha, interpolationPass, useWebWorker, resizeCallback) { 5 | this.widthOriginal = Math.abs(parseInt(widthOriginal) || 0); 6 | this.heightOriginal = Math.abs(parseInt(heightOriginal) || 0); 7 | this.targetWidth = Math.abs(parseInt(targetWidth) || 0); 8 | this.targetHeight = Math.abs(parseInt(targetHeight) || 0); 9 | this.colorChannels = (!!blendAlpha) ? 4 : 3; 10 | this.interpolationPass = !!interpolationPass; 11 | this.useWebWorker = !!useWebWorker; 12 | this.resizeCallback = (typeof resizeCallback == "function") ? resizeCallback : function (returnedArray) {}; 13 | this.targetWidthMultipliedByChannels = this.targetWidth * this.colorChannels; 14 | this.originalWidthMultipliedByChannels = this.widthOriginal * this.colorChannels; 15 | this.originalHeightMultipliedByChannels = this.heightOriginal * this.colorChannels; 16 | this.widthPassResultSize = this.targetWidthMultipliedByChannels * this.heightOriginal; 17 | this.finalResultSize = this.targetWidthMultipliedByChannels * this.targetHeight; 18 | this.initialize(); 19 | } 20 | Resize.prototype.initialize = function () { 21 | //Perform some checks: 22 | if (this.widthOriginal > 0 && this.heightOriginal > 0 && this.targetWidth > 0 && this.targetHeight > 0) { 23 | if (this.useWebWorker) { 24 | this.useWebWorker = (this.widthOriginal != this.targetWidth || this.heightOriginal != this.targetHeight); 25 | if (this.useWebWorker) { 26 | this.configureWorker(); 27 | } 28 | } 29 | if (!this.useWebWorker) { 30 | this.configurePasses(); 31 | } 32 | } 33 | else { 34 | throw(new Error("Invalid settings specified for the resizer.")); 35 | } 36 | } 37 | Resize.prototype.configureWorker = function () { 38 | try { 39 | var parentObj = this; 40 | this.worker = new Worker(sourceOfWorker.substring(0, sourceOfWorker.length - 3) + "Worker.js"); 41 | this.worker.onmessage = function (event) { 42 | parentObj.heightBuffer = event.data; 43 | parentObj.resizeCallback(parentObj.heightBuffer); 44 | } 45 | this.worker.postMessage(["setup", this.widthOriginal, this.heightOriginal, this.targetWidth, this.targetHeight, this.colorChannels, this.interpolationPass]); 46 | } 47 | catch (error) { 48 | this.useWebWorker = false; 49 | } 50 | } 51 | Resize.prototype.configurePasses = function () { 52 | if (this.widthOriginal == this.targetWidth) { 53 | //Bypass the width resizer pass: 54 | this.resizeWidth = this.bypassResizer; 55 | } 56 | else { 57 | //Setup the width resizer pass: 58 | this.ratioWeightWidthPass = this.widthOriginal / this.targetWidth; 59 | if (this.ratioWeightWidthPass < 1 && this.interpolationPass) { 60 | this.initializeFirstPassBuffers(true); 61 | this.resizeWidth = (this.colorChannels == 4) ? this.resizeWidthInterpolatedRGBA : this.resizeWidthInterpolatedRGB; 62 | } 63 | else { 64 | this.initializeFirstPassBuffers(false); 65 | this.resizeWidth = (this.colorChannels == 4) ? this.resizeWidthRGBA : this.resizeWidthRGB; 66 | } 67 | } 68 | if (this.heightOriginal == this.targetHeight) { 69 | //Bypass the height resizer pass: 70 | this.resizeHeight = this.bypassResizer; 71 | } 72 | else { 73 | //Setup the height resizer pass: 74 | this.ratioWeightHeightPass = this.heightOriginal / this.targetHeight; 75 | if (this.ratioWeightHeightPass < 1 && this.interpolationPass) { 76 | this.initializeSecondPassBuffers(true); 77 | this.resizeHeight = this.resizeHeightInterpolated; 78 | } 79 | else { 80 | this.initializeSecondPassBuffers(false); 81 | this.resizeHeight = (this.colorChannels == 4) ? this.resizeHeightRGBA : this.resizeHeightRGB; 82 | } 83 | } 84 | } 85 | Resize.prototype.resizeWidthRGB = function (buffer) { 86 | var ratioWeight = this.ratioWeightWidthPass; 87 | var ratioWeightDivisor = 1 / ratioWeight; 88 | var weight = 0; 89 | var amountToNext = 0; 90 | var actualPosition = 0; 91 | var currentPosition = 0; 92 | var line = 0; 93 | var pixelOffset = 0; 94 | var outputOffset = 0; 95 | var nextLineOffsetOriginalWidth = this.originalWidthMultipliedByChannels - 2; 96 | var nextLineOffsetTargetWidth = this.targetWidthMultipliedByChannels - 2; 97 | var output = this.outputWidthWorkBench; 98 | var outputBuffer = this.widthBuffer; 99 | do { 100 | for (line = 0; line < this.originalHeightMultipliedByChannels;) { 101 | output[line++] = 0; 102 | output[line++] = 0; 103 | output[line++] = 0; 104 | } 105 | weight = ratioWeight; 106 | do { 107 | amountToNext = 1 + actualPosition - currentPosition; 108 | if (weight >= amountToNext) { 109 | for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) { 110 | output[line++] += buffer[pixelOffset++] * amountToNext; 111 | output[line++] += buffer[pixelOffset++] * amountToNext; 112 | output[line++] += buffer[pixelOffset] * amountToNext; 113 | } 114 | currentPosition = actualPosition = actualPosition + 3; 115 | weight -= amountToNext; 116 | } 117 | else { 118 | for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) { 119 | output[line++] += buffer[pixelOffset++] * weight; 120 | output[line++] += buffer[pixelOffset++] * weight; 121 | output[line++] += buffer[pixelOffset] * weight; 122 | } 123 | currentPosition += weight; 124 | break; 125 | } 126 | } while (weight > 0 && actualPosition < this.originalWidthMultipliedByChannels); 127 | for (line = 0, pixelOffset = outputOffset; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetTargetWidth) { 128 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 129 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 130 | outputBuffer[pixelOffset] = output[line++] * ratioWeightDivisor; 131 | } 132 | outputOffset += 3; 133 | } while (outputOffset < this.targetWidthMultipliedByChannels); 134 | return outputBuffer; 135 | } 136 | Resize.prototype.resizeWidthInterpolatedRGB = function (buffer) { 137 | var ratioWeight = this.ratioWeightWidthPass; 138 | var weight = 0; 139 | var finalOffset = 0; 140 | var pixelOffset = 0; 141 | var firstWeight = 0; 142 | var secondWeight = 0; 143 | var outputBuffer = this.widthBuffer; 144 | //Handle for only one interpolation input being valid for start calculation: 145 | for (var targetPosition = 0; weight < 1/3; targetPosition += 3, weight += ratioWeight) { 146 | for (finalOffset = targetPosition, pixelOffset = 0; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 147 | outputBuffer[finalOffset] = buffer[pixelOffset]; 148 | outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1]; 149 | outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2]; 150 | } 151 | } 152 | //Adjust for overshoot of the last pass's counter: 153 | weight -= 1/3; 154 | for (var interpolationWidthSourceReadStop = this.widthOriginal - 1; weight < interpolationWidthSourceReadStop; targetPosition += 3, weight += ratioWeight) { 155 | //Calculate weightings: 156 | secondWeight = weight % 1; 157 | firstWeight = 1 - secondWeight; 158 | //Interpolate: 159 | for (finalOffset = targetPosition, pixelOffset = Math.floor(weight) * 3; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 160 | outputBuffer[finalOffset] = (buffer[pixelOffset] * firstWeight) + (buffer[pixelOffset + 3] * secondWeight); 161 | outputBuffer[finalOffset + 1] = (buffer[pixelOffset + 1] * firstWeight) + (buffer[pixelOffset + 4] * secondWeight); 162 | outputBuffer[finalOffset + 2] = (buffer[pixelOffset + 2] * firstWeight) + (buffer[pixelOffset + 5] * secondWeight); 163 | } 164 | } 165 | //Handle for only one interpolation input being valid for end calculation: 166 | for (interpolationWidthSourceReadStop = this.originalWidthMultipliedByChannels - 3; targetPosition < this.targetWidthMultipliedByChannels; targetPosition += 3) { 167 | for (finalOffset = targetPosition, pixelOffset = interpolationWidthSourceReadStop; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 168 | outputBuffer[finalOffset] = buffer[pixelOffset]; 169 | outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1]; 170 | outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2]; 171 | } 172 | } 173 | return outputBuffer; 174 | } 175 | Resize.prototype.resizeWidthRGBA = function (buffer) { 176 | var ratioWeight = this.ratioWeightWidthPass; 177 | var ratioWeightDivisor = 1 / ratioWeight; 178 | var weight = 0; 179 | var amountToNext = 0; 180 | var actualPosition = 0; 181 | var currentPosition = 0; 182 | var line = 0; 183 | var pixelOffset = 0; 184 | var outputOffset = 0; 185 | var nextLineOffsetOriginalWidth = this.originalWidthMultipliedByChannels - 3; 186 | var nextLineOffsetTargetWidth = this.targetWidthMultipliedByChannels - 3; 187 | var output = this.outputWidthWorkBench; 188 | var outputBuffer = this.widthBuffer; 189 | do { 190 | for (line = 0; line < this.originalHeightMultipliedByChannels;) { 191 | output[line++] = 0; 192 | output[line++] = 0; 193 | output[line++] = 0; 194 | output[line++] = 0; 195 | } 196 | weight = ratioWeight; 197 | do { 198 | amountToNext = 1 + actualPosition - currentPosition; 199 | if (weight >= amountToNext) { 200 | for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) { 201 | output[line++] += buffer[pixelOffset++] * amountToNext; 202 | output[line++] += buffer[pixelOffset++] * amountToNext; 203 | output[line++] += buffer[pixelOffset++] * amountToNext; 204 | output[line++] += buffer[pixelOffset] * amountToNext; 205 | } 206 | currentPosition = actualPosition = actualPosition + 4; 207 | weight -= amountToNext; 208 | } 209 | else { 210 | for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) { 211 | output[line++] += buffer[pixelOffset++] * weight; 212 | output[line++] += buffer[pixelOffset++] * weight; 213 | output[line++] += buffer[pixelOffset++] * weight; 214 | output[line++] += buffer[pixelOffset] * weight; 215 | } 216 | currentPosition += weight; 217 | break; 218 | } 219 | } while (weight > 0 && actualPosition < this.originalWidthMultipliedByChannels); 220 | for (line = 0, pixelOffset = outputOffset; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetTargetWidth) { 221 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 222 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 223 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 224 | outputBuffer[pixelOffset] = output[line++] * ratioWeightDivisor; 225 | } 226 | outputOffset += 4; 227 | } while (outputOffset < this.targetWidthMultipliedByChannels); 228 | return outputBuffer; 229 | } 230 | Resize.prototype.resizeWidthInterpolatedRGBA = function (buffer) { 231 | var ratioWeight = this.ratioWeightWidthPass; 232 | var weight = 0; 233 | var finalOffset = 0; 234 | var pixelOffset = 0; 235 | var firstWeight = 0; 236 | var secondWeight = 0; 237 | var outputBuffer = this.widthBuffer; 238 | //Handle for only one interpolation input being valid for start calculation: 239 | for (var targetPosition = 0; weight < 1/3; targetPosition += 4, weight += ratioWeight) { 240 | for (finalOffset = targetPosition, pixelOffset = 0; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 241 | outputBuffer[finalOffset] = buffer[pixelOffset]; 242 | outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1]; 243 | outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2]; 244 | outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3]; 245 | } 246 | } 247 | //Adjust for overshoot of the last pass's counter: 248 | weight -= 1/3; 249 | for (var interpolationWidthSourceReadStop = this.widthOriginal - 1; weight < interpolationWidthSourceReadStop; targetPosition += 4, weight += ratioWeight) { 250 | //Calculate weightings: 251 | secondWeight = weight % 1; 252 | firstWeight = 1 - secondWeight; 253 | //Interpolate: 254 | for (finalOffset = targetPosition, pixelOffset = Math.floor(weight) * 4; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 255 | outputBuffer[finalOffset] = (buffer[pixelOffset] * firstWeight) + (buffer[pixelOffset + 4] * secondWeight); 256 | outputBuffer[finalOffset + 1] = (buffer[pixelOffset + 1] * firstWeight) + (buffer[pixelOffset + 5] * secondWeight); 257 | outputBuffer[finalOffset + 2] = (buffer[pixelOffset + 2] * firstWeight) + (buffer[pixelOffset + 6] * secondWeight); 258 | outputBuffer[finalOffset + 3] = (buffer[pixelOffset + 3] * firstWeight) + (buffer[pixelOffset + 7] * secondWeight); 259 | } 260 | } 261 | //Handle for only one interpolation input being valid for end calculation: 262 | for (interpolationWidthSourceReadStop = this.originalWidthMultipliedByChannels - 4; targetPosition < this.targetWidthMultipliedByChannels; targetPosition += 4) { 263 | for (finalOffset = targetPosition, pixelOffset = interpolationWidthSourceReadStop; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 264 | outputBuffer[finalOffset] = buffer[pixelOffset]; 265 | outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1]; 266 | outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2]; 267 | outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3]; 268 | } 269 | } 270 | return outputBuffer; 271 | } 272 | Resize.prototype.resizeHeightRGB = function (buffer) { 273 | var ratioWeight = this.ratioWeightHeightPass; 274 | var ratioWeightDivisor = 1 / ratioWeight; 275 | var weight = 0; 276 | var amountToNext = 0; 277 | var actualPosition = 0; 278 | var currentPosition = 0; 279 | var pixelOffset = 0; 280 | var outputOffset = 0; 281 | var output = this.outputHeightWorkBench; 282 | var outputBuffer = this.heightBuffer; 283 | do { 284 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 285 | output[pixelOffset++] = 0; 286 | output[pixelOffset++] = 0; 287 | output[pixelOffset++] = 0; 288 | } 289 | weight = ratioWeight; 290 | do { 291 | amountToNext = 1 + actualPosition - currentPosition; 292 | if (weight >= amountToNext) { 293 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 294 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 295 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 296 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 297 | } 298 | currentPosition = actualPosition; 299 | weight -= amountToNext; 300 | } 301 | else { 302 | for (pixelOffset = 0, amountToNext = actualPosition; pixelOffset < this.targetWidthMultipliedByChannels;) { 303 | output[pixelOffset++] += buffer[amountToNext++] * weight; 304 | output[pixelOffset++] += buffer[amountToNext++] * weight; 305 | output[pixelOffset++] += buffer[amountToNext++] * weight; 306 | } 307 | currentPosition += weight; 308 | break; 309 | } 310 | } while (weight > 0 && actualPosition < this.widthPassResultSize); 311 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 312 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 313 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 314 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 315 | } 316 | } while (outputOffset < this.finalResultSize); 317 | return outputBuffer; 318 | } 319 | Resize.prototype.resizeHeightInterpolated = function (buffer) { 320 | var ratioWeight = this.ratioWeightHeightPass; 321 | var weight = 0; 322 | var finalOffset = 0; 323 | var pixelOffset = 0; 324 | var pixelOffsetAccumulated = 0; 325 | var pixelOffsetAccumulated2 = 0; 326 | var firstWeight = 0; 327 | var secondWeight = 0; 328 | var outputBuffer = this.heightBuffer; 329 | //Handle for only one interpolation input being valid for start calculation: 330 | for (; weight < 1/3; weight += ratioWeight) { 331 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 332 | outputBuffer[finalOffset++] = Math.round(buffer[pixelOffset++]); 333 | } 334 | } 335 | //Adjust for overshoot of the last pass's counter: 336 | weight -= 1/3; 337 | for (var interpolationHeightSourceReadStop = this.heightOriginal - 1; weight < interpolationHeightSourceReadStop; weight += ratioWeight) { 338 | //Calculate weightings: 339 | secondWeight = weight % 1; 340 | firstWeight = 1 - secondWeight; 341 | //Interpolate: 342 | pixelOffsetAccumulated = Math.floor(weight) * this.targetWidthMultipliedByChannels; 343 | pixelOffsetAccumulated2 = pixelOffsetAccumulated + this.targetWidthMultipliedByChannels; 344 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels; ++pixelOffset) { 345 | outputBuffer[finalOffset++] = Math.round((buffer[pixelOffsetAccumulated++] * firstWeight) + (buffer[pixelOffsetAccumulated2++] * secondWeight)); 346 | } 347 | } 348 | //Handle for only one interpolation input being valid for end calculation: 349 | while (finalOffset < this.finalResultSize) { 350 | for (pixelOffset = 0, pixelOffsetAccumulated = interpolationHeightSourceReadStop * this.targetWidthMultipliedByChannels; pixelOffset < this.targetWidthMultipliedByChannels; ++pixelOffset) { 351 | outputBuffer[finalOffset++] = Math.round(buffer[pixelOffsetAccumulated++]); 352 | } 353 | } 354 | return outputBuffer; 355 | } 356 | Resize.prototype.resizeHeightRGBA = function (buffer) { 357 | var ratioWeight = this.ratioWeightHeightPass; 358 | var ratioWeightDivisor = 1 / ratioWeight; 359 | var weight = 0; 360 | var amountToNext = 0; 361 | var actualPosition = 0; 362 | var currentPosition = 0; 363 | var pixelOffset = 0; 364 | var outputOffset = 0; 365 | var output = this.outputHeightWorkBench; 366 | var outputBuffer = this.heightBuffer; 367 | do { 368 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 369 | output[pixelOffset++] = 0; 370 | output[pixelOffset++] = 0; 371 | output[pixelOffset++] = 0; 372 | output[pixelOffset++] = 0; 373 | } 374 | weight = ratioWeight; 375 | do { 376 | amountToNext = 1 + actualPosition - currentPosition; 377 | if (weight >= amountToNext) { 378 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 379 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 380 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 381 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 382 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 383 | } 384 | currentPosition = actualPosition; 385 | weight -= amountToNext; 386 | } 387 | else { 388 | for (pixelOffset = 0, amountToNext = actualPosition; pixelOffset < this.targetWidthMultipliedByChannels;) { 389 | output[pixelOffset++] += buffer[amountToNext++] * weight; 390 | output[pixelOffset++] += buffer[amountToNext++] * weight; 391 | output[pixelOffset++] += buffer[amountToNext++] * weight; 392 | output[pixelOffset++] += buffer[amountToNext++] * weight; 393 | } 394 | currentPosition += weight; 395 | break; 396 | } 397 | } while (weight > 0 && actualPosition < this.widthPassResultSize); 398 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 399 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 400 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 401 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 402 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 403 | } 404 | } while (outputOffset < this.finalResultSize); 405 | return outputBuffer; 406 | } 407 | Resize.prototype.resize = function (buffer) { 408 | if (this.useWebWorker) { 409 | this.worker.postMessage(["resize", buffer]); 410 | } 411 | else { 412 | this.resizeCallback(this.resizeHeight(this.resizeWidth(buffer))); 413 | } 414 | } 415 | Resize.prototype.bypassResizer = function (buffer) { 416 | //Just return the buffer passsed: 417 | return buffer; 418 | } 419 | Resize.prototype.initializeFirstPassBuffers = function (BILINEARAlgo) { 420 | //Initialize the internal width pass buffers: 421 | this.widthBuffer = this.generateFloatBuffer(this.widthPassResultSize); 422 | if (!BILINEARAlgo) { 423 | this.outputWidthWorkBench = this.generateFloatBuffer(this.originalHeightMultipliedByChannels); 424 | } 425 | } 426 | Resize.prototype.initializeSecondPassBuffers = function (BILINEARAlgo) { 427 | //Initialize the internal height pass buffers: 428 | this.heightBuffer = this.generateUint8Buffer(this.finalResultSize); 429 | if (!BILINEARAlgo) { 430 | this.outputHeightWorkBench = this.generateFloatBuffer(this.targetWidthMultipliedByChannels); 431 | } 432 | } 433 | Resize.prototype.generateFloatBuffer = function (bufferLength) { 434 | //Generate a float32 typed array buffer: 435 | try { 436 | return new Float32Array(bufferLength); 437 | } 438 | catch (error) { 439 | return []; 440 | } 441 | } 442 | Resize.prototype.generateUint8Buffer = function (bufferLength) { 443 | //Generate a uint8 typed array buffer: 444 | try { 445 | return new Uint8Array(bufferLength); 446 | } 447 | catch (error) { 448 | return []; 449 | } 450 | } -------------------------------------------------------------------------------- /resizeWorker.js: -------------------------------------------------------------------------------- 1 | //JavaScript Image Resizer (c) 2012 - Grant Galitz 2 | var resizeWorker = null; 3 | self.onmessage = function (event) { 4 | switch (event.data[0]) { 5 | case "setup": 6 | resizeWorker = new Resize(event.data[1], event.data[2], event.data[3], event.data[4], event.data[5], event.data[6]); 7 | break; 8 | case "resize": 9 | resizeWorker.resize(event.data[1]); 10 | } 11 | } 12 | function Resize(widthOriginal, heightOriginal, targetWidth, targetHeight, colorChannels, interpolationPass) { 13 | this.widthOriginal = widthOriginal; 14 | this.heightOriginal = heightOriginal; 15 | this.targetWidth = targetWidth; 16 | this.targetHeight = targetHeight; 17 | this.colorChannels = colorChannels; 18 | this.interpolationPass = !!interpolationPass; 19 | this.targetWidthMultipliedByChannels = this.targetWidth * this.colorChannels; 20 | this.originalWidthMultipliedByChannels = this.widthOriginal * this.colorChannels; 21 | this.originalHeightMultipliedByChannels = this.heightOriginal * this.colorChannels; 22 | this.widthPassResultSize = this.targetWidthMultipliedByChannels * this.heightOriginal; 23 | this.finalResultSize = this.targetWidthMultipliedByChannels * this.targetHeight; 24 | this.initialize(); 25 | } 26 | Resize.prototype.initialize = function () { 27 | //Perform some checks: 28 | if (this.widthOriginal > 0 && this.heightOriginal > 0 && this.targetWidth > 0 && this.targetHeight > 0) { 29 | this.configurePasses(); 30 | } 31 | else { 32 | throw(new Error("Invalid settings specified for the resizer.")); 33 | } 34 | } 35 | Resize.prototype.configurePasses = function () { 36 | if (this.widthOriginal == this.targetWidth) { 37 | //Bypass the width resizer pass: 38 | this.resizeWidth = this.bypassResizer; 39 | } 40 | else { 41 | //Setup the width resizer pass: 42 | this.ratioWeightWidthPass = this.widthOriginal / this.targetWidth; 43 | if (this.ratioWeightWidthPass < 1 && this.interpolationPass) { 44 | this.initializeFirstPassBuffers(true); 45 | this.resizeWidth = (this.colorChannels == 4) ? this.resizeWidthInterpolatedRGBA : this.resizeWidthInterpolatedRGB; 46 | } 47 | else { 48 | this.initializeFirstPassBuffers(false); 49 | this.resizeWidth = (this.colorChannels == 4) ? this.resizeWidthRGBA : this.resizeWidthRGB; 50 | } 51 | } 52 | if (this.heightOriginal == this.targetHeight) { 53 | //Bypass the height resizer pass: 54 | this.resizeHeight = this.bypassResizer; 55 | } 56 | else { 57 | //Setup the height resizer pass: 58 | this.ratioWeightHeightPass = this.heightOriginal / this.targetHeight; 59 | if (this.ratioWeightHeightPass < 1 && this.interpolationPass) { 60 | this.initializeSecondPassBuffers(true); 61 | this.resizeHeight = this.resizeHeightInterpolated; 62 | } 63 | else { 64 | this.initializeSecondPassBuffers(false); 65 | this.resizeHeight = (this.colorChannels == 4) ? this.resizeHeightRGBA : this.resizeHeightRGB; 66 | } 67 | } 68 | } 69 | Resize.prototype.resizeWidthRGB = function (buffer) { 70 | var ratioWeight = this.ratioWeightWidthPass; 71 | var ratioWeightDivisor = 1 / ratioWeight; 72 | var weight = 0; 73 | var amountToNext = 0; 74 | var actualPosition = 0; 75 | var currentPosition = 0; 76 | var line = 0; 77 | var pixelOffset = 0; 78 | var outputOffset = 0; 79 | var nextLineOffsetOriginalWidth = this.originalWidthMultipliedByChannels - 2; 80 | var nextLineOffsetTargetWidth = this.targetWidthMultipliedByChannels - 2; 81 | var output = this.outputWidthWorkBench; 82 | var outputBuffer = this.widthBuffer; 83 | do { 84 | for (line = 0; line < this.originalHeightMultipliedByChannels;) { 85 | output[line++] = 0; 86 | output[line++] = 0; 87 | output[line++] = 0; 88 | } 89 | weight = ratioWeight; 90 | do { 91 | amountToNext = 1 + actualPosition - currentPosition; 92 | if (weight >= amountToNext) { 93 | for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) { 94 | output[line++] += buffer[pixelOffset++] * amountToNext; 95 | output[line++] += buffer[pixelOffset++] * amountToNext; 96 | output[line++] += buffer[pixelOffset] * amountToNext; 97 | } 98 | currentPosition = actualPosition = actualPosition + 3; 99 | weight -= amountToNext; 100 | } 101 | else { 102 | for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) { 103 | output[line++] += buffer[pixelOffset++] * weight; 104 | output[line++] += buffer[pixelOffset++] * weight; 105 | output[line++] += buffer[pixelOffset] * weight; 106 | } 107 | currentPosition += weight; 108 | break; 109 | } 110 | } while (weight > 0 && actualPosition < this.originalWidthMultipliedByChannels); 111 | for (line = 0, pixelOffset = outputOffset; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetTargetWidth) { 112 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 113 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 114 | outputBuffer[pixelOffset] = output[line++] * ratioWeightDivisor; 115 | } 116 | outputOffset += 3; 117 | } while (outputOffset < this.targetWidthMultipliedByChannels); 118 | return outputBuffer; 119 | } 120 | Resize.prototype.resizeWidthInterpolatedRGB = function (buffer) { 121 | var ratioWeight = this.ratioWeightWidthPass; 122 | var weight = 0; 123 | var finalOffset = 0; 124 | var pixelOffset = 0; 125 | var firstWeight = 0; 126 | var secondWeight = 0; 127 | var outputBuffer = this.widthBuffer; 128 | //Handle for only one interpolation input being valid for start calculation: 129 | for (var targetPosition = 0; weight < 1/3; targetPosition += 3, weight += ratioWeight) { 130 | for (finalOffset = targetPosition, pixelOffset = 0; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 131 | outputBuffer[finalOffset] = buffer[pixelOffset]; 132 | outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1]; 133 | outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2]; 134 | } 135 | } 136 | //Adjust for overshoot of the last pass's counter: 137 | weight -= 1/3; 138 | for (var interpolationWidthSourceReadStop = this.widthOriginal - 1; weight < interpolationWidthSourceReadStop; targetPosition += 3, weight += ratioWeight) { 139 | //Calculate weightings: 140 | secondWeight = weight % 1; 141 | firstWeight = 1 - secondWeight; 142 | //Interpolate: 143 | for (finalOffset = targetPosition, pixelOffset = Math.floor(weight) * 3; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 144 | outputBuffer[finalOffset] = (buffer[pixelOffset] * firstWeight) + (buffer[pixelOffset + 3] * secondWeight); 145 | outputBuffer[finalOffset + 1] = (buffer[pixelOffset + 1] * firstWeight) + (buffer[pixelOffset + 4] * secondWeight); 146 | outputBuffer[finalOffset + 2] = (buffer[pixelOffset + 2] * firstWeight) + (buffer[pixelOffset + 5] * secondWeight); 147 | } 148 | } 149 | //Handle for only one interpolation input being valid for end calculation: 150 | for (interpolationWidthSourceReadStop = this.originalWidthMultipliedByChannels - 3; targetPosition < this.targetWidthMultipliedByChannels; targetPosition += 3) { 151 | for (finalOffset = targetPosition, pixelOffset = interpolationWidthSourceReadStop; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 152 | outputBuffer[finalOffset] = buffer[pixelOffset]; 153 | outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1]; 154 | outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2]; 155 | } 156 | } 157 | return outputBuffer; 158 | } 159 | Resize.prototype.resizeWidthRGBA = function (buffer) { 160 | var ratioWeight = this.ratioWeightWidthPass; 161 | var ratioWeightDivisor = 1 / ratioWeight; 162 | var weight = 0; 163 | var amountToNext = 0; 164 | var actualPosition = 0; 165 | var currentPosition = 0; 166 | var line = 0; 167 | var pixelOffset = 0; 168 | var outputOffset = 0; 169 | var nextLineOffsetOriginalWidth = this.originalWidthMultipliedByChannels - 3; 170 | var nextLineOffsetTargetWidth = this.targetWidthMultipliedByChannels - 3; 171 | var output = this.outputWidthWorkBench; 172 | var outputBuffer = this.widthBuffer; 173 | do { 174 | for (line = 0; line < this.originalHeightMultipliedByChannels;) { 175 | output[line++] = 0; 176 | output[line++] = 0; 177 | output[line++] = 0; 178 | output[line++] = 0; 179 | } 180 | weight = ratioWeight; 181 | do { 182 | amountToNext = 1 + actualPosition - currentPosition; 183 | if (weight >= amountToNext) { 184 | for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) { 185 | output[line++] += buffer[pixelOffset++] * amountToNext; 186 | output[line++] += buffer[pixelOffset++] * amountToNext; 187 | output[line++] += buffer[pixelOffset++] * amountToNext; 188 | output[line++] += buffer[pixelOffset] * amountToNext; 189 | } 190 | currentPosition = actualPosition = actualPosition + 4; 191 | weight -= amountToNext; 192 | } 193 | else { 194 | for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) { 195 | output[line++] += buffer[pixelOffset++] * weight; 196 | output[line++] += buffer[pixelOffset++] * weight; 197 | output[line++] += buffer[pixelOffset++] * weight; 198 | output[line++] += buffer[pixelOffset] * weight; 199 | } 200 | currentPosition += weight; 201 | break; 202 | } 203 | } while (weight > 0 && actualPosition < this.originalWidthMultipliedByChannels); 204 | for (line = 0, pixelOffset = outputOffset; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetTargetWidth) { 205 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 206 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 207 | outputBuffer[pixelOffset++] = output[line++] * ratioWeightDivisor; 208 | outputBuffer[pixelOffset] = output[line++] * ratioWeightDivisor; 209 | } 210 | outputOffset += 4; 211 | } while (outputOffset < this.targetWidthMultipliedByChannels); 212 | return outputBuffer; 213 | } 214 | Resize.prototype.resizeWidthInterpolatedRGBA = function (buffer) { 215 | var ratioWeight = this.ratioWeightWidthPass; 216 | var weight = 0; 217 | var finalOffset = 0; 218 | var pixelOffset = 0; 219 | var firstWeight = 0; 220 | var secondWeight = 0; 221 | var outputBuffer = this.widthBuffer; 222 | //Handle for only one interpolation input being valid for start calculation: 223 | for (var targetPosition = 0; weight < 1/3; targetPosition += 4, weight += ratioWeight) { 224 | for (finalOffset = targetPosition, pixelOffset = 0; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 225 | outputBuffer[finalOffset] = buffer[pixelOffset]; 226 | outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1]; 227 | outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2]; 228 | outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3]; 229 | } 230 | } 231 | //Adjust for overshoot of the last pass's counter: 232 | weight -= 1/3; 233 | for (var interpolationWidthSourceReadStop = this.widthOriginal - 1; weight < interpolationWidthSourceReadStop; targetPosition += 4, weight += ratioWeight) { 234 | //Calculate weightings: 235 | secondWeight = weight % 1; 236 | firstWeight = 1 - secondWeight; 237 | //Interpolate: 238 | for (finalOffset = targetPosition, pixelOffset = Math.floor(weight) * 4; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 239 | outputBuffer[finalOffset] = (buffer[pixelOffset] * firstWeight) + (buffer[pixelOffset + 4] * secondWeight); 240 | outputBuffer[finalOffset + 1] = (buffer[pixelOffset + 1] * firstWeight) + (buffer[pixelOffset + 5] * secondWeight); 241 | outputBuffer[finalOffset + 2] = (buffer[pixelOffset + 2] * firstWeight) + (buffer[pixelOffset + 6] * secondWeight); 242 | outputBuffer[finalOffset + 3] = (buffer[pixelOffset + 3] * firstWeight) + (buffer[pixelOffset + 7] * secondWeight); 243 | } 244 | } 245 | //Handle for only one interpolation input being valid for end calculation: 246 | for (interpolationWidthSourceReadStop = this.originalWidthMultipliedByChannels - 4; targetPosition < this.targetWidthMultipliedByChannels; targetPosition += 4) { 247 | for (finalOffset = targetPosition, pixelOffset = interpolationWidthSourceReadStop; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels, finalOffset += this.targetWidthMultipliedByChannels) { 248 | outputBuffer[finalOffset] = buffer[pixelOffset]; 249 | outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1]; 250 | outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2]; 251 | outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3]; 252 | } 253 | } 254 | return outputBuffer; 255 | } 256 | Resize.prototype.resizeHeightRGB = function (buffer) { 257 | var ratioWeight = this.ratioWeightHeightPass; 258 | var ratioWeightDivisor = 1 / ratioWeight; 259 | var weight = 0; 260 | var amountToNext = 0; 261 | var actualPosition = 0; 262 | var currentPosition = 0; 263 | var pixelOffset = 0; 264 | var outputOffset = 0; 265 | var output = this.outputHeightWorkBench; 266 | var outputBuffer = this.heightBuffer; 267 | do { 268 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 269 | output[pixelOffset++] = 0; 270 | output[pixelOffset++] = 0; 271 | output[pixelOffset++] = 0; 272 | } 273 | weight = ratioWeight; 274 | do { 275 | amountToNext = 1 + actualPosition - currentPosition; 276 | if (weight >= amountToNext) { 277 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 278 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 279 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 280 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 281 | } 282 | currentPosition = actualPosition; 283 | weight -= amountToNext; 284 | } 285 | else { 286 | for (pixelOffset = 0, amountToNext = actualPosition; pixelOffset < this.targetWidthMultipliedByChannels;) { 287 | output[pixelOffset++] += buffer[amountToNext++] * weight; 288 | output[pixelOffset++] += buffer[amountToNext++] * weight; 289 | output[pixelOffset++] += buffer[amountToNext++] * weight; 290 | } 291 | currentPosition += weight; 292 | break; 293 | } 294 | } while (weight > 0 && actualPosition < this.widthPassResultSize); 295 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 296 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 297 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 298 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 299 | } 300 | } while (outputOffset < this.finalResultSize); 301 | return outputBuffer; 302 | } 303 | Resize.prototype.resizeHeightInterpolated = function (buffer) { 304 | var ratioWeight = this.ratioWeightHeightPass; 305 | var weight = 0; 306 | var finalOffset = 0; 307 | var pixelOffset = 0; 308 | var pixelOffsetAccumulated = 0; 309 | var pixelOffsetAccumulated2 = 0; 310 | var firstWeight = 0; 311 | var secondWeight = 0; 312 | var outputBuffer = this.heightBuffer; 313 | //Handle for only one interpolation input being valid for start calculation: 314 | for (; weight < 1/3; weight += ratioWeight) { 315 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 316 | outputBuffer[finalOffset++] = Math.round(buffer[pixelOffset++]); 317 | } 318 | } 319 | //Adjust for overshoot of the last pass's counter: 320 | weight -= 1/3; 321 | for (var interpolationHeightSourceReadStop = this.heightOriginal - 1; weight < interpolationHeightSourceReadStop; weight += ratioWeight) { 322 | //Calculate weightings: 323 | secondWeight = weight % 1; 324 | firstWeight = 1 - secondWeight; 325 | //Interpolate: 326 | pixelOffsetAccumulated = Math.floor(weight) * this.targetWidthMultipliedByChannels; 327 | pixelOffsetAccumulated2 = pixelOffsetAccumulated + this.targetWidthMultipliedByChannels; 328 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels; ++pixelOffset) { 329 | outputBuffer[finalOffset++] = Math.round((buffer[pixelOffsetAccumulated++] * firstWeight) + (buffer[pixelOffsetAccumulated2++] * secondWeight)); 330 | } 331 | } 332 | //Handle for only one interpolation input being valid for end calculation: 333 | while (finalOffset < this.finalResultSize) { 334 | for (pixelOffset = 0, pixelOffsetAccumulated = interpolationHeightSourceReadStop * this.targetWidthMultipliedByChannels; pixelOffset < this.targetWidthMultipliedByChannels; ++pixelOffset) { 335 | outputBuffer[finalOffset++] = Math.round(buffer[pixelOffsetAccumulated++]); 336 | } 337 | } 338 | return outputBuffer; 339 | } 340 | Resize.prototype.resizeHeightRGBA = function (buffer) { 341 | var ratioWeight = this.ratioWeightHeightPass; 342 | var ratioWeightDivisor = 1 / ratioWeight; 343 | var weight = 0; 344 | var amountToNext = 0; 345 | var actualPosition = 0; 346 | var currentPosition = 0; 347 | var pixelOffset = 0; 348 | var outputOffset = 0; 349 | var output = this.outputHeightWorkBench; 350 | var outputBuffer = this.heightBuffer; 351 | do { 352 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 353 | output[pixelOffset++] = 0; 354 | output[pixelOffset++] = 0; 355 | output[pixelOffset++] = 0; 356 | output[pixelOffset++] = 0; 357 | } 358 | weight = ratioWeight; 359 | do { 360 | amountToNext = 1 + actualPosition - currentPosition; 361 | if (weight >= amountToNext) { 362 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 363 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 364 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 365 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 366 | output[pixelOffset++] += buffer[actualPosition++] * amountToNext; 367 | } 368 | currentPosition = actualPosition; 369 | weight -= amountToNext; 370 | } 371 | else { 372 | for (pixelOffset = 0, amountToNext = actualPosition; pixelOffset < this.targetWidthMultipliedByChannels;) { 373 | output[pixelOffset++] += buffer[amountToNext++] * weight; 374 | output[pixelOffset++] += buffer[amountToNext++] * weight; 375 | output[pixelOffset++] += buffer[amountToNext++] * weight; 376 | output[pixelOffset++] += buffer[amountToNext++] * weight; 377 | } 378 | currentPosition += weight; 379 | break; 380 | } 381 | } while (weight > 0 && actualPosition < this.widthPassResultSize); 382 | for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) { 383 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 384 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 385 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 386 | outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor); 387 | } 388 | } while (outputOffset < this.finalResultSize); 389 | return outputBuffer; 390 | } 391 | Resize.prototype.resize = function (buffer) { 392 | self.postMessage(this.resizeHeight(this.resizeWidth(buffer))); 393 | } 394 | Resize.prototype.bypassResizer = function (buffer) { 395 | //Just return the buffer passsed: 396 | return buffer; 397 | } 398 | Resize.prototype.initializeFirstPassBuffers = function (BILINEARAlgo) { 399 | //Initialize the internal width pass buffers: 400 | this.widthBuffer = this.generateFloatBuffer(this.widthPassResultSize); 401 | if (!BILINEARAlgo) { 402 | this.outputWidthWorkBench = this.generateFloatBuffer(this.originalHeightMultipliedByChannels); 403 | } 404 | } 405 | Resize.prototype.initializeSecondPassBuffers = function (BILINEARAlgo) { 406 | //Initialize the internal height pass buffers: 407 | this.heightBuffer = this.generateUint8Buffer(this.finalResultSize); 408 | if (!BILINEARAlgo) { 409 | this.outputHeightWorkBench = this.generateFloatBuffer(this.targetWidthMultipliedByChannels); 410 | } 411 | } 412 | Resize.prototype.generateFloatBuffer = function (bufferLength) { 413 | //Generate a float32 typed array buffer: 414 | try { 415 | return new Float32Array(bufferLength); 416 | } 417 | catch (error) { 418 | return []; 419 | } 420 | } 421 | Resize.prototype.generateUint8Buffer = function (bufferLength) { 422 | //Generate a uint8 typed array buffer: 423 | try { 424 | return new Uint8Array(bufferLength); 425 | } 426 | catch (error) { 427 | return []; 428 | } 429 | } --------------------------------------------------------------------------------