iOS 保存原图相关
2019-03-15 本文已影响0人
木木子席
在app开发中,经常会遇到保存图片的需求。
在对图片数据要求不高的情况下,可以直接拿到UIImage对象,然后保存这个UIImage。
比如我们常用SDWebImage框架来下载和获取图片。
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;
}