Я разрабатываю приложение-раскраску для iPad (iOS4+). Приложение должно позволять окрашивать только одну область изображения за раз.
Я имею в виду, что если пользователь коснется любого места на экране и начнет двигать пальцем, цвет должен применяться только к тем пикселям, которые находятся в той же области, что и первая точка касания. Например, если пользователь коснется центра левого изображения и начнет двигать пальцем по всему изображению, он должен получить что-то вроде правого изображения.

Я думаю, что одним из решений задачи может быть создание маски в форме затронутой области, а затем применение этой маски к изображению, прежде чем выполнять дальнейшие модификации. Но, честно говоря, я понятия не имею, с чего начать.
Подскажите, пожалуйста, как сделать такую маску?
Решение может использовать Core Graphics и Open GL.
Ответ 1 · рейтинг 2 · Bobrovsky
Как предложил @Till, я реализовал алгоритм заполнения очереди. Мне пришлось выполнить некоторые оптимизации удерживать потребление памяти и скорость выполнения в разумных пределах.
Я не использую алгоритм, чтобы действительно заполнить изображение. Я использую алгоритм для создания масок:
- Создайте массив байтов маски (image_width * image_height bytes)
- Заполните весь массив значениями 0xFF
- Используйте алгоритм заливки, чтобы найти все пиксели в области и координаты прямоугольника, содержащего область.
- Для каждого найденного пикселя установите соответствующее значение в массиве байтов маски равным 0
- Создайте другой (меньший массив) байтов маски и скопируйте часть (определяемую вычисленным прямоугольником) массива байтов маски в новый массив.
- Создайте маску, используя следующий код
NSData* maskData = // construct NSData from mask bytes
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((CFMutableDataRef)maskData);
int width = maskRight - maskLeft + 1;
int height = maskBottom - maskTop + 1;
CGImageRef maskImage = CGImageMaskCreate(width, height, 8, 8, width, dataProvider, NULL, YES);
CGDataProviderRelease(dataProvider);
- Вы можете использовать маску позже, используя код, подобный следующему
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0, 768);
CGContextScaleCTM(context, 1.0, -1.0);
CGRect r = CGRectApplyAffineTransform(maskImageRect, CGContextGetCTM(context));
CGContextClipToMask(context, r, maskImage);
CGContextTranslateCTM(context, 0.0, 768);
CGContextScaleCTM(context, 1.0, -1.0);
// mask is setup, draw here
CGContextRestoreGState(context);
Используя этот код, вы можете создать маску любой формы. Вы даже можете создать полупрозрачную маску, если хотите. Для создания полупрозрачной маски необходимо в массиве байтов маски для прозрачных областей установить значения, отличные от 0 (0 - полностью прозрачная, 255 - полностью непрозрачная).