Skip to content

Commit

Permalink
fix: update the logic of getting bitmapInfo to honor the original alp…
Browse files Browse the repository at this point in the history
…ha channel information (#360)

* fix: simplify getBitmapInfo to honor the original alpha settings

It might be simplified further. TBD

* fix: use bitmapInfo from original image first, then set up custom bitmapInfo if it does not work

to honor the original image setting first

* chore: add / update some comments
  • Loading branch information
guoyingtao committed Nov 21, 2023
1 parent 167e8b0 commit f3180fe
Showing 1 changed file with 53 additions and 35 deletions.
88 changes: 53 additions & 35 deletions Sources/Mantis/Extensions/CGImageExtensions.swift
Expand Up @@ -13,7 +13,9 @@ import UIKit

enum ImageProcessError: Error {
case noColorSpace
case failedToBuildContext(colorSpaceModel: CGColorSpaceModel, bitsPerPixel: Int, bitsPerComponent: Int)
case failedToBuildContext(colorSpaceModel: CGColorSpaceModel,
bitsPerPixel: Int,
bitsPerComponent: Int)
}

extension CGImage {
Expand All @@ -32,51 +34,38 @@ extension CGImage {

var bitmapBytesPerRow = 0

var bitmapInfoData = bitmapInfo.rawValue
/*
for Indexed Color Image (or Palette-based Image)
we output the edited image with RGBA format
*/
we output the edited image with RGB format
*/
if bitsPerPixel == 8 && bitsPerComponent == 8 {
bitmapBytesPerRow = Int(round(outputSize.width)) * 4
bitmapInfoData = CGImageAlphaInfo.noneSkipLast.rawValue
}

func getBitmapInfo() -> UInt32 {
if colorSpaceRef.model == .rgb {
switch(bitsPerPixel, bitsPerComponent) {
case (16, 5):
return CGImageAlphaInfo.noneSkipFirst.rawValue
case (24, 8), (48, 16):
return CGImageAlphaInfo.noneSkipLast.rawValue
case (8, 8), (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
}
case (128, 32):
return CGImageAlphaInfo.premultipliedLast.rawValue | (bitmapInfo.rawValue & CGBitmapInfo.floatComponents.rawValue)
default:
break
}
}

return bitmapInfo.rawValue
}
let context = CGContext(data: nil,
width: Int(round(outputSize.width)),
height: Int(round(outputSize.height)),
bitsPerComponent: bitsPerComponent,
bytesPerRow: bitmapBytesPerRow,
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))

guard let context = CGContext(data: nil,
width: Int(round(outputSize.width)),
height: Int(round(outputSize.height)),
bitsPerComponent: bitsPerComponent,
bytesPerRow: bitmapBytesPerRow,
space: colorSpaceRef,
bitmapInfo: getBitmapInfo()) else {
guard let context = context else {
throw ImageProcessError.failedToBuildContext(colorSpaceModel: colorSpaceRef.model,
bitsPerPixel: bitsPerPixel,
bitsPerComponent: bitsPerComponent)
}

context.setFillColor(UIColor.clear.cgColor)
context.fill(CGRect(origin: .zero, size: outputSize))

Expand All @@ -96,4 +85,33 @@ extension CGImage {

return context.makeImage()
}

/**
Just in case the bitmapInfo from original image is not supported by CGContext, we will use this backup bitmapInfo instead.
*/
private func getBackupBitmapInfo(_ colorSpaceRef: CGColorSpace) -> UInt32 {
// https://developer.apple.com/forums/thread/679891
if colorSpaceRef.model == .rgb {
switch(bitsPerPixel, bitsPerComponent) {
case (16, 5):
return CGImageAlphaInfo.noneSkipFirst.rawValue
case (24, 8), (48, 16):
return CGImageAlphaInfo.noneSkipLast.rawValue
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
}
case (128, 32):
return CGImageAlphaInfo.premultipliedLast.rawValue | (bitmapInfo.rawValue & CGBitmapInfo.floatComponents.rawValue)
default:
break
}
}

return bitmapInfo.rawValue
}
}

0 comments on commit f3180fe

Please sign in to comment.