Как я могу замаскировать UIImageView?
Я пытаюсь замаскировать изображение чем-то вроде этого:
![image to be masked]()
Не могли бы вы помочь мне?
Я использую этот код:
- (void) viewDidLoad {
UIImage *OrigImage = [UIImage imageNamed:@"dogs.png"];
UIImage *mask = [UIImage imageNamed:@"mask.png"];
UIImage *maskedImage = [self maskImage:OrigImage withMask:mask];
myUIIMage.image = maskedImage;
}
Ответы
Ответ 1
Там более простой способ.
#import <QuartzCore/QuartzCore.h>
// remember to include Framework as well
CALayer *mask = [CALayer layer];
mask.contents = (id)[[UIImage imageNamed:@"mask.png"] CGImage];
mask.frame = CGRectMake(0, 0, <img_width>, <img_height>);
yourImageView.layer.mask = mask;
yourImageView.layer.masksToBounds = YES;
Для Swift 4 и выше следуйте приведенному ниже коду
let mask = CALayer()
mask.contents = [ UIImage(named: "right_challenge_bg")?.cgImage] as Any
mask.frame = CGRect(x: 0, y: 0, width: leftBGImage.frame.size.width, height: leftBGImage.frame.size.height)
leftBGImage.layer.mask = mask
leftBGImage.layer.masksToBounds = true
Ответ 2
Учебник использует этот метод с двумя параметрами: image
и maskImage
, которые вы должны установить при вызове метода. Пример вызова может выглядеть следующим образом: предполагается, что метод находится в одном классе и изображения находятся в вашем пакете:
Примечание. Удивительно, что изображения даже не должны быть одинакового размера.
...
UIImage *image = [UIImage imageNamed:@"dogs.png"];
UIImage *mask = [UIImage imageNamed:@"mask.png"];
// result of the masking method
UIImage *maskedImage = [self maskImage:image withMask:mask];
...
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef maskedImageRef = CGImageCreateWithMask([image CGImage], mask);
UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];
CGImageRelease(mask);
CGImageRelease(maskedImageRef);
// returns new image with mask applied
return maskedImage;
}
После предоставления кода я добавил некоторые номера в качестве комментариев к нему для справки. У вас все еще есть два варианта. Все это метод, который вы вызываете где-то. Вам не нужно создавать изображения внутри него: это уменьшает возможность повторного использования метода до нуля.
Чтобы ваш код работал. Измените метод head (1.) на
- (UIImage *)maskImageMyImages {
Затем измените имя переменной в 2. на
UIImage *maskImage = [UIImage imageNamed:@"mask.png"];
Метод вернет ваши маскированные изображения, поэтому вам нужно будет вызвать этот метод в некотором месте.
Можете ли вы показать нам код, в котором вы вызываете свой метод?
Ответ 3
Я пробовал использовать оба кода с помощью CALayer или CGImageCreateWithMask, но ни один из них не работал у меня
Но я узнал, что проблема заключается в формате файла PNG, а не в коде!!
так что просто поделиться своим находкой!
Если вы хотите использовать
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage
вы должны использовать 24bit png без альфа-канала
Если вы хотите использовать маску CALayer, вы должны использовать (24 бит или 8 бит) png с альфа-каналом, где прозрачная часть вашего png замаскирует изображение (для гладкой градиентной альфа-маски.. используйте 24 бит png с альфа-каналом)
Ответ 4
Swift 3 - самое простое решение, которое я нашел
Я создал @IBDesignable
для этого, чтобы вы могли сразу увидеть эффект на вашей раскадровке.
import UIKit
@IBDesignable
class UIImageViewWithMask: UIImageView {
var maskImageView = UIImageView()
@IBInspectable
var maskImage: UIImage? {
didSet {
maskImageView.image = maskImage
updateView()
}
}
// This updates mask size when changing device orientation (portrait/landscape)
override func layoutSubviews() {
super.layoutSubviews()
updateView()
}
func updateView() {
if maskImageView.image != nil {
maskImageView.frame = bounds
mask = maskImageView
}
}
}
Как пользоваться
- Создайте новый файл и вставьте этот код выше.
- Добавьте UIImageView к вашей раскадровке (назначьте изображение, если хотите).
- В Identity Inspector: измените пользовательский класс на "UIImageViewWithMask" (имя пользовательского класса указано выше).
- Инспектор атрибутов: выберите изображение маски, которое вы хотите использовать.
пример
![Masking on Storyboard]()
Заметки
- Ваше изображение маски должно иметь прозрачный фон (PNG) для не черной части.
Ответ 5
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef maskImageRef = [maskImage CGImage];
// create a bitmap graphics context the size of the image
CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, maskImage.size.width, maskImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
if (mainViewContentContext==NULL)
return NULL;
CGFloat ratio = 0;
ratio = maskImage.size.width/ image.size.width;
if(ratio * image.size.height < maskImage.size.height) {
ratio = maskImage.size.height/ image.size.height;
}
CGRect rect1 = {{0, 0}, {maskImage.size.width, maskImage.size.height}};
CGRect rect2 = {{-((image.size.width*ratio)-maskImage.size.width)/2 , -((image.size.height*ratio)-maskImage.size.height)/2}, {image.size.width*ratio, image.size.height*ratio}};
CGContextClipToMask(mainViewContentContext, rect1, maskImageRef);
CGContextDrawImage(mainViewContentContext, rect2, image.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef newImage = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
UIImage *theImage = [UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);
// return the image
return theImage;
}
Это работает для меня.
Ответ 6
SWIFT 3 XCODE 8.1
func maskImage(image: UIImage, withMask maskImage: UIImage) -> UIImage {
let maskRef = maskImage.cgImage
let mask = CGImage(
maskWidth: maskRef!.width,
height: maskRef!.height,
bitsPerComponent: maskRef!.bitsPerComponent,
bitsPerPixel: maskRef!.bitsPerPixel,
bytesPerRow: maskRef!.bytesPerRow,
provider: maskRef!.dataProvider!,
decode: nil,
shouldInterpolate: false)
let masked = image.cgImage!.masking(mask!)
let maskedImage = UIImage(cgImage: masked!)
// No need to release. Core Foundation objects are automatically memory managed.
return maskedImage
}
//для использования
testImage.image = maskImage(image: UIImage(named: "OriginalImage")!, withMask: UIImage(named: "maskImage")!)
Ответ 7
Быстрая версия принятого решения:
func maskImage(image: UIImage, withMask maskImage: UIImage) -> UIImage {
let maskRef = maskImage.CGImage
let mask = CGImageMaskCreate(
CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef),
nil,
false)
let masked = CGImageCreateWithMask(image.CGImage, mask)
let maskedImage = UIImage(CGImage: masked)!
// No need to release. Core Foundation objects are automatically memory managed.
return maskedImage
}
На всякий случай кому-то это нужно.
Он работает для меня безупречно.
Ответ 8
мы обнаружили, что правильный ответ сейчас не работает и реализован небольшой класс вставки, который помогает замаскировать любое изображение в UIImageView.
Он доступен здесь: https://github.com/Werbary/WBMaskedImageView
Пример:
WBMaskedImageView *imgView = [[WBMaskedImageView alloc] initWithFrame:frame];
imgView.originalImage = [UIImage imageNamed:@"original_image.png"];
imgView.maskImage = [UIImage imageNamed:@"mask_image.png"];