Цвета пикселей меняются, когда я сохраняю MTLTexture в CGImage?

avatar
Rob N
7 апреля 2018 в 23:34
2491
1
4

Мне нужно сохранить и загрузить текстуры металла в файл. Пример кода ниже приведен ниже. Я заметил, что значения RGB меняются при сохранении и повторной загрузке.

metal texture pixel: RGBA: 42,79,12,95  
after save and reload:     66,88,37,95

Это стало ярче и серее. При следующем сохранении становится темнее. У меня iPad Pro, поэтому мне интересно, не связано ли это с цветовым пространством. Любые указания, почему это может происходить и как это исправить?

В строке ниже, которая сохраняет cgImage, я могу проверить необработанные данные пикселей и увидеть, что RGBA составляет 66,88,37.

// saving...
let ciCtx = CIContext()
let ciImage = CIImage(mtlTexture: metalTexture, options: [:])
// [ … transfrom to flip y-coordinate …]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let cgImage = ciCtx.createCGImage(ciImage, from: fullRect, format: kCIFormatRGBA8, colorSpace: colorSpace)!
let imageDest = CGImageDestinationCreateWithData(mData, kUTTypePNG, 1, nil)!
CGImageDestinationAddImage(imageDest, cgImage, nil)
CGImageDestinationFinalize(imageDest)

// loading...
let src = CGImageSourceCreateWithData(imgData, nil)
let img = CGImageSourceCreateImageAtIndex(src, 0, nil)
let loader = MTKTextureLoader(device: self.metalDevice)
let texture = try! loader.newTexture(cgImage: img, options: [:])
Источник
warrenm
8 апреля 2018 в 16:38
0

Вообще говоря, данные PNG хранятся в кодировке sRGB, но вы указываете Core Image обрабатывать данные текстуры так, как если бы они находились в цветовом пространстве устройства, которым может быть Display P3 (это можно определить, напечатав colorspace) . В любом случае цветовое пространство устройства редко является тем, что вам нужно. Вероятно, имеет смысл вместо этого предоставить цветовое пространство sRGB (CGColorSpace(name: CGColorSpace.sRGB)) для CI. Когда загрузчик текстур загружает изображение, он должен сделать вывод, что данные изображения имеют цветовую палитру sRGB, и вы должны увидеть лучшие результаты.

Rob N
8 апреля 2018 в 21:16
0

Когда я печатаю этот объект colorSpace, он дает: <CGColorSpace 0x1c40af360> (kCGColorSpaceDeviceRGB), который не выглядит как Display P3. Я только что попытался использовать как .sRGB, так и .displayP3 для создания этого цветового пространства, и оба приводят к изменению цветов при сохранении и перезагрузке. Должен быть способ сохранить пиксельную карту и вернуть те же значения RGB.

Ответы (1)

avatar
Plutovman
13 июля 2018 в 04:40
9

Я столкнулся с очень похожей проблемой. Я думаю, что если вы передадите некоторые параметры в CIImage() вместо того, чтобы управлять цветовым пространством, то есть «options: [:]», вы избавитесь от проблемы смещения цвета.

let kciOptions = [kCIImageColorSpace: CGColorSpaceCreateDeviceRGB(),
                      kCIContextOutputPremultiplied: true,
                      kCIContextUseSoftwareRenderer: false] as [String : Any]
let ciImage = CIImage(mtlTexture: metalTexture, options: kciOptions)

Вышеизложенное работало для меня, когда у меня была эта проблема.

Jonathan Zrake
7 января 2019 в 18:13
0

Спасибо @Plutovman! Вы случайно не знаете эквивалент в коде Objective C? Объект NSDictionary не будет принимать CGColorSpaceRef в качестве значения.

Plutovman
8 января 2019 в 00:12
0

К сожалению, нет, так как мои знания Objective-C довольно минимальны. Я уверен, что вы найдете свой путь в кратчайшие сроки. Лучший.

karel
23 апреля 2020 в 11:00
1

для объективного использования: @{kCIImageColorSpace:(__bridge_transfer id)CGColorSpaceCreateDeviceRGB()}