#iphone #ios #uiimage #quartz-graphics #cgimage
#iPhone #iOS #uiimage #quartz-graphics #cgimage
Вопрос:
Я хочу взять изображение (кисть) и нарисовать его в отображаемом изображении. Я хочу повлиять только на альфа-версию этого изображения, и мне нужно экспортировать его позже.
Из того, что я видел, большинство инструкций действительно сводятся к некоторым дорогостоящим операциям, которые не срабатывают. т.е. они рекомендуют вам рисовать в закадровом контексте, создавать CGImage маски и создавать CGImageWithMask практически каждый раз, когда кисть применяется вообще.
Я уже знаю, что это дорого, потому что даже просто делать это и рисовать в контексте довольно грубо для iPhone.
Что я хотел бы сделать, это взять UIImage UIImageView и напрямую управлять его альфа-каналом. Я также делаю это не попиксельно, а с помощью большой (радиус 20 пикселей) кисти, которая сама по себе мягче.
Ответ №1:
Я бы не стал использовать UIImageView для этого. Достаточно обычного UIView.
Просто поместите изображение в слой с
UIView *view = ...
view.layer.contents = (id)image.CGImage;
после этого вы можете сделать части изображения прозрачными, добавив маску к слою
CALayer *mask = [[CALayer alloc] init]
mask.contents = maskimage.CGImage;
view.layer.mask = mask;
для проекта я сделал кое-что, где у меня была кисть в формате png, которую можно использовать для отображения изображения пальцем… моя функция обновления маски там была:
- (void)updateMask {
const CGSize size = self.bounds.size;
const size_t bitsPerComponent = 8;
const size_t bytesPerRow = size.width; //1byte per pixel
BOOL freshData = NO;
if(NULL == _maskData || !CGSizeEqualToSize(size, _maskSize)) {
_maskData = calloc(sizeof(char), bytesPerRow * size.height);
_maskSize = size;
freshData = YES;
}
//release the ref to the bitmat context so it doesn't get copied when we manipulate it later
_maskLayer.contents = nil;
//create a context to draw into the mask
CGContextRef context =
CGBitmapContextCreate(_maskData, size.width, size.height,
bitsPerComponent, bytesPerRow,
NULL,
kCGImageAlphaOnly);
if(NULL == context) {
LogDebug(@"Could not create the context");
return;
}
if(freshData) {
//fill with mask with alpha == 0, which means nothing gets revealed
CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
}
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0f, -1.0f);
//Draw all the points in the array into a mask
for (NSValue* pointValue in _pointsToDraw)
{
CGPoint point;
[pointValue getValue:amp;point];
//LogDebug(@"location: %@", NSStringFromCGPoint(point));
[self drawBrush:[_brush CGImage] at:point inContext:context];
}
[_pointsToDraw removeAllObjects];
//extract an image from it
CGImageRef newMask = CGBitmapContextCreateImage(context);
//release the context
CGContextRelease(context);
//now update the mask layer
_maskLayer.contents = (id)newMask;
//self.layer.contents = (id)newMask;
//and release the mask as it's retained by the layer
CGImageRelease(newMask);
}
Комментарии:
1. Итак, мне нужно изменить только базовое maskImage? Является ли лучший способ сделать это по-прежнему просто постоянным восстановлением CGImage из отредактированного контекста? Я также полагаю, что это сведет на нет мои усилия заставить ее работать внутри scrollview? Потому что я ранее использовал это для центрирования и масштабирования.
2. Это работает, за исключением того, что мне нужно ввести альфа-версию маски. Но когда у вас есть CGImage с 0 alpha, он не вписывается в контекст, потому что это 0 alpha! Какой режим рисования позволит вам записывать в маску?
3. Я думаю, проблема в том, что вы не можете изменить cgimage … Я настраиваю контекст растрового изображения, который кэширую, изменяю и копирую его в маску при каждом обновлении маски, используя CGBitmapContextCreateImage
4. Это работает, за исключением ранее упомянутых проблем с альфа-интерфейсом. Производительность хороша при простом изменении изображения маски. Не уверен, но, возможно, придется изменить режим.
5. Я бы поставил 1, если бы вы прикрепили пример кода или добавили другие функции.