png-palette 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/PNGPaletteImage.cjs +2 -0
- package/dist/PNGPaletteImage.cjs.map +1 -0
- package/dist/PNGPaletteImage.d.cts +29 -0
- package/dist/PNGPaletteImage.d.ts +29 -0
- package/dist/PNGPaletteImage.js +2 -0
- package/dist/PNGPaletteImage.js.map +1 -0
- package/package.json +55 -0
- package/readme.md +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rychellos
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var P=Object.create;var g=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var v=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var R=(a,t)=>{for(var e in t)g(a,e,{get:t[e],enumerable:!0})},x=(a,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of k(t))!E.call(a,n)&&n!==e&&g(a,n,{get:()=>t[n],enumerable:!(r=I(t,n))||r.enumerable});return a};var C=(a,t,e)=>(e=a!=null?P(v(a)):{},x(t||!a||!a.__esModule?g(e,"default",{value:a,enumerable:!0}):e,a)),T=a=>x(g({},"__esModule",{value:!0}),a);var N={};R(N,{PNGPaletteImage:()=>U});module.exports=T(N);var A=C(require("pako"),1),D=C(require("crc-32"),1),U=class a{constructor(t,e,r=256){this.width=t;this.height=e;this.maxColors=r;this.pixels=new Uint8Array(t*e)}palette=[];transparency=[];pixels;static fromPngBytes(t){let e=new DataView(t.buffer,t.byteOffset,t.byteLength);if(t[0]!==137||t[1]!==80||t[2]!==78||t[3]!==71)throw new Error("Not a PNG file");let r=0,n=0,h=[],u=[],b=[],o=8;for(;o<t.length;){let s=e.getUint32(o,!1),p=String.fromCharCode(t[o+4],t[o+5],t[o+6],t[o+7]),w=t.subarray(o+8,o+8+s);if(p==="IHDR")r=e.getUint32(o+8,!1),n=e.getUint32(o+12,!1);else if(p==="PLTE")for(let c=0;c<s/3;c++)h[c]={r:w[c*3],g:w[c*3+1],b:w[c*3+2]};else if(p==="tRNS")for(let c=0;c<s;c++)u[c]=w[c];else if(p==="IDAT")b.push(w);else if(p==="IEND")break;o+=12+s}if(r===0||n===0)throw new Error("Invalid PNG: Missing IHDR");let f=new a(r,n,256);f.palette=h,f.transparency=u;let y=b.reduce((s,p)=>s+p.length,0),m=new Uint8Array(y),d=0;for(let s of b)m.set(s,d),d+=s.length;let i=A.default.inflate(m),l=r+1;for(let s=0;s<n;s++){let p=i[s*l],w=i.subarray(s*l+1,s*l+1+r);f.pixels.set(w,s*r)}return f}setPaletteColor(t,e,r,n){if(t<0||t>=this.maxColors)throw new Error(`Palette index ${t} out of bounds`);this.palette[t]={r:e,g:r,b:n}}getPaletteColor(t){return this.palette[t]}setTransparency(t,e){if(t<0||t>=this.maxColors)throw new Error(`Transparency index ${t} out of bounds`);this.transparency[t]=e}getTransparency(t){return this.transparency[t]}setPixelPaletteIndex(t,e,r){t<0||t>=this.width||e<0||e>=this.height||(this.pixels[e*this.width+t]=r)}getPixelPaletteIndex(t,e){return t<0||t>=this.width||e<0||e>=this.height?0:this.pixels[e*this.width+t]}encodeToPngBytes(){let t=new Uint8Array([137,80,78,71,13,10,26,10]),e=new Uint8Array(13),r=new DataView(e.buffer);r.setUint32(0,this.width,!1),r.setUint32(4,this.height,!1),e[8]=8,e[9]=3;let n=this.createChunk("IHDR",e),h=new Uint8Array(this.maxColors*3);for(let i=0;i<this.maxColors;i++){let l=this.palette[i]||{r:0,g:0,b:0};h[i*3]=l.r,h[i*3+1]=l.g,h[i*3+2]=l.b}let u=this.createChunk("PLTE",h),b=null;if(this.transparency.length>0){let i=new Uint8Array(this.maxColors);i.fill(255);for(let l=0;l<this.maxColors;l++)this.transparency[l]!==void 0&&(i[l]=this.transparency[l]);b=this.createChunk("tRNS",i)}let o=this.width+1,f=new Uint8Array(this.height*o);for(let i=0;i<this.height;i++)f[i*o]=0,f.set(this.pixels.subarray(i*this.width,(i+1)*this.width),i*o+1);let y=this.createChunk("IDAT",A.default.deflate(f)),m=this.createChunk("IEND",new Uint8Array(0)),d=[t,n,u];return b&&d.push(b),d.push(y,m),this.concat(d)}createChunk(t,e){let r=new Uint8Array(12+e.length),n=new DataView(r.buffer);n.setUint32(0,e.length,!1);for(let u=0;u<4;u++)r[4+u]=t.charCodeAt(u);r.set(e,8);let h=D.default.buf(r.subarray(4,8+e.length));return n.setInt32(8+e.length,h,!1),r}concat(t){let e=new Uint8Array(t.reduce((n,h)=>n+h.length,0)),r=0;for(let n of t)e.set(n,r),r+=n.length;return e}};0&&(module.exports={PNGPaletteImage});
|
|
2
|
+
//# sourceMappingURL=PNGPaletteImage.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/PNGPaletteImage.ts"],"sourcesContent":["import pako from 'pako';\nimport CRC32 from 'crc-32';\n\nexport interface RGB {\n r: number;\n g: number;\n b: number;\n}\n\nexport class PNGPaletteImage {\n private palette: RGB[] = [];\n private transparency: number[] = [];\n private pixels: Uint8Array;\n\n constructor(\n public readonly width: number,\n public readonly height: number,\n public readonly maxColors: number = 256\n ) {\n this.pixels = new Uint8Array(width * height);\n }\n\n /**\n * Creates a PNGPaletteImage from a PNG file byte array.\n */\n public static fromPngBytes(bytes: Uint8Array): PNGPaletteImage {\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n if (bytes[0] !== 0x89 || bytes[1] !== 0x50 || bytes[2] !== 0x4E || bytes[3] !== 0x47) {\n throw new Error('Not a PNG file');\n }\n\n let width = 0;\n let height = 0;\n let rawPalette: RGB[] = [];\n let rawTransparency: number[] = [];\n let idatChunks: Uint8Array[] = [];\n\n let pos = 8;\n while (pos < bytes.length) {\n const length = view.getUint32(pos, false);\n const type = String.fromCharCode(bytes[pos + 4]!, bytes[pos + 5]!, bytes[pos + 6]!, bytes[pos + 7]!);\n const data = bytes.subarray(pos + 8, pos + 8 + length);\n\n if (type === 'IHDR') {\n width = view.getUint32(pos + 8, false);\n height = view.getUint32(pos + 12, false);\n } else if (type === 'PLTE') {\n for (let i = 0; i < length / 3; i++) {\n rawPalette[i] = { r: data[i * 3]!, g: data[i * 3 + 1]!, b: data[i * 3 + 2]! };\n }\n } else if (type === 'tRNS') {\n for (let i = 0; i < length; i++) {\n rawTransparency[i] = data[i]!;\n }\n } else if (type === 'IDAT') {\n idatChunks.push(data);\n } else if (type === 'IEND') {\n break;\n }\n\n pos += 12 + length;\n }\n\n if (width === 0 || height === 0) throw new Error('Invalid PNG: Missing IHDR');\n\n const img = new PNGPaletteImage(width, height, 256);\n img.palette = rawPalette;\n img.transparency = rawTransparency;\n\n const totalIdatLen = idatChunks.reduce((acc, chunk) => acc + chunk.length, 0);\n const combinedIdat = new Uint8Array(totalIdatLen);\n let idatPos = 0;\n for (const chunk of idatChunks) {\n combinedIdat.set(chunk, idatPos);\n idatPos += chunk.length;\n }\n\n const inflated = pako.inflate(combinedIdat);\n const stride = width + 1;\n for (let y = 0; y < height; y++) {\n // Internal parser unfiltering (Manual Logic)\n // Since we use Filter Type 0 in our encoder, we skip unfiltering complexity for now.\n // But we MUST support Filter 0 correctly by skipping the first byte of each row.\n const filterType = inflated[y * stride];\n const rowData = inflated.subarray(y * stride + 1, y * stride + 1 + width);\n if (filterType === 0) {\n img.pixels.set(rowData, y * width);\n } else {\n // Warning: other filter types not yet robustly supported for external files.\n img.pixels.set(rowData, y * width);\n }\n }\n\n return img;\n }\n\n public setPaletteColor(index: number, r: number, g: number, b: number): void {\n if (index < 0 || index >= this.maxColors) throw new Error(`Palette index ${index} out of bounds`);\n this.palette[index] = { r, g, b };\n }\n\n public getPaletteColor(index: number): RGB | undefined {\n return this.palette[index];\n }\n\n public setTransparency(index: number, alpha: number): void {\n if (index < 0 || index >= this.maxColors) throw new Error(`Transparency index ${index} out of bounds`);\n this.transparency[index] = alpha;\n }\n\n public getTransparency(index: number): number | undefined {\n return this.transparency[index];\n }\n\n public setPixelPaletteIndex(x: number, y: number, colorIndex: number): void {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) return;\n this.pixels[y * this.width + x] = colorIndex;\n }\n\n public getPixelPaletteIndex(x: number, y: number): number {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) return 0;\n return this.pixels[y * this.width + x]!;\n }\n\n public encodeToPngBytes(): Uint8Array {\n const signature = new Uint8Array([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);\n const ihdrData = new Uint8Array(13);\n const ihdrView = new DataView(ihdrData.buffer);\n ihdrView.setUint32(0, this.width, false);\n ihdrView.setUint32(4, this.height, false);\n ihdrData[8] = 8; ihdrData[9] = 3;\n const ihdr = this.createChunk('IHDR', ihdrData);\n\n const plteData = new Uint8Array(this.maxColors * 3);\n for (let i = 0; i < this.maxColors; i++) {\n const color = this.palette[i] || { r: 0, g: 0, b: 0 };\n plteData[i * 3] = color.r;\n plteData[i * 3 + 1] = color.g;\n plteData[i * 3 + 2] = color.b;\n }\n const plte = this.createChunk('PLTE', plteData);\n\n let trns: Uint8Array | null = null;\n if (this.transparency.length > 0) {\n const trnsData = new Uint8Array(this.maxColors);\n trnsData.fill(255);\n for (let i = 0; i < this.maxColors; i++) {\n if (this.transparency[i] !== undefined) trnsData[i] = this.transparency[i]!;\n }\n trns = this.createChunk('tRNS', trnsData);\n }\n\n const stride = this.width + 1;\n const idatData = new Uint8Array(this.height * stride);\n for (let y = 0; y < this.height; y++) {\n idatData[y * stride] = 0;\n idatData.set(this.pixels.subarray(y * this.width, (y + 1) * this.width), y * stride + 1);\n }\n const idat = this.createChunk('IDAT', pako.deflate(idatData));\n const iend = this.createChunk('IEND', new Uint8Array(0));\n\n const chunks = [signature, ihdr, plte];\n if (trns) chunks.push(trns);\n chunks.push(idat, iend);\n return this.concat(chunks);\n }\n\n private createChunk(type: string, data: Uint8Array): Uint8Array {\n const chunk = new Uint8Array(12 + data.length);\n const view = new DataView(chunk.buffer);\n view.setUint32(0, data.length, false);\n for (let i = 0; i < 4; i++) chunk[4 + i] = type.charCodeAt(i);\n chunk.set(data, 8);\n const crc = CRC32.buf(chunk.subarray(4, 8 + data.length));\n view.setInt32(8 + data.length, crc, false);\n return chunk;\n }\n\n private concat(arrays: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(arrays.reduce((a, b) => a + b.length, 0));\n let off = 0;\n for (const a of arrays) { out.set(a, off); off += a.length; }\n return out;\n }\n}\n"],"mappings":"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","names":["PNGPaletteImage_exports","__export","PNGPaletteImage","__toCommonJS","import_pako","import_crc_32","_PNGPaletteImage","width","height","maxColors","bytes","view","rawPalette","rawTransparency","idatChunks","pos","length","type","data","i","img","totalIdatLen","acc","chunk","combinedIdat","idatPos","inflated","pako","stride","y","filterType","rowData","index","r","g","b","alpha","x","colorIndex","signature","ihdrData","ihdrView","ihdr","plteData","color","plte","trns","trnsData","idatData","idat","iend","chunks","crc","CRC32","arrays","out","a","off"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface RGB {
|
|
2
|
+
r: number;
|
|
3
|
+
g: number;
|
|
4
|
+
b: number;
|
|
5
|
+
}
|
|
6
|
+
declare class PNGPaletteImage {
|
|
7
|
+
readonly width: number;
|
|
8
|
+
readonly height: number;
|
|
9
|
+
readonly maxColors: number;
|
|
10
|
+
private palette;
|
|
11
|
+
private transparency;
|
|
12
|
+
private pixels;
|
|
13
|
+
constructor(width: number, height: number, maxColors?: number);
|
|
14
|
+
/**
|
|
15
|
+
* Creates a PNGPaletteImage from a PNG file byte array.
|
|
16
|
+
*/
|
|
17
|
+
static fromPngBytes(bytes: Uint8Array): PNGPaletteImage;
|
|
18
|
+
setPaletteColor(index: number, r: number, g: number, b: number): void;
|
|
19
|
+
getPaletteColor(index: number): RGB | undefined;
|
|
20
|
+
setTransparency(index: number, alpha: number): void;
|
|
21
|
+
getTransparency(index: number): number | undefined;
|
|
22
|
+
setPixelPaletteIndex(x: number, y: number, colorIndex: number): void;
|
|
23
|
+
getPixelPaletteIndex(x: number, y: number): number;
|
|
24
|
+
encodeToPngBytes(): Uint8Array;
|
|
25
|
+
private createChunk;
|
|
26
|
+
private concat;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { PNGPaletteImage, type RGB };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface RGB {
|
|
2
|
+
r: number;
|
|
3
|
+
g: number;
|
|
4
|
+
b: number;
|
|
5
|
+
}
|
|
6
|
+
declare class PNGPaletteImage {
|
|
7
|
+
readonly width: number;
|
|
8
|
+
readonly height: number;
|
|
9
|
+
readonly maxColors: number;
|
|
10
|
+
private palette;
|
|
11
|
+
private transparency;
|
|
12
|
+
private pixels;
|
|
13
|
+
constructor(width: number, height: number, maxColors?: number);
|
|
14
|
+
/**
|
|
15
|
+
* Creates a PNGPaletteImage from a PNG file byte array.
|
|
16
|
+
*/
|
|
17
|
+
static fromPngBytes(bytes: Uint8Array): PNGPaletteImage;
|
|
18
|
+
setPaletteColor(index: number, r: number, g: number, b: number): void;
|
|
19
|
+
getPaletteColor(index: number): RGB | undefined;
|
|
20
|
+
setTransparency(index: number, alpha: number): void;
|
|
21
|
+
getTransparency(index: number): number | undefined;
|
|
22
|
+
setPixelPaletteIndex(x: number, y: number, colorIndex: number): void;
|
|
23
|
+
getPixelPaletteIndex(x: number, y: number): number;
|
|
24
|
+
encodeToPngBytes(): Uint8Array;
|
|
25
|
+
private createChunk;
|
|
26
|
+
private concat;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { PNGPaletteImage, type RGB };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import g from"pako";import U from"crc-32";var y=class A{constructor(t,e,r=256){this.width=t;this.height=e;this.maxColors=r;this.pixels=new Uint8Array(t*e)}palette=[];transparency=[];pixels;static fromPngBytes(t){let e=new DataView(t.buffer,t.byteOffset,t.byteLength);if(t[0]!==137||t[1]!==80||t[2]!==78||t[3]!==71)throw new Error("Not a PNG file");let r=0,s=0,l=[],c=[],w=[],a=8;for(;a<t.length;){let i=e.getUint32(a,!1),f=String.fromCharCode(t[a+4],t[a+5],t[a+6],t[a+7]),p=t.subarray(a+8,a+8+i);if(f==="IHDR")r=e.getUint32(a+8,!1),s=e.getUint32(a+12,!1);else if(f==="PLTE")for(let h=0;h<i/3;h++)l[h]={r:p[h*3],g:p[h*3+1],b:p[h*3+2]};else if(f==="tRNS")for(let h=0;h<i;h++)c[h]=p[h];else if(f==="IDAT")w.push(p);else if(f==="IEND")break;a+=12+i}if(r===0||s===0)throw new Error("Invalid PNG: Missing IHDR");let u=new A(r,s,256);u.palette=l,u.transparency=c;let m=w.reduce((i,f)=>i+f.length,0),d=new Uint8Array(m),b=0;for(let i of w)d.set(i,b),b+=i.length;let n=g.inflate(d),o=r+1;for(let i=0;i<s;i++){let f=n[i*o],p=n.subarray(i*o+1,i*o+1+r);u.pixels.set(p,i*r)}return u}setPaletteColor(t,e,r,s){if(t<0||t>=this.maxColors)throw new Error(`Palette index ${t} out of bounds`);this.palette[t]={r:e,g:r,b:s}}getPaletteColor(t){return this.palette[t]}setTransparency(t,e){if(t<0||t>=this.maxColors)throw new Error(`Transparency index ${t} out of bounds`);this.transparency[t]=e}getTransparency(t){return this.transparency[t]}setPixelPaletteIndex(t,e,r){t<0||t>=this.width||e<0||e>=this.height||(this.pixels[e*this.width+t]=r)}getPixelPaletteIndex(t,e){return t<0||t>=this.width||e<0||e>=this.height?0:this.pixels[e*this.width+t]}encodeToPngBytes(){let t=new Uint8Array([137,80,78,71,13,10,26,10]),e=new Uint8Array(13),r=new DataView(e.buffer);r.setUint32(0,this.width,!1),r.setUint32(4,this.height,!1),e[8]=8,e[9]=3;let s=this.createChunk("IHDR",e),l=new Uint8Array(this.maxColors*3);for(let n=0;n<this.maxColors;n++){let o=this.palette[n]||{r:0,g:0,b:0};l[n*3]=o.r,l[n*3+1]=o.g,l[n*3+2]=o.b}let c=this.createChunk("PLTE",l),w=null;if(this.transparency.length>0){let n=new Uint8Array(this.maxColors);n.fill(255);for(let o=0;o<this.maxColors;o++)this.transparency[o]!==void 0&&(n[o]=this.transparency[o]);w=this.createChunk("tRNS",n)}let a=this.width+1,u=new Uint8Array(this.height*a);for(let n=0;n<this.height;n++)u[n*a]=0,u.set(this.pixels.subarray(n*this.width,(n+1)*this.width),n*a+1);let m=this.createChunk("IDAT",g.deflate(u)),d=this.createChunk("IEND",new Uint8Array(0)),b=[t,s,c];return w&&b.push(w),b.push(m,d),this.concat(b)}createChunk(t,e){let r=new Uint8Array(12+e.length),s=new DataView(r.buffer);s.setUint32(0,e.length,!1);for(let c=0;c<4;c++)r[4+c]=t.charCodeAt(c);r.set(e,8);let l=U.buf(r.subarray(4,8+e.length));return s.setInt32(8+e.length,l,!1),r}concat(t){let e=new Uint8Array(t.reduce((s,l)=>s+l.length,0)),r=0;for(let s of t)e.set(s,r),r+=s.length;return e}};export{y as PNGPaletteImage};
|
|
2
|
+
//# sourceMappingURL=PNGPaletteImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/PNGPaletteImage.ts"],"sourcesContent":["import pako from 'pako';\nimport CRC32 from 'crc-32';\n\nexport interface RGB {\n r: number;\n g: number;\n b: number;\n}\n\nexport class PNGPaletteImage {\n private palette: RGB[] = [];\n private transparency: number[] = [];\n private pixels: Uint8Array;\n\n constructor(\n public readonly width: number,\n public readonly height: number,\n public readonly maxColors: number = 256\n ) {\n this.pixels = new Uint8Array(width * height);\n }\n\n /**\n * Creates a PNGPaletteImage from a PNG file byte array.\n */\n public static fromPngBytes(bytes: Uint8Array): PNGPaletteImage {\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n if (bytes[0] !== 0x89 || bytes[1] !== 0x50 || bytes[2] !== 0x4E || bytes[3] !== 0x47) {\n throw new Error('Not a PNG file');\n }\n\n let width = 0;\n let height = 0;\n let rawPalette: RGB[] = [];\n let rawTransparency: number[] = [];\n let idatChunks: Uint8Array[] = [];\n\n let pos = 8;\n while (pos < bytes.length) {\n const length = view.getUint32(pos, false);\n const type = String.fromCharCode(bytes[pos + 4]!, bytes[pos + 5]!, bytes[pos + 6]!, bytes[pos + 7]!);\n const data = bytes.subarray(pos + 8, pos + 8 + length);\n\n if (type === 'IHDR') {\n width = view.getUint32(pos + 8, false);\n height = view.getUint32(pos + 12, false);\n } else if (type === 'PLTE') {\n for (let i = 0; i < length / 3; i++) {\n rawPalette[i] = { r: data[i * 3]!, g: data[i * 3 + 1]!, b: data[i * 3 + 2]! };\n }\n } else if (type === 'tRNS') {\n for (let i = 0; i < length; i++) {\n rawTransparency[i] = data[i]!;\n }\n } else if (type === 'IDAT') {\n idatChunks.push(data);\n } else if (type === 'IEND') {\n break;\n }\n\n pos += 12 + length;\n }\n\n if (width === 0 || height === 0) throw new Error('Invalid PNG: Missing IHDR');\n\n const img = new PNGPaletteImage(width, height, 256);\n img.palette = rawPalette;\n img.transparency = rawTransparency;\n\n const totalIdatLen = idatChunks.reduce((acc, chunk) => acc + chunk.length, 0);\n const combinedIdat = new Uint8Array(totalIdatLen);\n let idatPos = 0;\n for (const chunk of idatChunks) {\n combinedIdat.set(chunk, idatPos);\n idatPos += chunk.length;\n }\n\n const inflated = pako.inflate(combinedIdat);\n const stride = width + 1;\n for (let y = 0; y < height; y++) {\n // Internal parser unfiltering (Manual Logic)\n // Since we use Filter Type 0 in our encoder, we skip unfiltering complexity for now.\n // But we MUST support Filter 0 correctly by skipping the first byte of each row.\n const filterType = inflated[y * stride];\n const rowData = inflated.subarray(y * stride + 1, y * stride + 1 + width);\n if (filterType === 0) {\n img.pixels.set(rowData, y * width);\n } else {\n // Warning: other filter types not yet robustly supported for external files.\n img.pixels.set(rowData, y * width);\n }\n }\n\n return img;\n }\n\n public setPaletteColor(index: number, r: number, g: number, b: number): void {\n if (index < 0 || index >= this.maxColors) throw new Error(`Palette index ${index} out of bounds`);\n this.palette[index] = { r, g, b };\n }\n\n public getPaletteColor(index: number): RGB | undefined {\n return this.palette[index];\n }\n\n public setTransparency(index: number, alpha: number): void {\n if (index < 0 || index >= this.maxColors) throw new Error(`Transparency index ${index} out of bounds`);\n this.transparency[index] = alpha;\n }\n\n public getTransparency(index: number): number | undefined {\n return this.transparency[index];\n }\n\n public setPixelPaletteIndex(x: number, y: number, colorIndex: number): void {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) return;\n this.pixels[y * this.width + x] = colorIndex;\n }\n\n public getPixelPaletteIndex(x: number, y: number): number {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) return 0;\n return this.pixels[y * this.width + x]!;\n }\n\n public encodeToPngBytes(): Uint8Array {\n const signature = new Uint8Array([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);\n const ihdrData = new Uint8Array(13);\n const ihdrView = new DataView(ihdrData.buffer);\n ihdrView.setUint32(0, this.width, false);\n ihdrView.setUint32(4, this.height, false);\n ihdrData[8] = 8; ihdrData[9] = 3;\n const ihdr = this.createChunk('IHDR', ihdrData);\n\n const plteData = new Uint8Array(this.maxColors * 3);\n for (let i = 0; i < this.maxColors; i++) {\n const color = this.palette[i] || { r: 0, g: 0, b: 0 };\n plteData[i * 3] = color.r;\n plteData[i * 3 + 1] = color.g;\n plteData[i * 3 + 2] = color.b;\n }\n const plte = this.createChunk('PLTE', plteData);\n\n let trns: Uint8Array | null = null;\n if (this.transparency.length > 0) {\n const trnsData = new Uint8Array(this.maxColors);\n trnsData.fill(255);\n for (let i = 0; i < this.maxColors; i++) {\n if (this.transparency[i] !== undefined) trnsData[i] = this.transparency[i]!;\n }\n trns = this.createChunk('tRNS', trnsData);\n }\n\n const stride = this.width + 1;\n const idatData = new Uint8Array(this.height * stride);\n for (let y = 0; y < this.height; y++) {\n idatData[y * stride] = 0;\n idatData.set(this.pixels.subarray(y * this.width, (y + 1) * this.width), y * stride + 1);\n }\n const idat = this.createChunk('IDAT', pako.deflate(idatData));\n const iend = this.createChunk('IEND', new Uint8Array(0));\n\n const chunks = [signature, ihdr, plte];\n if (trns) chunks.push(trns);\n chunks.push(idat, iend);\n return this.concat(chunks);\n }\n\n private createChunk(type: string, data: Uint8Array): Uint8Array {\n const chunk = new Uint8Array(12 + data.length);\n const view = new DataView(chunk.buffer);\n view.setUint32(0, data.length, false);\n for (let i = 0; i < 4; i++) chunk[4 + i] = type.charCodeAt(i);\n chunk.set(data, 8);\n const crc = CRC32.buf(chunk.subarray(4, 8 + data.length));\n view.setInt32(8 + data.length, crc, false);\n return chunk;\n }\n\n private concat(arrays: Uint8Array[]): Uint8Array {\n const out = new Uint8Array(arrays.reduce((a, b) => a + b.length, 0));\n let off = 0;\n for (const a of arrays) { out.set(a, off); off += a.length; }\n return out;\n }\n}\n"],"mappings":"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","names":["pako","CRC32","PNGPaletteImage","_PNGPaletteImage","width","height","maxColors","bytes","view","rawPalette","rawTransparency","idatChunks","pos","length","type","data","i","img","totalIdatLen","acc","chunk","combinedIdat","idatPos","inflated","stride","y","filterType","rowData","index","r","g","b","alpha","x","colorIndex","signature","ihdrData","ihdrView","ihdr","plteData","color","plte","trns","trnsData","idatData","idat","iend","chunks","crc","arrays","out","a","off"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "png-palette",
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "Small library to work with palette based pngs.",
|
|
5
|
+
"main": "dist/PNGPaletteImage.cjs",
|
|
6
|
+
"module": "dist/PNGPaletteImage.js",
|
|
7
|
+
"types": "dist/PNGPaletteImage.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/PNGPaletteImage.d.ts",
|
|
12
|
+
"import": "./dist/PNGPaletteImage.js",
|
|
13
|
+
"require": "./dist/PNGPaletteImage.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"png",
|
|
27
|
+
"color-palette"
|
|
28
|
+
],
|
|
29
|
+
"author": "Rychellos",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/Rychellos/png-palette.git"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/Rychellos/png-palette/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/Rychellos/png-palette#readme",
|
|
39
|
+
"packageManager": "pnpm@10.7.1",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"crc-32": "^1.2.2",
|
|
42
|
+
"pako": "^2.1.0",
|
|
43
|
+
"upng-js": "^2.1.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^25.1.0",
|
|
47
|
+
"@types/pako": "^2.0.4",
|
|
48
|
+
"@types/upng-js": "^2.1.5",
|
|
49
|
+
"@vitest/ui": "^4.0.18",
|
|
50
|
+
"ts-node": "^10.9.2",
|
|
51
|
+
"tsup": "^8.5.1",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
|
+
"vitest": "^4.0.18"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# PNG palette library (`png-palette`)
|
|
2
|
+
|
|
3
|
+
Small library to help working with palette based PNGs. It provides low-level control over the `PLTE` (Palette) and `tRNS` (Transparency) chunks, making it ideal for creating indexed-color images directly.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Palette Control**: Easily set and get RGB colors in the palette.
|
|
8
|
+
- **Transparency Support**: Set alpha values for individual palette indices via the `tRNS` chunk.
|
|
9
|
+
- **Efficient Encoding/Decoding**: Fast round-trip between raw bytes and a manipulatable image object.
|
|
10
|
+
- **Minimal Dependencies**: Lightweight with only `pako` for compression and `crc-32` for integrity checks.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install png-palette
|
|
16
|
+
# or
|
|
17
|
+
pnpm add png-palette
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Programmatic Usage
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { PNGPaletteImage } from "png-palette";
|
|
24
|
+
import * as fs from "fs";
|
|
25
|
+
|
|
26
|
+
// 1. Create a new 10x10 image
|
|
27
|
+
const img = new PNGPaletteImage(10, 10);
|
|
28
|
+
|
|
29
|
+
// 2. Define colors in the palette
|
|
30
|
+
img.setPaletteColor(0, 255, 255, 255); // Index 0: White
|
|
31
|
+
img.setPaletteColor(1, 255, 0, 0); // Index 1: Red
|
|
32
|
+
img.setPaletteColor(2, 0, 0, 255); // Index 2: Blue
|
|
33
|
+
|
|
34
|
+
// 3. Set transparency (optional)
|
|
35
|
+
img.setTransparency(0, 0); // Index 0 is fully transparent
|
|
36
|
+
|
|
37
|
+
// 4. Draw pixels using palette indices
|
|
38
|
+
for (let y = 0; y < 10; y++) {
|
|
39
|
+
for (let x = 0; x < 10; x++) {
|
|
40
|
+
img.setPixelPaletteIndex(x, y, (x + y) % 2 === 0 ? 1 : 2);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 5. Encode to PNG bytes
|
|
45
|
+
const pngBytes = img.encodeToPngBytes();
|
|
46
|
+
|
|
47
|
+
// 6. Save to a file
|
|
48
|
+
fs.writeFileSync("output.png", pngBytes);
|
|
49
|
+
|
|
50
|
+
// 7. Load from existing bytes
|
|
51
|
+
const loadedImg = PNGPaletteImage.fromPngBytes(pngBytes);
|
|
52
|
+
console.log(`Loaded image size: ${loadedImg.width}x${loadedImg.height}`);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Development
|
|
56
|
+
|
|
57
|
+
### Build
|
|
58
|
+
```bash
|
|
59
|
+
npm run build
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Run Tests
|
|
63
|
+
```bash
|
|
64
|
+
npm test
|
|
65
|
+
```
|