{"record":{"id":"225cc811e9c41398","repo":"HMCL-dev/HMCL","slug":"valid-greyscale-bit-depths-are-1-2-4-8-not-d","errorCode":null,"errorMessage":"Valid greyscale bit depths are 1, 2, 4, 8, not %d","messagePattern":"Valid greyscale bit depths are 1, 2, 4, 8, not (.+?)","errorType":"exception","errorClass":"PngIntegrityException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/argb8888/Argb8888Palette.java","lineNumber":111,"sourceCode":"                if (null == greyPalette2) {\n                    greyPalette2 = forGreyscale(4, 0x55);\n                }\n                yield greyPalette2;\n            }\n            case 4 -> {\n                if (null == greyPalette4) {\n                    greyPalette4 = forGreyscale(16, 0x11);\n                }\n                yield greyPalette4;\n            }\n            case 8 -> {\n                if (null == greyPalette8) {\n                    greyPalette8 = forGreyscale(256, 0x01);\n                }\n                yield greyPalette8;\n            }\n            default ->\n                    throw new PngIntegrityException(String.format(\"Valid greyscale bit depths are 1, 2, 4, 8, not %d\", bitDepth));\n        };\n    }\n}\n","sourceCodeStart":93,"sourceCodeEnd":115,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/argb8888/Argb8888Palette.java#L93-L115","documentation":"Thrown by Argb8888Palette.forGreyscale as PngIntegrityException when the greyscale bit depth is not one of 1, 2, 4, or 8 — the only depths the PNG spec allows for greyscale images. The palette factory has no ramp for other depths.","triggerScenarios":"Decoding a greyscale PNG whose IHDR declares a bit depth of 3, 5, 6, 7, 16+, or 0 — a corrupt header or a non-conformant file.","commonSituations":"Corrupt or hand-edited PNG headers; crafted images; misparsed chunk data producing a bogus bit-depth value.","solutions":["Re-export or re-download the PNG — a valid greyscale PNG always uses bit depth 1, 2, 4, or 8","Validate IHDR bit depth against the colour type before building palettes","Catch PngIntegrityException and skip/reject the image with a clear diagnostic","Use pngcheck to identify exactly which header field is non-conformant"],"exampleFix":"// before\nArgb8888Palette p = Argb8888Palette.forGreyscale(bitDepth); // throws for 16-bit or odd depths\n// after\nif (bitDepth == 1 || bitDepth == 2 || bitDepth == 4 || bitDepth == 8) {\n    p = Argb8888Palette.forGreyscale(bitDepth);\n} else {\n    throw new PngIntegrityException(\"Unsupported greyscale depth: \" + bitDepth);\n}","handlingStrategy":"validation","validationCode":"if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 && bitDepth != 8) {\n    throw new IllegalArgumentException(\"Unsupported greyscale bit depth: \" + bitDepth);\n}","typeGuard":"static boolean isGreyscaleBitDepth(int depth) {\n    return depth == 1 || depth == 2 || depth == 4 || depth == 8;\n}","tryCatchPattern":"try {\n    palette = Argb8888Palette.forGreyscale(bitDepth);\n} catch (PngIntegrityException e) {\n    throw new IOException(\"Non-conformant PNG bit depth: \" + e.getMessage(), e);\n}","preventionTips":["Cross-check IHDR bit depth against the allowed values per colour type","Reject 16-bit depth inputs up front if you cannot down-convert","Use pngcheck to validate headers of untrusted files","Never hand-edit PNG header bytes; re-export via a tool instead"],"tags":["png","bit-depth","greyscale","validation"],"backgroundTag":"invalid-enum-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"}