{"record":{"id":"c5d2b5598938fa15","repo":"d2phap/ImageGlass","slug":"the-image-is-too-large-to-open-fullinfo-width-n0","errorCode":null,"errorMessage":"The image is too large to open: {fullInfo.Width:n0}x{fullInfo.Height:n0} ({megaPixels:n0} MP) needs {(double)fullInfo.Width * fullInfo.Height * fullInfo.BytesPerPixel / 1024 / 1024 / 1024:n2} GB in one buffer, but the renderer cannot address more than 2 GB per image. This format cannot be decoded at a reduced size.","messagePattern":"The image is too large to open: (.+?)x(.+?) \\((.+?) MP\\) needs (.+?) GB in one buffer, but the renderer cannot address more than 2 GB per image\\. This format cannot be decoded at a reduced size\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"source/ImageGlass.Lib/Common/Photoing/Codecs/SkiaCodecs/SkiaCodec.cs","lineNumber":299,"sourceCode":"        var fullInfo = codec.Info;\n        if (FitsInPixelBuffer(fullInfo)) return fullInfo;\n\n        foreach (var candidate in NATIVE_DECODE_SCALES)\n        {\n            var size = codec.GetScaledDimensions(candidate);\n\n            // codecs without native scaling just echo the full size back\n            if (size.Width >= fullInfo.Width || size.Width <= 0 || size.Height <= 0) continue;\n\n            var scaledInfo = fullInfo.WithSize(size.Width, size.Height);\n            if (!FitsInPixelBuffer(scaledInfo)) continue;\n\n            scale = (double)size.Width / fullInfo.Width;\n            return scaledInfo;\n        }\n\n        var megaPixels = (double)fullInfo.Width * fullInfo.Height / 1_000_000;\n        throw new NotSupportedException(\n            $\"The image is too large to open: {fullInfo.Width:n0}x{fullInfo.Height:n0} \"\n            + $\"({megaPixels:n0} MP) needs {(double)fullInfo.Width * fullInfo.Height * fullInfo.BytesPerPixel / 1024 / 1024 / 1024:n2} GB \"\n            + $\"in one buffer, but the renderer cannot address more than 2 GB per image. \"\n            + $\"This format cannot be decoded at a reduced size.\");\n    }\n\n\n    /// <summary>\n    /// Checks whether a full pixel buffer for the info stays within Skia's byte-size ceiling.\n    /// </summary>\n    private static bool FitsInPixelBuffer(SKImageInfo info)\n    {\n        return (long)info.Width * info.Height * info.BytesPerPixel <= MAX_PIXEL_BUFFER_BYTES;\n    }\n\n\n    /// <summary>\n    /// Returns the linear scale that brings a <c>width * height * bytesPerPixel</c> buffer","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/d2phap/ImageGlass/blob/4a3c4feceffc5a8bb5e56ba836509634aaae47a9/source/ImageGlass.Lib/Common/Photoing/Codecs/SkiaCodecs/SkiaCodec.cs#L281-L317","documentation":"Thrown by SkiaCodec.GetDecodableImageInfo when an image's full pixel buffer would exceed int.MaxValue (~2 GB) and no native decode scale fits under the cap. Skia cannot address a single bitmap over 2 GB regardless of free RAM. The method first tries the codec's native scales (JPEG IDCT eighths, largest-first); if none fits it throws NotSupportedException listing width, height, megapixels, and the required buffer size in GB. Non-JPEG codecs echo the full size back, so they cannot scale and always hit this path on large inputs.","triggerScenarios":"Opening a very large non-JPEG image (PNG, TIFF, BMP) whose full buffer exceeds 2 GB, e.g. a 30k x 30k RGBA PNG (~3.6 GB); a JPEG so large that even 1/8 decode exceeds 2 GB.","commonSituations":"Scientific stitching/microscopy TIFFs; print-resolution artwork exported as PNG; satellite imagery; large scanned documents saved as uncompressed BMP/TIFF.","solutions":["Pre-process the file in an external tool to downsample or crop it below the 2 GB buffer ceiling before opening.","Convert the source to JPEG so Skia can use native IDCT scaling (1/8...7/8) and decode a reduced size.","Split multi-page TIFFs and open a single page, or tile the image.","For formats ImageGlass routes through Magick, rely on the in-place resize path which lands closer to the ceiling."],"exampleFix":"// before\nvar photo = await Core.Photos.LoadAsync(hugePngPath);\n\n// after\n// downsample offline first, e.g. via Magick.NET:\n// using var m = new MagickImage(hugePngPath);\n// m.Resize(8000, 8000); m.Write(smallerJpgPath);\nvar photo = await Core.Photos.LoadAsync(smallerJpgPath);","handlingStrategy":"validation","validationCode":"long EstimateBufferBytes(string path)\n{\n    using var c = SKCodec.Create(path);\n    var info = c.Info;\n    return (long)info.Width * info.Height * info.BytesPerPixel;\n}\n// if EstimateBufferBytes(path) > int.MaxValue and the codec is not JPEG, expect this throw","typeGuard":null,"tryCatchPattern":"try { photo = await Core.Photos.LoadAsync(path); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"too large to open\"))\n{ /* prompt user to downsample or convert to JPEG */ }","preventionTips":["Downsample or crop very large non-JPEG images in an external tool first.","Convert huge sources to JPEG so Skia can use native IDCT scaling.","Remember the ceiling is int.MaxValue bytes per buffer, not free RAM."],"tags":["codec","skia","memory","large-image","decode"],"backgroundTag":null,"analyzedSha":"4a3c4feceffc5a8bb5e56ba836509634aaae47a9","analyzedAt":"2026-08-13T16:58:15.523Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}