HMCL-dev/HMCL · error · PngIntegrityException

Illegal to have tRNS chunk with image type

Error message

Illegal to have tRNS chunk with image type 

What it means

PngIntegrityException thrown when a tRNS chunk is present for a colour type that must not carry one: greyscale-with-alpha (4), truecolour-with-alpha (6), or any unrecognized colour type. Per the PNG spec, images whose samples already include an alpha channel are fully transparent-capable, so tRNS is illegal. The processor rejects this as an integrity violation.

Solutions

  1. Remove the tRNS chunk from the PNG (e.g. with pngcrush -rem trns or an image editor re-save)
  2. If transparency is needed, encode the alpha directly in the image's alpha channel instead of tRNS
  3. Verify the IHDR colour type matches the chunk set produced by the encoder
  4. Catch PngIntegrityException and treat the file as invalid or strip transparency

Example fix

// before: tRNS chunk kept on a RGBA (colour type 6) image
pngWriter.writeChunk("tRNS", trnsData); // processor throws
// after: drop tRNS for alpha-channel colour types
if (colourType != GREYSCALE_WITH_ALPHA && colourType != TRUECOLOUR_WITH_ALPHA) {
    pngWriter.writeChunk("tRNS", trnsData);
}
Defensive patterns

Strategy: validation

Validate before calling

if ((header.colourType == PngColourType.PNG_GREYSCALE_WITH_ALPHA
        || header.colourType == PngColourType.PNG_TRUECOLOUR_WITH_ALPHA)
        && chunkPresent("tRNS")) {
    throw new IllegalArgumentException("tRNS is illegal for alpha-channel colour types");
}

Type guard

boolean tRnsAllowed(PngHeader header) {
    return header.colourType == PngColourType.PNG_GREYSCALE
        || header.colourType == PngColourType.PNG_TRUECOLOUR
        || header.colourType == PngColourType.PNG_INDEXED_COLOUR;
}

Try / catch

try {
    processor.processTransparency(bytes, position, length);
} catch (PngIntegrityException e) {
    LOG.warn("Illegal tRNS for image type, skipping: " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling processTransparency on an Argb8888Processor when header.colourType is PNG_GREYSCALE_WITH_ALPHA or PNG_TRUECOLOUR_WITH_ALPHA, or falls into the default branch with an unknown colour type.

Common situations: PNG files edited to add an alpha channel while retaining a legacy tRNS chunk; broken encoders emitting tRNS for RGBA images; files converted from palette to RGBA with chunks copied over verbatim.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/216813c440262eae. Report an issue: GitHub.

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/image/apng/argb8888/Argb8888Processor.java:88

                }
                builder.processTransparentGreyscale(bytes[0], bytes[1]);
                break;

            case PNG_TRUECOLOUR: // colour type 2
                // red, green, blue samples, EACH with two bytes (16-bits)
                builder.processTransparentTruecolour(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]);
                break;

            case PNG_INDEXED_COLOUR: // colour type 3
                // This is a sequence of one-byte alpha values to apply to each palette entry starting at zero.
                // The number of entries may be less than the size of the palette, but not more.
                builder.processTransparentPalette(bytes, position, length);
                break;

            case PNG_GREYSCALE_WITH_ALPHA:
            case PNG_TRUECOLOUR_WITH_ALPHA:
            default:
                throw new PngIntegrityException("Illegal to have tRNS chunk with image type " + header.colourType.name);
        }
    }

    /**
     * The only supported animation type is not "NOT_ANIMATED".
     */
//    @Override
//    public PngAnimationType chooseApngImageType(PngAnimationType type, PngFrameControl currentFrame) throws PngException {
//        scanlineProcessor = Argb8888ScanlineProcessor.from(header, scanlineReader, currentFrame);
//        return PngAnimationType.NOT_ANIMATED;
//    }
    @Override
    public void processDefaultImageData(InputStream inputStream, PngChunkCode code, int position, int length) throws IOException, PngException {
        if (!builder.wantDefaultImage()) {
            inputStream.skip(length); // important!
            return;
        }

View on GitHub (pinned to 24702dc5a0)