{"record":{"id":"91f456c5cab7de6d","repo":"HMCL-dev/HMCL","slug":"invalid-indexed-colour-bit-depth-d","errorCode":null,"errorMessage":"Invalid indexed colour bit-depth: %d","messagePattern":"Invalid indexed colour bit-depth: (.+?)","errorType":"exception","errorClass":"PngIntegrityException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/argb8888/Argb8888Processors.java","lineNumber":72,"sourceCode":"                        return new Greyscale8Alpha(bytesPerScanline, bitmap);\n                    case 16:\n                        return new Greyscale16Alpha(bytesPerScanline, bitmap);\n                    default:\n                        throw new PngIntegrityException(String.format(\"Invalid greyscale-with-alpha bit-depth: %d\", header.bitDepth)); // TODO: should be in header parse.\n                }\n\n            case PNG_INDEXED_COLOUR:\n                switch (header.bitDepth) {\n                    case 1:\n                        return new IndexedColourBits(bytesPerScanline, bitmap, 7, 0x01, PngConstants.SHIFTS_1);\n                    case 2:\n                        return new IndexedColourBits(bytesPerScanline, bitmap, 3, 0x03, PngConstants.SHIFTS_2);\n                    case 4:\n                        return new IndexedColourBits(bytesPerScanline, bitmap, 1, 0x0F, PngConstants.SHIFTS_4);\n                    case 8:\n                        return new IndexedColour8(bytesPerScanline, bitmap);\n                    default:\n                        throw new PngIntegrityException(String.format(\"Invalid indexed colour bit-depth: %d\", header.bitDepth)); // TODO: should be in header parse.\n                }\n\n            case PNG_TRUECOLOUR:\n                switch (header.bitDepth) {\n                    case 8:\n                        return new Truecolour8(bytesPerScanline, bitmap);\n                    case 16:\n                        return new Truecolour16(bytesPerScanline, bitmap);\n                    default:\n                        throw new PngIntegrityException(String.format(\"Invalid truecolour bit-depth: %d\", header.bitDepth)); // TODO: should be in header parse.\n\n                }\n\n            case PNG_TRUECOLOUR_WITH_ALPHA:\n                switch (header.bitDepth) {\n                    case 8:\n                        return new Truecolour8Alpha(bytesPerScanline, bitmap);\n                    case 16:","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/argb8888/Argb8888Processors.java#L54-L90","documentation":"PngIntegrityException thrown when an indexed-colour (colour type 3) PNG declares a bit depth other than the PNG-legal 1, 2, 4, or 8. Indexed colour cannot be 16-bit, so anything outside the four legal values means the IHDR is corrupt or was produced by a broken encoder.","triggerScenarios":"Calling Argb8888Processors.from with a header of colourType PNG_INDEXED_COLOUR and bitDepth not in {1,2,4,8} — notably 16, or garbage values like 0 or 3.","commonSituations":"Fuzzed/corrupted palette PNGs; naive encoders that copy a 16-bit depth byte when converting from RGB; hand-crafted PNG binaries in tests; damaged downloads.","solutions":["Validate IHDR bit depth (1/2/4/8 for indexed colour) during header parsing before constructing processors","Reject the file as structurally invalid","Re-encode the image with a compliant tool to regenerate a correct IHDR","Catch PngIntegrityException and report a corrupt-header error"],"exampleFix":"// before: 16-bit indexed PNG passed straight through\nArgb8888ScanlineProcessor p = Argb8888Processors.from(header, bitmap); // throws for bitDepth=16\n// after: validate colour-type/depth pair first\nif (header.colourType == PngColourType.PNG_INDEXED_COLOUR\n        && !(header.bitDepth == 1 || header.bitDepth == 2 || header.bitDepth == 4 || header.bitDepth == 8)) {\n    throw new PngIntegrityException(\"IHDR bit depth invalid for indexed colour: \" + header.bitDepth);\n}\nArgb8888ScanlineProcessor p = Argb8888Processors.from(header, bitmap);","handlingStrategy":"validation","validationCode":"if (header.colourType == PngColourType.PNG_INDEXED_COLOUR\n        && !(header.bitDepth == 1 || header.bitDepth == 2 || header.bitDepth == 4 || header.bitDepth == 8)) {\n    throw new IllegalArgumentException(\"Invalid indexed bit depth: \" + header.bitDepth);\n}","typeGuard":null,"tryCatchPattern":"try {\n    processor = Argb8888Processors.from(header, bitmap);\n} catch (PngIntegrityException e) {\n    throw new IOException(\"Corrupt PNG IHDR (indexed depth): \" + e.getMessage(), e);\n}","preventionTips":["Remember indexed colour can never be 16-bit — reject at header parse","Re-encode palette PNGs with standard tools when provenance is unknown","Add round-trip tests for all legal colour-type/depth pairs"],"tags":["png","bit-depth","palette","corrupt-file"],"backgroundTag":"invalid-config-value","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}