Как изменить палитру индексированного PNG во время выполнения на iOS?

У меня есть серия изображений PNG, которые используют индексы в палитре цвета (тип цвета PNG 3). В некоторых случаях мне нужно сделать копию изображения, на котором были изменены некоторые записи в палитре. Таким образом мы снова и снова перекрашиваем исходный PNG.

В Java это решается путем получения значений RGB из IndexedColorModel, изменения значений и создания нового IndexedColorModel, а также создания нового BufferedImage с растровыми данными исходного изображения и новой цветовой моделью.

В ActionScript мне пришлось прочитать байты PNG как чистый ByteArray, найти фрагмент палитры, изменить значения, а затем заставить среду выполнения загрузить изображение из ByteArray.

Сейчас я хочу реализовать ту же систему для iOS через MonoTouch (в котором я новичок), но я уперся в стену. Я считаю, что подход ActionScript и здесь будет работать, но было бы неплохо в этот раз не работать на таком низком уровне, и, похоже, я смогу приблизиться.

Если я начинаю с UIImage, я могу получить цветовое пространство с UIImage.CGImage.ColorSpace. Я могу проверить, что это индексированная цветовая модель с colorSpace.Model. Я не уверен в том, как получить фактический массив байтов палитры.

А с другой стороны, как мне создать новое изображение с новой палитрой? CGImage.WithColorSpace похоже, что он сделает то, что я хочу ... может быть? И затем я должен иметь возможность создать цветовое пространство с моей новой палитрой: на первый взгляд CGColorSpace.CreateIndexed выглядит так, как я хочу, но я не понимаю, как используется параметр baseSpace. Я хочу создать CGColorSpace с совершенно новой цветовой палитрой, которую я предоставляю, а затем использовать индексы исходного изображения с новой палитрой. Может, я неправильно понимаю, для чего используется CGColorSpace.


person roguenet    schedule 19.04.2012    source источник


Ответы (1)


В ActionScript мне пришлось прочитать байты PNG как чистый массив ByteArray, найти фрагмент палитры, изменить значения, а затем заставить среду выполнения загрузить изображение из ByteArray.

Это немного грубо, но это сработает. Однако я почти уверен, что в CoreGraphics есть все необходимое, чтобы этого избежать.

Если я начинаю с UIImage

Поскольку вы в любом случае будете использовать CoreGraphics (CG), вы можете начать с CGImage. Пример кода (objc) здесь: iPhone SDK: доступ к индексированным цветным изображениям PNG

Я не уверен в том, как получить фактический массив байтов палитры.

CGColorSpaceGetColorTable выглядит идеальным кандидатом. Однако похоже, что он отсутствует в привязках MonoTouch (я проверю это), но было бы легко (это p / invoke) привязать вручную и использовать в своем приложении.

но я не понимаю, как используется параметр baseSpace

CGColorSpace.CreateIndexed может принимать параметр null для baseSpace, но, возможно, вам лучше скопировать его. , base, GCColorSpace из исходного изображения PNG.

person poupou    schedule 19.04.2012
comment
p.s. если вы можете заполнить отчет об ошибке на bugzilla.xamarin.com за отсутствующий CGColorSpaceGetColorTable и прикрепить проиндексированный файл PNG I ' Я добавлю его в следующий (стабильный) выпуск MonoTouch. Объявление p / invoke будет заканчиваться в (общедоступном) репозитории maccore на github (так что вы сможете скопировать / вставить его оттуда). Спасибо! - person poupou; 19.04.2012
comment
Ага, недостающий метод. Я отправлю отчет об ошибке сегодня. Кроме того, я не упомянул об этом, потому что не был уверен, что это будет уместно, но на самом деле я работаю с дополнительным слоем: мой источник на самом деле находится на Java, преобразован в DLL через IKVM . Я не знаю (пока), как выполнить ручную привязку, а затем, если я смогу получить к нему доступ через IKVM, но сейчас я займусь исследованием в этом направлении. Спасибо! - person roguenet; 20.04.2012
comment
Ошибка отправлена ​​с прикрепленным примером изображения: bugzilla.xamarin.com/show_bug.cgi?id=4573. Надеюсь, у меня будет время покопаться в ручном связывании сегодня, и тогда я сообщу об успехе. - person roguenet; 21.04.2012
comment
Спасибо! Это будет намного лучше :-) Объявление можно увидеть на странице github.com/mono / maccore / commit /, но вам, вероятно, потребуется немного больше C #, чтобы реализовать это через IKVM. - person poupou; 21.04.2012
comment
Отметив это, я ответил: «Я убежден, что все части, которые мне нужны, сейчас там, где я могу их видеть». У меня еще не было возможности поиграть с ним, и вместо того, чтобы пытаться получить ручную привязку, доступную через IKVM, я просто собираюсь дождаться следующего выпуска MonoTouch :). Спасибо за помощь! - person roguenet; 23.04.2012