2012-02-22 6 views
3

У меня есть этот код, чтобы повернуть CGImage:CGImage вращение утечки метод память на прошивке

- (CGImageRef)rotateCGImageRef:(CGImageRef)imageRef toOrientation:(UIImageOrientation)orientation 
{ 
    CGRect    bnds = CGRectZero; 
    CGImageRef   copy = nil; 
    CGContextRef  ctxt = nil; 
    CGRect    rect = CGRectZero; 
    CGAffineTransform tran = CGAffineTransformIdentity; 

    @autoreleasepool { 
     bnds.size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); //self.size; 
     rect.size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); //self.size; 

     switch (orientation) 
     { 
      case UIImageOrientationUp: 
       return imageRef; 

      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(bnds.size); 
     ctxt = UIGraphicsGetCurrentContext(); 

     switch (orientation) 
     { 
      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, rect, imageRef); 

     //copy = UIGraphicsGetImageFromCurrentImageContext(); 
     copy = CGBitmapContextCreateImage(ctxt); 
     UIGraphicsEndImageContext(); 
    } 
    return copy; 
} 

Но анализатор говорит, что есть утечка: memory leak

Я не могу освободить объект копирования, потому что я метод возвращает его.

Что на самом деле протекает?

EDIT: Вот окончательный код преобразуется в функцию C:

CGImageRef CreateRotatedImage(CGImageRef imageRef, UIImageOrientation orientation) 
{ 
    CGRect    bnds = CGRectZero; 
    CGImageRef   copy = nil; 
    CGContextRef  ctxt = nil; 
    CGRect    rect = CGRectZero; 
    CGAffineTransform tran = CGAffineTransformIdentity; 

    bnds.size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); //self.size; 
    rect.size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); //self.size; 

    switch (orientation) 
    { 
     case UIImageOrientationUp: 
      return imageRef; 

     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(bnds.size); 
    ctxt = UIGraphicsGetCurrentContext(); 

    switch (orientation) 
    { 
     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, rect, imageRef); 

    //copy = UIGraphicsGetImageFromCurrentImageContext(); 
    copy = CGBitmapContextCreateImage(ctxt); 
    UIGraphicsEndImageContext(); 
    return copy; 
} 

Вызов этой функции C:

imageRef = CreateRotatedImage(imageRef, UIImageOrientationRight); 

ответ

2

Я думаю, ваша проблема в том, что вы возвращаете CGImageRef из метода Obj-C. CGImageRef - это typedef для указателя C-struct, а не NSObject и, следовательно, он не может быть автореализован.

Я бы рассмотрел два варианта: преобразовать метод в функцию C или поместить возвращаемое значение в NSObject (например, UIImage).

EDIT:

CGImageRef CreateRotatedImage(CGImageRef imageRef, UIImageOrientation toOrientation) { 
    [... your code ...] 
} 

Вызов:

CGImageRef rotatedImage = CreateRotatedImage(image, orientation); 
+0

Второй вариант не хорош, потому что я прохожу в CGImage, а также ожидаю возвращения CGImage, а не UIImage. О первом варианте я действительно не знаю, как создать функцию C и как ее называть ...? –

+0

Вам обязательно нужно научиться этому: в коде вы уже 20 раз вызываете C-функции. Отредактировал ответ. – Sulthan

+0

Спасибо, что работает. На данный момент нет утечек ... –

0

Вы должны освободить свой CGImageRef copy. CFType должен знать, как обращаться с release и autorelease. Попробуйте следующее:

return (CGImageRef)[(id)copy autorelease]; 

Во-первых, вы должны указать его на указатель Objective-C. Затем вы возвращаете его обратно в CGImageRef. См. Этот ответ: https://stackoverflow.com/a/7061168/656036

+0

Это должно работать, но я использую ARC, и это autorelease является устаревшим ... –

+0

Вы могли бы назвать 'CGImageRelease (imgRef)' на возвращаемый 'CGImageRef' – fscheidl

+0

К сожалению, это не работает ... –

0

Вы должны прочитать в то, что говорит анализатор: это потенциал утечки. Анализатор не скажет вам, действительно ли это утечка или нет, чтобы получить эту информацию, необходимую для запуска инструмента «Утечки» из инструментов.

Анализатор правильно предупреждает вас о том, что вы возвращаете значение, которое вам придется освободить.

В вашей приемной функции, просто вызовите

CGImageRelease(img); 

После вашего сделаны с CGImageRef.

 Смежные вопросы

  • Нет связанных вопросов^_^