Sfoglia il codice sorgente

Do not trust image color space and bitmap info

Force use an alpha based rgb
onevcat 1 anno fa
parent
commit
e4d98dc8d8
1 ha cambiato i file con 22 aggiunte e 28 eliminazioni
  1. 22 28
      Sources/Image/ImageDrawing.swift

+ 22 - 28
Sources/Image/ImageDrawing.swift

@@ -303,7 +303,7 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
     /// > This method is only applicable to CG-based images. The current image scale is preserved.
     /// > For any non-CG-based image, the `base` image itself is returned.
     public func blurred(withRadius radius: CGFloat) -> KFCrossPlatformImage {
-        guard let cgImage = cgImage, let colorSpace = cgImage.colorSpace else {
+        guard let cgImage = cgImage else {
             assertionFailure("[Kingfisher] Blur only works for CG-based image.")
             return base
         }
@@ -332,21 +332,26 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
             iterations = 3
         }
         
-        let inProvider = cgImage.dataProvider
+        func createEffectBuffer(_ context: CGContext) -> vImage_Buffer {
+            let data = context.data
+            let width = vImagePixelCount(context.width)
+            let height = vImagePixelCount(context.height)
+            let rowBytes = context.bytesPerRow
+            
+            return vImage_Buffer(data: data, height: height, width: width, rowBytes: rowBytes)
+        }
         
-        let width = vImagePixelCount(cgImage.width)
-        let height = vImagePixelCount(cgImage.height)
-        let rowBytes = cgImage.bytesPerRow
-
-        let inBitmapData = inProvider?.data
+        guard let inputContext = CGContext.fresh(cgImage: cgImage) else {
+            return base
+        }
+        inputContext.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
+        var inBuffer = createEffectBuffer(inputContext)
 
-        let inData = UnsafeMutableRawPointer(mutating: CFDataGetBytePtr(inBitmapData))
-        var inBuffer = vImage_Buffer(data: inData, height: height, width: width, rowBytes: rowBytes)
+        guard let outContext = CGContext.fresh(cgImage: cgImage) else {
+            return base
+        }
+        var outBuffer = createEffectBuffer(outContext)
 
-        let outData = malloc(cgImage.bytesPerRow * cgImage.height)
-        defer { free(outData) }
-        var outBuffer = vImage_Buffer(data: outData, height: height, width: width, rowBytes: rowBytes)
-        
         for _ in 0 ..< iterations {
             let flag = vImage_Flags(kvImageEdgeExtend)
             vImageBoxConvolve_ARGB8888(
@@ -354,18 +359,7 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
             // Next inBuffer should be the outButter of current iteration
             (inBuffer, outBuffer) = (outBuffer, inBuffer)
         }
-        guard let outContext = CGContext(
-            data: outBuffer.data,
-            width: cgImage.width,
-            height: cgImage.height,
-            bitsPerComponent: cgImage.bitsPerComponent,
-            bytesPerRow: cgImage.bytesPerRow,
-            space: colorSpace,
-            bitmapInfo: cgImage.bitmapInfo.rawValue
-        ) ?? .fallback(data: outBuffer.data, cgImage: cgImage) else {
-            assertionFailure("[Kingfisher] Creating CG context failed.")
-            return base
-        }
+        
         #if os(macOS)
         let result = outContext.makeImage().flatMap {
             fixedForRetinaPixel(cgImage: $0, to: size)
@@ -696,9 +690,9 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
 }
 
 extension CGContext {
-    fileprivate static func fallback(data: UnsafeMutableRawPointer?, cgImage: CGImage) -> CGContext? {
-        return CGContext(
-            data: data,
+    fileprivate static func fresh(cgImage: CGImage) -> CGContext? {
+        CGContext(
+            data: nil,
             width: cgImage.width,
             height: cgImage.height,
             bitsPerComponent: 8,