2016-04-26 3 views
0

Я работаю над проектом, где я хотел бы скрыть фотографию, которую пользователь только что снял с помощью своей камеры. Маска создается с определенным соотношением сторон, чтобы добавить почтовые ящики к фотографии.Примените маску к AVCaptureStillImageOutput

Я могу создать изображение, создать маску и сохранить ее в рулоне камеры, но не могу применить маску к изображению. Вот код, у меня сейчас

func takePhoto() { 
    dispatch_async(self.sessionQueue) {() -> Void in 
    if let photoOutput = self.output as? AVCaptureStillImageOutput { 
     photoOutput.captureStillImageAsynchronouslyFromConnection(self.outputConnection) { (imageDataSampleBuffer, err) -> Void in 
     if err == nil { 
      let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer) 
      let image = UIImage(data: imageData) 

      if let _ = image { 
      let maskedImage = self.maskImage(image!) 

      print("masked image: \(maskedImage)") 

      self.savePhotoToLibrary(maskedImage) 
      } 
     } else { 
      print("Error while capturing the image: \(err)") 
     } 
     } 
    } 
    } 
} 

func maskImage (image: UIImage) -> UIImage { 
    let mask = createImageMask(image) 

    let maskedImage = CGImageCreateWithMask(image.CGImage, mask!) 

    return UIImage(CGImage: maskedImage!) 
} 

func createImageMask (image: UIImage) -> CGImage? { 
    let width = image.size.width 
    let height = width/CGFloat(store.state.aspect.rawValue) 
    let x = CGFloat(0.0) 
    let y = (image.size.height - height)/2 
    let maskRect = CGRectMake(0.0, 0.0, image.size.width, image.size.height) 
    let maskContents = CGRectMake(x, y, width, height) 

    var color = UIColor(white: 1.0, alpha: 0.0) 

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(maskRect.size.width, maskRect.size.height), false, 0.0) 

    color.setFill() 
    UIRectFill(maskRect) 

    color = UIColor(white: 0.0, alpha: 1.0) 
    color.setFill() 
    UIRectFill(maskContents) 

    let maskImage = UIGraphicsGetImageFromCurrentImageContext() 

    UIGraphicsEndImageContext() 

    print("mask: \(maskImage)") 
    savePhotoToLibrary(image) 
    savePhotoToLibrary(maskImage) 

    let mask = CGImageMaskCreate(
    CGImageGetWidth(maskImage.CGImage), 
    CGImageGetHeight(maskImage.CGImage), 
    CGImageGetBitsPerComponent(maskImage.CGImage), 
    CGImageGetBitsPerPixel(maskImage.CGImage), 
    CGImageGetBytesPerRow(maskImage.CGImage), 
    CGImageGetDataProvider(maskImage.CGImage), 
    nil, 
    false) 

    return mask 
} 

Из того, что я понимаю, CGImageCreateWithMask требует, чтобы изображение маскироваться имеет альфа-канал. Я пробовал все, что я видел здесь, чтобы добавить альфа-канал в представление jpeg, но мне не повезло. Любая помощь будет супер.

ответ

1

Это может быть ошибка, или, может быть, она немного вводит в заблуждение. CGImageCreateWithMask() фактически не модифицирует изображение - он просто связывает данные маски с данными изображения и использует маску при рисовании изображения в контексте (например, в UIImageView), но не при сохранении изображения в диск.

Есть пара подходов к созданию «визуализированной» версии маскированного изображения, но если я понимаю ваше намерение, вам действительно не нужна «маска» ... вы хотите, чтобы версия с буквенным обозначением образ.

Вот один из вариантов, который эффективно рисует черные полосы сверху и снизу вашего изображения (штрих/цвет рамки является необязательным параметром, если вы не хотите черный). Затем вы можете сохранить изображение.

В коде выше, замените

let maskedImage = self.maskImage(image!) 

с

let height = image.size.width/CGFloat(store.state.aspect.rawValue) 
    let maskedImage = self.doLetterBox(image!, visibleHeight: height) 

и добавить эту функцию:

func doLetterBox(sourceImage: UIImage, visibleHeight: CGFloat, frameColor: UIColor?=UIColor.blackColor()) -> UIImage! { 

    // local rect based on sourceImage size 
    let imageRect: CGRect = CGRectMake(0.0, 0.0, sourceImage.size.width, sourceImage.size.height) 

    // rect for "visible" part of letter-boxed image 
    let clipRect: CGRect = CGRectMake(0.0, (imageRect.size.height - visibleHeight)/2.0, imageRect.size.width, visibleHeight) 

    // setup the image context, using sourceImage size 
    UIGraphicsBeginImageContextWithOptions(imageRect.size, true, UIScreen.mainScreen().scale) 

    let ctx: CGContextRef = UIGraphicsGetCurrentContext()! 
    CGContextSaveGState(ctx) 

    // fill new empty image with frameColor (defaults to black) 
    CGContextSetFillColorWithColor(ctx, frameColor?.CGColor) 
    CGContextFillRect(ctx, imageRect) 

    // set Clipping rectangle to allow drawing only in desired area 
    UIRectClip(clipRect) 

    // draw the sourceImage to full-image-size (the letter-boxed portion will be clipped) 
    sourceImage.drawInRect(imageRect) 

    // get new letter-boxed image 
    let resultImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() 

    // clean up 
    CGContextRestoreGState(ctx) 
    UIGraphicsEndImageContext() 

    return resultImage 

} 
+0

Это, по существу, что я закончил с. Благодаря! – Mike

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