QL-Win/QuickLook · error · ArgumentException

1 BPP mask underrun parsing ICNS file

Error message

1 BPP mask underrun parsing ICNS file

What it means

Thrown by IcnsProvider.Apply1BPPMask when the mask data buffer is shorter than expected. For 1-bit-per-pixel ICNS icons the entry packs image data then mask data contiguously; the method computes totalBytes = (W*H+7)/8 and requires maskData.Length >= 2*totalBytes so it can start the mask at offset totalBytes. If the buffer is shorter, the mask underruns and parsing is aborted with ArgumentException.

Source

Thrown at QuickLook.Plugin/QuickLook.Plugin.ImageViewer/AnimatedImage/Providers/IcnsProvider.cs:305

                             (0xffu & imageData[4 * (y * imageType.Width + x) + 3]));

                SetPixel(image, x, y, argb);
            }
    }

    private static void Apply1BPPMask(byte[] maskData, BitmapData image)
    {
        int position;
        int bitsLeft = 0;
        int value = 0;

        // 1 bit icon types have image data followed by mask data in the same entry
        int totalBytes = (image.Width * image.Height + 7) / 8;

        if (maskData.Length >= 2 * totalBytes)
            position = totalBytes;
        else
            throw new ArgumentException("1 BPP mask underrun parsing ICNS file");

        for (int y = 0; y < image.Height; y++)
            for (int x = 0; x < image.Width; x++)
            {
                if (bitsLeft == 0)
                {
                    value = 0xff & maskData[position++];
                    bitsLeft = 8;
                }

                uint alpha;
                alpha = (value & 0x80u) != 0 ? 0xffu : 0x00u;
                value <<= 1;
                bitsLeft--;

                SetPixel(image, x, y, (alpha << 24) | (0xffffffu & GetPixel(image, x, y)));
            }
    }

View on GitHub (pinned to cb5d9c429c)

Solutions

  1. Re-export the ICNS with a spec-compliant tool (iconutil, Axialis, or sips) that writes the full image+mask block.
  2. Pad the mask buffer to 2*totalBytes with zeros before calling Apply1BPPMask so underrun cannot occur.
  3. Catch ArgumentException during ICNS decode and skip the offending icon rather than failing the whole file.
  4. Verify the element's declared length equals the expected bytes for its 1BPP type before decoding.

Example fix

// before
if (maskData.Length >= 2 * totalBytes)
    position = totalBytes;
else
    throw new ArgumentException("1 BPP mask underrun parsing ICNS file");

// after — tolerate a short mask by clamping
position = Math.Min(totalBytes, Math.Max(0, maskData.Length - totalBytes));
Defensive patterns

Strategy: validation

Validate before calling

int totalBytes = (image.Width*image.Height + 7)/8;
bool maskOk = maskData.Length >= 2*totalBytes;
// only call Apply1BPPMask when maskOk; otherwise pad: Array.Resize(ref maskData, 2*totalBytes);

Type guard

static bool HasFull1BppMask(int w, int h, byte[] data) { int t=(w*h+7)/8; return data != null && data.Length >= 2*t; }

Try / catch

try { Apply1BPPMask(maskData, bitmapData); }
catch (ArgumentException) { /* skip mask, keep image */ }

Prevention

When it happens

Trigger: For a 1BPP ICNS type, the element's data array has fewer than 2*ceil(W*H/8) bytes, so the mask half is missing or partial. Occurs with hand-edited, truncated, or non-spec ICNS files where the icon entry was not fully written.

Common situations: An ICNS exported by a tool that omits the mask channel for monochrome icons; a file truncated mid-entry; an icon type misidentified as 1BPP due to a wrong type-code mapping.

Related errors


AI-assisted analysis of QL-Win/QuickLook@cb5d9c429c (2026-08-13). Data as JSON: /api/errors/db57cbde866da744. Report an issue: GitHub.