From 24005d0790239ee2ce7cf733be9686fb20d320f9 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Fri, 24 Jul 2026 00:31:51 +0200 Subject: [PATCH] fix: label iOS pixel format correctly for default byte order CGImage's .orderDefault byte order has big-endian semantics: the components are stored in memory in the order alphaInfo names them (for example premultipliedLast + orderDefault is physically [R, G, B, A]). It is a property of the Core Graphics format description, not the host CPU's endianness. getPixelFormat treated .orderDefault as little-endian, so toRawPixelData reported reversed pixel format labels for ImageIO-decoded images (such as PNG/JPEG loads). Treat .orderDefault as big-endian so the reported label matches the physical bytes. --- .../ios/Extensions/CGImage+getPixelFormat.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/react-native-nitro-image/ios/Extensions/CGImage+getPixelFormat.swift b/packages/react-native-nitro-image/ios/Extensions/CGImage+getPixelFormat.swift index d5376cc7..a43812c8 100644 --- a/packages/react-native-nitro-image/ios/Extensions/CGImage+getPixelFormat.swift +++ b/packages/react-native-nitro-image/ios/Extensions/CGImage+getPixelFormat.swift @@ -12,8 +12,11 @@ extension CGImage { private var isLittleEndian: Bool { switch self.byteOrderInfo { case .orderDefault: - // iOS uses little endian by default - return true + // The "default" byte order has big-endian semantics: components are stored + // in memory in exactly the order alphaInfo names them - e.g. premultipliedLast + // + orderDefault is physically [R, G, B, A] bytes. This is a property of the + // Core Graphics format description, unrelated to the host CPU's endianness. + return false case .order16Little, .order32Little: return true case .order16Big, .order32Big: @@ -37,10 +40,12 @@ extension CGImage { // ___A return self.isLittleEndian ? .abgr : .rgba case .noneSkipFirst: - // X___ + // X___ - the padding byte is reported as alpha on purpose: Apple's decoders + // and renderers fill it with 0xFF, so the bytes read correctly as opaque alpha, + // and consumers don't need to special-case the X formats. return self.isLittleEndian ? .bgra : .argb case .noneSkipLast: - // ___X + // ___X - see above, reported as alpha on purpose. return self.isLittleEndian ? .abgr : .rgba case .none: // ___