Изображения

Изображения являются важной частью любого приложения Mac. В Какао изображения играют очень важную, но гибкую, роль в Вашем пользовательском интерфейсе. Можно использовать изображения для рендеринга существующего ранее содержания или действия как буфер для команд рисования приложения. В основе обработки изображения Какао код NSImage класс. Этот класс управляет всем связанным с данными изображения и используется для следующих задач:

Можно использовать изображения в программе для множества задач. Можно загрузить изображения из существующих файлов изображения (таких как JPEG, GIF, PDF и файлы EPS) для рисования элементов пользовательского интерфейса, который мог бы быть слишком трудным (или слишком неэффективным) нарисовать использующие примитивные формы. Можно также использовать изображения в качестве внеэкранных или временных буферов и получить последовательность команд рисования, которые Вы хотите использовать в более позднее время.

Несмотря на то, что битовые массивы являются одним из наиболее распространенных типов изображения, важно не думать NSImage класс как простое управление фотографическими или растровыми данными. NSImage класс в Какао способен к отображению множества типов изображения и форматов. Это предоставляет поддержку для фотографии и растровых данных во многих стандартных форматах. Это также предоставляет поддержку для вектора или основанные на команде данные, такие как PDF, EPS и PICT. Можно даже использовать NSImage класс для представления изображения, создаваемого с Базовой платформой Изображения.

Основы изображения

NSImage класс обеспечивает высокоуровневый интерфейс для управления изображениями во многих различных форматах. Поскольку это обеспечивает высокоуровневый интерфейс, NSImage почти ничего не знает об управлении данными действительного образа. Вместо этого NSImage класс управляет одним или более объектами представления изображения — объекты, полученные из NSImageRep класс. Каждый объект представления изображения понимает данные изображения для определенного формата и способен к рендерингу тех данных к текущему контексту.

Следующие разделы обеспечивают понимание отношения между объектами изображения и отображают представления.

Представления изображения

Объект представления изображения представляет изображение в определенном размере, используя определенное цветовое пространство, и в определенном формате данных. Представления изображения используются NSImage объект управлять данными изображения. Объект представления изображения знает, как считать данные изображения из файла, записать те данные обратно к файлу и преобразовать данные изображения в необработанный битовый массив, который может тогда быть представлен к текущему контексту. Некоторые представления изображения также обеспечивают интерфейс для управления данными изображения непосредственно.

Для основанных на файле изображений, NSImage создает объект представления изображения для каждого отдельного изображения, сохраненного в файле. Несмотря на то, что большинство форматов изображения поддерживает только единственное изображение, форматы, такие как TIFF позволяют повторным изображениям быть сохраненными. Например, файл TIFF мог бы сохранить и версию в натуральную величину изображения и миниатюру.

При создании изображений динамично Вы ответственны за создание объектов представления изображения, в которых что Вы нуждаетесь для своего изображения. Как с основанными на файле изображениями, большинство изображений Вы создаете потребность только единственное представление изображения. Поскольку NSImage владеет мастерством масштабирования и корректировки изображений для адаптации целевому холсту, обычно не необходимо создать различные представления изображения в различных разрешениях. Вы могли бы создать многократные представления в следующих ситуациях, однако:

  • Для печати Вы могли бы хотеть создать представление PDF или битовый массив с высокой разрешающей способностью Вашего изображения.

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

Когда Вы рисуете изображение, NSImage объект выбирает представление, подходящее лучше всего для целевого холста. Этот выбор основывается на нескольких факторах, объясненных в том, Как Выбрано Представление Изображения. Если Вы хотите гарантировать, что определенное представление изображения используется, можно использовать drawRepresentation:inRect: метод NSImage.

Классы представления изображения

Каждый объект представления изображения основывается на подклассе NSImageRep. Какао определяет несколько определенных подклассов для обработки обычно используемых форматов. Таблица 5-1 перечисляет класс и типы изображения, которые это поддерживает.

Табличные 5-1  классы представления Изображения

Класс

Поддерживаемые типы

Описание

NSBitmapImageRep

TIFF, BMP, JPEG, GIF, PNG, DIB, ICO, среди других

Обрабатывает растровые данные. Несколько общих растровых форматов поддерживаются непосредственно. Для форматов пользовательского изображения Вам, вероятно, придется декодировать данные изображения самим прежде, чем создать Ваше представление изображения. NSBitmapImageRep возразите использует любые доступные данные цветового профиля (ICC или ColorSync) при рендеринге.

NSCachedImageRep

Представленные данные

Этот класс используется внутренне Какао для кэширования изображений для рисования на экран. Вы не должны должны быть использовать этот класс непосредственно.

NSCIImageRep

N/A

Обеспечивает представление для a CIImage объект, сам поддерживающий наиболее растровые форматы.

NSPDFImageRep

PDF

Обрабатывает дисплей данных PDF.

NSEPSImageRep

EPS

Обрабатывает дисплей данных инкапсулированного формата PostScript или PostScript.

NSCustomImageRep

Пользовательский

Обрабатывает данные пользовательского изображения путем передачи его объекту делегата, который что Вы обеспечиваете.

NSPICTImageRep

ПИКТ

Обрабатывает дисплей версии формата PICT 1, версия 2 и расширенные изображения версии 2. Формат PICT является унаследованным форматом, описанным в Углероде менеджер QuickDraw документация.

В большинстве ситуаций Вы не должны знать, как создается представление изображения. Например, если Вы загружаете существующее изображение из файла, NSImage автоматически определяет который тип представления изображения создать на основе данных файла. Все, что необходимо сделать, является получением изображение в представлении.

Если Вы хотите поддерживать новые форматы изображения, можно создать новый класс представления изображения. NSImage класс и NSImageRep подклассы не следуют за моделью кластера класса, найденной в нескольких других классах Какао. Создание новых представлений изображения является относительно прямым и объяснено в Создании Новых Классов Представления Изображения.

Как выбрано представление изображения

Когда Вы говорите NSImage возразите для рисования себя, это ищет свой список представлений изображения для того что лучшие соответствия атрибуты устройства назначения. В определении, которые отображают представление для выбора, оно следует за рядом упорядоченных правил, сравнивающих цветовое пространство, разрешение изображения, битовую глубину и размер изображения к соответствующим значениям в устройстве назначения. Правила применяются в следующем порядке:

  1. Выберите представление изображения, цветовое пространство которого наиболее близко соответствует цветовое пространство устройства. Если устройство является цветом, выберите представление цветного изображения. Если устройство является монохромом, выберите представление полутонового изображения.

  2. Выберите представление изображения, имеющее, по крайней мере, столько же пикселей сколько целевой прямоугольник и на горизонтальных и на вертикальных осях. Если никакое представление изображения не соответствует точно, выберите тот, имеющий больше пикселей, чем место назначения.

    По умолчанию любое представление изображения с разрешением, это - целочисленное кратное число разрешения устройства, считают соответствием. Если больше чем одно представление соответствует, NSImage выбирает тот, который это является самым близким к разрешению устройства. Можно вынудить соответствия разрешения быть точными путем передачи NO к setMatchesOnMultipleResolution: метод. Можно вынудить соответствия разрешения быть точными только на одной размерности путем установки setMatchesOnlyOnBestFittingAxis: свойство к YES.

    Это правило предпочитает TIFF и растровые представления, имеющие определенное разрешение, по не делающим представлениям EPS. Можно использовать setUsesEPSOnResolutionMismatch: метод для порождения NSImage выбрать представление EPS в случае, если соответствие разрешения не возможно.

  3. Выберите представление, битовая глубина которого (биты на выборку) соответствует глубину устройства. Если никакое представление не соответствует, выберите тот с самым большим количеством битов на выборку.

Можно изменить порядок, в котором эти правила применяются с помощью методов NSImage. Например, если Вы хотите инвертировать первые и вторые правила, передачу NO к setPrefersColorMatch: метод. Выполнение так причины NSImage соответствовать разрешение перед цветовым пространством.

Если этим правилам не удается сузить выбор к единственному представлению — например, если NSImage объект имеет два цветных представления TIFF с тем же разрешением и глубиной — выбранное представление зависимо от операционной системы.

Изображения и кэширование

NSImage класс включает внутреннюю схему кэширования, нацеленную на улучшение производительности получения Вашего приложения. Эта схема кэширования является важной частью управления изображением и включена по умолчанию для всех объектов изображения; однако, можно изменить кэширующиеся опции для определенного изображения с помощью setCacheMode: метод NSImage. Таблица 5-2 перечисляет доступные режимы кэширования.

Табличные 5-2  режимы кэширования Изображения

Режим

Описание

NSImageCacheDefault

Используйте режим кэширования значения по умолчанию, подходящий для представления изображения. Это - значение по умолчанию. Для получения дополнительной информации посмотрите Таблицу 5-3.

NSImageCacheAlways

Всегда кэширует версию изображения.

NSImageCacheBySize

Если набор размера для изображения меньше, чем размер данных действительного образа, создает кэшированную версию изображения.

NSImageCacheNever

Не кэширует изображение. Данные изображения растеризируются каждый раз, когда они нарисованы.

Когда его режим кэширования установлен в, таблица 5-3 перечисляет поведение каждого представления изображения NSImageCacheDefault.

Таблица 5-3  Подразумеваемые параметры кэширования

Представление изображения

Поведение кэша

NSBitmapImageRep

Ведет себя как будто NSImageCacheBySize установка имела силу. Создает кэшируемую копию, если растровая глубина не соответствует экранную глубину или если растровое разрешение больше, чем 72 точки на дюйм.

NSCachedImageRep

Не применимый. Этот класс используется для реализации кэширования.

NSCIImageRep

Ведет себя как будто NSImageCacheBySize установка имела силу. Создает кэшируемую копию, если растровая глубина не соответствует экранную глубину или если растровое разрешение больше, чем 72 точки на дюйм.

NSPDFImageRep

Ведет себя как будто NSImageCacheAlways установка имела силу.

NSEPSImageRep

Ведет себя как будто NSImageCacheAlways установка имела силу.

NSCustomImageRep

Ведет себя как будто NSImageCacheAlways установка имела силу.

NSPICTImageRep

Ведет себя как будто NSImageCacheBySize установка имела силу. Создает кэшируемую копию изображения PICT, если оно содержит битовый массив, глубина которого не соответствует экранную глубину или если то растровое разрешение больше, чем 72 точки на дюйм.

Кэширование является полезным шагом к подготовке изображения для дисплея на экране. Когда сначала загруженный, данные для представления изображения могут не быть в формате, который может быть представлен непосредственно на экран. Например, данные PDF, когда загружено в представление изображения PDF, должны быть растеризированы, прежде чем они смогут быть отправлены в видеокарту для дисплея. С кэшированием включенного, a NSPDFImageRep объект растеризирует данные PDF прежде, чем нарисовать его на экран. Представление изображения тогда сохраняет растровые данные для улучшения потребности воссоздать его позже. При отключении кэширования для таких изображений процесс растеризации происходит каждый раз, когда Вы представляете изображение, которое может привести к значительной потере производительности.

Для представлений растрового изображения решение кэшироваться зависит от данных растрового изображения. Если цветовое пространство битового массива, разрешение и битовая глубина соответствуют соответствующие атрибуты в устройстве назначения, битовый массив может использоваться непосредственно без любого кэширования. Если какой-либо из этих атрибутов варьируется, однако, представление растрового изображения может создать кэшированную версию вместо этого.

Если Вы изменяетесь, содержание представления изображения возражает непосредственно, необходимо вызвать recache метод владения NSImage возразите, когда Вы будете сделаны и захотите, чтобы изменения были отражены на экране. Какао автоматически не отслеживает изменения, которые Вы вносите в свои объекты представления изображения. Вместо этого это продолжает использовать кэшированную версию Вашего представления изображения, пока Вы явно не очищаете тот кэш с помощью recache метод.

Кэширование и отставание данных изображения

Поскольку кэширование может привести к многократным копиям данных изображения в памяти, NSImage обычно отклоняет данные исходного изображения, как только создается кэшируемая копия. Отклонение данных исходного изображения сохраняет память и улучшает производительность и является надлежащим в ситуациях, где Вы не планируете изменение размера изображения или атрибутов. Если Вы действительно планируете изменение размера изображения или атрибутов, можно хотеть отключить это поведение. Включение хранения данных предотвращает качество изображения путем базирования изменений на данных исходного изображения, в противоположность в настоящее время кэшируемой копии.

Для сохранения данных изображения для определенного изображения необходимо отправить a setDataRetained: обменивайтесь сообщениями к NSImage объект. Предпочтительно, необходимо сразу отправить это сообщение после создания объекта изображения. При отправке сообщения после рендеринга изображения или блокировки внимания на него Какао, возможно, должно считать данные изображения несколько раз.

Кэширование изображений отдельно

Для улучшения производительности большая часть кэширования изображений приложения происходит в один или несколько внеэкранные окна. Эти окна действуют как репозитории образов для приложения и не совместно используются другими приложениями. Какао управляет ими автоматически и присваивает изображения им на основе атрибутов текущего изображения.

По умолчанию Какао пытается сократить количество внеэкранных окон путем помещения повторных изображений в единственное окно. Для изображений, размер которых часто не изменяется, этот метод обычно быстрее, чем хранение каждого изображения в его собственном окне. Для изображений, размер которых действительно часто изменяется, может быть лучше кэшировать изображение отдельно путем отправки a setCachedSeparately: обменивайтесь сообщениями к объекту изображения.

Размер изображения и разрешение

Оба NSImage и NSImageRep определите методы для получения и установки размера изображения. Значение размеров может отличаться для каждого типа объекта, как бы то ни было. Для NSImage, размер всегда указывается в модулях пользовательского координатного пространства. Таким образом изображение, которое является 72 72 точками, всегда представляется в 1-дюймовом квадрате. Для NSImageRep, размер обычно связывается к размеру собственного или кэшированного растрового изображения. Для независимых от разрешения представлений изображения кэшированное растровое изображение создается чьи соответствия размера который возвращенный NSImage. Для истинных растровых изображений, однако, размер равен ширине и высоте (в пикселях) растрового изображения.

Если Вы создаете свое изображение из объекта данных или файла, NSImage объект берет свою информацию о размере изображения от предоставленных данных. Например, с данными EPS, размер взят от ограничительного прямоугольника, тогда как с данными TIFF, размер взят от ImageLength и ImageWidth поля. Когда Вы инициализируете, при создании пустого изображения необходимо установить размер изображения сами NSImage объект.

Можно изменить размер изображения в любое время с помощью setSize: метод также NSImage или NSImageRep. Размер, возвращенный NSImage версия метода представляет размерности изображения в пользовательском координатном пространстве. Изменение этого значения поэтому изменяет размер изображения, поскольку это нарисовано в одном из Ваших представлений. Это изменение обычно влияет только на кэшируемую копию данных изображения, если Вы существуете. Изменение размера объекта представления изображения изменяется, фактическое число битов раньше содержало данные изображения. Это изменение прежде всего влияет на растровые изображения и может привести к потере данных для Вашей копии в памяти изображения.

Если размер данных в представлении изображения меньше, чем прямоугольник, в котором это будет представлено, изображение должно масштабироваться для адаптации целевому прямоугольнику. Для независимых от разрешения изображений, таких как изображения PDF, масштабирование является меньшим количеством проблемы. Для растровых изображений, однако, пиксельные значения в битовом массиве должны быть интерполированы для заполнения дополнительного пространства. Таблица 5-4 перечисляет доступные настройки интерполяции.

Табличные 5-4  константы Интерполяции изображения

Постоянная интерполяция

Описание

NSImageInterpolationDefault

Используйте интерполяцию контекста по умолчанию.

NSImageInterpolationNone

Никакая интерполяция.

NSImageInterpolationLow

Быстро, низкокачественная интерполяция.

NSImageInterpolationMedium

Среднее качество, медленнее, чем низкокачественная интерполяция.

NSImageInterpolationHigh

Высшее качество, медленнее, чем интерполяция среднего качества.

Предыдущие настройки интерполяции управляют и качеством и скоростью алгоритма интерполяции. Для изменения текущих настроек интерполяции используйте setImageInterpolation: метод NSGraphicsContext.

С хранением данных, отключенным в изображении, масштабируя изображение многократно, может серьезно ухудшить получающееся качество изображения. Создание изображения, меньшего посредством масштабирования, является работой с потерями. При последующем создании изображения больше снова путем масштабирования результаты основываются на упрощенной версии изображения.

При необходимости в нескольких различных размерах изображения Вы могли бы хотеть создать объекты представления повторного изображения, один для каждого размера, избежать любого поведения с потерями. Также можно использовать setDataRetained: метод, чтобы гарантировать, что кэширующаяся система имеет доступ к данным исходного изображения.

Отобразите системы координат

Как представления, NSImage объекты используют свою собственную систему координат для управления их содержанием, которое в этом случае является самими данными изображения. Эта внутренняя система координат независима от любого содержащего представления, в которые нарисовано изображение. Несмотря на то, что Вы могли бы думать, понимая, что эта система координат важна для рисования изображений в Ваших представлениях, это фактически не. Цель внутренней системы координат состоит в том, чтобы ориентировать сами данные изображения. В результате единственное время, которое необходимо когда-либо должны быть знать об этой внутренней системе координат, - при создании нового изображения путем соединения фокуса NSImage объект и вовлечение его.

Объекты изображения имеют две возможных ориентации: стандарт и зеркально отраженный. Когда Вы создаете новое, пустое NSImage объект, можно установить ориентацию на основе того, как Вы хотите нарисовать данные изображения. По умолчанию изображения используют стандартную Декартову (незеркально отраженную) систему координат, но можно вынудить их использовать зеркально отраженную систему координат путем вызова setFlipped: метод NSImage до получения. Необходимо всегда устанавливать ориентацию изображения, прежде чем Вы заблокируете внимание на изображение и начнете рисовать все же. Изменение ориентации системы координат после a lockFocus вызов не имеет никакого эффекта. Кроме того, вызов setFlipped: метод после разблокирования фокуса снова может не иметь желаемых результатов и должен избежаться.

При рисовании изображений в представлении можно думать об изображении как просто прямоугольник с некоторыми данными в нем. Независимо от ориентации его внутренней системы координат Вы всегда помещаете изображение относительно системы координат текущего представления. Рисунок 5-1 показывает два изображения, нарисованные в незеркально отраженном представлении. Код, используемый для рисования каждого изображения, использует координатные точки, показанные в числе, которые находятся в (незеркально отраженной) системе координат представления. Поскольку первое изображение использует зеркально отраженную систему координат внутренне, однако, оно рисует свое содержание вверх тормашками.

  Ориентация изображения рисунка 5-1 в незеркально отраженном представлении
Image orientation in an unflipped view

Получение по сравнению с составлением композита

NSImage класс предлагает различные группы методов для упрощения рисования изображений к текущему контексту. Две основных группы методов могут обычно категоризироваться как «получение» по сравнению с «составляющими композит» методами. Существует три метода «получения» NSImage:

Методы рисования среди обычно используемых методов NSImage из-за их основной безопасности. Изображения обычно представляются во внеэкранных окнах и затем копируются в экран по мере необходимости. В некоторых случаях несколько изображений могут быть составлены в то же окно по причинам эффективности. Методы получения используют дополнительную проверку безопасности, чтобы гарантировать, что только содержание текущего изображения когда-либо рисуется в одном из Ваших представлений. То же не верно для методов составления композита, из которых существует следующее:

Эти методы могут быть более эффективными, чем методы рисования, потому что они выполняют, меньше проверяют границы изображения. Эти методы действительно имеют другие способы поведения, которые необходимо понять, как бы то ни было. Самое важное поведение состоит в том, что методы составления композита отменяют любой масштаб, или факторы вращения (но не факторы перевода) применились к CTM до получения. Если Вы нарисуете в зеркально отраженном представлении или вручную примененном масштабировании, или вращение оценивает текущему контексту, то эти методы проигнорируют те трансформации. Несмотря на то, что это могло бы походить на проблему, это фактически может быть очень полезный инструмент. Например, если Ваша программа масштабирует графический элемент, Вы могли бы хотеть добавить, что масштаб оценивает Вашему преобразованию, чтобы сделать масштабирование (по крайней мере, временно). Если Ваш элемент использует основанные на изображении маркеры выделения, Вы могли бы использовать методы составления композита, чтобы препятствовать тому, чтобы те дескрипторы масштабировались вместе с остальной частью Вашего графического элемента.

Другая вещь помнить о методах составления композита состоит в том, что ни один из них не позволяет Вам масштабировать свое изображение к целевому прямоугольнику. Какао составляет все изображение (или определяемая часть этого) поразрядно к указанному расположению. Это в отличие от drawInRect:fromRect:operation:fraction: метод, позволяющий Вам масштабировать все или часть Вашего изображения к определяемому целевому прямоугольнику в Вашем представлении.

Форматы поддерживаемого файла изображения

Какао поддерживает много общих форматов изображения внутренне и может импортировать данные изображения еще из многих форматов с помощью Изображения платформа I/O (ImageIO.framework).

Основные форматы

Таблица 5-5 перечисляет форматы, поддерживаемые исходно Какао. (Прописные версии расширений файла также распознаны.)

Табличное 5-5  Какао поддерживало форматы файлов

Формат

Расширения файла

UTI

Portable Document Format (PDF)

.pdf

com.adobe.pdf

Инкапсулированный формат PostScript (EPS)

.eps, .epi, .epsf, .epsi, .ps

Тегированный формат файлов изображений (TIFF)

.tiff, .tif

public.tiff

Совместная экспертная группа по фотографии (JPEG), JPEG 2000

.jpg, .jpeg, .jpe

public.jpeg, public.jpeg-2000

Формат обмена графическими данными (GIF)

.gif

com.compuserve.gif

Portable Network Graphic (PNG)

.png

public.png

Формат изображения Macintosh (PICT)

.pict, .pct, .pic

com.apple.pict

Формат Windows Bitmap (DIB)

.bmp, .BMPf

com.microsoft.bmp

Windows Icon Format

.ico

com.microsoft.ico

Формат файла значка

.icns

com.apple.icns

Сжатие TIFF

Изображения TIFF могут быть считаны из сжатых данных, пока алгоритм сжатия является одной из этих четырех схем, описанных в Таблице 5-6.

Таблица 5-6  настройки сжатия TIFF

Сжатие

Описание

LZW

Сжатия и распаковки без информационной потери, достигая коэффициентов сжатия до 5:1. Это может быть несколько медленнее, чтобы сжать и распаковать, чем схема PackBits.

PackBits

Сжатия и распаковки без информационной потери, но может не достигнуть тех же коэффициентов сжатия как LZW.

JPEG

Сжатие JPEG больше не поддерживается в файлах TIFF, и этот фактор проигнорирован.

CCITTFAX

Сжатия и полутоновые изображения распаковок 1 бита с помощью международных стандартов сжатия CCITT3 и CCITT4 факса.

NSImage объект может также произвести, сжал данные TIFF с помощью любой из этих схем. Для получения данных TIFF используйте TIFFRepresentationUsingCompression:factor: метод NSImage.

Поддержка других форматов файлов

В OS X v10.4 и позже, NSImage поддержки много дополнительных форматов файлов с помощью Изображения платформа I/O. Для получения полного списка поддерживаемых расширений файла используйте imageFileTypes метод класса NSImage. Список поддерживаемых форматов файлов продолжает расти, но Таблица 5-7 перечисляет некоторые из большего количества распространенных форматов, которые могут быть импортированы.

Таблица 5-7  Дополнительные форматы поддерживается Какао

Ввести

Расширение файла

Adobe RAW

.dng

Canon 2 RAW

.cr2

Canon RAW

.crw

FlashPix

.fpx, .fpix

Фуджи RAW

.raf

Kodak RAW

.dcr

Макпэйнт

.ptng, .pnt, .mac

Minolta RAW

.mrw

Nikon RAW

.nef

Olympus RAW

.orf

OpenEXR

.exr

Photoshop

.psd

Формат импорта QuickTime

.qti, .qtif

Сияние

.hdr

SGI

.sgi

Sony RAW

.srf

Тарга

.targa, .tga

Windows Cursor

.cur

Битовый массив XWindow

.xbm

Платформа I/O Изображения является частью Кварца, несмотря на то, что фактическая платформа является частью платформы Прикладных служб. Отобразите дескрипторы I/O импорт и экспорт многих форматов файлов. Для использования Кварца непосредственно Вы читаете данные изображения с помощью CGImageSourceRef непрозрачный тип и запись с помощью CGImageDestinationRef ввести. Для получения дополнительной информации об использовании Изображения платформа I/O, чтобы читать и записать изображения, посмотрите Ссылку Ссылки и CGImageDestination CGImageSource.

Инструкции для Использования изображений

Вот некоторые инструкции, чтобы помочь Вам работать с изображениями эффективнее:

OS X определяет несколько технологий для работы с изображениями. Несмотря на то, что NSImage класс является хорошим классом общего назначения для создания, управления и рисования изображений, могут быть времена, когда это могло бы быть проще или более эффективным использовать другие технологии формирования изображений. Например, вместо того, чтобы вручную распасться от одного изображения до другого путем рисования частично прозрачных версий каждого изображения в течение долгого времени, было бы более эффективно использовать Базовое Изображение для выполнения растворить работы для Вас. Для получения информации о других технологиях изображения, и когда Вы могли бы использовать их, посмотрите Выбор Right Imaging Technology.

Создание объекты NSImage

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

Загрузка существующего изображения

Для существующих изображений можно загрузить изображение непосредственно из файла или URL с помощью методов NSImage. Когда Вы открываете файл образа, NSImage автоматически создает представление изображения что лучшие соответствия тип данных в том файле. Какао поддерживает многочисленные форматы файлов внутренне. В OS X v10.4 и позже, Какао поддерживает еще больше форматов файлов с помощью Изображения платформа I/O. Для получения информации о поддерживаемых типах файлов посмотрите Форматы Поддерживаемого файла изображения.

Следующий пример показывает, как загрузить существующее изображение из файла. Важно помнить, что изображения, загруженные из существующего файла, предназначаются прежде всего для рендеринга. Если Вы хотите управлять данными непосредственно, скопируйте их во внеэкранное окно или другую локальную структуру данных и управляйте ими там.

NSString* imageName = [[NSBundle mainBundle]
                    pathForResource:@"image1" ofType:@"JPG"];
NSImage* tempImage = [[NSImage alloc] initWithContentsOfFile:imageName];

Загрузка именованного изображения

Для часто используемых изображений можно использовать именованный реестр изображения Набора Приложения, чтобы загрузить и сохранить их. Этот реестр обеспечивает быстрый и удобный способ получить изображения, не создавая новое NSImage возразите каждый раз. Можно добавить изображения к этому реестру явно, или можно использовать сам реестр для загрузки известной системы или специализированных изображений, таких как следующее:

  • Образы системы, сохраненные в Resources каталог платформы Набора Приложения

  • Значок Вашего приложения или другие изображения расположились в Resources каталог Вашего основного пакета.

Для получения изображений из реестра Вы используете imageNamed: метод класса NSImage. Этот метод смотрит в реестре для изображения, связанного с именем, которое Вы обеспечиваете. Если ни один не найден, это ищет изображение среди совместно используемых ресурсов Набора Приложения. После этого это ищет файл в Resources каталог Вашего комплекта приложений, и наконец это проверяет пакет Набора Приложения. Если это находит файл образа, это загружает изображение, добавляет его к реестру и возвращает соответствие NSImage объект. Пока соответствующий объект изображения сохраняется где-нибудь Вашим кодом, последующие попытки получить тот же файл образа возвращают уже загруженный NSImage объект.

Для получения значка приложения попросите изображение с константой, NSImageNameApplicationIcon (на версиях OS X прежде v10.6, можно использовать строку @"NSApplicationIcon"). Пользовательский значок Вашего приложения возвращается, если он имеет тот; иначе, Какао возвращает значок универсального приложения, предоставленный системой. Для списка названий картинки можно использовать, чтобы загрузить другие стандартные образы системы, видеть раздел констант в Ссылке класса NSImage.

В дополнение к загрузке существующих файлов изображения можно также добавить изображения к реестру явно путем отправки a setName: обменивайтесь сообщениями к NSImage объект. setName: метод добавляет изображение к реестру под определяемым именем. Вы могли бы использовать этот метод в случаях, где изображение создавалось динамично или не расположено в Вашем комплекте приложений.

Рисование к изображению путем блокировки фокуса

Возможно создать изображения программно путем соединения фокуса NSImage объект и вовлечение других изображений или путей в контекст изображения. Этот метод является самым полезным для создания изображений, которые Вы намереваетесь представить на экран, несмотря на то, что можно также сохранить получающиеся данные изображения к файлу.

Перечисление 5-1 показывает Вам, как создать новое пустое изображение и сконфигурировать его для рисования. При создании пустого изображения необходимо указать размер нового изображения в пикселях. Если Вы блокируете внимание на изображение, содержащее существующее содержание, новое содержание составляется со старым содержанием. При рисовании можно использовать любые подпрограммы, которые Вы обычно использовали бы при рисовании для представления.

  Получение перечисления 5-1 к изображению

NSImage* anImage = [[NSImage alloc] initWithSize:NSMakeSize(100.0,  100.0)];
[anImage lockFocus];
 
// Do your drawing here...
 
[anImage unlockFocus];
 
// Draw the image in the current context.
[anImage drawAtPoint:NSMakePoint(0.0, 0.0)
            fromRect: NSMakeRect(0.0, 0.0, 100.0, 100.0)
            operation: NSCompositeSourceOver
            fraction: 1.0];

Рисование к изображению создает NSCachedImageRep объект или использование существующее кэшируемое представление изображения, если Вы существуете. Даже когда Вы используете lockFocusOnRepresentation: метод для блокировки на определенное представление изображения Вы не блокируете на само представление. Вместо этого Вы блокируете на кэшируемое внеэкранное окно, связанное с тем представлением изображения. Это поведение могло бы казаться запутывающим, но укрепляет понятие неизменности изображений и их представлений изображения.

Изображения и их представления считают неизменными для эффективности и соображений безопасности. Если бы Вы считаете файлы образа сохраненными в Вашем комплекте приложений, Вы действительно хотели бы внести постоянные изменения в исходное изображение? Вместо того, чтобы изменять данные исходного изображения, NSImage и его представления изображения изменяют копию тех данных. Изменение кэшируемой копии данных также более эффективно для основанного на экране получения, потому что данные уже находятся в формате, готовом к дисплею на экране.

Рисование внеэкранных изображений Используя основанный на блоке метод рисования поддерживать дисплеи высокого разрешения

Если Ваше приложение использует lockFocus и unlockFocus методы NSImage класс для внеэкранного получения, рассмотрите использование метода imageWithSize:flipped:drawingHandler: вместо этого (доступный в OS X v10.8). При использовании методов фокуса блокировки для рисования можно получить неожиданные результаты — любой, который Вы получите низкое разрешение NSImage возразите, что взгляды, неправильные, когда нарисовано, или Вы доберетесь 2x изображение, имеющее больше пикселей в его битовом массиве, чем Вы ожидаете.

Используя imageWithSize:flipped:drawingHandler: метод гарантирует, что Вы получите корректные результаты под стандартным и высоким разрешением. Обработчик получения является блоком, который может быть вызван каждый раз, когда изображение нарисовано к, и на любом потоке происходит получение. Необходимо удостовериться, что любое состояние, к которому Вы получаете доступ в блоке, сделано ориентированным на многопотоковое исполнение способом.

Код в блоке должен быть тем же кодом, который Вы использовали бы между lockFocus и unlockFocus методы.

Создание битового массива

Существует несколько различных способов создать битовые массивы в Какао. Некоторые из этих методов более удобны, чем другие, и некоторые могут не быть доступными во всех версиях OS X, таким образом, необходимо рассмотреть каждого тщательно. Следующий список суммирует наиболее распространенные методы и ситуации, в которых Вы могли бы использовать их:

  • Создать битовый массив из содержания существующего CIImage объект (в OS X v10.5 и позже), используйте initWithCIImage: метод NSBitmapImageRep.

  • Для создания битового массива из содержания Кварцевого изображения (в OS X v10.5 и позже) используйте initWithCGImage: метод NSBitmapImageRep. При инициализации битовых массивов с помощью этого метода необходимо обработать возвращенный битовый массив как объект только для чтения. Кроме того, необходимо избежать получать доступ к растровым данным непосредственно, поскольку выполнение так требует распаковки CGImageRef данные в отдельный набор буферов.

  • Для получения содержания существующего представления или изображения используйте один из следующих методов:

    • Внимание блокировки на требуемый объект и использование initWithFocusedViewRect: метод NSBitmapImageRep.

    • В OS X v10.4 и позже, используйте bitmapImageRepForCachingDisplayInRect: и cacheDisplayInRect:toBitmapImageRep: методы NSView. Первый метод создает представление растрового изображения, подходящее для использования в получении содержания представления в то время как вторые получения содержание представления к битовому массиву. Можно снова использовать объект представления растрового изображения обновлять содержание представления периодически, пока Вы не забываете очищать старый битовый массив прежде, чем получить новый.

  • Для рисования непосредственно в битовый массив создайте новое NSBitmapImageRep объект с параметрами Вы хотите и используете graphicsContextWithBitmapImageRep: метод NSGraphicsContext создать контекст получения. Сделайте новый контекст текущим контекстом и нарисуйте. Этот метод доступен только в OS X v10.4 и позже.

    Также можно создать NSImage объект (или внеэкранное окно), вовлеките его, и затем получите содержимые изображения. Этот метод поддерживается во всех версиях OS X.

  • Для создания битового массива поразрядно создайте новое NSBitmapImageRep объект с параметрами Вы хотите и управляете пикселями непосредственно. Можно использовать bitmapData метод для получения буфера необработанного пикселя. NSBitmapImageRep также определяет методы для получения и установки отдельных пиксельных значений. Этот метод является самым трудоемким, но дает Вам большую часть контроля растровым содержанием. Например, Вы могли бы использовать его, если Вы хотите декодировать необработанные данные изображения сами и передать их представлению растрового изображения.

Следующие разделы обеспечивают примеры того, как использовать первые два метода из предыдущего списка. Для получения информации о том, как управлять битовым массивом, посмотрите Ссылку класса NSBitmapImageRep.

Получение содержания представления или изображения

Простой способ создать битовый массив состоит в том, чтобы получить содержание существующего представления или изображения. При получении представления представление может или принадлежать экранному окну или быть полностью отсоединено и не на экране вообще. При получении изображения Какао выбирает представление изображения, обеспечивающее лучшее соответствие для целевого битового массива.

Прежде, чем попытаться получить содержание представления, необходимо рассмотреть вызов представления canDraw метод, чтобы видеть, должно ли быть нарисовано представление. Какао просматривает возврат NO от этого метода в ситуациях, где представление в настоящее время скрыто или не связывается с допустимым окном. При попытке получить текущее состояние представления, Вы могли бы использовать canDraw метод, чтобы препятствовать тому, чтобы Ваш код получил представление, когда это скрыто.

Как только Вы имеете свое представление или изображение, блокируете внимание на него и используете initWithFocusedViewRect: метод NSBitmapImageRep получать содержание. При использовании этого метода Вы указываете точный прямоугольник, который Вы хотите получить от представления или изображения. Таким образом можно получить все содержание или только часть; Вы не можете масштабировать содержание, которое Вы получаете. initWithFocusedViewRect: метод получает биты точно, поскольку они появляются в фокусируемом изображении или представлении.

Перечисление 5-2 показывает, как создать растровое представление от существующего изображения. Пример заставляет изображение получать от пользовательской подпрограммы, внимания блокировок на нее, и создает NSBitmapImageRep объект. Ваша собственная реализация должна была бы заменить вызов к myGetCurrentImage с кодом для создания или использовали изображение программой.

Перечисление 5-2  Получая содержание существующего изображения

NSImage* image = [self myGetCurrentImage];
NSSize size = [image size];
[image lockFocus];
 
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:
                        NSMakeRect(0,0,size.width,size.height)];
 
[image unlockFocus];

Для получения содержания экранного представления Вы использовали бы код очень как предыдущий пример. После блокировки внимания на представление Вы создали бы Ваш NSBitmapImageRep объект с помощью initWithFocusedViewRect: метод.

Для получения содержания отдельного (внеэкранного) представления необходимо создать внеэкранное окно для представления, прежде чем Вы попытаетесь получить его содержание. Объект окна обеспечивает отступающий буфер, в котором можно содержать представленное содержание представления. Пока Вы не упорядочиваете окно на экран, источник, который Вы указываете для своего окна, действительно не имеет значения. Пример в Перечислении 5-3 использует большие отрицательные величины для координат источника (только, чтобы удостовериться, что окно не видимо), но мог так же, как легко использовать координату (0, 0).

  Получение перечисления 5-3 к внеэкранному окну

NSRect offscreenRect = NSMakeRect(-10000.0, -10000.0,
                            windowSize.width, windowSize.height);
NSWindow* offscreenWindow = [[NSWindow alloc]
                initWithContentRect:offscreenRect
                styleMask:NSBorderlessWindowMask
                backing:NSBackingStoreRetained
                defer:NO];
 
[offscreenWindow setContentView:myView];
[[offscreenWindow contentView] display]; // Draw to the backing  buffer
 
// Create the NSBitmapImageRep
[[offscreenWindow contentView] lockFocus];
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:
                NSMakeRect(0, 0, windowSize.width, windowSize.height)];
 
// Clean up and delete the window, which is no longer needed.
[[offscreenWindow contentView] unlockFocus];
[offscreenWindow release];

Рисование непосредственно к битовому массиву

В OS X v10.4 и позже, возможно создать представление растрового изображения, возражают и рисуют к нему непосредственно. Этот метод прост и не требует создания никаких посторонних объектов, таких как изображение или окно. Если Ваш код должен работать в более ранних версиях OS X, однако, Вы не можете использовать этот метод.

Перечисление 5-4, создает новое NSBitmapImageRep объект с желаемой битовой глубиной, разрешением и цветовым пространством. Это тогда создает новый графический объект контекста с помощью битового массива и делает тот контекст текущим контекстом.

Перечисление 5-4  , Рисующее непосредственно к битовому массиву

NSRect offscreenRect = NSMakeRect(0.0, 0.0, 500.0, 500.0);
NSBitmapImageRep* offscreenRep = nil;
 
offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
                        pixelsWide:offscreenRect.size.width
                        pixelsHigh:offscreenRect.size.height
                        bitsPerSample:8
                        samplesPerPixel:4
                        hasAlpha:YES
                        isPlanar:NO
                        colorSpaceName:NSCalibratedRGBColorSpace
                        bitmapFormat:0
                        bytesPerRow:(4 * offscreenRect.size.width)
                        bitsPerPixel:32];
 
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
                        graphicsContextWithBitmapImageRep:offscreenRep]];
 
// Draw your content...
 
[NSGraphicsContext restoreGraphicsState];

Как только получение завершено, можно добавить объект представления растрового изображения к NSImage объект и дисплей это как любое другое изображение. Можно использовать этот объект представления изображения, поскольку текстура в OpenGL кодирует или исследует биты битового массива с помощью методов NSBitmapImageRep.

Создание PDF или представления изображения EPS

Процесс для создания представления изображения для PDF или данных EPS является тем же для обоих. В обоих случаях Вы используете пользовательское NSView возразите вместе с системой печати Какао для генерации желаемых данных. От сгенерированных данных Вы тогда создаете представление изображения желаемого типа.

NSView класс определяет два удобных метода для генерации данных на основе содержания представления:

При отправке одного из этих сообщений к представлению Какао запускает систему печати, управляющую процессом генерации данных. Система печати обрабатывает большую часть процесса генерации данных, отправление надлежащих сообщений к Вашему представлению возражает по мере необходимости. Например, Какао отправляет a drawRect: обменивайтесь сообщениями к своему представлению для каждой страницы, которая должна быть нарисована. Система печати также вызывает другие методы для вычислений диапазонов страницы и границ.

После системных концов печати, код, вызвавший также dataWithPDFInsideRect: или dataWithEPSInsideRect: получает NSData объект с PDF или данными EPS. Необходимо тогда передать этот объект imageRepWithData: метод также NSEPSImageRep или NSPDFImageRep инициализировать новый объект представления изображения, который можно тогда добавить к Вашему NSImage объект.

Перечисление 5-5 показывает основные шаги для создания изображения PDF от некоторого содержания представления. Само представление должно быть тем, знающим, как нарисовать желаемое содержание. Это может быть независимым взглядом, разработанным исключительно для рисования желаемого содержания с любым желаемым разбиением на страницы, или это могло быть существующее представление в одном из Ваших окон.

Перечисление 5-5  , Создающее данные PDF из представления

MyPDFView* myView = GetMyPDFRenderView();
NSRect viewBounds = [myView bounds];
 
NSData* theData = [myView dataWithPDFInsideRect:viewBounds];
NSPDFImageRep* pdfRep = [NSPDFImageRep imageRepWithData:theData];
 
// Create a new image to hold the PDF representation.
NSImage* pdfImage = [[NSImage alloc] initWithSize:viewBounds.size];
[pdfImage addRepresentation:pdfRep];

Если Вы принимаете решение использовать существующее экранное представление, код для прорисовки Вашего представления должен различить содержание, нарисованное для экрана или для системы печати, и скорректировать содержание соответственно. Используйте currentContextDrawingToScreen метод класса или isDrawingToScreen метод экземпляра NSGraphicsContext определить, предназначен ли текущий контекст для экрана или основанного на печати холста. Эти методы возврат NO для операций, генерирующих данные EPS или PDF.

Используя кварцевое изображение для создания NSImage

NSImage класс не обеспечивает прямых средних значений для обертывания данных от Кварцевого объекта изображения. Если у Вас есть a CGImageRef объект, самый простой способ создать соответствующее изображение Какао состоит в том, чтобы соединить фокус NSImage возразите и нарисуйте свое Кварцевое изображение с помощью CGContextDrawImage функция. Основные методы для того, как сделать это, охвачены в Рисовании к Изображению путем Блокировки Фокуса.

Работа с изображениями

Как только у Вас есть изображение, существует много способов, которыми можно использовать его. Самая простая вещь, которую можно сделать, вовлекают его в представление как часть пользовательского интерфейса программы. Можно также обработать изображение далее путем изменения его в любом числе путей. Следующие разделы показывают Вам, как выполнить несколько общих задач, связанных с изображениями.

Вовлечение изображений в представление

NSImage класс определяет несколько методов для того, чтобы вовлечь изображение в текущий контекст. Два обычно используемых метода:

Эти методы предлагают простой интерфейс для рендеринга Ваших изображений, но что еще более важно, они гарантируют, что только нарисовано Ваше содержимое изображения. Другие методы, такой как compositeToPoint:operation: метод и его варианты, быстры в рисовании изображений, но они не проверяют границы изображения перед получением. Если прямоугольник получения отклоняется за пределами границ изображения, возможно нарисовать содержание, не принадлежащее Вашему изображению. Если изображение находится на совместно используемом внеэкранном окне, которое многие делают, даже возможно нарисовать части других изображений. Для получения дополнительной информации о различиях между этими методами, см. Получение По сравнению с Составлением композита.

За одним исключением все получение и составление композита методов выбирает представление изображения, подходящее лучше всего для целевого холста — видят, Как Выбрано Представление Изображения. Одно исключение drawRepresentation:inRect: метод, использующий представление изображения, возражает, что Вы указываете. Для получения дополнительной информации об использовании этих методов, посмотрите NSImage ссылка.

Изображения поддерживают тот же набор составляющих композит опций как другое содержание Какао с теми же результатами. Для полного списка составляющих композит опций и иллюстрации их эффектов, посмотрите, что Установка Составляет Опции.

Рисование текстур изменяемого размера Используя изображения

Если Вы реализуете пользовательский элемент управления изменяемого размера и хотите, чтобы управление имело текстурированный фон, не искажающий, поскольку управление изменено, Вы обычно разбивали бы фоновую часть в несколько различных изображений и составляли бы их вместе. Несмотря на то, что некоторые изображения содержали бы содержание фиксированного размера, другие должны будут быть разработаны для представления гладкой текстуры, даже будучи измененным или размещены рядом. Когда это прибывает время для рисования изображений, однако, необходимо избежать делать получение сами. Вместо этого необходимо использовать следующие функции AppKit, представленные в OS X v10.5:

Рисование многослойных изображений чисто на экранах с высокой разрешающей способностью может быть очень сложным. Если Вы не осторожны относительно выравнивания изображений правильно на целочисленных границах, получающаяся текстура могла бы содержать пиксельные трещины или другие визуальные артефакты. Функции AppKit принимают во внимание все факторы, требуемые нарисовать многослойные изображения правильно в любой ситуации, включая ситуации, где используются масштабные коэффициенты независимости разрешения кроме 1,0.

Рисунок 5-2 показывает, как Вы собираете трехчастное изображение для горизонтально управления изменяемого размера. Эти две заглушки являются изображениями фиксированного размера, обеспечивающими необходимое художественное оформление для краев фона. Центральная часть заливки тогда изменяет размеры соответственно для адаптации ограничительному прямоугольнику, который Вы передаете в NSDrawThreePartImage функция. (Если бы Вы хотели, чтобы управление было изменяемого размера в вертикальном направлении, то Вы сложили бы эти изображения вертикально вместо горизонтально.) После рисования фона с этой функцией Вы тогда разделили бы любое дополнительное содержание на уровни поверх фона по мере необходимости.

Рисунок 5-2  , Получающий трехчастное изображение
Drawing a three-part image

Рисунок 5-3 показывает Вам, как собрать изображение с девятью частями для управления, которое может быть изменено и вертикально и горизонтально. В этом случае размер угловых частей остается фиксированным, но пять остающихся изображений заливки варьируются по размеру для адаптации текущему ограничительному прямоугольнику.

Рисунок 5-3  , Получающий изображение с девятью частями
Drawing a nine-part image

Для получения дополнительной информации об этих функциях, см. их описания в Ссылке Функций AppKit.

Создание текстуры OpenGL

В OpenGL текстура является одним способом нарисовать поверхность объекта. Для сложных или фотореалистических поверхностей может быть проще применить текстуру, чем рендеринг тот же довольный использующие примитивные формы. Почти любое представление или изображение в Какао могут использоваться для создания текстуры OpenGL. От представления или изображения, Вы создаете объект представления растрового изображения (как описано в Получении Содержания Представления или Изображения) и затем используете тот объект создать Вашу текстуру.

Перечисление 5-6 показывает автономный метод для создания текстуры от NSImage объект. После создания NSBitmapImageRep объект, этот метод конфигурирует некоторые связанные с текстурой параметры, создает новый объект текстуры, и затем связывает растровые данные с тем объектом. Этот метод обрабатывает 24-разрядный RGB и 32-разрядные изображения RGBA, но Вы могли с готовностью изменить его для поддержки других форматов изображения. Необходимо передать в указателе на допустимое GLuint переменная для texName но значение, сохраненное в том параметре, может быть 0. При указании ненулевого значения идентификатор связан с объектом текстуры и может использоваться для идентификации текстуры позже; иначе, идентификатор возвращается Вам в texName параметр.

Перечисление 5-6  , Создающее OpenGL, текстурирует от изображения

- (void)textureFromImage:(NSImage*)theImg textureName:(GLuint*)texName
{
    NSBitmapImageRep* bitmap = [NSBitmapImageRep alloc];
    int samplesPerPixel = 0;
    NSSize imgSize = [theImg size];
 
    [theImg lockFocus];
    [bitmap initWithFocusedViewRect:
                    NSMakeRect(0.0, 0.0, imgSize.width, imgSize.height)];
    [theImg unlockFocus];
 
    // Set proper unpacking row length for bitmap.
    glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);
 
    // Set byte aligned unpacking (needed for 3 byte per pixel bitmaps).
    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
 
    // Generate a new texture name if one was not provided.
    if (*texName == 0)
        glGenTextures (1, texName);
    glBindTexture (GL_TEXTURE_RECTANGLE_EXT, *texName);
 
    // Non-mipmap filtering (redundant for texture_rectangle).
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER,  GL_LINEAR);
    samplesPerPixel = [bitmap samplesPerPixel];
 
    // Nonplanar, RGB 24 bit bitmap, or RGBA 32 bit bitmap.
    if(![bitmap isPlanar] &&
        (samplesPerPixel == 3 || samplesPerPixel == 4))
    {
        glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
            samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
            [bitmap pixelsWide],
            [bitmap pixelsHigh],
            0,
            samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
            GL_UNSIGNED_BYTE,
            [bitmap bitmapData]);
    }
    else
    {
        // Handle other bitmap formats.
    }
 
    // Clean up.
    [bitmap release];
}

В предыдущем коде существуют некоторые дополнительные точки, которые стоит упомянуть:

  • GL_TEXTURE_RECTANGLE_EXT используется для не питание двух поддержки текстуры, не поддерживающейся на Гневе 128 аппаратных средств.

  • gluScaleImage() функция может использоваться для масштабирования текстур не-PoT в размерности PoT для не поддерживающих аппаратных средств GL_TEXTURE_RECTANGLE_EXT.

  • При вызове этого метода текущий контекст должен быть допустимым контекстом OpenGL. Для получения дополнительной информации о контекстах графики OpenGL, посмотрите Используя OpenGL в Вашем Приложении.

  • После завершения текстура связывается со значением в texName. Если Вы указали 0 для texName параметр, новая текстура ID сгенерирован для Вас и возвращен в texName.

Для получения дополнительной информации о поддержке Apple OpenGL см. Руководство по программированию OpenGL для Mac.

Применение базовых фильтров изображения

В OS X v10.4 и позже, Базовые фильтры Изображения являются быстрым и эффективным способом изменить изображение, не изменяя само изображение. Базовые фильтры Изображения используют графическое ускорение для применения эффектов в реальном времени, таких как Гауссова размытость, искажения и коррекции цвета к изображению. Поскольку фильтры применяются, когда содержание составляется на экран, они не изменяют данные действительного образа.

Базовые фильтры Изображения воздействуют на CIImage объекты. Если у Вас есть существующее CIImage объект, можно просто применить любые желаемые фильтры к нему и использовать его для создания NSCIImageRep объект. Можно тогда добавить этот объект представления изображения к NSImage возразите и нарисуйте результаты в своем представлении. В OS X v10.5 и позже, можно также использовать initWithCIImage: метод NSBitmapImageRep представлять уже обработанные изображения непосредственно к растровому представлению.

Если у Вас уже нет a CIImage объект, необходимо создать тот с помощью существующего содержания программы. Первый шаг должен создать представление растрового изображения для содержания, которое Вы хотите изменить, процесс, для которого описан в Создании Битового массива. Как только Вы имеете NSBitmapImageRep объект, используйте initWithBitmapImageRep: метод CIImage создать Базовый объект изображения Изображения.

Для получения информации о том, как применить Базовые фильтры Изображения к a CIImage возразите, посмотрите Используя Базовое Изображение, Просачивается Базовое Руководство по программированию Изображения.

Получение и установка растровых свойств

Каждый NSBitmapImageRep объект содержит словарь, определяющий связанные свойства битового массива. Эти свойства идентифицируют важную информацию о битовом массиве, такой как, как это было сжато, его цветовой профиль (если таковые имеются), его текущий гамма уровень, его связанные данные EXIF, и т.д. Когда Вы создаете новое NSBitmapImageRep от существующего файла изображения многие из этих свойств установлены автоматически. Можно также получить доступ и изменить эти свойства с помощью valueForProperty: и setProperty:withValue: методы NSBitmapImageRep.

Для полного списка свойств можно получить и установить для битового массива, видеть Ссылку класса NSBitmapImageRep.

Преобразование битового массива к другому формату

NSBitmapImageRep класс предоставляет встроенную поддержку для преобразования растровых данных к нескольким стандартным форматам. Для преобразования растровых изображений в другие форматы можно использовать любой из следующих методов:

Первый набор методов генерирует данные TIFF для битового массива. Для всех других поддерживаемых форматов Вы используете representationOfImageRepsInArray:usingType:properties: и representationUsingType:properties: методы. Эти методы поддерживают преобразование растровых данных к BMP, GIF, JPEG, PNG и форматам файлов TIFF.

Все предыдущие методы возвращаются NSData объект с отформатированными данными изображения. Можно выписать эти данные к файлу или использовать их для создания новогоNSBitmapImageRep объект.

Соединение пользовательского цветового профиля с изображением

Можно связать пользовательский профиль ColorSync с a NSBitmapImageRep объект, содержащий пиксельные данные, произведенные путем декодирования TIFF, JPEG, GIF или файла PNG. Для соединения данных с представлением растрового изображения Вы используете setProperty:withValue: метод NSBitmapImageRep и NSImageColorSyncProfileData свойство. Перечисление 5-7 показывает пример того, как загрузить данные ColorSync и связать их с представлением растрового изображения.

Перечисление 5-7  , Добавляющее ColorSync, профилирует к изображению

@implementation NSBitmapImageRep (MoreColorMethods)
- (NSBitmapImageRep *) imageRepWithProfileAtPath:(NSString *) pathToProfile
{
    id result = [self copy];
 
    // Build an NSData object using the specified ColorSync profile
    id profile = [NSData dataWithContentsOfFile: pathToProfile];
 
    // Set the ColorSync profile for the object
    [result setProperty:NSImageColorSyncProfileData withValue:profile];
 
    return [result autorelease];
}
@end

В OS X v10.5, также возможно связать пользовательский цветовой профиль ICC с NSBitmapImageRep объект. Для этого необходимо инициализировать Ваш NSBitmapImageRep экземпляр с помощью калиброванного цветового пространства RGB (NSCalibratedRGBColorSpace). После этого Вы загружаете профиль и связываете соответствующий объект данных с NSImageColorSyncProfileData введите точно, как Вы были бы для профиля ColorSync.

Преобразование между цветовыми пространствами

Какао не обеспечивает прямых способов преобразовать изображения от одного цветового пространства до другого. Несмотря на то, что Какао полностью поддерживает цветовые пространства, включенные с существующими файлами изображения, нет никакого способа преобразовать данные изображения непосредственно с помощью NSImage. Вместо этого необходимо использовать комбинацию Кварца и Какао для преобразования данных изображения.

Создание целевого изображения

Преобразование цветового пространства существующего изображения требует, чтобы использование Кварца установило контекст получения, использующий пространство целевого цвета. Как только у Вас есть a CGContextRef объект с пространством требуемого цвета, можно использовать его, чтобы сконфигурировать среду рисования Какао и нарисовать изображение.

Перечисление 5-8 показывает Вам, как создать Кварцевый растровый контекст, использующий пространство пользовательского цвета. Эта функция получает a CMProfileRef объект, который можно получить от менеджера ColorSync или от colorSyncProfile метод NSColorSpace. Это использует цветовой профиль для определения числа каналов в цветовом пространстве. Как только это знает общее количество каналов (включая альфу) необходимый для битового массива, это создает и возвращает соответствующий растровый контекст.

Перечисление 5-8  , Создающее битовый массив с пользовательским цветовым профилем

CGContextRef CreateCGBitmapContextWithColorProfile(size_t width,
                size_t height,
                CMProfileRef profile,
                CGImageAlphaInfo alphaInfo)
{
    size_t bytesPerRow = 0;
    size_t alphaComponent = 0;
 
    // Get the type of the color space.
    CMAppleProfileHeader header;
    if (noErr != CMGetProfileHeader(profile, &header))
        return nil;
 
    // Get the color space info from the profile.
    CGColorSpaceRef csRef = CGColorSpaceCreateWithPlatformColorSpace(profile);
    if (csRef == NULL)
        return NULL;
 
    // Add 1 channel if there is an alpha component.
    if (alphaInfo != kCGImageAlphaNone)
        alphaComponent = 1;
 
    // Check the major color spaces.
    OSType space = header.cm2.dataColorSpace;
    switch (space)
    {
        case cmGrayData:
            bytesPerRow = width;
 
            // Quartz doesn’t support alpha for grayscale bitmaps.
            alphaInfo = kCGImageAlphaNone;
            break;
 
        case cmRGBData:
            bytesPerRow = width * (3 + alphaComponent);
            break;
 
        case cmCMYKData:
            bytesPerRow = width * 4;
 
            // Quartz doesn’t support alpha for CMYK bitmaps.
            alphaInfo = kCGImageAlphaNone;
            break;
 
        default:
            return NULL;
    }
 
    // Allocate the memory for the bitmap.
    void*   bitmapData = malloc(bytesPerRow * height);
 
    CGContextRef    theRef = CGBitmapContextCreate(bitmapData, width,
                                    height, 8,  bytesPerRow,
                                    csRef, alphaInfo);
 
    // Cleanup if an error occurs; otherwise, the caller is responsible
    // for releasing the bitmap data.
    if ((!theRef) && bitmapData)
        free(bitmapData);
 
    CGColorSpaceRelease(csRef);
    return theRef;
}

Как только у Вас есть Кварцевый растровый контекст, можно создать новый объект контекста графики Какао и использовать его для рисования. Создать NSGraphicsContext объект, Вы используете graphicsContextWithGraphicsPort:flipped: метод, берущий a CGContextRef объект в качестве параметра. Вы тогда используете setCurrentContext: метод, чтобы сделать его текущим и начать рисовать. Когда Вы сделаны, таща, Вы используете Кварц для создания a CGImageRef объект, содержащий результаты. Перечисление 5-9 показывает этот процесс.

Перечисление 5-9  , Преобразовывающее битовый массив в различное цветовое пространство

- (CGImageRef) convertBitmapImageRep:(NSBitmapImageRep*)theRep toColorSpace:(NSColorSpace*)colorspace
{
    if (!theRep)
        return nil;
 
    // Map the Cocoa constants returned by -bitmapFormat to their
    // Quartz equivalents.
    CGImageAlphaInfo alphaInfo = GetAlphaInfoFromBitmapImageRep(theRep);
 
    // Get the rest of the image info.
    NSSize imageSize = [theRep size];
    size_t width = imageSize.width;
    size_t height = imageSize.height;
    CMProfileRef profile = (CMProfileRef)[colorspace colorSyncProfile];
 
    // Create a new 8-bit bitmap context based on the image info.
    CGContextRef cgContext = CreateCGBitmapContextWithColorProfile(width,
                                     height, profile, alphaInfo);
 
    if (cgContext == NULL)
        return NULL;
 
    // Create an NSGraphicsContext that draws into the CGContext.
    NSGraphicsContext *graphicsContext = [NSGraphicsContext
             graphicsContextWithGraphicsPort:cgContext flipped:NO];
 
    // Make the NSGraphicsContext current and draw into it.
    [NSGraphicsContext saveGraphicsState];
    [NSGraphicsContext setCurrentContext:graphicsContext];
 
    // Create a new image for rendering the original bitmap.
    NSImage*  theImage = [[[NSImage alloc] initWithSize:imageSize] autorelease];
    [theImage addRepresentation:theRep];
 
    // Draw the original image in the Quartz bitmap context.
    NSRect imageRect = NSMakeRect(0.0, 0.0, imageSize.width, imageSize.height);
    [theImage drawAtPoint:NSMakePoint(0.0, 0.0)
                fromRect:imageRect
                operation: NSCompositeSourceOver
                fraction: 1.0];
    [NSGraphicsContext restoreGraphicsState];
 
    // Create a CGImage from the CGContext's contents.
    CGImageRef cgImage = CGBitmapContextCreateImage(cgContext);
 
    // Release the context. Note that this does not release the bitmap data.
    CGContextRelease(cgContext);
 
    return cgImage;
}

Существует два способа добраться NSImage объект от a CGImageRef ввести. В OS X v10.5 и позже, можно создать NSBitmapImageRep объект с помощью initWithCGImage: метод и затем добавляет что представление изображения NSImage объект. Если Ваш код должен работать в версиях OS X v10.4 или ранее, однако, можно соединить фокус NSImage возразите и используйте CGContextDrawImage функция для вовлечения Кварцевого изображения в изображение. Этот последний метод создает копию данных изображения и требует большего усилия, чем использование initWithCGImage: метод, но доступен на всех версиях OS X. Перечисление 5-10 показывает выборочный метод, демонстрирующий оба подхода, но всегда использующий лучший подход, доступный для целевой платформы.

Перечисление 5-10  Используя CGImageRef возражает для создания объекта NSImage

- (NSImage*)imageFromCGImageRef:(CGImageRef)image
{
    NSImage* newImage = nil;
 
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
    NSBitmapImageRep*    newRep = [[NSBitmapImageRep alloc] initWithCGImage:image];
    NSSize imageSize;
 
    // Get the image dimensions.
    imageSize.height = CGImageGetHeight(image);
    imageSize.width = CGImageGetWidth(image);
 
    newImage = [[NSImage alloc] initWithSize:imageSize];
    [newImage addRepresentation:newRep];
 
#else
 
    NSRect imageRect = NSMakeRect(0.0, 0.0, 0.0, 0.0);
    CGContextRef imageContext = nil;
 
    // Get the image dimensions.
    imageRect.size.height = CGImageGetHeight(image);
    imageRect.size.width = CGImageGetWidth(image);
 
    // Create a new image to receive the Quartz image data.
    newImage = [[NSImage alloc] initWithSize:imageRect.size];
    [newImage lockFocus];
 
    // Get the Quartz context and draw.
    imageContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
    CGContextDrawImage(imageContext, *(CGRect*)&imageRect, image);
    [newImage unlockFocus];
 
#endif
 
    return [newImage autorelease];
}

Используя пользовательский цветовой профиль

Если Вы имеете существующий профиль ICC и хотите связать тот профиль с изображением, необходимо сделать настолько использующий менеджера ColorSync. Если Вы работаете с Кварцем графические контексты, Вы используете профиль ICC для получения информации о цветовом пространстве, должен был создать a CGImageRef объект. Можно тогда использовать ту информацию о цветовом пространстве для создания надлежащего контекста для рендеринга изображения.

Перечисление 5-11 показывает Вам, как создать a CGColorSpaceRef объект от профиля ICC. Этот код использует несколько менеджеров ColorSync функции для создания a CMProfileRef объект, из которого можно тогда извлечь объект цветового пространства. OS X включает несколько стандартных профилей ICC в /System/Library/ColorSync/Profiles/ каталог.

Перечисление 5-11  , Создающее цветовое пространство от пользовательского цветового профиля

CGColorSpaceRef CreateColorSpaceForProfileAtPath(NSString* path)
{
    CMProfileLocation profileLoc;
    CMProfileRef profileRef;
    CGColorSpaceRef csRef = NULL;
 
    // Specify where the ICC profile data file is located.
    profileLoc.locType = cmPathBasedProfile;
    strncpy(profileLoc.u.pathLoc.path, [path fileSystemRepresentation],  255);
 
    // Get the ColorSync profile information from the data file.
    CMOpenProfile(&profileRef, &profileLoc);
 
    // Use the profile to create the color space object.
    csRef = CGColorSpaceCreateWithPlatformColorSpace(profileRef);
    CMCloseProfile(profileRef);
 
    return csRef;
}

Для получения дополнительной информации о ColorSync и его функциях, посмотрите менеджера ColorSync Референса.

Предварительное умножение альфа-значений для битовых массивов

Несмотря на то, что предварительное умножение альфа-значений раньше было распространенным способом улучшить производительность при рендеринге битовых массивов, метод не рекомендуется для программ, работающих в OS X. Умножение в обратном порядке вовлекает умножающиеся значения в альфа-канал битового массива с соответствующими пиксельными значениями и хранением результатов назад к исходному файлу битового массива. Когда битовый массив составляется с другим содержанием, цель умножения в обратном порядке состоит в том, чтобы сократить количество вычислений, выполняемых. В OS X умножение в обратном порядке может фактически привести к большему количеству вычислений.

В OS X коррекция цвета является неотъемлемой частью операционной системы. Чтобы к смесевым цветам правильно, ColorSync нужны исходные пиксельные значения цвета. Если битовый массив содержит предварительно умноженные значения цвета, ColorSync должен отменить умножение в обратном порядке, прежде чем это сможет проверить цвета. Этот дополнительный шаг добавляет существенное количество работы к системе, потому что это должно быть выполнено каждый раз, когда цвета проверяются.

Единственная причина рассмотреть умножение в обратном порядке альфа-значений для Ваших битовых массивов состоит в том, если Ваши данные уже предварительно умножаются и отъезд его, тот путь выгоден для модели данных Вашей программы. Несмотря на это, необходимо сделать, некоторые тесты производительности для наблюдения при использовании предварительно умноженных битовых массивов повреждают полную производительность приложения. Какао включает управление цветом во многие части платформы. Если Ваши пути выполнения кода используют эти части платформы, Вы могли бы счесть его выгодным для изменения модели.

Создание новых классов представления изображения

Если Вы хотите добавить поддержку новых форматов изображения или генерировать изображения от других типов информации об источнике, можно хотеть разделить на подклассы NSImageRep. Несмотря на то, что Какао поддерживает много форматов изображения непосредственно и многих более косвенно через Изображение платформа IO, разделяя на подклассы NSImageRep дает Вам контроль над обработкой данных изображения, одновременно поддерживая тесную интеграцию с NSImage класс. Если Вы решаете разделить на подклассы, необходимо обеспечить реализации для следующих методов:

Эти методы обеспечивают основной интерфейс что родитель NSImageRep класс должен взаимодействовать с Вашим подклассом. Методы предоставляют информацию о том, какие данные изображения форматируют Ваши поддержки класса вместе с точками входа для инициализации Вашего объекта и рисования изображения.

Прежде чем Ваш подкласс может использоваться, он должен быть зарегистрирован в Наборе Приложения. Необходимо сделать это рано в выполнении приложения путем вызова registerImageRepClass: метод класса NSImageRep. Регистрация Вашего класса позволяет Какао знать, что Ваш класс существует и что это может обработать определенный набор типов файлов. Ваша реализация imageUnfilteredTypes метод должен возвратить массив типов UTI, соответствующих типам файла изображения Ваши поддержки класса непосредственно.

Другой метод, который необходимо всегда переопределять, canInitWithData: метод. Как только Ваш класс представления изображения был идентифицирован как обработка определенного типа данных, Какао может уведомить его, когда получены данные надлежащего типа. В то время Какао передает объект данных Вашему canInitWithData: метод. Ваша реализация этого метода должна исследовать данные быстро и проверить, что это может действительно обработать формат.

Как только Ваш класс выбран для обработки данных изображения, Какао ищет initWithData: метод и использование это для инициализации объекта с данными изображения. Ваша реализация этого метода должна сохранить данные и использовать его для инициализации объекта. В некоторый момент позже, Ваш draw метод можно вызвать для рендеринга данных в текущем контексте. Ваш draw метод должен представить данные в текущей точке источника и с текущим размером и настройками, указанными NSImageRep родительский класс.