2

When extracting the RGB values from an NSImage with a transparent background I obtain the correct RGB values for the actual colored object within a particular image, but I am also getting RGB values of (0,0,0) even though there are no black pixels in sight within the particular image I test with. My guess was that I am getting (0,0,0) from the parts of the transparent image. How do I only get the RGB values from the image minus the transparent background. This behavior happens when I resize the image and extract the pixels values with the code down below.

Resizing Code (credit):

open func resizeImage(image:NSImage, newSize:NSSize) -> NSImage{

    let rep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(newSize.width), pixelsHigh: Int(newSize.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)

    rep?.size = newSize

    NSGraphicsContext.saveGraphicsState()
    let bitmap = NSGraphicsContext.init(bitmapImageRep: rep!)
    NSGraphicsContext.setCurrent(bitmap)
    image.draw(in: NSMakeRect(0, 0, newSize.width, newSize.height), from: NSMakeRect(0, 0, image.size.width, image.size.height), operation: .sourceOver, fraction: CGFloat(1))

    let newImage = NSImage(size: newSize)
    newImage.addRepresentation(rep!)
    return newImage

}

The code I used to extract the RGB values from an NSImage is down below:

RGB Extraction Code (credit) :

extension NSImage {

    func pixelData() -> [Pixel] {
        var bmp = self.representations[0] as! NSBitmapImageRep
        var data: UnsafeMutablePointer<UInt8> = bmp.bitmapData!
        var r, g, b, a: UInt8
        var pixels: [Pixel] = []

        NSLog("%d", bmp.pixelsHigh)
        NSLog("%d", bmp.pixelsWide)
        for var row in 0..<bmp.pixelsHigh {
            for var col in 0..<bmp.pixelsWide {
                r = data.pointee
                data = data.advanced(by: 1)
                g = data.pointee
                data =  data.advanced(by: 1)
                b = data.pointee
                data =  data.advanced(by: 1)
                a = data.pointee
                data =  data.advanced(by: 1)
                pixels.append(Pixel(r: r, g: g, b: b, a: a))
            }
        }

        return pixels
    }
}

class Pixel {

    var r: Float!
    var g: Float!
    var b: Float!

    init(r: UInt8, g: UInt8, b: UInt8, a: UInt8) {
        self.r = Float(r)
        self.g = Float(g)
        self.b = Float(b)
    }

}

I have also tried changing the operation parameter in the draw method of the resizing code to .copy, but with no luck.

Community
  • 1
  • 1
Guled
  • 659
  • 1
  • 5
  • 18

2 Answers2

3

You need to look at the alpha value of each pixel. If the alpha value is 0, the RGB value is irrelevant. (A fully transparent pixels's color is washed out to completely clear.)

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thank you so much! (I accept the answer, but I gotta wait 7 min to click the check button lol) – Guled Dec 27 '16 at 23:51
0

Apple Document:

NSImageRep

hasAlpha

A Boolean value indicating whether the image data has an alpha channel.

ref: https://developer.apple.com/documentation/appkit/nsimagerep/1534506-hasalpha

iHTCboy
  • 2,715
  • 21
  • 20