* Build a PNG with a specific filter type applied to every row. Encodes a * 3×2 RGBA image with unique per-channel values so any cross-channel mistake * in the defilter loop shows up as an assertion failure. * * @param filterType 0=None, 1=Sub, 2=Up, 3=Average, 4=Paeth
(filterType: 0 | 1 | 2 | 3 | 4)
| 184 | * @param filterType 0=None, 1=Sub, 2=Up, 3=Average, 4=Paeth |
| 185 | */ |
| 186 | function makePngWithFilter(filterType: 0 | 1 | 2 | 3 | 4): { |
| 187 | png: Buffer; |
| 188 | expectedPixels: number[]; |
| 189 | } { |
| 190 | const width = 3; |
| 191 | const height = 2; |
| 192 | const bpp = 4; // RGBA, 8-bit |
| 193 | const stride = width * bpp; |
| 194 | |
| 195 | // Unique pixels so any defilter bug is observable |
| 196 | const expectedPixels = [ |
| 197 | 10, 20, 30, 255, 50, 60, 70, 255, 90, 100, 110, 255, 130, 140, 150, 255, 170, 180, 190, 255, |
| 198 | 210, 220, 230, 255, |
| 199 | ]; |
| 200 | |
| 201 | const filtered: number[] = []; |
| 202 | const prev = new Uint8Array(stride); |
| 203 | for (let y = 0; y < height; y++) { |
| 204 | filtered.push(filterType); |
| 205 | const rowStart = y * stride; |
| 206 | const curr = new Uint8Array(stride); |
| 207 | for (let x = 0; x < stride; x++) curr[x] = expectedPixels[rowStart + x] ?? 0; |
| 208 | |
| 209 | const out = new Uint8Array(stride); |
| 210 | for (let x = 0; x < stride; x++) { |
| 211 | const a = x >= bpp ? (curr[x - bpp] ?? 0) : 0; |
| 212 | const b = prev[x] ?? 0; |
| 213 | const c = x >= bpp ? (prev[x - bpp] ?? 0) : 0; |
| 214 | const cv = curr[x] ?? 0; |
| 215 | switch (filterType) { |
| 216 | case 0: |
| 217 | out[x] = cv; |
| 218 | break; |
| 219 | case 1: |
| 220 | out[x] = (cv - a) & 0xff; |
| 221 | break; |
| 222 | case 2: |
| 223 | out[x] = (cv - b) & 0xff; |
| 224 | break; |
| 225 | case 3: |
| 226 | out[x] = (cv - Math.floor((a + b) / 2)) & 0xff; |
| 227 | break; |
| 228 | case 4: |
| 229 | out[x] = (cv - paethRef(a, b, c)) & 0xff; |
| 230 | break; |
| 231 | } |
| 232 | } |
| 233 | for (let x = 0; x < stride; x++) filtered.push(out[x] ?? 0); |
| 234 | prev.set(curr); |
| 235 | } |
| 236 | |
| 237 | const ihdr = Buffer.allocUnsafe(13); |
| 238 | ihdr.writeUInt32BE(width, 0); |
| 239 | ihdr.writeUInt32BE(height, 4); |
| 240 | ihdr[8] = 8; |
| 241 | ihdr[9] = 6; |
| 242 | ihdr[10] = 0; |
| 243 | ihdr[11] = 0; |
no test coverage detected