import BitStream from '../../common/bitstream' ; import { bytesOf } from '../../common/bytesof' ; import convertBitRange from '../../common/convertbitrange' ; import { JpegImage } from './jpg.js' ; export const BLP1_MAGIC = 0x31504c42 ; export const CONTENT_JPG = 0x0 ; /**
 * A BLP1 image.
 */ export class BlpImage { content = 0 ; alphaBits = 0 ; width = 0 ; height = 0 ; type = 0 ; hasMipmaps = false ; mipmapOffsets = new Uint32Array ( 16 ) ; mipmapSizes = new Uint32Array ( 16 ) ; uint8array : Uint8Array | null = null ; /**
     * Used for JPG images.
     */ jpgHeader : Uint8Array | null = null ; /**
     * Used for indexed images.
     */ pallete : Uint8Array | null = null ; load ( buffer ) { const bytes = bytesOf ( buffer ) ; const header = new Int32Array ( bytes . buffer , 0 , 40 ) ; if ( header [ 0 ] !== BLP1_MAGIC ) { throw new Error ( 'WrongMagicNumber' ) ; } this . content = header [ 1 ] ; this . alphaBits = header [ 2 ] ; this . width = header [ 3 ] ; this . height = header [ 4 ] ; this . type = header [ 5 ] ; this . hasMipmaps = header [ 6 ] !== 0 ; for ( let i = 0 ; i < 16 ; i ++ ) { this . mipmapOffsets [ i ] = header [ 7 + i ] ; this . mipmapSizes [ i ] = header [ 23 + i ] ; } this . uint8array = bytes ; if ( this . content === CONTENT_JPG ) { this . jpgHeader = bytes . subarray ( 160 , 160 + header [ 39 ] ) ; } else { this . pallete = bytes . subarray ( 156 , 156 + 1024 ) ; } } getMipmap ( level ) { const uint8array = < Uint8Array > this . uint8array ; const offset = this . mipmapOffsets [ level ] ; const size = this . mipmapSizes [ level ] ; let imageData ; if ( this . content === CONTENT_JPG ) { const jpgHeader = < Uint8Array > this . jpgHeader ; const data = new Uint8Array ( jpgHeader . length + size ) ; const jpegImage = new JpegImage ( ) ; data . set ( jpgHeader ) ; data . set ( uint8array . subarray ( offset , offset + size ) , jpgHeader . length ) ; jpegImage . parse ( data ) ; imageData = new ImageData ( jpegImage . width , jpegImage . height ) ; jpegImage . getData ( imageData ) ; } else { const pallete = < Uint8Array > this . pallete ; const width = Math . max ( this . width / ( 1 << level ) , 1 ) ; const height = Math . max ( this . height / ( 1 << level ) , 1 ) ; const size = width * height ; let alphaBits = this . alphaBits ; let bitStream ; let bitsToByte = 0 ; imageData = new ImageData ( width , height ) ; if ( alphaBits > 0 ) { if ( alphaBits > 8 ) { alphaBits = 8 ; } bitStream = new BitStream ( uint8array . buffer , offset + size , Math . ceil ( ( size * alphaBits ) / 8 ) ) ; bitsToByte = convertBitRange ( alphaBits , 8 ) ; } const data = imageData . data ; for ( let i = 0 ; i < size ; i ++ ) { const dataIndex = i * 4 ; const paletteIndex = uint8array [ offset + i ] * 4 ; data [ dataIndex ] = pallete [ paletteIndex + 2 ] ; data [ dataIndex + 1 ] = pallete [ paletteIndex + 1 ] ; data [ dataIndex + 2 ] = pallete [ paletteIndex ] ; if ( alphaBits > 0 ) { data [ dataIndex + 3 ] = ( < BitStream > bitStream ) . readBits ( alphaBits ) * bitsToByte ; } else { data [ dataIndex + 3 ] = 255 ; } } } return imageData ; } mipmaps ( ) { let mipmaps = 0 ; for ( const size of this . mipmapSizes ) { if ( size > 0 ) { mipmaps += 1 ; } } return mipmaps ; } fakeMipmaps ( ) { const offsets = this . mipmapOffsets ; let mipmaps = 0 ; for ( let i = 0 ; i < 16 ; i ++ ) { const offset = offsets [ i ] ; if ( offset > 0 ) { for ( let j = i + 1 ; j < 16 ; j ++ ) { if ( offset === offsets [ j ] ) { mipmaps += 1 ; break ; } } } } return mipmaps ; } }