Răsfoiți Sursa

Fix blur context creating

onevcat 9 ani în urmă
părinte
comite
657d2ebdd8
1 a modificat fișierele cu 63 adăugiri și 39 ștergeri
  1. 63 39
      Sources/Image.swift

+ 63 - 39
Sources/Image.swift

@@ -460,57 +460,42 @@ extension Kingfisher where Base: Image {
             let h = Int(size.height)
             let rowBytes = Int(CGFloat(cgImage.bytesPerRow))
             
-            let inDataPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: rowBytes * Int(h))
-            inDataPointer.initialize(to: 0)
-            defer {
-                inDataPointer.deinitialize()
-                inDataPointer.deallocate(capacity: rowBytes * Int(h))
-        }
-            
-            let bitmapInfo = cgImage.bitmapInfo.fixed
-            guard let context = CGContext(data: inDataPointer,
-                                          width: w,
-                                          height: h,
-                                          bitsPerComponent: cgImage.bitsPerComponent,
-                                          bytesPerRow: rowBytes,
-                                          space: cgImage.colorSpace ?? CGColorSpaceCreateDeviceRGB(),
-                                          bitmapInfo: bitmapInfo.rawValue) else
-            {
+            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)
+            }
+
+            guard let context = beginContext() else {
                 assertionFailure("[Kingfisher] Failed to create CG context for blurring image.")
                 return base
             }
+            defer { endContext() }
             
-            context.draw(cgImage, in: CGRect(x: 0, y: 0, width: w, height: h))
-            
+            #if !os(macOS)
+            context.scaleBy(x: 1.0, y: -1.0)
+            context.translateBy(x: 0, y: -size.height)
+            #endif
             
-            var inBuffer = vImage_Buffer(data: inDataPointer, height: vImagePixelCount(h), width: vImagePixelCount(w), rowBytes: rowBytes)
+            context.draw(cgImage, in: CGRect(x: 0, y: 0, width: w, height: h))
             
-            let outDataPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: rowBytes * Int(h))
-            outDataPointer.initialize(to: 0)
-            defer {
-                outDataPointer.deinitialize()
-                outDataPointer.deallocate(capacity: rowBytes * Int(h))
-        }
+            var inBuffer = createEffectBuffer(context)
             
-            var outBuffer = vImage_Buffer(data: outDataPointer, height: vImagePixelCount(h), width: vImagePixelCount(w), rowBytes: rowBytes)
+            guard let outContext = beginContext() else {
+                assertionFailure("[Kingfisher] Failed to create CG context for blurring image.")
+                return base
+            }
+            defer { endContext() }
+            var outBuffer = createEffectBuffer(outContext)
             
             for _ in 0 ..< iterations {
                 vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, nil, 0, 0, UInt32(targetRadius), UInt32(targetRadius), nil, vImage_Flags(kvImageEdgeExtend))
                 (inBuffer, outBuffer) = (outBuffer, inBuffer)
             }
             
-            guard let outContext = CGContext(data: inDataPointer,
-                                             width: w,
-                                             height: h,
-                                             bitsPerComponent: cgImage.bitsPerComponent,
-                                             bytesPerRow: rowBytes,
-                                             space: cgImage.colorSpace ?? CGColorSpaceCreateDeviceRGB(),
-                                             bitmapInfo: bitmapInfo.rawValue) else
-            {
-                assertionFailure("[Kingfisher] Failed to create CG context for blurring image.")
-                return base
-            }
-            
             #if os(macOS)
                 let result = outContext.makeImage().flatMap { fixedForRetinaPixel(cgImage: $0, to: size) }
             #else
@@ -736,9 +721,48 @@ extension CGBitmapInfo {
     }
 }
 
-
 extension Kingfisher where Base: Image {
     
+    func beginContext() -> CGContext? {
+        #if os(macOS)
+            guard let rep = NSBitmapImageRep(
+                bitmapDataPlanes: nil,
+                pixelsWide: Int(size.width),
+                pixelsHigh: Int(size.height),
+                bitsPerSample: cgImage?.bitsPerComponent ?? 8,
+                samplesPerPixel: 4,
+                hasAlpha: true,
+                isPlanar: false,
+                colorSpaceName: NSCalibratedRGBColorSpace,
+                bytesPerRow: 0,
+                bitsPerPixel: 0) else
+            {
+                assertionFailure("[Kingfisher] Image representation cannot be created.")
+                return nil
+            }
+            rep.size = size
+            NSGraphicsContext.saveGraphicsState()
+            guard let context = NSGraphicsContext(bitmapImageRep: rep) else {
+                assertionFailure("[Kingfisher] Image contenxt cannot be created.")
+                return nil
+            }
+            
+            NSGraphicsContext.setCurrent(context)
+            return context.cgContext
+        #else
+            UIGraphicsBeginImageContextWithOptions(size, false, scale)
+            return UIGraphicsGetCurrentContext()
+        #endif
+    }
+    
+    func endContext() {
+        #if os(macOS)
+            NSGraphicsContext.restoreGraphicsState()
+        #else
+            UIGraphicsEndImageContext()
+        #endif
+    }
+    
     func draw(cgImage: CGImage?, to size: CGSize, draw: ()->()) -> Image {
         #if os(macOS)
         guard let rep = NSBitmapImageRep(