Изменение цветового пространства NSImage - PullRequest
2 голосов
/ 15 июля 2010

Есть ли способ, которым я могу изменить цветовое пространство NSimage или NSBitmapImageRep / CGimage и т.п.Я открыт для любого пути.Предпочтительно способ, которым фотошоп делает это.

Ответы [ 2 ]

4 голосов
/ 02 декабря 2015

Проблема с кодом, который вы видите ниже

CGImageRef CGImageCreateCopyWithColorSpace (
CGImageRef image,
CGColorSpaceRef colorspace
);

не работает, потому что Quartz2D не поддерживает альфа для изображений CMYK или серых изображений, он поддерживается только изображениями RGB.Что вы должны сделать, это создать 2 изображения, а затем объединить их в случае цветового пространства CMYK и изображения с альфа-каналом.Я много искал по этой теме и, наконец, нашел.Возможно, автору этого вопроса он больше не нужен, но кому-то другому он может понадобиться.

  1. Создать новый 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)
    
  2. Вам нужно нарисовать ваше изображение в новом растровом изображении, скажем, у вас есть colorSpace: NSColorSpace

    let context = NSGraphicsContext(bitmapImageRep: imageRep)
    NSGraphicsContext.saveGraphicsState()
    NSGraphicsContext.setCurrentContext(context)
    imageRep.setProperty(NSImageColorSyncProfileData, withValue: colorSpace.ICCProfileData)
    // Do your drawing here
    NSGraphicsContext.restoreGraphicsState()
    
  3. После этого у вас будет imageRep, то есть изображение с правильным цветовым пространством, но безальфа (прозрачность).

  4. Вам нужна маска битмапа.Получить маску сложно.

    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)
    
  5. Прикрепите белое изображение к вашему изображению с прозрачностью

    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)
    }
    
  6. Раскрасьте все пиксели в белый цвет,это будет обрезано до изображения.

    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()
    
  7. На этом этапе у вас есть изображение и маска.Далее нам нужно их объединить.Я использую этот маленький алгоритм (вам нужно убедиться, что маска и исходное изображение имеют одинаковые размеры и одинаковую 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
        }
    }
    
4 голосов
/ 15 июля 2010
CGImageRef CGImageCreateCopyWithColorSpace (
   CGImageRef image,
   CGColorSpaceRef colorspace
);

Чтобы получить CGColorSpaceRef, вы можете сделать что-то вроде

CGColorSpaceRef CGColorSpaceCreateDeviceRGB();

ИЛИ см. на этой странице , чтобы узнать, как создавать другие цветовые пространства.

...