2012-02-21 7 views
4

나는이 코드를 사용하여 사진 카메라로 촬영 한 이미지의 크기를 조절하고 회전시킵니다. 내가 이것을 사용할 때 나는 엄청난 메모리 피크를 볼 수있다. 20 MB와 같은 것. 악기를 사용할 때 다음 줄이 있음을 알 수 있습니다 :거대한 메모리 최고점 - CGContextDrawImage

CGContextDrawImage (ctxt, orig, self.CGImage);

은 20MB를 유지합니다. 전체 해상도 사진의 경우 정상입니까? iPhone 4S에서 처리 할 수 ​​있습니다. 이 코드 때문에 오래된 장치가 충돌합니다.

이미지의 크기를 조정 한 후에 NSData에서 필요하므로 UIImageJPEGRepresentation() 메서드를 사용합니다. 이렇게하면 메모리 피크가 훨씬 높아집니다. 몇 초 동안 메모리 사용량이 70MB가됩니다.

그리고 네, 메모리 사용에 관한 거의 모든 iOS 카메라 관련 질문을 읽었습니다. 하지만 거기에 아무 대답. 당신이 당신의 카메라로 촬영 한 사진에서 온다 맞습니다

// WBImage.mm -- extra UIImage methods 
// by allen brunson march 29 2009 

#include "WBImage.h" 

static inline CGFloat degreesToRadians(CGFloat degrees) 
{ 
    return M_PI * (degrees/180.0); 
} 

static inline CGSize swapWidthAndHeight(CGSize size) 
{ 
CGFloat swap = size.width; 

size.width = size.height; 
size.height = swap; 

return size; 
} 

@implementation UIImage (WBImage) 

// rotate an image to any 90-degree orientation, with or without mirroring. 
// original code by kevin lohman, heavily modified by yours truly. 
// http://blog.logichigh.com/2008/06/05/uiimage-fix/ 

-(UIImage*)rotate:(UIImageOrientation)orient 
{ 
CGRect    bnds = CGRectZero; 
UIImage*   copy = nil; 
CGContextRef  ctxt = nil; 
CGRect    rect = CGRectZero; 
CGAffineTransform tran = CGAffineTransformIdentity; 

bnds.size = self.size; 
rect.size = self.size; 

switch (orient) 
{ 
    case UIImageOrientationUp: 
     return self; 

    case UIImageOrientationUpMirrored: 
     tran = CGAffineTransformMakeTranslation(rect.size.width, 0.0); 
     tran = CGAffineTransformScale(tran, -1.0, 1.0); 
     break; 

    case UIImageOrientationDown: 
     tran = CGAffineTransformMakeTranslation(rect.size.width, 
               rect.size.height); 
     tran = CGAffineTransformRotate(tran, degreesToRadians(180.0)); 
     break; 

    case UIImageOrientationDownMirrored: 
     tran = CGAffineTransformMakeTranslation(0.0, rect.size.height); 
     tran = CGAffineTransformScale(tran, 1.0, -1.0); 
     break; 

    case UIImageOrientationLeft: 
     bnds.size = swapWidthAndHeight(bnds.size); 
     tran = CGAffineTransformMakeTranslation(0.0, rect.size.width); 
     tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0)); 
     break; 

    case UIImageOrientationLeftMirrored: 
     bnds.size = swapWidthAndHeight(bnds.size); 
     tran = CGAffineTransformMakeTranslation(rect.size.height, 
               rect.size.width); 
     tran = CGAffineTransformScale(tran, -1.0, 1.0); 
     tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0)); 
     break; 

    case UIImageOrientationRight: 
     bnds.size = swapWidthAndHeight(bnds.size); 
     tran = CGAffineTransformMakeTranslation(rect.size.height, 0.0); 
     tran = CGAffineTransformRotate(tran, degreesToRadians(90.0)); 
     break; 

    case UIImageOrientationRightMirrored: 
     bnds.size = swapWidthAndHeight(bnds.size); 
     tran = CGAffineTransformMakeScale(-1.0, 1.0); 
     tran = CGAffineTransformRotate(tran, degreesToRadians(90.0)); 
     break; 

    default: 
     // orientation value supplied is invalid 
     assert(false); 
     return nil; 
} 

UIGraphicsBeginImageContext(rect.size); 
ctxt = UIGraphicsGetCurrentContext(); 

switch (orient) 
{ 
    case UIImageOrientationLeft: 
    case UIImageOrientationLeftMirrored: 
    case UIImageOrientationRight: 
    case UIImageOrientationRightMirrored: 
     CGContextScaleCTM(ctxt, -1.0, 1.0); 
     CGContextTranslateCTM(ctxt, -rect.size.height, 0.0); 
     break; 

    default: 
     CGContextScaleCTM(ctxt, 1.0, -1.0); 
     CGContextTranslateCTM(ctxt, 0.0, -rect.size.height); 
     break; 
} 

CGContextConcatCTM(ctxt, tran); 
CGContextDrawImage(ctxt, bnds, self.CGImage); 

copy = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

return copy; 
} 

-(UIImage*)rotateAndScaleFromCameraWithMaxSize:(CGFloat)maxSize 
{ 
UIImage* imag = self; 

imag = [imag rotate:imag.imageOrientation]; 
imag = [imag scaleWithMaxSize:maxSize]; 

return imag; 
} 

-(UIImage*)scaleWithMaxSize:(CGFloat)maxSize 
{ 
return [self scaleWithMaxSize:maxSize quality:kCGInterpolationHigh]; 
} 

-(UIImage*)scaleWithMaxSize:(CGFloat)maxSize 
       quality:(CGInterpolationQuality)quality 
{ 
CGRect  bnds = CGRectZero; 
UIImage*  copy = nil; 
CGContextRef ctxt = nil; 
CGRect  orig = CGRectZero; 
CGFloat  rtio = 0.0; 
CGFloat  scal = 1.0; 

bnds.size = self.size; 
orig.size = self.size; 
rtio = orig.size.width/orig.size.height; 

if ((orig.size.width <= maxSize) && (orig.size.height <= maxSize)) 
{ 
    return self; 
} 

if (rtio > 1.0) 
{ 
    bnds.size.width = maxSize; 
    bnds.size.height = maxSize/rtio; 
} 
else 
{ 
    bnds.size.width = maxSize * rtio; 
    bnds.size.height = maxSize; 
} 

UIGraphicsBeginImageContext(bnds.size); 
ctxt = UIGraphicsGetCurrentContext(); 

scal = bnds.size.width/orig.size.width; 
CGContextSetInterpolationQuality(ctxt, quality); 

CGContextScaleCTM(ctxt, scal, -scal); 
CGContextTranslateCTM(ctxt, 0.0, -orig.size.height); 

CGContextDrawImage(ctxt, orig, self.CGImage); 

copy = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

return copy; 
} 

@end 

답변

2

나는, 적은 메모리를 ImageIO에서를 사용하여 종료!

-(UIImage *)resizeImageToMaxDimension: (float) dimension withPaht: (NSString *)path 
{ 

NSURL *imageUrl = [NSURL fileURLWithPath:path]; 
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((__bridge CFURLRef)imageUrl, NULL); 

NSDictionary *thumbnailOptions = [NSDictionary dictionaryWithObjectsAndKeys: 
            (id)kCFBooleanTrue, kCGImageSourceCreateThumbnailWithTransform, 
            kCFBooleanTrue, kCGImageSourceCreateThumbnailFromImageAlways, 
            [NSNumber numberWithFloat:dimension], kCGImageSourceThumbnailMaxPixelSize, 
            nil]; 
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (__bridge CFDictionaryRef)thumbnailOptions); 

UIImage *resizedImage = [UIImage imageWithCGImage:thumbnail]; 

CFRelease(thumbnail); 
CFRelease(imageSource); 

return resizedImage; 

} 
+0

에 감사드립니다! 이것은 많은 도움이되었습니다. – timthetoolman

1


은 오래된 장치는 존중 아이폰 3g로 촬영 한 이미지는 해상도 (따라서 크기)가 작은 것을 의미 적은 해상도와 카메라를 사용 당신이 당신의 iPhone4s에 가지고있는 하나. 이미지는 일반적으로 압축되지만 일종의 작업을 위해 메모리에서 열면 압축이 필요합니다. 실제로 기억하는 경우 number_of_pixel_in_row*number_of_pixel_in_height*byte_for_pixel이기 때문에 필요한 크기가 실제로 파일에있는 크기보다 큽니다.
안녕, 안드레아

+0

답장을 보내 주셔서 감사합니다. 그러나 메모리 사용을 줄이기위한 해결책이 있습니다. 당신이 압축을 언급했을 때 어쩌면 당신은 엄밀한 방향으로 나를 가리킬 수 있습니다. – Melvin

+0

이미지를 압축 해제해야하는 작업을 수행 할 때 파일에 대한 압축이 작동합니다. 나는 당신이 충돌을 경험했는지 아닌지 아직도 이해하지 못했다. 이 기사 [link] (http://www.cocoanetics.com/2011/10/avoiding-image-decompression-sickness/)를 읽고 Apple 사이트에서 샘플 코드 LargeImageDownsizing을 다운로드하십시오. Ciao – Andrea

+0

아마도 하나의 솔루션은 mmap unix 기능을 사용하여 이미지 메모리를 파일에 매핑 할 수 있지만 상당히 어렵거나 느려질 수도 있습니다. – Andrea

0

당신의 방법의 끝에 삽입이와 return copy; 전에이 :

CGContextRelease(ctxt); 
+0

지금 막 시도했지만 효과가없는 것 같습니다. ARC를 사용 중이므로 ARC가이를 처리하고 있습니다. – Melvin

+1

ARC는 "오래된"Core Foundation 객체 인 – Andrea

관련 문제