@@ -386,26 +386,82 @@ export class RawImage {
386
386
}
387
387
388
388
if ( IS_BROWSER_OR_WEBWORKER ) {
389
- // TODO use `resample` in browser environment
390
-
391
389
// Store number of channels before resizing
392
390
const numChannels = this . channels ;
393
391
394
- // Create canvas object for this image
395
- const canvas = this . toCanvas ( ) ;
392
+ // Create the output array for the resized image
393
+ const resizedData = new Uint8ClampedArray ( width * height * numChannels ) ;
396
394
397
- // Actually perform resizing using the canvas API
398
- const ctx = createCanvasFunction ( width , height ) . getContext ( '2d' ) ;
395
+ // Scale factors for mapping new dimensions back to original dimensions
396
+ const xScale = this . width / width ;
397
+ const yScale = this . height / height ;
399
398
400
- // Draw image to context, resizing in the process
401
- ctx . drawImage ( canvas , 0 , 0 , width , height ) ;
399
+ switch ( resampleMethod ) {
400
+ case 'bilinear' :
401
+ // Iterate over each pixel in the new image.
402
+ for ( let y = 0 ; y < height ; y ++ ) {
403
+ for ( let x = 0 ; x < width ; x ++ ) {
404
+ // Map new coordinates to original coordinates.
405
+ const srcX = x * xScale ;
406
+ const srcY = y * yScale ;
407
+
408
+ // Calculate the surrounding pixels.
409
+ // Ensure that the pixels are within the bounds
410
+ // of the image.
411
+ const x0 = Math . floor ( srcX ) ;
412
+ const x1 = Math . min ( x0 + 1 , this . width - 1 ) ;
413
+ const y0 = Math . floor ( srcY ) ;
414
+ const y1 = Math . min ( y0 + 1 , this . height - 1 ) ;
415
+
416
+ // Calculate fractional parts for interpolation.
417
+ const dx = srcX - x0 ;
418
+ const dy = srcY - y0 ;
419
+
420
+ for ( let c = 0 ; c < numChannels ; c ++ ) {
421
+ // Get the values of the new pixel area.
422
+ // Always multiply by the width because we
423
+ // storing the data in a 1D array.
424
+ // To get the second row, we must add a full
425
+ // width, then adding the x offset.
426
+ const topLeft = this . data [ ( ( ( y0 * this . width ) + x0 ) * numChannels ) + c ] ;
427
+ const topRight = this . data [ ( ( ( y0 * this . width ) + x1 ) * numChannels ) + c ] ;
428
+ const bottomLeft = this . data [ ( ( ( y1 * this . width ) + x0 ) * numChannels ) + c ] ;
429
+ const bottomRight = this . data [ ( ( ( y1 * this . width ) + x1 ) * numChannels ) + c ] ;
430
+
431
+ // Perform bilinear interpolation.
432
+ // Find the horizontal position along the
433
+ // top and bottom rows.
434
+ const top = ( topLeft * ( 1 - dx ) ) + ( topRight * dx ) ;
435
+ const bottom = ( bottomLeft * ( 1 - dx ) ) + ( bottomRight * dx ) ;
436
+ // Find the value between these two values.
437
+ const interpolatedValue = ( top * ( 1 - dy ) ) + ( bottom * dy ) ;
438
+
439
+ // Set the value in the resized data.
440
+ resizedData [ ( ( ( y * width ) + x ) * numChannels ) + c ] = Math . round ( interpolatedValue ) ;
441
+ }
442
+ }
443
+ }
444
+ break ;
402
445
403
- // Create image from the resized data
404
- const resizedImage = new RawImage ( ctx . getImageData ( 0 , 0 , width , height ) . data , width , height , 4 ) ;
446
+ // Fallback to the Canvas API.
447
+ default :
448
+ // Create canvas object for this image
449
+ const canvas = this . toCanvas ( ) ;
405
450
406
- // Convert back so that image has the same number of channels as before
407
- return resizedImage . convert ( numChannels ) ;
451
+ // Actually perform resizing using the canvas API
452
+ const ctx = createCanvasFunction ( width , height ) . getContext ( '2d' ) ;
453
+
454
+ // Draw image to context, resizing in the process
455
+ ctx . drawImage ( canvas , 0 , 0 , width , height ) ;
456
+
457
+ // Create image from the resized data
458
+ const resizedImage = new RawImage ( ctx . getImageData ( 0 , 0 , width , height ) . data , width , height , 4 ) ;
459
+
460
+ // Convert back so that image has the same number of channels as before
461
+ return resizedImage . convert ( numChannels ) ;
462
+ }
408
463
464
+ return new RawImage ( resizedData , width , height , numChannels ) ;
409
465
} else {
410
466
// Create sharp image from raw data, and resize
411
467
let img = this . toSharp ( ) ;
0 commit comments