@@ -638,19 +638,33 @@ export class RawImage {
638638 }
639639
640640 /**
641- * Splits the image data into separate channels.
642- * The number of elements in the array corresponds to the number of channels in the image.
643- * @returns {Array<Uint8ClampedArray|Uint8Array> } An array containing separate channel data.
641+ * Split the image data into individual bands. This method returns an array of individual image bands from an image.
642+ * For example, splitting an "RGB" image creates three new images each containing a copy of one of the original bands (red, green, blue).
643+ *
644+ * Inspired by PIL's `Image.split()` [function](https://pillow.readthedocs.io/en/latest/reference/Image.html#PIL.Image.Image.split).
645+ * @returns {(Uint8Array|Uint8ClampedArray)[] } An array containing bands.
644646 */
645- toChannels ( ) {
646- // Split each channel into a separate entry in a `channels` array.
647- const channels = [ ] ;
648- for ( let c = 0 ; c < this . channels ; c ++ ) {
649- channels . push (
650- this . data . filter ( ( _ , i ) => i % this . channels === c )
651- ) ;
647+ split ( ) {
648+ const { data, channels } = this ;
649+
650+ /** @type {typeof Uint8Array | typeof Uint8ClampedArray } */
651+ const data_type = /** @type {any } */ ( data . constructor ) ;
652+ const per_channel_length = data . length / channels ;
653+
654+ // Pre-allocate buffers for each channel
655+ const split_data = Array . from (
656+ { length : channels } ,
657+ ( ) => new data_type ( per_channel_length ) ,
658+ ) ;
659+
660+ // Write pixel data
661+ for ( let i = 0 ; i < per_channel_length ; ++ i ) {
662+ const data_offset = channels * i ;
663+ for ( let j = 0 ; j < channels ; ++ j ) {
664+ split_data [ j ] [ i ] = data [ data_offset + j ] ;
665+ }
652666 }
653- return channels ;
667+ return split_data ;
654668 }
655669
656670 /**
0 commit comments