{"record":{"id":"39b8de79ccde4854","repo":"HMCL-dev/HMCL","slug":"invalid-greyscale-with-alpha-bit-depth-d","errorCode":null,"errorMessage":"Invalid greyscale-with-alpha bit-depth: %d","messagePattern":"Invalid greyscale-with-alpha 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":58,"sourceCode":"                        return new IndexedColourBits(bytesPerScanline, bitmap, 1, 0x0F, PngConstants.SHIFTS_4, Argb8888Palette.forGreyscale(4));\n                    case 8:\n                        return new Greyscale8(bytesPerScanline, bitmap);\n                    case 16:\n                        throw new PngFeatureException(\"Greyscale supports 1, 2, 4, 8 but not 16.\");\n                    default:\n                        throw new PngIntegrityException(String.format(\"Invalid greyscale bit-depth: %d\", header.bitDepth)); // TODO: should be in header parse.\n                }\n\n            case PNG_GREYSCALE_WITH_ALPHA:\n                switch (header.bitDepth) {\n                    case 4:\n                        return new Greyscale4Alpha(bytesPerScanline, bitmap);\n                    case 8:\n                        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) {","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/argb8888/Argb8888Processors.java#L40-L76","documentation":"PngIntegrityException thrown when a greyscale-with-alpha (colour type 4) PNG declares a bit depth other than the legal 8 or 16. Note the factory accepts a 4-bit case here but the switch's default still catches any other unsupported value. It signals a malformed IHDR rather than an unsupported feature.","triggerScenarios":"Calling Argb8888Processors.from with a header of colourType PNG_GREYSCALE_WITH_ALPHA and bitDepth not in {4,8,16} — e.g. 1, 2, or any garbage value.","commonSituations":"Fuzzed or corrupted PNG headers; hand-written PNG generators writing wrong depth bytes; files damaged in transit; test fixtures with deliberately invalid IHDR values.","solutions":["Validate IHDR bit depth against the colour type before decoding (legal for type 4: 8 and 16 per PNG spec)","Reject the file as corrupt at header-parse time","Re-export or re-obtain the image from a reliable encoder","Catch PngIntegrityException and report the invalid header to the caller"],"exampleFix":"// before: unchecked header\nArgb8888ScanlineProcessor p = Argb8888Processors.from(header, bitmap); // throws for bitDepth=2\n// after: guard before construction\nSet<Integer> legal = Set.of(8, 16);\nif (header.colourType == PngColourType.PNG_GREYSCALE_WITH_ALPHA && !legal.contains(header.bitDepth)) {\n    throw new PngIntegrityException(\"IHDR bit depth invalid for greyscale+alpha: \" + header.bitDepth);\n}\nArgb8888ScanlineProcessor p = Argb8888Processors.from(header, bitmap);","handlingStrategy":"validation","validationCode":"if (header.colourType == PngColourType.PNG_GREYSCALE_WITH_ALPHA\n        && !(header.bitDepth == 8 || header.bitDepth == 16)) {\n    throw new IllegalArgumentException(\"Invalid greyscale+alpha 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: \" + e.getMessage(), e);\n}","preventionTips":["Enforce the spec's colour-type/bit-depth matrix during header parsing","Sanitize third-party images before ingestion","Log and reject rather than attempting best-effort decode of corrupt headers"],"tags":["png","bit-depth","corrupt-file","header-validation"],"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"}