2012-06-22 1 views
3

UIScrollView에 의해 제어되는 UIView에 표시되는 CGImage가 있습니다. 이미지는 일반적으로 알파 채널이없는 24 비트 색상의 1680 * 1050입니다.drawRect는 뷰가 축소 될 때 항상 전체 화면을 업데이트하려고합니다.

화상은 다음과 같이 생성된다 :

는 이미지 콘텐츠 m_pvBits의 픽셀을 변경하여 백그라운드에서 정기적으로 업데이트하여 UIView의 갱신된다
CGImageRef bitmapClass::CreateBitmap(int width, int height, int imageSize, int colorDepth, int bytesPerRow) 
{ 
    unsigned char* m_pvBits = malloc(imageSize); 

    // Initializt bitmap buffer to black (red, green, blue) 
    memset(m_pvBits, 0, imageSize); 

    m_DataProviderRef = 
     CGDataProviderCreateWithData(NULL, m_pvBits, imageSize, NULL); 

    m_ColorSpaceRef = 
     CGColorSpaceCreateDeviceRGB(); 

    return 
     CGImageCreate(width, height, 
        8, //kBitsPerComponent 
        colorDepth, 
        bytesPerRow, 
        m_ColorSpaceRef, 
        kCGBitmapByteOrderDefault | kCGImageAlphaNone, 
        m_DataProviderRef, 
        NULL, false, kCGRenderingIntentDefault); 
} 

:

[myView setNeedsDisplayInRect:rect]; 

는의 drawRect를 호출하는 다음과 같은 이미지를 표시합니다 :

- (void)drawRect:(CGRect)rect 
{ 
    CGRect imageRect; 
    imageRect.origin = CGPointMake(0.0, 0.0); 
    imageRect.size = CGSizeMake(self.imageWidth, self.imageHeight); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGContextSetInterpolationQuality(context, kCGInterpolationNone); 

    // Drawing code 
    CGContextDrawImage(context, imageRect, (CGImageRef)pWindow->GetImageRef()); 
} 

이것은 그는보기가 축소되지 않습니다 (축소). drawRect에서는 'rect'가 실제로는 직접 사용되지 않지만 'context'는 CGContextDrawImage가 업데이트해야하는 부분을 알고있는 것으로 보입니다.

내 문제는 setNeedsDisplayInRect를 사용하여 화면의 작은 영역 만 무효화해도 뷰가 축소되면 전체 화면에서 drawRect가 호출된다는 것입니다. 그래서 내 이미지가 1680 * 1050이고 작은 직사각형 (x, y, w, h) = (512, 640, 32, 32)을 무효화하면 drawRect는 (x, y, w, h) = , 0, 1680, 1050).

왜?

답변

1

답변 해 주셔서 감사합니다.

drawRect에 전달되는 rect 매개 변수의 내용은 CGContextGetClipBoundingBox()를 쿼리 할 때 얻는 것과 같습니다.

내 그림을 클리핑 경계에 맞게 최적화해야한다고 제안합니다.하지만 여기서는 계산을하지 않습니다. CGContextDrawImage()를 호출하고 있습니다. CGContextDrawImage의 성능 저하에 대해 불평하는 다른 프로그래머와 iPhone 3에서 iPhone 4로 느린 속도가 느껴지는 것을 볼 수 있습니다. 물론 성능이 더 좋아졌지만 가장 큰 문제는 iOS가 전체 이미지를 업데이트하는 것입니다 작은 부분이 무효화됩니다 (setNeedsDisplay를 사용).

축소하면 이미지를 더 볼 수 있지만 이미지가 축소됩니다. 지속적으로 확대/축소하지는 않지만 이미지의 작은 부분이 정기적으로 업데이트되어 setNeedsDisplay를 호출합니다. 확대/축소 할 때 또는 iOS에서 업데이트하도록 전체 화면을 설정했기 때문에 팬 속도가 매우 느리고 갑작 스럽습니다.

CGContextDrawImage가 실제로 그려지는 것을 최적화하는 것이 맞습니다. 작업을 수행하는 데 걸리는 시간을 측정하여 볼 수 있습니다.

본인은 이미지 비트를 malloc으로 할당 할 수 있습니다. 그래픽 프로세서에 더 잘 최적화 된 이미지 비트를 할당 할 수있는 또 다른 방법이 있습니까?

CGImageCreate에 더 적합한 ColorRef 모드 또는 다른 플래그가 있습니까?

3

Apple의 흥미로운 샘플 코드 프로젝트가 도움이 될 것입니다. Large Image Downsizing이라고합니다. 그것은 많은 일을하지만 실제로 흥미로운 부분은 TiledImageView.m입니다.

+ (Cl ass)layerClass { 
    return [CATiledLayer class]; 
} 

이 TiledLayer 속성이 init 방법에 설정되고있다 : 그것에서는, 뷰의 레이어 클래스는 CATiledLayer로 설정되어 마침내

// Create a new TiledImageView with the desired frame and scale. 
-(id)initWithFrame:(CGRect)_frame image:(UIImage*)_image scale:(CGFloat)_scale { 
    if ((self = [super initWithFrame:_frame])) { 
     self.image = _image; 
     imageRect = CGRectMake(0.0f, 0.0f, CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage)); 
     imageScale = _scale; 
     CATiledLayer *tiledLayer = (CATiledLayer *)[self layer]; 
     // levelsOfDetail and levelsOfDetailBias determine how 
     // the layer is rendered at different zoom levels. This 
     // only matters while the view is zooming, since once the 
     // the view is done zooming a new TiledImageView is created 
     // at the correct size and scale. 
     tiledLayer.levelsOfDetail = 4; 
     tiledLayer.levelsOfDetailBias = 4; 
     tiledLayer.tileSize = CGSizeMake(512.0, 512.0); 
    } 
    return self; 
} 

하고,이,이를 정말 흥미로운 부분이다 인 drawRect: 구현 (NSLog 나 출신) :

-(void)drawRect:(CGRect)_rect { 
    CGContextRef context = UIGraphicsGetCurrentContext();  
    CGContextSaveGState(context); 
    // Scale the context so that the image is rendered 
    // at the correct size for the zoom level. 
    CGContextScaleCTM(context, imageScale,imageScale); 
    NSLog(@"rect: %@, imageScale: %.4f, clip: %@", NSStringFromCGRect(_rect), imageScale, NSStringFromCGRect(CGContextGetClipBoundingBox(context))); 
    CGContextDrawImage(context, imageRect, image.CGImage); 
    CGContextRestoreGState(context);  
} 

drawRect:마다 512 × 512 타일라고 . 그러나 _rect에 전달 된 것은 메서드 내에서 전혀 사용되지 않습니다. 현재 컨텍스트의 클리핑 패스가 올바른 지역으로 설정되었으므로 (반드시 CGContextGetClipBoundingBox의 출력에서 ​​볼 수 있듯이) 그렇게 할 필요가 없습니다. Rob이 말했듯이, CGContextDrawImage을 사용할 수 있고 큰 이미지의 요청 된 "타일"만 그려 지지만 전체 이미지가 반복해서 그려지는 것처럼 보입니다. CATiledLayer을 사용하지 않으면 실제로 전체 이미지가 반복해서 그려 지므로 모든 작업이 느려집니다. 그러나 CATiledLayer을 사용하면 현재 필요한 "타일"만 그려 지므로 훨씬 빠르게 처리됩니다.

이 정보가 도움이되기를 바랍니다.