HMCL-dev/HMCL · error · PngFeatureException
ARGB8888 doesn't support PNG mode
Error message
ARGB8888 doesn't support PNG mode
What it means
PngFeatureException thrown when the PNG colour type is not one of the five standard types the ARGB8888 backend handles (0, 2, 3, 4, 6). Any other/unrecognized colourType value falls through the switch's default branch and is rejected as an unsupported feature rather than a corrupt file.
Solutions
- Use a decoder backend that supports the image's colour type, or convert the image to a standard type (e.g. RGBA 8-bit) before decoding
- Validate the IHDR colour type against {0,2,3,4,6} during header parsing and reject nonstandard values early
- Re-encode the image with a mainstream tool to normalize the colour type
- Catch PngFeatureException and route to an alternative decoder or show a 'format not supported' message
Example fix
// before: unsupported colour type byte 7 decoded directly
Argb8888ScanlineProcessor p = Argb8888Processors.from(header, bitmap); // throws
// after: pre-validate and convert if needed
int typeByte = header.colourType.ordinal(); // or raw value
if (typeByte != 0 && typeByte != 2 && typeByte != 3 && typeByte != 4 && typeByte != 6) {
header = convertToRgba8(header, bitmap); // or reject the file
}
Argb8888ScanlineProcessor p = Argb8888Processors.from(header, bitmap); Defensive patterns
Strategy: try-catch
Validate before calling
int t = header.colourTypeValue();
if (t != 0 && t != 2 && t != 3 && t != 4 && t != 6) {
throw new IllegalArgumentException("Nonstandard PNG colour type: " + t);
} Type guard
boolean isStandardColourType(PngHeader header) {
switch (header.colourType) {
case PNG_GREYSCALE:
case PNG_TRUECOLOUR:
case PNG_INDEXED_COLOUR:
case PNG_GREYSCALE_WITH_ALPHA:
case PNG_TRUECOLOUR_WITH_ALPHA:
return true;
default:
return false;
}
} Try / catch
try {
processor = Argb8888Processors.from(header, bitmap);
} catch (PngFeatureException e) {
// unknown colour type: try generic decoder or notify 'format not supported'
processor = genericDecoderFactory.from(header, bitmap);
} Prevention
- Reject nonstandard colour-type bytes at header parse time
- Keep an alternative decoder path for exotic PNG variants
- Constrain the enum parse so unknown bytes cannot become colourType values
- Re-encode unusual images with mainstream tools before ingestion
When it happens
Trigger: Calling Argb8888Processors.from with a header whose colourType is not one of PNG_GREYSCALE, PNG_TRUECOLOUR, PNG_INDEXED_COLOUR, PNG_GREYSCALE_WITH_ALPHA, PNG_TRUECOLOUR_WITH_ALPHA — e.g. a newly added or nonstandard colour-type byte.
Common situations: PNG files with reserved or future colour-type values; memory-corrupted IHDR colour byte that still looks like a type enum; custom extended PNG variants; enum deserialization producing an unexpected constant.
Related errors
- Greyscale supports 1, 2, 4, 8 but not 16.
- Indexed images (colour type ) cannot have bitdepth > 8 (bit…
- Interlaced images are not yet supported
- Valid PNG colour types are 0, 2, 3, 4, 6. Type
- Valid greyscale bit depths are 1, 2, 4, 8, not
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/972b5bdb7f7fd15c.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/argb8888/Argb8888Processors.java:98
return new Truecolour16(bytesPerScanline, bitmap);
default:
throw new PngIntegrityException(String.format("Invalid truecolour bit-depth: %d", header.bitDepth)); // TODO: should be in header parse.
}
case PNG_TRUECOLOUR_WITH_ALPHA:
switch (header.bitDepth) {
case 8:
return new Truecolour8Alpha(bytesPerScanline, bitmap);
case 16:
return new Truecolour16Alpha(bytesPerScanline, bitmap);
default:
throw new PngIntegrityException(String.format("Invalid truecolour with alpha bit-depth: %d", header.bitDepth)); // TODO: should be in header parse.
}
default:
throw new PngFeatureException("ARGB8888 doesn't support PNG mode " + header.colourType.name());
}
}
/**
* Transforms 1-, 2-, 4-bit indexed colour source pixels to ARGB8888 pixels.
*/
public static class IndexedColourBits extends Argb8888ScanlineProcessor {
private int highBit;
private int mask;
private byte[] shifts;
public IndexedColourBits(int bytesPerScanline, Argb8888Bitmap bitmap, int highBit, int mask, byte[] shifts) {
this(bytesPerScanline, bitmap, highBit, mask, shifts, null);
}
public IndexedColourBits(int bytesPerScanline, Argb8888Bitmap bitmap, int highBit, int mask, byte[] shifts, Argb8888Palette palette) {
super(bytesPerScanline, bitmap);View on GitHub (pinned to 24702dc5a0)