问题
Is there a way I can change the color space of an NSimage or NSBitmapImageRep/CGimage or the like. I am open to any way. Preferably the way photoshop does it.
回答1:
CGImageRef CGImageCreateCopyWithColorSpace (
CGImageRef image,
CGColorSpaceRef colorspace
);
To get a CGColorSpaceRef, you can do things like
CGColorSpaceRef CGColorSpaceCreateDeviceRGB();
OR see this page for how to create other color spaces.
回答2:
The problem with the code you see below
CGImageRef CGImageCreateCopyWithColorSpace (
CGImageRef image,
CGColorSpaceRef colorspace
);
is not working because Quartz2D does not support alpha for CMYK images or gray images, it is supported only by RGB images. What you should do is creating 2 images then combine then in case of a CMYK color space and image with alpha. I have searched a lot about this topic and finally found. May be author of this question doesn't need it anymore but someone else may need it.
Create new
NSBitmapImageRep
let imageRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(round(imageSize.width)), pixelsHigh: Int(round(imageSize.height)), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: false, isPlanar: false, colorSpaceName: NSDeviceCMYKColorSpace, bitmapFormat: NSBitmapFormat(rawValue: 0), bytesPerRow: Int(round(imageSize.width) * CGFloat(4)), bitsPerPixel: 0)
You need to draw your image into the new bitmap lets say you have
colorSpace: NSColorSpace
let context = NSGraphicsContext(bitmapImageRep: imageRep) NSGraphicsContext.saveGraphicsState() NSGraphicsContext.setCurrentContext(context) imageRep.setProperty(NSImageColorSyncProfileData, withValue: colorSpace.ICCProfileData) // Do your drawing here NSGraphicsContext.restoreGraphicsState()
After this you will have an imageRep that is the image with correct color space but no alpha (transparency).
You need a mask bitmap. Obtaining mask is tricky.
let imageRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(round(imageSize.width)), pixelsHigh: Int(round(imageSize.height)), bitsPerSample: 8, samplesPerPixel: 1, hasAlpha: false, isPlanar: false, colorSpaceName: NSDeviceWhiteColorSpace, bitmapFormat: NSBitmapFormat(rawValue: 0), bytesPerRow: Int(round(imageSize.width)), bitsPerPixel: 0)
Clip white image to your image with transparency
if let graphicsPort = NSGraphicsContext.currentContext()?.graphicsPort { let context = unsafeBitCast(graphicsPort, CGContextRef.self) let imgRect = NSRect(origin: NSPoint.zero, size: image.extent.size) let ciContext = CIContext() let cgImage = ciContext.createCGImage(image, fromRect: image.extent) CGContextClipToMask(context, imgRect, cgImage) }
Colorize all pixel in white color, this will be clipped to image.
let context = NSGraphicsContext(bitmapImageRep: imageRep) NSGraphicsContext.saveGraphicsState() NSGraphicsContext.setCurrentContext(context) imageRep.setProperty(NSImageColorSyncProfileData, withValue: colorSpace.ICCProfileData) NSColor.whiteColor().setFill() NSBezierPath.fillRect(NSRect(origin: NSPoint.zero, size: imageSize)) NSGraphicsContext.restoreGraphicsState()
At this step you have a image and a mask. Next we need to combine them. I am using this little algorithm (you need to verify that mask and source image have same sizes and same colorSpaceModel):
func createCMYKAImageRepByApplingAlphaMask(srcImageRep: NSBitmapImageRep, alphaMaskImageRep alphaMask: NSBitmapImageRep) -> NSBitmapImageRep? { if canApplyMaskRepOnImageRep(srcImageRep, maskRep: alphaMask) == false { return nil } let alphaData = alphaMask.bitmapData let srcData = srcImageRep.bitmapData if let imageWithAlphaMaskRep = createEmptyCMYKABitmapImageRep(alphaMask.size) { if let colorSpaceData = imageColorSpace?.ICCProfileData { imageWithAlphaMaskRep.setProperty(NSImageColorSyncProfileData, withValue: colorSpaceData) } fillPixelsWithComponentsData(imageWithAlphaMaskRep, components: { (pixelIdx: Int) -> (UInt8, UInt8, UInt8, UInt8, UInt8) in let cyan = srcData[pixelIdx * 4 + 0] let magenta = srcData[pixelIdx * 4 + 1] let yellow = srcData[pixelIdx * 4 + 2] let black = srcData[pixelIdx * 4 + 3] let alpha = alphaData[pixelIdx] return (cyan, magenta, yellow, black, alpha) }) return imageWithAlphaMaskRep } return nil } func createEmptyBitmapImageRep() -> NSBitmapImageRep? { let imageRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(round(imageSize.width)), pixelsHigh: Int(round(imageSize.height)), bitsPerSample: 8, samplesPerPixel: 5, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceCMYKColorSpace, bitmapFormat: NSBitmapFormat(rawValue: 0), bytesPerRow: Int(round(imageSize.width) * CGFloat(5)), bitsPerPixel: 0) return imageRep } private func fillPixelsWithComponentsData(imgRep: NSBitmapImageRep, components: (Int) -> (cyan:UInt8, magenta:UInt8, yellow:UInt8, black:UInt8, alpha:UInt8)) { let imageRawData = imgRep.bitmapData let imageWidth = Int(imgRep.size.width) let imageHeight = Int(imgRep.size.height) for pixelIdx in 0 ..< (imageWidth * imageHeight) { let (cyan, magenta, yellow, black, alpha) = components(pixelIdx) let fAlpha = Float(alpha) / 255 imageRawData[pixelIdx * 5 + 0] = UInt8(Float(cyan) * fAlpha) imageRawData[pixelIdx * 5 + 1] = UInt8(Float(magenta) * fAlpha) imageRawData[pixelIdx * 5 + 2] = UInt8(Float(yellow) * fAlpha) imageRawData[pixelIdx * 5 + 3] = UInt8(Float(black) * fAlpha) imageRawData[pixelIdx * 5 + 4] = alpha } }
来源:https://stackoverflow.com/questions/3253521/changing-the-color-space-of-nsimage