3

I use a method introduced in this post, modified for Swift:

func getRaster() -> [UIColor] {
    let result = NSMutableArray()
    
    let img = self.CGImage
    let width = CGImageGetWidth(img)
    let height = CGImageGetHeight(img)
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    
    var rawData = [UInt8](count: width * height * 4, repeatedValue: 0)
    let bytesPerPixel = 4
    let bytesPerRow = bytesPerPixel * width
    let bytesPerComponent = 8
    
    let bitmapInfo = CGImageAlphaInfo.PremultipliedLast.rawValue | CGBitmapInfo.ByteOrder32Big.rawValue
    let context = CGBitmapContextCreate(&rawData, width, height, bytesPerComponent, bytesPerRow, colorSpace, bitmapInfo)
    
    CGContextDrawImage(context, CGRectMake(0, 0, CGFloat(width), CGFloat(height)), img);
    for x in 0..<width {
        for y in 0..<height {
            let byteIndex = (bytesPerRow * x) + y * bytesPerPixel
            
            let red   = CGFloat(rawData[byteIndex]    ) / 255.0
            let green = CGFloat(rawData[byteIndex + 1]) / 255.0
            let blue  = CGFloat(rawData[byteIndex + 2]) / 255.0
            let alpha = CGFloat(rawData[byteIndex + 3]) / 255.0
            
            let color = UIColor(red: red, green: green, blue: blue, alpha: alpha)
            result.addObject(color)
        }
    }
    
    return (result as NSArray) as! [UIColor]
}

But the problem is that it only ever succeeds if the image is square (i.e. 32x32 sprite), whenever I try to get a "raster" of an image, which dimensions are not equal, I get an "Index out of range" fatal error for red on x = 16 and y = 0 (for image of size h: 16, w: 32). What could be a solution for this problem?

Thank you in advance!

Community
  • 1
  • 1
EBDOKUM
  • 1,696
  • 3
  • 15
  • 33
  • 1
    Just to clarify, I've got the interpreted for Swift version [here](http://stackoverflow.com/questions/38163523/uiimage-to-uicolor-array-of-pixel-colors). It is now also fixed there. – EBDOKUM Aug 02 '16 at 06:32
  • This will incur a lot of overhead from array reallocation. Performance would improve greatly if you preallocate the array. In fact, this really has no reason to be using `NSMutableArray` instead of a native Swift `Array` – Alexander Aug 02 '16 at 06:57
  • @AMomchilov again, I used an implementation, introduced in the [post](http://stackoverflow.com/questions/38163523/uiimage-to-uicolor-array-of-pixel-colors). The one I practically use is a bit different and yes, I agree, there is absolutely no reason for that. – EBDOKUM Aug 02 '16 at 07:00
  • Yes, I'm aware. Still thought it was worth pointing out. – Alexander Aug 02 '16 at 07:18

1 Answers1

1

It was pretty easy to solve, actually, here's the problem part:

for x in 0..<width {
    for y in 0..<height {
        let byteIndex = (bytesPerRow * x) + y * bytesPerPixel

And here's how it's supposed to be:

for y in 0..<height {
        for x in 0..<width {
            let byteIndex = (bytesPerRow * y) + x * bytesPerPixel

I do not think this needs any further explanation.

EBDOKUM
  • 1,696
  • 3
  • 15
  • 33