Открыть сервис

CGBitmapContextCreate

CGBitmapContextCreate — это функция из фреймворка Core Graphics (также известного как Quartz 2D) в операционных системах Apple (iOS, macOS, tvOS, watchOS). Она используется для создания растрового контекста (bitmap context) — области памяти, в которой можно выполнять двумерное рисование с помощью векторных и растровых операций Core Graphics. Функция возвращает объект типа CGContextRef, который представляет собой контекст, привязанный к заданному буферу пиксельных данных.

Назначение и область применения

Функция CGBitmapContextCreate является одним из ключевых инструментов для программного создания и обработки изображений в экосистеме Apple. Она позволяет разработчику:

  • Создавать изображения «с нуля» (например, для генерации графиков, диаграмм, текстур, иконок).
  • Рендерить содержимое векторной графики (путей, шрифтов, градиентов) в растровый формат.
  • Выполнять низкоуровневые манипуляции с пикселями: чтение, запись, фильтрацию, цветокоррекцию.
  • Сохранять результат в файл (PNG, JPEG, TIFF) или передавать его в другие API (например, в UIImage или NSImage).

В отличие от более высокоуровневых инструментов (например, UIGraphicsImageRenderer), CGBitmapContextCreate предоставляет прямой доступ к памяти пикселей, что важно для производительности и тонкой настройки.

Синтаксис и параметры

Функция объявлена в заголовочном файле <CoreGraphics/CGBitmapContext.h> и имеет следующий прототип на языке C:

``c CGContextRef CGBitmapContextCreate( void * __nullable data, size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow, CGColorSpaceRef cg_nullable space, uint32_t bitmapInfo ); ``

Параметры

  • dataуказатель на буфер памяти, в который будет записываться растровое изображение. Если передать NULL, Core Graphics автоматически выделит память. Если передать существующий буфер, он должен быть достаточно большим, чтобы вместить все пиксели (ширина × высота × количество байт на пиксель).
  • width и height — ширина и высота изображения в пикселях. Должны быть положительными целыми числами.
  • bitsPerComponent — количество бит на один компонент цвета (например, 8 для 8-битного канала). Стандартное значение — 8. Для 16-битных изображений используется 16, для 32-битных с плавающей точкой — 32.
  • bytesPerRow — количество байт на одну строку пикселей. Если передать 0, Core Graphics вычислит его автоматически (обычно width * bitsPerPixel / 8, с выравниванием до 16 байт). Ручное задание позволяет использовать субдискретизацию или выравнивание под конкретные нужды.
  • space — цветовое пространство (CGColorSpaceRef). Определяет, как интерпретируются числовые значения компонентов (например, sRGB, Generic RGB, Gray). Не может быть NULL.
  • bitmapInfo — битовая маска, определяющая формат пикселей (порядок байт, альфа-канал, тип компонентов). Тип — CGBitmapInfo (uint32_t).

Возвращаемое значение

Функция возвращает объект CGContextRef. В случае ошибки (например, неверные параметры или недостаточно памяти) возвращается NULL.

Формат пикселей (bitmapInfo)

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

  • Порядок байт (byte order): kCGBitmapByteOrderDefault, kCGBitmapByteOrder16Little, kCGBitmapByteOrder32Big и т.д. Для современных устройств Apple (ARM64) нативный порядок — little-endian, но для совместимости с файлами часто используется big-endian (например, PNG хранит данные в big-endian).
  • Информация об альфа-канале: kCGImageAlphaNone (без альфы), kCGImageAlphaPremultipliedFirst (альфа перед цветом, предумноженная), kCGImageAlphaPremultipliedLast (альфа после цвета), kCGImageAlphaOnly (только альфа), kCGImageAlphaNoneSkipFirst (альфа игнорируется, но байт зарезервирован) и другие.
  • Флаг плавающей точки: kCGBitmapFloatComponents — если установлен, компоненты хранятся как числа с плавающей точкой (обычно 32-битные float).

Наиболее распространённые комбинации для 8-битных изображений:

  • RGBA (8 бит на канал, альфа последняя, без предумножения): kCGImageAlphaLast | kCGBitmapByteOrderDefault. На практике часто используется kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast.
  • BGRA (8 бит на канал, альфа последняя, предумноженная): kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst. Этот формат используется по умолчанию в UIGraphicsImageRenderer на iOS.
  • Только оттенки серого (8 бит, без альфы): kCGImageAlphaNone с цветовым пространством Gray.

Пример использования

Ниже приведён фрагмент кода на Objective-C, демонстрирующий создание растрового контекста, рисование красного круга и получение изображения:

```objc // Создаём цветовое пространство sRGB CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);

// Создаём контекст: 200x200 пикселей, 8 бит на компонент, BGRA, предумноженная альфа CGContextRef context = CGBitmapContextCreate(NULL, 200, 200, 8, 0, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);

// Рисуем красный круг CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); CGContextFillEllipseInRect(context, CGRectMake(20, 20, 160, 160));

// Получаем изображение CGImageRef cgImage = CGBitmapContextCreateImage(context);

// Освобождаем ресурсы CGContextRelease(context); CGColorSpaceRelease(colorSpace);

// Далее cgImage можно использовать, например, с UIImage UIImage *image = [UIImage imageWithCGImage:cgImage]; CGImageRelease(cgImage); ```

Производительность и управление памятью

  • Если data равен NULL, Core Graphics выделяет память внутри контекста. При освобождении контекста (CGContextRelease) память автоматически освобождается.
  • Если data предоставлен пользователем, он должен оставаться действительным на всё время жизни контекста. Освобождение памяти — ответственность разработчика.
  • Для больших изображений (например, 4K или 8K) выделение памяти может быть затратным. Рекомендуется использовать bytesPerRow = 0, чтобы Core Graphics выбрал оптимальное выравнивание.
  • Функция CGBitmapContextGetData позволяет получить прямой указатель на пиксели для низкоуровневого доступа. Изменение пикселей через этот указатель немедленно отражается на контексте.

Ограничения и особенности

  • Функция не поддерживает создание контекстов с плавающей точкой на всех устройствах (требуется поддержка OpenGL или Metal).
  • Для изображений с альфа-каналом часто требуется предумножение (premultiplied alpha). Непредумноженный альфа-канал может привести к артефактам при рендеринге в некоторых API (например, UIImageView).
  • Начиная с iOS 10 и macOS 10.12, Apple рекомендует использовать UIGraphicsImageRenderer (iOS) или NSGraphicsContext (macOS) как более высокоуровневую и безопасную альтернативу. Однако CGBitmapContextCreate остаётся незаменимым для низкоуровневых задач, работы с пикселями и совместимости с кодом на C.

Сравнение с альтернативами

ИнструментУровеньГибкостьПроизводительностьПростота
CGBitmapContextCreateНизкийВысокаяВысокаяСредняя
UIGraphicsImageRendererВысокийСредняяВысокаяВысокая
Core Image (CIFilter)СреднийСредняяВысокая (GPU)Средняя
Metal / OpenGLНизкийМаксимальнаяМаксимальнаяНизкая

История

Функция CGBitmapContextCreate появилась в первых версиях Core Graphics (Quartz 2D) для Mac OS X 10.0 (2001 год). С выходом iOS 2.0 (2008) она стала доступна и на мобильных устройствах. Несмотря на появление более современных API, её сигнатура и поведение остаются стабильными на протяжении десятилетий, что обеспечивает обратную совместимость.

Источники

  • Apple Inc. Core Graphics Framework Reference (документация Xcode).
  • Apple Inc. Quartz 2D Programming Guide (официальное руководство).
  • Apple Inc. iOS and macOS Release Notes (описание изменений API).
  • Книга: Mark Dalrymple, Scott Knaster. Learn Objective-C on the Mac (главы по Core Graphics).
  • Книга: Erica Sadun. The Core iOS Developer’s Cookbook (раздел по растровым контекстам).

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →