import IImageData from '../model/IImageData' ; import PixelImage from '../model/PixelImage' ; import Pixels from '../model/Pixels' ; import ColorMap from '../model/ColorMap' ; import Quantizer from './Quantizer' ; export default class Converter { private readonly quantizer : Quantizer ; constructor ( quantizer ) { this . quantizer = quantizer ; } public convert ( imageData , pixelImage ) { const unrestrictedImage = this . quantizer . quantizeImage ( imageData ) ; pixelImage . colorMaps . forEach ( ( map , index ) => { Converter . extractColorMap ( unrestrictedImage , map , index , pixelImage ) ; } ) ; for ( let y = 0 ; y < pixelImage . mode . height ; y += 1 ) { for ( let x = 0 ; x < pixelImage . mode . width ; x += 1 ) { if ( pixelImage . pixelIndex [ y ] [ x ] === undefined ) { this . mapToExistingColorMap ( pixelImage , x , y , Pixels . peek ( imageData , x , y ) ) ; } } } } private mapToExistingColorMap ( image , x , y , realColor ) { let closestMap = 0 ; let minDistance ; for ( let i = 0 ; i < image . colorMaps . length ; i ++ ) { const paletteIndex = image . colorMaps [ i ] . get ( x , y ) ; if ( paletteIndex !== undefined ) { const distance = this . quantizer . distance ( realColor , paletteIndex ) ; if ( minDistance === undefined || distance < minDistance ) { minDistance = distance ; closestMap = i ; } } } image . pixelIndex [ y ] [ x ] = closestMap ; } private static reduceToMax ( colors ) { const weights = [ ] ; let maxWeight ; let maxColor ; colors . forEach ( c => { weights [ c ] = weights [ c ] === undefined ? 1 : weights [ c ] + 1 ; if ( maxWeight === undefined || weights [ c ] > maxWeight ) { maxWeight = weights [ c ] ; maxColor = c ; } } ) ; return maxColor ; } private static extractColorMap ( quantizedImage , toColorMap , colorMapIndex , pixelImage ) { const imageWidth = pixelImage . mode . width ; toColorMap . forEachCell ( ( x , y ) => { const colorIndices = [ ] ; if ( toColorMap . get ( x , y ) === undefined ) { toColorMap . forEachPixelInCell ( x , y , ( xx , yy ) => { if ( quantizedImage [ xx + yy * imageWidth ] !== undefined ) { colorIndices . push ( quantizedImage [ xx + yy * imageWidth ] ) ; } } ) ; if ( colorIndices . length > 0 ) { const winner = this . reduceToMax ( colorIndices ) ; toColorMap . put ( x , y , winner ) ; toColorMap . forEachPixelInCell ( x , y , ( xx , yy ) => { if ( quantizedImage [ xx + yy * imageWidth ] === winner ) { quantizedImage [ xx + yy * imageWidth ] = undefined ; pixelImage . pixelIndex [ yy ] [ xx ] = colorMapIndex ; } } ) ; } } } ) ; } }