레이블이 UIImage인 게시물을 표시합니다. 모든 게시물 표시
레이블이 UIImage인 게시물을 표시합니다. 모든 게시물 표시

2013/11/19

[iOS] ScreenShot으로 현재 화면을 UIImage로 만들자


사용자에게 현재 화면의 ScreenShot 을 만들어서 Email에 첨부하고 싶다면..
CALayer의 -renderInContext를 이용해서 화면을 그대로 이미지로 만들 수 있다.

(출처: https://developer.apple.com/library/ios/qa/qa1703/_index.html)

먼저 스크린의 크기를 가져와야 되는데, iOS4부터 Retina Display가 나오면서, Scale로 구분을 하도록 변경이 되었다. 그래서, scale을 고려해서 화면 Size를 가져와야 한다.

화면크기를 확보를 했으면, 이제 UIContextRef를 가져오고, 이미지를 읽어 온다.

Source Code

- (UIImage*)screenshot 
{
    // Create a graphics context with the target size
    // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
    // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
    CGSize imageSize = [[UIScreen mainScreen] bounds].size;
    if (NULL != UIGraphicsBeginImageContextWithOptions)
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
    else
        UIGraphicsBeginImageContext(imageSize);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Iterate over every window from back to front
    for (UIWindow *window in [[UIApplication sharedApplication] windows]) 
    {
        if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen])
        {
            // -renderInContext: renders in the coordinate space of the layer,
            // so we must first apply the layer's geometry to the graphics context
            CGContextSaveGState(context);
            // Center the context around the window's anchor point
            CGContextTranslateCTM(context, [window center].x, [window center].y);
            // Apply the window's transform about the anchor point
            CGContextConcatCTM(context, [window transform]);
            // Offset by the portion of the bounds left of and above the anchor point
            CGContextTranslateCTM(context,
                                  -[window bounds].size.width * [[window layer] anchorPoint].x,
                                  -[window bounds].size.height * [[window layer] anchorPoint].y);

            // Render the layer hierarchy to the current context
            [[window layer] renderInContext:context];

            // Restore the context
            CGContextRestoreGState(context);
        }
    }

    // Retrieve the screenshot image
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return image;
}
(출처: https://developer.apple.com/library/ios/qa/qa1703/_index.html)


위 함수를 이용해서 이미지를 읽어오면, 디바이스의 화면 크기에 맞는 이미지가 생성이 된다.
이것을 그대로 Email로 첨부를 하게 되면, 5.4MB정도 크기가 되어서 보내기 부담스러워 진다.
그렇게 되면 이미지의 크기를 변경해서 이미지를 표시를 하고, 그 이미지를 바탕으로 data를 가져오면 될 것이다.
큰이미지를 작은 이미지로 리사이징 하는 것은 이전 블로그(http://hidavidbae.blogspot.kr/2012/12/ios6.html)를 참고하여 주시길..

2012/12/19

[iOS6] 큰 이미지를 작게 표시할 때..


큰 이미지를 iPhone의 작은 화면에 표시를 하거나, 작은 이미지로 사용해야 되는 경우가 많다. 이 경우에 이미지를 그대로 사용하게 되면, 이미지 사이즈가 커서 이미지를 로딩하는 메모리도 많이 사용하게 되고, 이미지를 그대로 압축해서 표시하므로, 계단현상이나 부드럽지 못한 이미지가 표시되게 된다.
이런 경우 Context를 생성하고, 거기에 DrawImage를 해서 작은 이미지와 Blend된 이미지로 표시할 수 있다.

소스
- (UIImage*)getResizedImage:(UIImage*)image inBound:(CGSize)size
{
    if (NULL != UIGraphicsBeginImageContextWithOptions)
        UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    else
        UIGraphicsBeginImageContext(size);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // Flip the context because UIKit coordinate system is upside down to Quartz coordinate system
    CGContextTranslateCTM(context, 0.0, size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    
    // Draw the original image to the context
    CGContextSetBlendMode(context, kCGBlendModeCopy);
    CGContextDrawImage(context, CGRectMake(0.0, 0.0, size.width, size.height), image.CGImage);
    
    // Retrieve the UIImage from the current context
    UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return imageOut;
}

설명
UIImage로 받은 큰 사이즈의 원본을 context에 작게 그리고, 그린 Context에서 UIImage를 받아오면, 작게 Blend된 이미지를 추출할 수 있게 된다.

비교


왼쪽이 원 이미지를 그대로 사용한 것이고 오른쪽이 이미지를 작게 렌더링 한 후 표시한 것입니다.
이미지를 캡춰해서 별 차이가 나지 않지만, 실제로 보면, 차이가 나고 메모리 사용량도 차이가 나는 겁니다.
 많이 필요없는 곳에 많은 데이터를 쓰고 있는 것이지요..