Skip to content

Commit

Permalink
fix: use createBackupCGContext in cgImageWithFixedOrientation (#414)
Browse files Browse the repository at this point in the history
convert 10-bit image to 16-bit image to preserve accuracy
  • Loading branch information
guoyingtao authored Oct 13, 2024
1 parent 40ad916 commit 3430aaf
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@
ReferencedContainer = "container:MantisExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "CGBITMAP_CONTEXT_LOG_ERRORS"
value = "1"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
37 changes: 25 additions & 12 deletions Sources/Mantis/Extensions/CGImageExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,7 @@ extension CGImage {
space: colorSpaceRef,
bitmapInfo: bitmapInfoData)
??
CGContext(data: nil,
width: Int(round(outputSize.width)),
height: Int(round(outputSize.height)),
bitsPerComponent: bitsPerComponent,
bytesPerRow: bitmapBytesPerRow,
space: colorSpaceRef,
bitmapInfo: getBackupBitmapInfo(colorSpaceRef))
createBackupCGContext(size: outputSize, bitmapBytesPerRow: bitsPerComponent, colorSpaceRef: colorSpaceRef)

guard let context = context else {
throw ImageProcessError.failedToBuildContext(colorSpaceModel: colorSpaceRef.model,
Expand Down Expand Up @@ -86,6 +80,29 @@ extension CGImage {
return context.makeImage()
}

func createBackupCGContext(size: CGSize,
bitmapBytesPerRow: Int = 0,
colorSpaceRef: CGColorSpace) -> CGContext? {
var actualBitsPerComponent = bitsPerComponent
var actualBitmapBytesPerRow = bitmapBytesPerRow

/* Convert a 10-bit image to a 16-bit image to preserve accuracy.
Since we haven't successfully created a 10-bit image CGContext yet, we're temporarily using this method.
*/
if (32, 10) == (bitsPerPixel, bitsPerComponent) {
actualBitsPerComponent = 16
actualBitmapBytesPerRow = Int(round(size.width)) * 8
}

return CGContext(data: nil,
width: Int(round(size.width)),
height: Int(round(size.height)),
bitsPerComponent: actualBitsPerComponent,
bytesPerRow: actualBitmapBytesPerRow,
space: colorSpaceRef,
bitmapInfo: getBackupBitmapInfo(colorSpaceRef))
}

/**
Just in case the bitmapInfo from original image is not supported by CGContext, we will use this backup bitmapInfo instead.
*/
Expand All @@ -100,11 +117,7 @@ extension CGImage {
case (32, 8), (64, 16):
return CGImageAlphaInfo.premultipliedLast.rawValue
case (32, 10):
if #available(iOS 12, macOS 10.14, *) {
return CGImageAlphaInfo.alphaOnly.rawValue | CGImagePixelFormatInfo.RGBCIF10.rawValue
} else {
break
}
return CGImageAlphaInfo.premultipliedLast.rawValue
case (128, 32):
return CGImageAlphaInfo.premultipliedLast.rawValue | (bitmapInfo.rawValue & CGBitmapInfo.floatComponents.rawValue)
default:
Expand Down
14 changes: 10 additions & 4 deletions Sources/Mantis/Extensions/UIImageExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extension UIImage {
if imageOrientation == .up {
return cgImage
}

guard let cgImage = cgImage, let colorSpace = cgImage.colorSpace else {
return nil
}
Expand Down Expand Up @@ -49,16 +49,22 @@ extension UIImage {
break
}

guard let context = CGContext(
var context = CGContext(
data: nil,
width: Int(width),
height: Int(height),
bitsPerComponent: cgImage.bitsPerComponent,
bytesPerRow: 0,
space: colorSpace,
bitmapInfo: UInt32(cgImage.bitmapInfo.rawValue)
) else {
return nil
)

if context == nil {
context = cgImage.createBackupCGContext(size: size, bitmapBytesPerRow: 0, colorSpaceRef: colorSpace)
}

guard let context else {
return nil
}

context.concatenate(transform)
Expand Down

0 comments on commit 3430aaf

Please sign in to comment.