Создать маску из части изображения в iOS - PullRequest
2 голосов
/ 31 января 2012

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

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

enter image description here

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

Подскажите, пожалуйста, как мне создать такую ​​маску?

Решение может использовать Core Graphics и Open GL.

1 Ответ

2 голосов
/ 09 февраля 2012

Как и предполагал @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 - полностью непрозрачный).

...