| 1802 | }; |
| 1803 | |
| 1804 | function encodeAndDownloadGif(pImg, filename) { |
| 1805 | const props = pImg.gifProperties; |
| 1806 | |
| 1807 | //convert loopLimit back into Netscape Block formatting |
| 1808 | let loopLimit = props.loopLimit; |
| 1809 | if (loopLimit === 1) { |
| 1810 | loopLimit = null; |
| 1811 | } else if (loopLimit === null) { |
| 1812 | loopLimit = 0; |
| 1813 | } |
| 1814 | const buffer = new Uint8Array(pImg.width * pImg.height * props.numFrames); |
| 1815 | |
| 1816 | const allFramesPixelColors = []; |
| 1817 | |
| 1818 | // Used to determine the occurrence of unique palettes and the frames |
| 1819 | // which use them |
| 1820 | const paletteFreqsAndFrames = {}; |
| 1821 | |
| 1822 | // Pass 1: |
| 1823 | //loop over frames and get the frequency of each palette |
| 1824 | for (let i = 0; i < props.numFrames; i++) { |
| 1825 | const paletteSet = new Set(); |
| 1826 | const data = props.frames[i].image.data; |
| 1827 | const dataLength = data.length; |
| 1828 | // The color for each pixel in this frame ( for easier lookup later ) |
| 1829 | const pixelColors = new Uint32Array(pImg.width * pImg.height); |
| 1830 | for (let j = 0, k = 0; j < dataLength; j += 4, k++) { |
| 1831 | const r = data[j + 0]; |
| 1832 | const g = data[j + 1]; |
| 1833 | const b = data[j + 2]; |
| 1834 | const color = (r << 16) | (g << 8) | (b << 0); |
| 1835 | paletteSet.add(color); |
| 1836 | |
| 1837 | // What color does this pixel have in this frame ? |
| 1838 | pixelColors[k] = color; |
| 1839 | } |
| 1840 | |
| 1841 | // A way to put use the entire palette as an object key |
| 1842 | const paletteStr = [...paletteSet].sort().toString(); |
| 1843 | if (paletteFreqsAndFrames[paletteStr] === undefined) { |
| 1844 | paletteFreqsAndFrames[paletteStr] = { freq: 1, frames: [i] }; |
| 1845 | } else { |
| 1846 | paletteFreqsAndFrames[paletteStr].freq += 1; |
| 1847 | paletteFreqsAndFrames[paletteStr].frames.push(i); |
| 1848 | } |
| 1849 | |
| 1850 | allFramesPixelColors.push(pixelColors); |
| 1851 | } |
| 1852 | |
| 1853 | let framesUsingGlobalPalette = []; |
| 1854 | |
| 1855 | // Now to build the global palette |
| 1856 | // Sort all the unique palettes in descending order of their occurrence |
| 1857 | const palettesSortedByFreq = Object.keys(paletteFreqsAndFrames).sort(function( |
| 1858 | a, |
| 1859 | b |
| 1860 | ) { |
| 1861 | return paletteFreqsAndFrames[b].freq - paletteFreqsAndFrames[a].freq; |