I am trying to take an NSImage and change pixels of a specific color to another color
This is my test code (this SHOULD change all pixels to gray)
func makeMask() {
let bitmapRep : NSBitmapImageRep = self.representations[0] as! NSBitmapImageRep
for x in (0...bitmapRep.pixelsWide-1) {
for y in(0...bitmapRep.pixelsHigh-1) {
if let color : NSColor = bitmapRep.colorAt(x: x, y:y) {
let xxx=NSColor(rgb:0x777777).usingColorSpace(color.colorSpace)
bitmapRep.setColor(xxx!, atX: x, y: y)
}
}
}
print(bitmapRep.colorSpace)
}
where SELF is an NSImage
the line
bitmapRep.setColor(xxx!, atX: x, y: y)
gives these errors
Unrecognized colorspace number -1
Unknown number of components for colorspace model -1
even though I made sure the old [color] and new [xxx] are the same colorspace
and I can't find ANYTHING on the Net the points to a cause :(
func makeMask() {
let BMP : NSBitmapImageRep = self.representations[0] as! NSBitmapImageRep
let data = BMP.bitmapData
var ptr : Int = 0
for _ in(0...BMP.pixelsHigh-1) {
for _ in (0...BMP.pixelsWide-1) {
let clr = getPixel(data: data, pointer: ptr)
if clr.IntValue() == NSColor.white.IntValue() {
putPixel(data: data, pointer: ptr, newColor: NSColor.magenta.withAlphaComponent(0))
}
ptr+=4
}
}
self.addRepresentation(BMP)
}
private func getPixel(data:UnsafeMutablePointer<UInt8>?,pointer:Int) -> NSColor {
let r : CGFloat = CGFloat(data![pointer])/255
let g : CGFloat = CGFloat(data![pointer+1])/255
let b : CGFloat = CGFloat(data![pointer+2])/255
let a : CGFloat = CGFloat(data![pointer+3])/255
let clr = NSColor(calibratedRed: r, green: g, blue: b, alpha: a)
// make sure it returns an RGB color
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
return NSColor(cgColor:clr.cgColor.converted(to: rgbColorSpace, intent: .defaultIntent, options: nil)!)!
}
private func putPixel(data:UnsafeMutablePointer<UInt8>?,pointer:Int,newColor:NSColor) {
data![pointer] = UInt8(newColor.redValue*255)
data![pointer+1] = UInt8(newColor.greenValue*255)
data![pointer+2] = UInt8(newColor.blueValue*255)
data![pointer+3] = UInt8(newColor.alpha*255)
}
IntValue is an extension to NSColor the returns the integervalue of the color… due to the various colorspaces Swift uses, the was a way to make the color directly comparable
also the use of Magenta was unimportant, just the fact the alpha was 0
A NSImage may not have a NSBitmapImageRep to start with.
The macOS is funny with colorSpaces, it supports a lot, but not all can be used to create colors or images with. IIRC there is only a handful that can actually be used for creation, you must also ensure that the color matches the color space, for instance trying to create a cmyk color with a RGB colorSpace will fail.
Try using the colorSpace of the image and not the pixel, if that fails, use a close matched colorspace.
Xojo makes this easy, by simply ignoring colorSpaces, so it takes some getting use to, to work with colorSpaces.