Я почти сошел с ума по этой проблеме, из-за того, что перебрал добрую дюжину других веб-сайтов (а также этот) в поисках прямого ответа на мою проблему ...
Во-первых, я пытаюсь найти способ, учитывая начальное изображение, созданное с помощью [UIImage imageNamed:], чтобы добавить украшения, основанные на обработке во времени. (Подумайте о тепловой карте.) Я рано осознал, что мне нужно скопировать изображение, поскольку изображения, вызываемые с помощью imageNamed, находятся в специальном кэше, поэтому я копирую необработанные данные и создаю новые изображения и контексты через Базовый графический API. Несмотря на то, что я смог скопировать изображение и связать его с UIView, я не могу понять, как впоследствии изменить его содержимое ... Вот что я сейчас делаю в своем коде ...
@interface HeatMapTestViewController : UIViewController {
CFDataRef imageData;
CGColorSpaceRef colorSpace;
CGContextRef context;
CGColorRef paintColor;
CGImageRef image;
}
- (IBAction) imageButtonTapped:(UIButton*)sender forEvent:(UIEvent*)event;
@end
@implementation HeatMapTestViewController
- (void) viewDidLoad {
[super viewDidLoad];
UIImage* backImage = [UIImage imageNamed:@"Grey Checkerboard.png"];
UIColor* backdrop = [UIColor colorWithPatternImage:backImage];
[[self view] setBackgroundColor:backdrop];
UIImage* startImage = [UIImage imageNamed:@"Starting Image.png"];
CGImageRef pixelmap = [startImage CGImage];
// http://www.iphonedevsdk.com/forum/iphone-sdk-development/34247-cgimage-pixel-array.html
CGDataProviderRef dataProvider = CGImageGetDataProvider(pixelmap);
imageData = CGDataProviderCopyData(dataProvider);
void* rawPixels = (void*)CFDataGetBytePtr(imageData);
colorSpace = CGColorSpaceCreateDeviceRGB();
// http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(pixelmap);
if ( ( bitmapInfo & kCGBitmapAlphaInfoMask ) == kCGImageAlphaLast )
bitmapInfo = ( bitmapInfo & kCGBitmapByteOrderMask ) | kCGImageAlphaPremultipliedLast;
if ( ( bitmapInfo & kCGBitmapAlphaInfoMask ) == kCGImageAlphaFirst )
bitmapInfo = ( bitmapInfo & kCGBitmapByteOrderMask ) | kCGImageAlphaPremultipliedFirst;
context = CGBitmapContextCreate(
rawPixels,
CGImageGetWidth(pixelmap),
CGImageGetHeight(pixelmap),
CGImageGetBitsPerComponent(pixelmap),
CGImageGetBytesPerRow(pixelmap),
colorSpace,
bitmapInfo
);
CGFloat components[] = {1.0, 0.0, 0.0, 1.0};
paintColor = CGColorCreate(colorSpace, components);
image = CGBitmapContextCreateImage(context);
UIImage* newImage = [UIImage imageWithCGImage:image];
UIButton* button = (id)[[self view] viewWithTag:327];
[button setBackgroundImage:newImage forState:UIControlStateNormal];
}
- (IBAction) imageButtonTapped:(UIButton*)sender forEvent:(UIEvent*)event {
UITouch* touch;
CGPoint touchPoint;
touch = [[event touchesForView:sender] anyObject];
// Assuming we always just get one due to IB setting...
touchPoint = [touch locationInView:sender];
CGRect touchRect = CGRectZero;
touchRect.origin = touchPoint;
touchRect = CGRectInset(touchRect, -11.0, -11.0);
UIGraphicsPushContext(context);
CGContextSetFillColorWithColor(context, paintColor);
CGContextFillEllipseInRect(context, touchRect);
UIGraphicsPopContext();
UIImage* newImage = [UIImage imageWithCGImage:image];
[sender setBackgroundImage:newImage forState:UIControlStateNormal];
[sender setNeedsDisplayInRect:touchRect];
} // imageButtonTapped:forEvent:
@end
Обратная связь в режиме реального времени предназначена только для демонстрационных целей ... Что я действительно планирую сделать в конечном продукте, так это показать измененное изображение по запросу пользователя за экраном, на который он / она в данный момент смотрит. Мой Google-fu меня подводил, я не могу найти пример кода в документации Apple. Я даже пытался найти примеры кода для «рисования» приложений для iPhone, так как приложения такого типа, кажется, разделяют основную функциональность того, чего я пытаюсь достичь. Нет кости. / -:
РЕДАКТИРОВАТЬ: После гораздо большего количества экспериментов и исследований, я получил что-то вроде этого, приняв другой подход ...
@interface HeatMapTestViewController : UIViewController {
CGColorSpaceRef colorSpace;
CGColorRef paintColor;
}
- (IBAction) imageButtonTapped:(UIButton*)sender forEvent:(UIEvent*)event;
@end
@implementation HeatMapTestViewController
- (void) viewDidLoad {
[super viewDidLoad];
UIImage* backImage = [UIImage imageNamed:@"Grey Checkerboard.png"];
UIColor* backdrop = [UIColor colorWithPatternImage:backImage];
[[self view] setBackgroundColor:backdrop];
UIImage* startImage = [UIImage imageNamed:@"Starting Image.png"];
UIButton* button = (id)[[self view] viewWithTag:327];
[button setBackgroundImage:startImage forState:UIControlStateNormal];
colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {1.0, 0.0, 0.0, 1.0};
paintColor = CGColorCreate(colorSpace, components);
}
- (IBAction) imageButtonTapped:(UIButton*)sender forEvent:(UIEvent*)event {
UITouch* touch;
CGPoint touchPoint;
touch = [[event touchesForView:sender] anyObject];
// Assuming we always just get one due to IB setting...
touchPoint = [touch locationInView:sender];
CGRect touchRect = CGRectZero;
touchRect.origin = touchPoint;
touchRect = CGRectInset(touchRect, -11.0, -11.0);
UIImage* image = [sender backgroundImageForState:UIControlStateNormal];
// http://www.ipodtouchfans.com/forums/showthread.php?t=132024
UIGraphicsBeginImageContext([image size]);
CGContextRef context = UIGraphicsGetCurrentContext();
[image drawInRect:CGRectMake(0.0, 0.0, [image size].width, [image size].height)];
// This repaints the entire image! Boo hiss!
CGContextSetFillColorWithColor(context, paintColor);
CGContextFillEllipseInRect(context, touchRect);
[sender setBackgroundImage:UIGraphicsGetImageFromCurrentImageContext()
forState:UIControlStateNormal];
UIGraphicsEndImageContext();
} // imageButtonTapped:forEvent:
@end
Большая проблема с этим сигналом отмечена в комментарии. Если я правильно понимаю вышеизложенное, я перерисовываю все содержимое изображения в новое, просто чтобы обновить его небольшую часть. Это не похоже на то, что я могу делать с 20-30 раз в секунду.