Compare commits

..

1 Commits
main ... j3g

1 changed files with 29 additions and 3 deletions

View File

@ -212,8 +212,28 @@ final class ImageConverterDarwin implements ImageConverterPlatform {
);
}
final bitsPerComponent = CGImageGetBitsPerComponent(originalImage);
final bitmapInfo = CGImageGetBitmapInfo(originalImage);
// FIX: Always use 8 bits per component for the output bitmap context.
//
// 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(
nullptr,
@ -251,7 +271,13 @@ final class ImageConverterDarwin implements ImageConverterPlatform {
}
return resizedImage;
} 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());
}
}
}
}