import Histogram from "./Histogram" ; import { LUT_ARRAY_LENGTH } from "./Histogram" ; export default class Channel { public loaded : boolean ; public imgData : ImageData ; public volumeData : Uint8Array ; public name : string ; public histogram : Histogram ; public lut : Uint8Array ; public colorPalette : Uint8Array ; public colorPaletteAlpha : number ; public dims : [ number , number , number ] ; constructor ( name ) { this . loaded = false ; this . imgData = { data : new Uint8ClampedArray ( ) , width : 0 , height : 0 } ; this . volumeData = new Uint8Array ( ) ; this . name = name ; this . histogram = new Histogram ( new Uint8Array ( ) ) ; this . dims = [ 0 , 0 , 0 ] ; this . lut = new Uint8Array ( LUT_ARRAY_LENGTH ) . fill ( 0 ) ; this . colorPalette = new Uint8Array ( LUT_ARRAY_LENGTH ) . fill ( 0 ) ; this . colorPaletteAlpha = 0.0 ; } public combineLuts ( rgbColor , out ? ) { const ret = out ? out : new Uint8Array ( LUT_ARRAY_LENGTH ) ; if ( ! rgbColor ) { return ret ; } const rgb = [ rgbColor [ 0 ] / 255.0 , rgbColor [ 1 ] / 255.0 , rgbColor [ 2 ] / 255.0 ] ; if ( this . colorPaletteAlpha === 1.0 ) { ret . set ( this . colorPalette ) ; } else if ( this . colorPaletteAlpha === 0.0 ) { ret . set ( this . lut ) ; for ( let i = 0 ; i < LUT_ARRAY_LENGTH / 4 ; ++ i ) { ret [ i * 4 + 0 ] *= rgb [ 0 ] ; ret [ i * 4 + 1 ] *= rgb [ 1 ] ; ret [ i * 4 + 2 ] *= rgb [ 2 ] ; } } else { for ( let i = 0 ; i < LUT_ARRAY_LENGTH / 4 ; ++ i ) { ret [ i * 4 + 0 ] = this . colorPalette [ i * 4 + 0 ] * this . colorPaletteAlpha + this . lut [ i * 4 + 0 ] * ( 1.0 - this . colorPaletteAlpha ) * rgb [ 0 ] ; ret [ i * 4 + 1 ] = this . colorPalette [ i * 4 + 1 ] * this . colorPaletteAlpha + this . lut [ i * 4 + 1 ] * ( 1.0 - this . colorPaletteAlpha ) * rgb [ 1 ] ; ret [ i * 4 + 2 ] = this . colorPalette [ i * 4 + 2 ] * this . colorPaletteAlpha + this . lut [ i * 4 + 2 ] * ( 1.0 - this . colorPaletteAlpha ) * rgb [ 2 ] ; ret [ i * 4 + 3 ] = this . colorPalette [ i * 4 + 3 ] * this . colorPaletteAlpha + this . lut [ i * 4 + 3 ] * ( 1.0 - this . colorPaletteAlpha ) ; } } return ret ; } public getHistogram ( ) { return this . histogram ; } public getIntensity ( x , y , z ) { return this . volumeData [ x + y * this . dims [ 0 ] + z * ( this . dims [ 0 ] * this . dims [ 1 ] ) ] ; } public getIntensityFromAtlas ( x , y , z ) { const numXtiles = this . imgData . width / this . dims [ 0 ] ; const tilex = z % numXtiles ; const tiley = Math . floor ( z / numXtiles ) ; const offset = tilex * this . dims [ 0 ] + x + ( tiley * this . dims [ 1 ] + y ) * this . imgData . width ; return this . imgData . data [ offset ] ; } public setBits ( bitsArray , w , h ) { this . imgData = { data : new Uint8ClampedArray ( bitsArray . buffer ) , width : w , height : h } ; this . loaded = true ; this . histogram = new Histogram ( bitsArray ) ; this . lutGenerator_auto2 ( ) ; } public unpackVolumeFromAtlas ( x , y , z ) { const volimgdata = this . imgData . data ; this . dims = [ x , y , z ] ; this . volumeData = new Uint8Array ( x * y * z ) ; const numXtiles = this . imgData . width / x ; const atlasrow = this . imgData . width ; let tilex = 0 , tiley = 0 , tileoffset = 0 , tilerowoffset = 0 ; for ( let i = 0 ; i < z ; ++ i ) { tilex = i % numXtiles ; tiley = Math . floor ( i / numXtiles ) ; tileoffset = tilex * x + tiley * y * atlasrow ; for ( let j = 0 ; j < y ; ++ j ) { tilerowoffset = j * atlasrow ; for ( let k = 0 ; k < x ; ++ k ) { this . volumeData [ i * ( x * y ) + j * x + k ] = volimgdata [ tileoffset + tilerowoffset + k ] ; } } } } public setFromVolumeData ( bitsArray , vx , vy , vz , ax , ay ) { this . dims = [ vx , vy , vz ] ; this . volumeData = bitsArray ; this . packToAtlas ( vx , vy , vz , ax , ay ) ; this . loaded = true ; this . histogram = new Histogram ( this . volumeData ) ; this . lutGenerator_auto2 ( ) ; } private packToAtlas ( vx , vy , vz , ax , ay ) { if ( ax % vx !== 0 || ay % vy !== 0 || ( ax / vx ) * ( ay / vy ) < vz ) { console . log ( "ERROR - atlas and volume dims are inconsistent" ) ; console . log ( ax , ay , vx , vy , vz ) ; } this . imgData = { width : ax , height : ay , data : new Uint8ClampedArray ( ax * ay ) , } ; this . imgData . data . fill ( 0 ) ; const volimgdata = this . imgData . data ; const x = vx , y = vy , z = vz ; const numXtiles = this . imgData . width / x ; const atlasrow = this . imgData . width ; let tilex = 0 , tiley = 0 , tileoffset = 0 , tilerowoffset = 0 ; for ( let i = 0 ; i < z ; ++ i ) { tilex = i % numXtiles ; tiley = Math . floor ( i / numXtiles ) ; tileoffset = tilex * x + tiley * y * atlasrow ; for ( let j = 0 ; j < y ; ++ j ) { tilerowoffset = j * atlasrow ; for ( let k = 0 ; k < x ; ++ k ) { volimgdata [ tileoffset + tilerowoffset + k ] = this . volumeData [ i * ( x * y ) + j * x + k ] ; } } } } public setLut ( lut ) { this . lut = lut ; } public setColorPalette ( palette ) { this . colorPalette = palette ; } public setColorPaletteAlpha ( alpha ) { this . colorPaletteAlpha = alpha ; } public lutGenerator_windowLevel ( wnd , lvl ) { if ( ! this . loaded ) { return ; } const lut = this . histogram . lutGenerator_windowLevel ( wnd , lvl ) ; this . setLut ( lut . lut ) ; } public lutGenerator_fullRange ( ) { if ( ! this . loaded ) { return ; } const lut = this . histogram . lutGenerator_fullRange ( ) ; this . setLut ( lut . lut ) ; } public lutGenerator_dataRange ( ) { if ( ! this . loaded ) { return ; } const lut = this . histogram . lutGenerator_dataRange ( ) ; this . setLut ( lut . lut ) ; } public lutGenerator_bestFit ( ) { if ( ! this . loaded ) { return ; } const lut = this . histogram . lutGenerator_bestFit ( ) ; this . setLut ( lut . lut ) ; } public lutGenerator_auto2 ( ) { if ( ! this . loaded ) { return ; } const lut = this . histogram . lutGenerator_auto2 ( ) ; this . setLut ( lut . lut ) ; } public lutGenerator_auto ( ) { if ( ! this . loaded ) { return ; } const lut = this . histogram . lutGenerator_auto ( ) ; this . setLut ( lut . lut ) ; } public lutGenerator_equalize ( ) { if ( ! this . loaded ) { return ; } const lut = this . histogram . lutGenerator_equalize ( ) ; this . setLut ( lut . lut ) ; } public lutGenerator_percentiles ( lo , hi ) { if ( ! this . loaded ) { return ; } const lut = this . histogram . lutGenerator_percentiles ( lo , hi ) ; this . setLut ( lut . lut ) ; } }