#cocoa-touch #core-graphics #quartz-graphics
#cocoa-touch #ядро-графика #quartz-графика
Вопрос:
У меня есть набор плиток в виде UIViews, которые имеют программируемый цвет фона, и каждый из них может быть разного цвета. Я хочу добавить текстуру, например, скос с боковой подсветкой, к каждому из них. Можно ли это сделать с помощью режима наложения или каким-либо другим методом?
Я ищу предложения, которые не требуют пользовательского файла изображения для каждого случая.
Ответ №1:
Это может кому-то помочь, хотя это было собрано по частям из других разделов SO. Чтобы создать скошенное изображение с произвольным цветом для обычного дисплея и для дисплея retina, я создал скошенное изображение в photoshop и установил насыщенность равной нулю, создав изображение в оттенках серого, называемое tileBevel.png
Я также создал текстуру для дисплея retina ( tileBevel@2x.png
)
Вот код:
(UIImage*) createTileWithColor:(UIColor*)tileColor {
int pixelsHigh = 44;
int pixelsWide = 46;
UIImage *bottomImage;
if([UIScreen respondsToSelector:@selector(scale)] amp;amp; [[UIScreen mainScreen] scale] == 2.0) {
pixelsHigh *= 2;
pixelsWide *= 2;
bottomImage = [UIImage imageNamed:@"tileBevel@2x.png"];
}
else {
bottomImage = [UIImage imageNamed:@"tileBevel.png"];
}
CGImageRef theCGImage = NULL;
CGContextRef tileBitmapContext = NULL;
CGRect rectangle = CGRectMake(0,0,pixelsWide,pixelsHigh);
UIGraphicsBeginImageContext(rectangle.size);
[bottomImage drawInRect:rectangle];
tileBitmapContext = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(tileBitmapContext, kCGBlendModeOverlay);
CGContextSetFillColorWithColor(tileBitmapContext, tileColor.CGColor);
CGContextFillRect(tileBitmapContext, rectangle);
theCGImage=CGBitmapContextCreateImage(tileBitmapContext);
UIGraphicsEndImageContext();
return [UIImage imageWithCGImage:theCGImage];
}
При этом проверяется, используется ли дисплей retina, определяется размер прямоугольника для рисования, выбирается подходящее базовое изображение в оттенках серого, устанавливается режим наложения на наложение, затем рисуется прямоугольник поверх нижнего изображения. Все это выполняется внутри графического контекста, заключенного в квадратные скобки вызовами BeginImageContext и EndImageContext. Они задают текущий контекст, необходимый UIImage drawRect: метод. Основным графическим функциям необходим контекст в качестве параметра, который получается вызовом для получения текущего контекста.
И результат выглядит следующим образом:
Ответ №2:
Если вы хотите сохранить альфа-канал исходного изображения, просто добавьте это в код jim перед заполнением прямоугольника:
// Apply mask
CGContextTranslateCTM(tileBitmapContext, 0, rectangle.size.height);
CGContextScaleCTM(tileBitmapContext, 1.0f, -1.0f);
CGContextClipToMask(tileBitmapContext, rectangle, bottomImage.CGImage);
Ответ №3:
Решение Swift 3, в основном основанное на ответе Джима с добавлением Scriptease и некоторыми незначительными изменениями:
class func image(bottomImage: UIImage, topImage: UIImage, tileColor: UIColor) -> UIImage? {
let pixelsHigh: CGFloat = bottomImage.size.height
let pixelsWide: CGFloat = bottomImage.size.width
let rectangle = CGRect.init(x: 0, y: 0, width: pixelsWide, height: pixelsHigh)
UIGraphicsBeginImageContext(rectangle.size);
bottomImage.draw(in: rectangle)
if let tileBitmapContext = UIGraphicsGetCurrentContext() {
tileBitmapContext.setBlendMode(.overlay)
tileBitmapContext.setFillColor(tileColor.cgColor)
tileBitmapContext.scaleBy(x: 1.0, y: -1.0)
tileBitmapContext.clip(to: rectangle, mask: bottomImage.cgImage!)
tileBitmapContext.fill(rectangle)
let theCGImage = tileBitmapContext.makeImage()
UIGraphicsEndImageContext();
if let theImage = theCGImage {
return UIImage.init(cgImage: theImage)
}
}
return nil
}