{"record":{"id":"49b1698257d367d4","repo":"siyuan-note/siyuan","slug":"decode-heif-image-w","errorCode":null,"errorMessage":"decode HEIF image: %w","messagePattern":"decode HEIF image: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/heif/convert.go","lineNumber":198,"sourceCode":"\t\t\terr = fmt.Errorf(\"decode HEIF image: %v\", recovered)\n\t\t}\n\t}()\n\n\tconfig, err := goheic.DecodeConfigBytes(source)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read HEIF image dimensions: %w\", err)\n\t}\n\tif !validDimensions(config.Width, config.Height) {\n\t\treturn nil, ErrImageTooLarge\n\t}\n\n\timg, err = goheic.DecodeBytes(source, goheic.Options{\n\t\tAutoRotate:     true,\n\t\tFrameSizeLimit: maxPixels,\n\t\tThreads:        1,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"decode HEIF image: %w\", err)\n\t}\n\treturn img, nil\n}\n\nfunc validDimensions(width, height int) bool {\n\treturn width > 0 && height > 0 && width <= maxDimension && height <= maxDimension &&\n\t\tuint64(width)*uint64(height) <= uint64(maxPixels)\n}\n\nfunc estimatedJPEGSize(img image.Image) int {\n\tpixels := int64(img.Bounds().Dx()) * int64(img.Bounds().Dy())\n\testimate := pixels / 2\n\tif estimate < 64*1024 {\n\t\testimate = 64 * 1024\n\t}\n\tif estimate > 32*1024*1024 {\n\t\testimate = 32 * 1024 * 1024\n\t}","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/heif/convert.go#L180-L216","documentation":"This wraps a failure from goheic.DecodeBytes, the full pixel decode of the HEIF image (with auto-rotation, a frame size limit of maxPixels, and single-threaded decode). Unlike the config-stage error, the header parsed fine but the actual HEVC/AV1 image data could not be decoded — unsupported profile, corrupt slice data, missing tiles, or decoder resource limits.","triggerScenarios":"convert or ImageSize on a file whose headers parse (DecodeConfigBytes succeeds) but whose image payload fails: unsupported 12-bit/HDR profile, alpha/layer features not implemented, corrupt slice NAL data, or grid images with missing tiles.","commonSituations":"ProHDR / 10-bit+ iPhone photos using profiles the decoder lacks; HEIFs with depth/auxiliary layers; files damaged after the header region; images exceeding the platform FrameSizeLimit.","solutions":["Check the wrapped cause to distinguish unsupported-profile from corrupt-data","Re-acquire the file; if it decodes in Preview.app/another viewer, report it as a decoder capability gap","Convert the photo to JPEG/HEIF-8-bit externally before importing","Lower expectations for very large images — reduce dimensions at capture, since maxPixels caps decode size"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"cfg, err := h265heic.DecodeConfigBytes(data)\nif err == nil && cfg.Width*cfg.Height > platformPixelBudget() {\n\treturn errors.New(\"image exceeds platform pixel budget\")\n}","typeGuard":null,"tryCatchPattern":"img, err := convert(ctx, data, mode)\nif err != nil && strings.Contains(err.Error(), \"decode HEIF image:\") {\n\treturn externalConvert(data, mode) // system HEIF toolchain\n}","preventionTips":["Maintain a fallback decoder path for profiles the internal decoder lacks (10/12-bit, HDR, layers)","Pre-convert exotic HEIFs at import time via an external tool","Keep FrameSizeLimit aligned with the platform budget and pre-filter oversized images","Log the wrapped cause to distinguish profile gaps from data corruption"],"tags":["heif","decode-failure","codec","unsupported-profile"],"backgroundTag":"unsupported-operation","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}