{"record":{"id":"be5873b6e083a350","repo":"HMCL-dev/HMCL","slug":"unsupported-blendop-at-frame","errorCode":null,"errorMessage":"Unsupported blendOp  at frame ","messagePattern":"Unsupported blendOp  at frame ","errorType":"validation","errorClass":"PngIntegrityException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/ui/image/ImageUtils.java","lineNumber":663,"sourceCode":"                            if (outAlpha == 0) {\n                                outR = outG = outB = 0;\n                            } else {\n                                outR = (srcR * srcAlpha + dstR * dstAlpha * invSrcAlpha / 255 + outAlpha / 2) / outAlpha;\n                                outG = (srcG * srcAlpha + dstG * dstAlpha * invSrcAlpha / 255 + outAlpha / 2) / outAlpha;\n                                outB = (srcB * srcAlpha + dstB * dstAlpha * invSrcAlpha / 255 + outAlpha / 2) / outAlpha;\n                            }\n\n                            outAlpha = Math.min(outAlpha, 255);\n                            outR = Math.min(outR, 255);\n                            outG = Math.min(outG, 255);\n                            outB = Math.min(outB, 255);\n\n                            currentFrameBuffer[dstIndex] = (outAlpha << 24) | (outR << 16) | (outG << 8) | outB;\n                        }\n                    }\n                }\n            } else {\n                throw new PngIntegrityException(\"Unsupported blendOp \" + control.blendOp + \" at frame \" + frameIndex);\n            }\n\n            if (doScale)\n                framePixels[frameIndex] = scale(currentFrameBuffer,\n                        width, height,\n                        targetWidth, targetHeight);\n            else\n                framePixels[frameIndex] = currentFrameBuffer;\n\n            if (control.delayNumerator == 0) {\n                durations[frameIndex] = 10;\n            } else {\n                int durationsMills = 1000 * control.delayNumerator;\n                if (control.delayDenominator == 0)\n                    durationsMills /= 100;\n                else\n                    durationsMills /= control.delayDenominator;\n","sourceCodeStart":645,"sourceCodeEnd":681,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/ui/image/ImageUtils.java#L645-L681","documentation":"Thrown by ImageUtils.toImage as PngIntegrityException when an APNG frame's blend_op is neither APNG_BLEND_OP_SOURCE (0) nor APNG_BLEND_OP_OVER (1). Only those two blend operations are defined by the APNG spec; anything else means a corrupt/invalid chunk.","triggerScenarios":"Decoding an APNG whose fcTL chunk carries a blend_op value other than 0 or 1 (e.g. 2+ from a corrupted or maliciously crafted file).","commonSituations":"Bit-rot or corruption in stored APNG files; crafted test images; outputs of experimental encoders.","solutions":["Re-encode the animation with a standard tool so blend_op is 0 or 1","Replace the file (corruption is the usual cause — no encoder legitimately emits other values)","Catch PngIntegrityException and fall back to a static image or placeholder","Sanity-check chunk fields during parse and reject non-spec APNGs early"],"exampleFix":"// before\nImage anim = ImageUtils.createAnimationFromAPNGApngStream(in);\n// after\ntry {\n    anim = ImageUtils.createAnimationFromAPNGApngStream(in);\n} catch (PngIntegrityException e) {\n    LOG.warning(\"Unsupported APNG feature: \" + e.getMessage());\n    anim = fallbackStaticImage;\n}","handlingStrategy":"try-catch","validationCode":"if (control.blendOp != 0 && control.blendOp != 1) {\n    throw new IllegalArgumentException(\"Non-spec blendOp: \" + control.blendOp);\n}","typeGuard":"static boolean hasKnownBlendOp(PngFrameControl c) {\n    return c.blendOp == 0 || c.blendOp == 1; // SOURCE or OVER\n}","tryCatchPattern":"try {\n    return ImageUtils.toImage(sequence, w, h, ...);\n} catch (PngIntegrityException e) {\n    return defaultImage; // static fallback\n}","preventionTips":["Only accept APNGs from encoders known to emit spec blend ops","Treat unexpected enum values in image chunks as corruption","Keep a static-image fallback path for all animated resources","Re-encode questionable files with ffmpeg before use"],"tags":["apng","unsupported-value","png-validation"],"backgroundTag":"unsupported-enum-value","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}