Причина, по которой уменьшенное изображение выглядит дрянно, заключается в том, что оно масштабируется в OpenGL, который использует быструю, но некачественную линейную интерполяцию. Как вы, наверное, знаете, UIView построен на основе CALayer, который, в свою очередь, является своего рода оболочкой для текстур OpenGL. Поскольку содержимое слоя находится в видеокарте, CALayer может выполнять всю свою магию на графическом процессоре, независимо от того, занят ли процессор загрузкой веб-сайта, заблокирован ли доступ к диску или что-то еще. Я упоминаю об этом только потому, что полезно обращать внимание на то, что на самом деле находится в текстурах внутри ваших слоев. В вашем случае слой UIImageView имеет полное растровое изображение 1024x768 на своей текстуре, и это не зависит от преобразования контейнера: CALayer внутри UIImageView не видит, что это будет (давайте посмотрим ..) 246x185 в -экран и масштабировать его растровое изображение, он просто позволяет OpenGL делать свое дело и уменьшать растровое изображение каждый раз, когда он обновляет дисплей.
Чтобы получить лучшее масштабирование, нам нужно сделать это в CoreGraphics вместо OpenGL. Вот один из способов сделать это:
- (UIImage*)scaleImage:(UIImage*)image by:(float)scale
{
CGSize size = CGSizeMake(image.size.width * scale, image.size.height * scale);
UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
- (void)loadView
{
// get landscape screen frame
CGRect screenFrame = [UIScreen mainScreen].bounds;
CGRect landscapeFrame = CGRectMake(0, 0, screenFrame.size.height, screenFrame.size.width);
UIView *view = [[UIView alloc] initWithFrame:landscapeFrame];
view.backgroundColor = [UIColor grayColor];
self.view = view;
// add container view for 2 images
CGRect startFrame = CGRectMake(-landscapeFrame.size.width/2, 0, landscapeFrame.size.width*2, landscapeFrame.size.height);
container = [[UIView alloc] initWithFrame:startFrame];
container.backgroundColor = [UIColor whiteColor];
// add image 1 (1024x768)
UIImage *img1 = [UIImage imageNamed:@"01.png"];
img1View = [[TapImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
img1View.userInteractionEnabled = YES; // important!
img1View.image = [self scaleImage:img1 by:0.24];
[container addSubview:img1View];
// add image 2 (1024x768)
UIImage *img2 = [UIImage imageNamed:@"02.png"];
img2View = [[TapImageView alloc] initWithFrame:CGRectMake(1024, 0, 1024, 768)];
img2View.userInteractionEnabled = YES;
img2View.image = [self scaleImage:img2 by:0.24];
[container addSubview:img2View];
// scale to 24% and layout subviews
zoomed = YES;
container.transform = CGAffineTransformMakeScale(0.24, 0.24);
[self.view addSubview:container];
}
- (void)viewTapped:(id)sender
{
zoomed = !zoomed;
[UIView animateWithDuration:0.5 animations:^
{
if ( zoomed )
{
container.transform = CGAffineTransformMakeScale(0.24, 0.24);
}
else
{
img1View.image = [UIImage imageNamed:@"01.png"];
img2View.image = [UIImage imageNamed:@"02.png"];
container.transform = CGAffineTransformMakeScale(1.0, 1.0);
}
}
completion:^(BOOL finished)
{
if ( zoomed )
{
UIImage *img1 = [UIImage imageNamed:@"01.png"];
img1View.image = [self scaleImage:img1 by:0.24];
UIImage *img2 = [UIImage imageNamed:@"02.png"];
img2View.image = [self scaleImage:img2 by:0.24];
}
}];
}
А вот TapImageView, подкласс UIImageView, который сообщает нам, когда его коснулись, отправив действие вверх по цепочке респондента:
@interface TapImageView : UIImageView
@end
@implementation TapImageView
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
[[UIApplication sharedApplication] sendAction:@selector(viewTapped:) to:nil from:self forEvent:event];
}
@end