iOS 保存原图相关

2019-03-15  本文已影响0人  木木子席
在app开发中,经常会遇到保存图片的需求。

在对图片数据要求不高的情况下,可以直接拿到UIImage对象,然后保存这个UIImage。
比如我们常用SDWebImage框架来下载和获取图片。

示例图片.JPG
SDWebImageDownloader *manager = [SDWebImageDownloader sharedDownloader];
    [manager downloadImageWithURL:imageUrl options:SDWebImageDownloaderUseNSURLCache progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
        saveToAsset(image); 
    }];

可以看到SDWebImage的下载方法给我们回调四个数据,其中一个是UIImage,一个是原始数据NSData。当我们直接存的UIImage,其实我们保存的并不是原图,这个图片保存后比原图小很多,很多信息都会丢失,比如我们打印示例图片中的EXIF信息,会发现有很大的区别。

  原图的exif:
{
ColorModel = RGB;
DPIHeight = 72;
DPIWidth = 72;
Depth = 8;
PixelHeight = 3968;
PixelWidth = 2976;
ProfileName = "sRGB IEC61966-2.1";
"{Exif}" =     {
    ApertureValue = "1.69";
    BrightnessValue = 0;
    ColorSpace = 1;
    ComponentsConfiguration =         (
        1,
        2,
        3,
        0
    );
    CompressedBitsPerPixel = "0.95";
    Contrast = 0;
    CustomRendered = 1;
    DateTimeDigitized = "2019:03:13 20:30:06";
    DateTimeOriginal = "2019:03:13 20:30:06";
    DigitalZoomRatio = 1;
    ExifVersion =         (
        2,
        1
    );
    ExposureBiasValue = 0;
    ExposureMode = 0;
    ExposureProgram = 2;
    ExposureTime = "0.01";
    FNumber = "1.8";
    FileSource = 3;
    Flash = 0;
    FlashPixVersion =         (
        1,
        0
    );
    FocalLenIn35mmFilm = 27;
    FocalLength = "4.75";
    GainControl = 0;
    ISOSpeedRatings =         (
        80
    );
    LightSource = 1;
    MaxApertureValue = "1.69";
    MeteringMode = 5;
    PixelXDimension = 2976;
    PixelYDimension = 3968;
    Saturation = 0;
    SceneCaptureType = 0;
    SceneType = 1;
    SensingMethod = 2;
    Sharpness = 0;
    ShutterSpeedValue = "29.89730002523341";
    SubjectDistRange = 0;
    SubsecTime = 298723;
    SubsecTimeDigitized = 298723;
    SubsecTimeOriginal = 298723;
    WhiteBalance = 0;
};
"{GPS}" =     {
    Altitude = 0;
    AltitudeRef = 1;
    DateStamp = "2019:03:13";
    GPSVersion =         (
        2,
        2,
        0,
        0
    );
    Latitude = "31.98787166666667";
    LatitudeRef = N;
    Longitude = "118.7609866666667";
    LongitudeRef = E;
    TimeStamp = "12:30:04";
};
"{JFIF}" =     {
    DensityUnit = 1;
    JFIFVersion =         (
        1,
        0,
        1
    );
    XDensity = 96;
    YDensity = 96;
};
"{TIFF}" =     {
    DateTime = "2019:03:13 20:30:06";
    ImageDescription = hdrpl;
    Make = HUAWEI;
    Model = "HMA-AL00";
    Orientation = 0;
    ResolutionUnit = 2;
    Software = "HMA-AL00 9.0.0.195(C00E195R1P21)";
    XResolution = 72;
    YResolution = 72;
};
  用UIImage保存后图片的exif:
      {
    ColorModel = RGB;
    DPIHeight = 72;
    DPIWidth = 72;
    Depth = 8;
    Orientation = 1;
    PixelHeight = 3968;
    PixelWidth = 2976;
    ProfileName = "sRGB IEC61966-2.1";
    "{Exif}" =     {
        ColorSpace = 1;
        ComponentsConfiguration =         (
            1,
            2,
            3,
            0
        );
        ExifVersion =         (
            2,
            2,
            1
        );
        FlashPixVersion =         (
            1,
            0
        );
        PixelXDimension = 2976;
        PixelYDimension = 3968;
        SceneCaptureType = 0;
    };
    "{JFIF}" =     {
        DensityUnit = 0;
        JFIFVersion =         (
            1,
            0,
            1
        );
        XDensity = 72;
        YDensity = 72;
    };
    "{TIFF}" =     {
        Orientation = 1;
        ResolutionUnit = 2;
        XResolution = 72;
        YResolution = 72;
    };
}

两者对比,会发现照片中GPS等信息都丢失了。当项目要求保证exif信息不丢失时,一种方法是直接保存原始数据,也就是直接保存返回NSData二进制数据。另一种方法是将原图的EXIF信息取出,再设置给处理好的图片。

这里记录下直接保存图片到相册的相关方法:

- (void)saveImageWithData:(NSData *)data imageUrl:(NSString *)imageUrl completion:(void(^)(void))completion{
//    [self getExifInfoWithImageData:data];
    BOOL dataValid = data && ([data isKindOfClass:NSData.class]||[data isKindOfClass:UIImage.class]);
    if (!dataValid) {
       //保存失败;
        return;
    }
    __block NSString* localIdentifier;
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        PHAssetCreationRequest *createRequest = nil;
        PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
        createRequest = [PHAssetCreationRequest creationRequestForAsset];
        [createRequest addResourceWithType:PHAssetResourceTypePhoto data:data options:options];
        localIdentifier = createRequest.placeholderForCreatedAsset.localIdentifier;
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        if (success && localIdentifier) {
            //以下代码是将图片放入新建的APP相册中,并给保存过的图片添加唯一标识,用做下载去重,如果不需要可以跳过
            //成功后取相册中的图片对象
            PHFetchResult *result = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];
            PHAsset* asset = [result firstObject];
            //获取自己app的相册  这里不实现方法了
            PHAssetCollection *collection = [self getCollection];
            // 3. 将“相机胶卷”中的图片添加到新的相册
            [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection];
                [request addAssets:@[asset]];
                //项目中的图片url有objId标识,具体看需求来
                NSString *objID = [imageUrl componentsSeparatedByString:@"="][1];
                if (objID) {
                     //给下载过的objID绑定一个相片标识   具体代码不实现了
                    [USER_TOOL addImageWithObjectID:objID localIdentifier:localIdentifier];
                }
            } completionHandler:^(BOOL success, NSError * _Nullable error) {
                NSLog(@"成功保存到相簿:%@", collection.localizedTitle);
                if (completion) {
                    completion();
                }
            }];
        }else{
            NSLog(@"保存失败 error: %@",error);
        }
    }];
}

获取exif的相关方法

- (NSMutableDictionary *)getExifInfoWithImageData:(NSData *)imageData{
    CGImageSourceRef cImageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
    NSDictionary *dict =  (NSDictionary *)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(cImageSource, 0, NULL));
    NSMutableDictionary *dictInfo = [NSMutableDictionary dictionaryWithDictionary:dict];
    NSLog(@"%@",dictInfo);
    return dictInfo;
}
上一篇下一篇

猜你喜欢

热点阅读