Как сохранить данные изображения JPEG / RAW в камеру в iOS 11, не может получить доступ к обработанным данным изображения - PullRequest
0 голосов
/ 28 апреля 2018

Я пытаюсь написать фото-приложение, которое может принимать изображения как в формате RAW, так и в формате JPEG, и сохранять их в фотоаппарате. Функции jpegPhotoDataRepresentation и dngPhotoDataRepresentation, похоже, являются ключом ко всем примерам, которые я нашел, однако оба они устарели в iOS 11, и функция сохранения после «capturePhoto» теперь

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

Главный пример, который мне удалось найти для работающего приложения RAW iOS11: https://ubunifu.co/swift/raw-photo-capture-sample-swift-4-ios-11 который работает, однако он снимает только RAW, а сохранение неуклюже, потому что его нет в списке.

Я изменил настройки фотографии, чтобы разрешить как необработанный, так и обработанный снимок с этой строкой

photoSettings = AVCapturePhotoSettings(rawPixelFormatType: availableRawFormat.uint32Value, processedFormat: [AVVideoCodecKey : AVVideoCodecType.jpeg])

Но как только я действительно сделал снимок, я понятия не имею, как получить доступ к данным обработанного формата. fileDataRepresentation, кажется, единственный способ получить доступ к материалу dng, но нет никакого способа получить в jpeg отдельно? Код, который я нашел в Apple до iOS11, предлагает использовать PHPhotoLibrary и добавить ресурс, но для этого требуется представление данных, к которому я не могу получить доступ, кроме как в виде файла dng, который при сохранении в библиотеке просто белый, потому что библиотека не может обрабатывать файлы RAW. Вот мой код photoOutput на случай, если это поможет.

 func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

    let dir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as String
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyyMMddHHmmss"
    formatter.locale = Locale.init(identifier: "en_US_POSIX")
    let filePath =  dir.appending(String(format: "/%@.dng", formatter.string(from: Date())))
    let dngFileURL = URL(fileURLWithPath: filePath)

    let dngData = photo.fileDataRepresentation()!
    do {
        try dngData.write(to: dngFileURL, options: [])
    } catch {
        print("Unable to write DNG file.")
        return
    }

    PHPhotoLibrary.shared().performChanges( {
        let creationRequest = PHAssetCreationRequest.forAsset()
        let creationOptions = PHAssetResourceCreationOptions()
        creationOptions.shouldMoveFile = true


        //dngData is the problem, this should be the jpeg representation
        creationRequest.addResource(with: .photo, data: dngData, options: nil)
        //This line works fine, the associated file is the correct RAW file, but the jpeg preview is garbage
        creationRequest.addResource(with: .alternatePhoto, fileURL: dngFileURL, options: creationOptions)

    }, completionHandler: nil)

}

1 Ответ

0 голосов
/ 29 апреля 2018

Хорошо, следите за комментариями из предыдущих версий и документами Apple по Захват фотографий в формате RAW :

Как вы заметили, если вы хотите снимать RAW и сохранять его в библиотеке Photos, вам необходимо сохранить обработанные версии DNG + вместе в одном активе, чтобы клиенты библиотеки Photos, которые не поддерживают RAW, все еще имели читаемая версия актива. (Это включает в себя и само приложение «Фотографии» ...) Сохранение обоих обработанных RAW + означает указание этого в захвате.

Если вы запрашиваете обработанный снимок в формате RAW + (где обрабатывается JPEG или, что еще лучше, HEIF), вы получаете две фотографии за каждый сделанный снимок. Это означает, что ваш didFinishProcessingPhoto обратный вызов вызывается дважды : один раз для доставки JPEG (или HEIF), снова для доставки RAW.

Поскольку вам необходимо добавить обработанные RAW + версии ресурса в Photos вместе, вам следует подождать, пока выходные данные захвата доставят обе версии, прежде чем пытаться создать ресурс Photos. Вы заметите фрагменты кода в том, что Apple doc хранит данные для обеих версий в обратном вызове didFinishProcessingPhoto:

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    if photo.isRawPhoto {
        // Save the RAW (DNG) fileDataRepresentation to a URL
    } else {
        // Hold JPEG/HEIF fileDataRepresentation in a property
    }
}

Затем, когда срабатывает обратный вызов didFinishCaptureFor, они проверяют, имеют ли они обе версии, и добавляют их вместе в библиотеку Photos.

Обратите внимание, что при добавлении версий фотографий DNG и JPEG или HEIF вместе ...

  • JPEG / HEIF должен быть основным photo ресурсом, а DNG - alternatePhoto ресурсом.
  • Вы можете добавить ресурс JPEG / HEIF прямо из Data в памяти, но DNG необходимо добавить из URL-адреса файла.

Итак, часть библиотеки Photos выглядит следующим образом (опять же внутри обратного вызова didFinishCaptureFor):

PHPhotoLibrary.shared().performChanges({
    // Add the compressed (HEIF) data as the main resource for the Photos asset.
    let creationRequest = PHAssetCreationRequest.forAsset()
    creationRequest.addResource(with: .photo, data: compressedData, options: nil)

    // Add the RAW (DNG) file as an altenate resource.
    let options = PHAssetResourceCreationOptions()
    options.shouldMoveFile = true
    creationRequest.addResource(with: .alternatePhoto, fileURL: rawURL, options: options)
}, completionHandler: self.handlePhotoLibraryError)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...