LoginSignup
45
45

More than 5 years have passed since last update.

写真/動画をアプリ領域に保存する方法

Last updated at Posted at 2014-02-06

UIImagePickerControllerで選択した写真/動画をアプリ領域に保存する方法です。

UIImagePickerControllerDelegateのdidFinishPickingMediaWithInfoを実装します。
ここでパラメータのpickerInfoに選択した写真/動画の情報が渡ってきます。

-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)pickerInfo {
    ...
}

まずは写真のみの場合を考えたシンプルな例

AssetsLibraryを使用して画像データにアクセスします。
生画像を取得したい場合はALAssetRepresentationのfullResolutionImageを、編集後の画像を取得したい場合はfullScreenImageを使います。

ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
NSURL *url = [pickerInfo objectForKey:UIImagePickerControllerReferenceURL];

[assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
    ALAssetRepresentation *rep = [asset defaultRepresentation];
    NSString *path = [NSString stringWithFormat:@"%@/%@.png", dir, fileName];

    // 写真アプリで編集後の画像取得(編集前の画像はfullResolutionImage)
    UIImage *image = [UIImage imageWithCGImage:rep.fullScreenImage];

    [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
    ...
} failureBlock:^(NSError *error) {
    ...
}];

巨大な動画が選択されても落ちないようにする

動画が選択された場合も考慮したケースです。
数十分の動画で数GBになったりすると、何も考えずに実装すると落ちてしまいます。
データを少しずつ読み込んでは開放を繰り返すように工夫してやる必要があります。

ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
NSURL *url = [pickerInfo objectForKey:UIImagePickerControllerReferenceURL];

NSString *extension = url.pathExtension.lowercaseString;
NSString *path = [NSString stringWithFormat:@"%@/%@.%@", dir, fileName, extension];

[assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
    ALAssetRepresentation *rep = [asset defaultRepresentation];

    [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
    NSFileHandle *output = [NSFileHandle fileHandleForWritingAtPath:path];

    int partSize = 8 * 1024 * 1024;
    NSUInteger offset = 0;

    @try {
        while (true) {
            @autoreleasepool {
                NSError *error = nil;

                // 少しずつ読み込む
                Byte *buffer = (Byte*)malloc(partSize);
                NSUInteger readByteLength = [rep getBytes:buffer fromOffset:offset length:partSize error:&error];
                if (error != nil) {
                    ...
                }
                if (readByteLength <= 0) {
                    free(buffer);
                    break;
                }
                offset += readByteLength;

                NSData *data = [NSData dataWithBytesNoCopy:buffer length:readByteLength freeWhenDone:YES];
                [output writeData:data];
            }
        }
        ...
    }
    @catch (NSException *exception) {
        ...
    }
    @finally {
        [output closeFile];
    }
} failureBlock:^(NSError *error) {
    ...
}];
45
45
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
45