Огромный пик памяти - CGContextDrawImage - PullRequest
4 голосов
/ 21 февраля 2012

Я использую этот фрагмент кода для масштабирования и поворота изображений, снятых фотоаппаратом. Когда я использую это, я вижу огромный пик памяти. Что-то вроде 20 МБ. Когда я использую инструменты, я вижу, что эта строка:

CGContextDrawImage (ctxt, orig, self.CGImage);

содержит 20 МБ. Это нормально для фотографий с полным разрешением? IPhone 4S может справиться с этим. но старые устройства зависают из-за этого кода.

После того, как я изменил масштаб изображения, он мне нужен в NSData, поэтому я использую метод UIImageJPEGRepresentation (). Это вместе делает пик памяти еще выше. На несколько секунд расходуется 70 МБ памяти.

И да, я прочитал почти все вопросы об использовании памяти камеры 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

Ответы [ 3 ]

3 голосов
/ 23 февраля 2012

Я использовал 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;

}
1 голос
/ 21 февраля 2012


это верно, это исходит из изображения, которое вы сняли на камеру, старые устройства используют камеры с меньшим разрешением, это означает, что изображения, сделанные на iPhone 3g, имеют меньшее разрешение (таким образом, размер) по сравнению с тем, что выесть на вашем iPhone4s.Изображения обычно сжимаются, но когда они открываются в памяти для какой-либо операции, они должны быть распакованы, размер, который им нужен, действительно больше размера файла, потому что это number_of_pixel_in_row*number_of_pixel_in_height*byte_for_pixel, если я хорошо помню.
Пока, Андреа

0 голосов
/ 21 февраля 2012

Вставьте это в конце ваших методов и перед return copy;:

CGContextRelease(ctxt);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...