2012-01-12 5 views
1

내 iPad 앱에는 여러 페이지의 스크린 샷을 표시하는 탐색 지점이 있으며 두 개 이상의 스크린 샷을 한 번에 표시하고 싶기 때문에 컨테이너를 원본 스크린 샷의 약 24 % (1024x768). 나는 "작은"텍스트와 이미지를 확장 할 때UIView가 포함되어있을 때 UIImage/UIImageView 다시 그리기

- (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.jpeg"]; 
    UIImageView *img1View = [[UIImageView alloc] initWithImage:img1]; 
    [container addSubview:img1View]; 

    // add image 2 (1024x768) 
    UIImage *img2 = [UIImage imageNamed:@"02.jpeg"]; 
    UIImageView *img2View = [[UIImageView alloc] initWithImage:img2]; 

    // move img2 to the right of img1 
    CGRect newFrame = img2View.frame; 
    newFrame.origin.x = 1024.0; 
    img2View.frame = newFrame; 

    [container addSubview:img2View]; 

    // scale to 24% 
    container.transform = CGAffineTransformMakeScale(0.24, 0.24); 

    [self.view addSubview:container]; 
} 

는하지만이 같은 STH 보이는 :

나는 사용자가 이미지를 도청 경우가 확장해야하기 때문에 큰 스크린 샷을 사용해야합니다 100 % 신선하고 깨끗합니다.

내가 성능을 망치지 않고 "부드럽게"이미지를 스케일 할 수있는 방법은 무엇입니까? 두 가지 버전, 즉 full-px 버전과 24 % 버전의 버전이 충분합니다.

답변

3

이유는 낮은 고속 뷰트 품질 선형 보간 OpenGL을 사용하고, 축소되는 것입니다. 아시다시피 UIView는 OpenGL 텍스처를위한 일종의 래퍼 인 CALayer를 기반으로 만들어졌습니다. 레이어의 내용이 비디오 카드에 있기 때문에, CALayer는 CPU가 웹 사이트를로드 하느냐, 디스크 액세스를 차단 하느냐에 관계없이 GPU에서 모든 마술을 수행 할 수 있습니다. 필자는 레이어 내의 텍스처에 실제로 무엇이 있는지주의하는 것이 유용하기 때문에 이것을 언급합니다. 귀하의 경우, UIImageView의 레이어는 질감에 대한 전체 1024x768 비트 맵 이미지를 가지고 있으며 컨테이너의 변형에 영향을받지 않습니다. UIImageView 내부의 CALayer가 보일 것입니다 (보자 ..) 246x185 on 화면을 다시 표시하고 비트 맵의 ​​크기를 조절하면 OpenGL에서 디스플레이를 업데이트 할 때마다 비트 맵의 ​​크기를 줄이고 크기를 조정할 수 있습니다.

더 나은 스케일링을 얻으려면 OpenGL 대신 CoreGraphics에서해야합니다. 여기 한 가지 방법이다 :

- (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 
1

컨테이너 및 모든 하위 뷰의 크기를 조정하는 대신. 컨테이너 내용에서 UIImageView를 만들고 프레임 크기를 원래 크기의 24 %로 조정합니다. 하향 스케일 이미지 엉터리 보이는

UIGraphicsBeginImageContext(container.bounds.size); 
[container renderInContext:UIGraphicsGetCurrentContext()]; 
UIImage *containerImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

UIImageView *containerImageView = [[UIImageView alloc] initWithImage:containerImage]; 
CGRectFrame containerFrame = startFrame; 
containerFrame.size.with *= 0.24; 
containerFrame.size.height *= 0.24; 
containerImageView.frame = containerFrame; 

[self.view addSubView:containerImageView]; 
+0

내가 코드를 조금 단순화은. 스크린 샷은 (종류의) 대화 형이어야하므로 모든 스크린 샷에서 큰 이미지를 만들 수는 없습니다. ( – pkyeck