2012-02-21 1 views
4

J'utilise ce morceau de code pour mettre à l'échelle et faire pivoter les images prises avec l'appareil photo. Quand je l'utilise, je peux voir un énorme pic de mémoire. Quelque chose comme 20 Mo. Quand j'utilise les instruments, je peux voir que cette ligne:Pic de mémoire énorme - CGContextDrawImage

CGContextDrawImage (ctxt, orig, self.CGImage);

contient 20 Mo. Est-ce normal pour les photos en pleine résolution? L'iPhone 4S peut le gérer. mais les appareils plus anciens se bloque à cause de ce code. Après avoir redimensionné l'image dont j'ai besoin dans NSData, j'utilise la méthode UIImageJPEGRepresentation(). Cela ensemble rend le pic de mémoire encore plus élevé. Il va à 70 Mo en utilisation de la mémoire pendant plusieurs secondes.

Et oui, j'ai lu presque toutes les questions liées à l'appareil photo iOS sur l'utilisation de la mémoire. Mais pas de réponse là-bas.

// 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 

Répondre

2

Je fini par utiliser ImageIO, moins de mémoire!

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

merci! Cela a beaucoup aidé. – timthetoolman

1


qui est correct, il vient de l'image que vous prises avec votre appareil photo, les appareils plus anciens utilisent des caméras avec une résolution moindre, cela signifie que les images prises avec un iPhone 3G sont plus petits dans la résolution (taille ainsi) respecter la celui que vous avez sur votre iPhone4s. Les images sont généralement compressées mais quand elles s'ouvrent en mémoire pour une sorte d'opération elles doivent être décompressées, la taille dont elles ont besoin est vraiment plus grande que celle d'un fichier, car c'est le number_of_pixel_in_row*number_of_pixel_in_height*byte_for_pixel si je me souviens bien.
Bye, Andrea

+0

merci pour votre réponse. Mais existe-t-il une solution pour réduire l'utilisation de la mémoire. Vous avez mentionné la compression, peut-être pourriez-vous me diriger dans la bonne direction. – Melvin

+0

La compression fonctionne sur fichier, lorsque vous effectuez des opérations sur une image, vous devez le décompresser. Je n'ai toujours pas compris si vous rencontrez un accident ou non. Je vous suggère de lire cet article [link] (http://www.cocoanetics.com/2011/10/avoiding-image-decompression-sickness/) et aussi de télécharger l'exemple de code LargeImageDownsizing du site Apple. Ciao – Andrea

+0

Peut-être une solution pourrait être la carte de la mémoire d'image sur un fichier en utilisant la fonction mmap unix, mais il pourrait être assez difficile et peut-être aussi lent. – Andrea

0

Insérer ceci à la fin de vos méthodes et avant la return copy;:

CGContextRelease(ctxt); 
+0

J'ai essayé cela tout à l'heure, mais il semble qu'il n'a aucun effet. J'utilise ARC, alors ARC est peut-être en train de s'en occuper. – Melvin

+1

ARC ne prendra pas soin des "anciens" objets de la Fondation Core – Andrea

Questions connexes