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 →