CGContextClipToMask возвращает пустое изображение

Я новичок в Кварце. У меня есть 2 изображения, фон и маска с формой выреза, которую я хочу наложить на фон, чтобы вырезать часть. Полученное изображение должно иметь форму выреза. Это моя маска (форма в середине — 0 альфа):

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

И это мой код:

UIView *canvas = [[[sender superview] subviews] objectAtIndex:0];

UIGraphicsBeginImageContext(canvas.bounds.size);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef cgContext = CGBitmapContextCreate(NULL, canvas.bounds.size.width, canvas.bounds.size.height, 8, 0, colourSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colourSpace);

CGImageRef maskImage = [[UIImage imageNamed:@"Mask.png"] CGImage];
CGContextClipToMask(cgContext, CGRectMake(0, 0, canvas.frame.size.width, canvas.frame.size.height), maskImage);

CGImageRef maskedImageRef = CGBitmapContextCreateImage(cgContext);
CGContextRelease(cgContext);

UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];
UIGraphicsEndImageContext();

[button setBackgroundImage:maskedImage forState:UIControlStateNormal];

За исключением того, что ничего не появляется... Есть идеи, где я ошибаюсь? Большое спасибо.


person Smikey    schedule 29.05.2012    source источник
comment
Кажется, ты ничего не рисуешь. Вы ничего не вырезаете из ничего и ничего не получаете. Как и ожидалось. Между отсечением по маске и созданием изображения вы должны что-то нарисовать.   -  person Svein Halvor Halvorsen    schedule 30.05.2012


Ответы (1)


После того, как вы обрезаете контекст с помощью маски, вы должны нарисовать что-то в этом контексте.

Кроме того:

  • вы должны использовать UIGraphicsBeginImageContextWithOptions для поддержки коэффициента масштабирования.
  • вы создаете два контекста, один с UIGraphicsBeginImageContext, а другой с CGBitmapContextCreate. Одного достаточно :)
  • вам следует «перевернуть» альфу вашей маски, потому что согласно документам The source samples of mask determine which points of the clipping area are changed. Другие слова прозрачный станет прозрачным

Простой пример кода, где я обрезаю изображение внутри imageView, а затем возвращаю его обратно:

UIGraphicsBeginImageContextWithOptions(self.imageView.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();

CGContextTranslateCTM(context, 0.0, self.imageView.frame.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGImageRef maskImage = [[UIImage imageNamed:@"mask.png"] CGImage];
CGContextClipToMask(context, self.imageView.bounds, maskImage); 

CGContextTranslateCTM(context, 0.0, self.imageView.frame.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

[[self.imageView image] drawInRect:self.imageView.bounds];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

self.imageView.image = image;

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

UIImage *image = [UIImage imageNamed:@"image"];

CGImageRef originalMask = [UIImage imageNamed:@"mask"].CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(originalMask),
                                    CGImageGetHeight(originalMask),
                                    CGImageGetBitsPerComponent(originalMask),
                                    CGImageGetBitsPerPixel(originalMask),
                                    CGImageGetBytesPerRow(originalMask),
                                    CGImageGetDataProvider(originalMask), nil, YES);

CGImageRef maskedImageRef = CGImageCreateWithMask(image.CGImage, mask);

UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef scale:image.scale orientation:image.imageOrientation];

CGImageRelease(mask);
CGImageRelease(maskedImageRef);
person Evgeny Shurakov    schedule 29.05.2012
comment
Ясно спасибо! Всего пара вопросов. Почему вам нужно вызывать TranslateCTM дважды? Кроме того, я получаю обратный эффект - часть маски с альфа-каналом 0 вырезается, а черная часть изображения рисуется. Согласно документам, мне нужно замаскировать изображение изображением, а не маской, используя CGImageCreateWithMask, но где мне это использовать? - person Smikey; 30.05.2012
comment
UIKit и CGGraphics имеют разные системы координат, поэтому нам нужно перевести матрицу. Альфа-0 часть маски вырезается — это именно то, что говорит вам документация для CGContextClipToMask и CGImageCreateWithMask. Добавлен пример CGImageCreateWithMask. - person Evgeny Shurakov; 30.05.2012
comment
К сожалению, ни одно из решений здесь не работает сейчас в ios 11, как я тестировал, я попытался замаскировать два UIImages и использовал оба этих метода. первый сжимает изображение после обрезки, а второй возвращает {0.0} @Evgeny Shurakov - person Reza.Ab; 01.02.2018