fix: png 16bit conversion crash, null guard added to handle if native returns null

This commit is contained in:
JohnE 2026-02-16 13:59:05 -08:00
parent c2f299fd4d
commit a58bec6bae
1 changed files with 29 additions and 3 deletions

View File

@ -212,8 +212,28 @@ final class ImageConverterDarwin implements ImageConverterPlatform {
); );
} }
final bitsPerComponent = CGImageGetBitsPerComponent(originalImage); // FIX: Always use 8 bits per component for the output bitmap context.
final bitmapInfo = CGImageGetBitmapInfo(originalImage); //
// The original code copied bitsPerComponent and bitmapInfo from the
// source CGImage. When the source is a 16-bit PNG, this produces a
// parameter combination that CGBitmapContextCreate does not support
// (e.g. RGB | 16 bits/component | kCGImageByteOrder16Little), causing
// it to return NULL. The subsequent CFRelease(NULL) in the finally
// block then triggers a fatal EXC_BREAKPOINT (brk #0x1).
//
// Since all output formats (JPEG, PNG, HEIC) produce 8-bit images,
// there is no need to create a 16-bit context. CGContextDrawImage()
// automatically downsamples 16-bit source pixels when drawing into
// an 8-bit context.
//
// kCGImageAlphaPremultipliedLast (value 1) is universally supported
// by CGBitmapContextCreate for all RGB colour spaces and correctly
// handles both opaque and transparent source images. For opaque
// output formats like JPEG, the alpha channel is discarded by the
// encoder.
const bitsPerComponent = 8;
// kCGImageAlphaPremultipliedLast = 1
const bitmapInfo = 1;
context = CGBitmapContextCreate( context = CGBitmapContextCreate(
nullptr, nullptr,
@ -251,7 +271,13 @@ final class ImageConverterDarwin implements ImageConverterPlatform {
} }
return resizedImage; return resizedImage;
} finally { } finally {
if (context != null) CFRelease(context.cast()); // FIX: Check both Dart null AND FFI nullptr before releasing.
// The Dart variable `context` is non-null once assigned, but the
// native pointer may be nullptr if CGBitmapContextCreate failed.
// CFRelease(NULL) is a fatal error in CoreFoundation (brk #0x1).
if (context != null && context != nullptr) {
CFRelease(context.cast());
}
} }
} }
} }