34

I am trying to create a CGContext in swift. It compiles but throws an error at runtime.

let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()
let context:CGContext = CGBitmapContextCreate(nil, 20, 20, 8, 0, colorSpace, CGBitmapInfo.AlphaInfoMask)
CGColorSpaceRelease(colorSpace);

....

And the error is:

Error: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component color space; unrecognized; 96 bytes/row.
fatal error: Can't unwrap Optional.None
Jawad Ali
  • 13,556
  • 3
  • 32
  • 49
loopmasta
  • 1,693
  • 3
  • 14
  • 19

8 Answers8

63

Just in case somebody is running into the same problem. The snippet below finally works.

let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue)
let context = CGBitmapContextCreate(nil, UInt(rect.size.width), UInt(rect.size.height), 8, 0, colorSpace, bitmapInfo)

It generates a 32 bit RGBA context in swift

Robert
  • 37,670
  • 37
  • 171
  • 213
loopmasta
  • 1,693
  • 3
  • 14
  • 19
  • 6
    With the current version of Swift (I'm using Xcode 6.1): let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue) – Ryan H. Oct 28 '14 at 00:17
  • 4
    And with the current version of the Xcode is now: let context = CGBitmapContextCreate(nil, Int(rect.size.width), Int(rect.size.height), 8, 0, colorSpace, bitmapInfo) – Janusz Chudzynski May 22 '15 at 15:43
  • 14
    Swift 2.0 actually expects a `UInt32` instead of a `CGBitMapInfo` object, so in Swift 2.0 use `let context = CGBitmapContextCreate(nil, Int(rect.size.width), Int(rect.size.height), 8, 0, colorSpace, bitmapInfo.rawValue)`. <- notice how we convert `CGBitMapInfo` to `UInt32` by using its `rawValue` – the_critic Sep 11 '15 at 13:22
  • Swift 2 let context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, bytesPerRow, colourSpace, CGBitmapInfo.ByteOrder32Little.rawValue) – Khaled Annajar Oct 10 '16 at 14:12
  • I want to use other that PremultipliedLast but if I am using none, first or last context become nil – Iraniya Naynesh Jul 05 '18 at 12:30
18

Updated for Swift 3:

    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
    guard let context = CGContext.init(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: Int(bitsPerComponent), bytesPerRow: Int(bytesPerRow), space: colorSpace, bitmapInfo: UInt32(bitmapInfo.rawValue)) else {
        // cannot create context - handle error
    }
Echelon
  • 7,306
  • 1
  • 36
  • 34
11

In Swift 2.1 one can access the fields properly, and even OR them together:

let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue | CGBitmapInfo.ByteOrder32Little.rawValue)

let context = CGBitmapContextCreate(baseAddress, width, height, 8,
                bytesPerRow, colorSpace, bitmapInfo.rawValue);

Whole lot of 'rawValue' going on :)

You don't even need to separate out the bitmapInfo, and can do a one-liner:

let context = CGBitmapContextCreate(baseAddress, width, height, 8,
                bytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedFirst.rawValue | CGBitmapInfo.ByteOrder32Little.rawValue
Graham Perks
  • 23,007
  • 8
  • 61
  • 83
6

Updated for Swift 5:

 let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()
 let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
 let context = CGContext(data: nil, width: UInt(rect.size.width), height: UInt(rect.size.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)

where rect has height and width

Jawad Ali
  • 13,556
  • 3
  • 32
  • 49
4

I had some issues in Swift 1.2 using UInt, now I'm using Int and it's working. This Example shows how to convert an Image to a grayscale image.

let imageRect = self.myImage.frame

let colorSpace = CGColorSpaceCreateDeviceGray()
let width = imageRect.width
let height = imageRect.height

let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.None.rawValue)
let context = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, colorSpace, bitmapInfo)
pkamb
  • 33,281
  • 23
  • 160
  • 191
Miralem Cebic
  • 1,276
  • 1
  • 15
  • 28
4

Suggested way compatible with both Xcode 8.3 and Xcode 9 which supports Swift 3 and Swift 4

let colorSpace = CGColorSpaceCreateDeviceRGB()
guard let bitmapContext = CGContext(data: nil, 
                                    width: Int(size.width),
                                    height: Int(size.height),
                                    bitsPerComponent: Int(bitsPerComponent),
                                    bytesPerRow: Int(bytesPerRow),
                                    space: colorSpace,
                                    bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
                                  return nil
    }
abdullahselek
  • 7,893
  • 3
  • 50
  • 40
1

In Swift 2.2:

let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue).rawValue
let colorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, colorSpace, bitmapInfo)
Sam Soffes
  • 14,831
  • 9
  • 76
  • 80
0

CGBitmapInfo.AlphaInfoMask is not a valid bitmap info.

Try setting CGBitmapInfo.AlphaLast or CGBitmapInfo.AlphaFirst.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • This does not compile and i can not find CGBitmapInfo.AlphaLast or CGBitmapInfo.AlphaFirst in https://developer.apple.com/library/prerelease/ios/documentation/GraphicsImaging/Reference/CGBitmapContext/index.html#//apple_ref/c/func/CGBitmapContextCreate – loopmasta Jun 08 '14 at 20:31