CGBitmapContextCreate: combinaison de parameters non prise en charge. Comment passer kCGImageAlphaNoneSkipFirst

J'ai initialement écrit cette application ( GitHub ) dans Obj-C, mais j'ai besoin de le convertir en Swift. Lors de la conversion, j'ai eu du mal à get le Context pour le Bitmap créé.

Message d'erreur:

Whiteboard[2833] <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 24 bits/pixel; 3-component color space; kCGImageAlphaNone; 1500 bytes/row. 

A l'origine, j'avais ceci:

 self.cacheContext = CGBitmapContextCreate (self.cacheBitmap, size.width, size.height, 8, bitmapBytesPerRow, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst); 

Et maintenant j'ai:

 self.cacheContext = CGBitmapContextCreate(self.cacheBitmap!, UInt(size.width), UInt(size.height), 8, bitmapBytesPerRow, CGColorSpaceCreateDeviceRGB(), CGBitmapInfo.ByteOrder32Little); 

Je crois que le problème a à voir avec CGBitmapInfo.ByteOrder32Little , mais je ne suis pas sûr de ce qu'il faut passer. Est-il possible de transmettre kCGImageAlphaNoneSkipFirst tant que CGBitmapInfo ?

Source complète:

 // // WhiteBoard.swift // Whiteboard // import Foundation import UIKit class WhiteBoard: UIView { var hue: CGFloat var cacheBitmap: UnsafeMutablePointer<Void>? var cacheContext: CGContextRef? override init(frame: CGRect) { self.hue = 0.0; // Create a UIView with the size of the parent view super.init(frame: frame); // Initialize the Cache Context of the bitmap self.initContext(frame); // Set the background color of the view to be White self.backgroundColor = UIColor.whiteColor(); // Add a Save Button to the bottom right corner of the screen let buttonFrame = CGRectMake(frame.size.width - 50, frame.size.height - 30, 40, 25); let button = UIButton(); button.frame = buttonFrame; button.setTitle("Save", forState: .Normal); button.setTitleColor(UIColor.blueColor(), forState: .Normal); button.addTarget(self, action: "downloadImage", forControlEvents: .TouchUpInside); // Add the button to the view self.addSubview(button); } required init(coder aDecoder: NSCoder) { self.hue = 0.0; super.init(coder: aDecoder) } func initContext(frame: CGRect)-> Bool { let size = frame.size; // Get the size of the UIView var bitmapByteCount: UInt! var bitmapBytesPerRow: UInt! // Calculate the number of bytes per row. 4 bytes per pixel: red, green, blue, alpha bitmapBytesPerRow = UInt(size.width * 4); // Total Bytes in the bitmap bitmapByteCount = UInt(CGFloat(bitmapBytesPerRow) * size.height); // Allocate memory for image data. This is the destination in memory where any // drawing to the bitmap context will be rendered self.cacheBitmap = malloc(bitmapByteCount); // Create the Cache Context from the Bitmap self.cacheContext = CGBitmapContextCreate(self.cacheBitmap!, UInt(size.width), UInt(size.height), 8, bitmapBytesPerRow, CGColorSpaceCreateDeviceRGB(), CGBitmapInfo.ByteOrder32Little); // Set the background as white CGContextSetRGBFillColor(self.cacheContext, 1.0, 1.0, 1.0, 1.0); CGContextFillRect(self.cacheContext, frame); CGContextSaveGState(self.cacheContext); return true; } // Fired everytime a touch event is dragged override func touchesMoved(touches: NSSet, withEvent event: UIEvent) { let touch = touches.anyObject() as UITouch; self.drawToCache(touch); } // Draw the new touch event to the cached Bitmap func drawToCache(touch: UITouch) { self.hue += 0.005; if(self.hue > 1.0) { self.hue = 0.0; } // Create a color object of the line color let color = UIColor(hue: CGFloat(self.hue), saturation: CGFloat(0.7), brightness: CGFloat(1.0), alpha: CGFloat(1.0)); // Set the line size, type, and color CGContextSetStrokeColorWithColor(self.cacheContext, color.CGColor); CGContextSetLineCap(self.cacheContext, kCGLineCapRound); CGContextSetLineWidth(self.cacheContext, CGFloat(15)); // Get the current and last touch point let lastPoint = touch.previousLocationInView(self) as CGPoint; let newPoint = touch.locationInView(self) as CGPoint; // Draw the line CGContextMoveToPoint(self.cacheContext, lastPoint.x, lastPoint.y); CGContextAddLineToPoint(self.cacheContext, newPoint.x, newPoint.y); CGContextStrokePath(self.cacheContext); // Calculate the dirty pixels that needs to be updated let dirtyPoint1 = CGRectMake(lastPoint.x-10, lastPoint.y-10, 20, 20); let dirtyPoint2 = CGRectMake(newPoint.x-10, newPoint.y-10, 20, 20); self.setNeedsDisplay(); // Only update the dirty pixels to improve performance //self.setNeedsDisplayInRect(dirtyPoint1); //self.setNeedsDisplayInRect(dirtyPoint2); } // Draw the cachedBitmap to the UIView override func drawRect(rect: CGRect) { // Get the current Graphics Context let context = UIGraphicsGetCurrentContext(); // Get the Image to draw let cacheImage = CGBitmapContextCreateImage(self.cacheContext); // Draw the ImageContext to the screen CGContextDrawImage(context, self.bounds, cacheImage); } // Download the image to the camera roll func downloadImage() { // Get the Image from the CGContext let image = UIImage(CGImage: CGBitmapContextCreateImage(self.cacheContext)); // Save the Image to their Camera Roll UIImageWriteToSavedPhotosAlbum(image, self, "image:didFinishSavingWithError:contextInfo:", nil); } func image(image: UIImage, didFinishSavingWithError error: NSError, contextInfo: UnsafeMutablePointer<Void>) { if(!error.localizedDescription.isEmpty) { UIAlertView(title: "Error", message: "Error Saving Photo", delegate: nil, cancelButtonTitle: "Ok").show(); } } } 

En Objective-C, vous devez simplement convertir à l'autre type enum, comme ceci:

 (CGBitmapInfo)kCGImageAlphaNoneSkipFirst 

Dans Swift, vous devez le faire comme ceci:

 CGBitmapInfo(CGImageAlphaInfo.NoneSkipFirst.rawValue) 

Bienvenue dans le monde sauvage et farfelu des numbers Swift. Vous devez extraire la valeur numérique de l'énumération originale CGImageAlphaInfo avec rawValue ; Vous pouvez maintenant utiliser cette valeur numérique dans l'initialiseur de l'énumération CGBitmapInfo.

EDIT Il est beaucoup plus simple dans iOS 9 / Swift 2.0, où vous pouvez simplement passer directement à CGImageAlphaInfo.NoneSkipFirst.rawValue dans CGBitmapContextCreate, qui attend maintenant juste un entier à cet endroit.