SubtitleEdit/subtitleedit · error · InvalidOperationException

Could not decode image

Error message

Could not decode image

What it means

Thrown by Helper.ResizeImageAsync when SKBitmap.Decode returns null for the input buffer. A null bitmap means SkiaSharp could not decode the bytes into a raster — the data is not a supported/valid image, or the native codec for that format is missing. This fires during the downscale step used to fit images into Lens's 1000x1000 limit.

Source

Thrown at src/ui/Logic/Ocr/GoogleLens/Helper.cs:18

using SkiaSharp;
using System;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;

namespace Nikse.SubtitleEdit.Logic.Ocr.GoogleLens;

internal class Helper
{
    public static async Task<byte[]> ResizeImageAsync(byte[] buffer, int maxWidth, int maxHeight)
    {
        using var inputStream = new MemoryStream(buffer);
        using var original = SKBitmap.Decode(inputStream);
        
        if (original == null)
        {
            throw new InvalidOperationException("Could not decode image");
        }

        // Calculate new dimensions maintaining aspect ratio
        float ratioX = (float)maxWidth / original.Width;
        float ratioY = (float)maxHeight / original.Height;
        float ratio = Math.Min(ratioX, ratioY);
        
        int newWidth = (int)(original.Width * ratio);
        int newHeight = (int)(original.Height * ratio);

        using var resized = original.Resize(new SKImageInfo(newWidth, newHeight), new SKSamplingOptions(SKFilterMode.Linear, SKMipmapMode.Linear));
        if (resized == null)
        {
            throw new InvalidOperationException("Could not resize image");
        }
            
        using var image = SKImage.FromBitmap(resized);
        using var data = image.Encode(SKEncodedImageFormat.Jpeg, 90);

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Validate/decode the image upstream (SKBitmap.Decode) and skip OCR if null.
  2. Re-export the image as standard sRGB PNG/JPEG.
  3. Ensure SkiaSharp native assets match the runtime/OS.
  4. Catch InvalidOperationException and fall back to the original bytes or skip resize.

Example fix

// before
var resized = await Helper.ResizeImageAsync(buffer, 1000, 1000);

// after
using var test = SKBitmap.Decode(new MemoryStream(buffer));
if (test == null) throw new InvalidDataException("Image cannot be decoded");
var resized = await Helper.ResizeImageAsync(buffer, 1000, 1000);
Defensive patterns

Strategy: validation

Validate before calling

using var probe = SKBitmap.Decode(new MemoryStream(buffer));
if (probe == null) throw new InvalidDataException("Image cannot be decoded by SkiaSharp");

Type guard

static bool IsDecodable(byte[] b) { using var bmp = SKBitmap.Decode(new MemoryStream(b)); return bmp != null; }

Try / catch

try { var resized = await Helper.ResizeImageAsync(buffer, 1000, 1000); }
catch (InvalidOperationException ex) when (ex.Message == "Could not decode image") { /* skip or re-export */ }

Prevention

When it happens

Trigger: ResizeImageAsync is called with a corrupt, truncated, or unsupported-format byte array (the earlier SKCodec.Create may have succeeded but full decode fails, or the path was reached with a different buffer).

Common situations: A partially downloaded image; a format whose codec is absent in the deployed SkiaSharp native binaries; a CMYK JPEG or exotic colorspace SkiaSharp refuses; a zero-length buffer.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/7bb6db83018dea09. Report an issue: GitHub.