插件通过传给我们一个图片的绝对路径,让我们进行图片的压缩,从而可以进行上传。
在模拟器上地址格式是这样的: @"file:///Users/qmc/Library/Developer/CoreSimulator/Devices/B450A007-3FFD-44E2-A893-69B5F94D23A5/data/Containers/Data/Application/0245F4E6-D1E5-42DC-8B60-15519395BAA4/tmp/cdv_photo_026.jpg" 。真机上也是差不多的。但是ios沙盒的路径是不识别这种的,只能是这样的/Users/qmc/...,所以我们首先需要将路径截取成我们需要的。而且需注意的是,该路径存放的是一个tmp文件夹,及临时文件夹,APP退出后里面的文件都会被清空。
fullPath = [fullPath stringByReplacingOccurrencesOfString:@"file://" withString:@""];
获取包换后缀名的文件名以及不不包含文件名的路径
NSString *imageName = [fullPath lastPathComponent];
// NSString *imagePath = [fullPath stringByReplacingOccurrence sOfString:[@"/" stringByAppendingString:imageName] withString:@""];
- (UIImage *)getPhotoFromName:(NSString *)name filePath:(NSString *)filePath {
// NSString *tmpDir = NSTemporaryDirectory();
// NSString *uniquePath=[[paths objectAtIndex:0] stringByAppendingPathComponent:name];
// BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@%@",tmpDir,name]];
BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath: filePath];
if (!blHave) {
return nil;
}else
{
NSData *data = [NSData dataWithContentsOfFile:filePath];
UIImage *img = [[UIImage alloc] initWithData:data];
return img;
}}
上面的方法是通过路径及文件名,首先判断该路径下是否有文件,如果存在的话将文件取出给UIImage.返回的UIImage我们就可以操作进行压缩了。
//对图片尺寸进行压缩--
-(UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize {
// Create a graphics image context
UIGraphicsBeginImageContext(newSize);
// Tell the old image to draw in this new context, with the desired
// new size
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Get the new image from the context
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the context
UIGraphicsEndImageContext();
// Return the new image.
return newImage;}
该方法传入原图片及需求的尺寸,便会返回需求的图片了!
实际原理就是重新给图片绘了一个需求宽高的边。
接下来就是讲图片保存到沙盒中,并且返回一个路径给js。
//保存新的图片 永久保存到沙盒
-(NSString *)saveNewImage:(UIImage *)image WithImageName:(NSString *)imageName{
//xxxx.png
NSString *newName = [imageName stringByReplacingOccurrencesOfString:@".png" withString:@""];
newName = [imageName stringByReplacingOccurrencesOfString:@".jpg" withString:@""];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:@"%@New.png",newName]];
//校验该文件名是否已经存在
if([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:@"%@New02.png",newName]];
}
// UIImageWriteToSavedPhotosAlbum(image, self, nil, NULL);
[UIImagePNGRepresentation(image) writeToFile:filePath atomically:YES];
return filePath;}
可能会出现我们新取得图片名已经有了,这时候做一个判断,如果有相同的名字了就换一个。然后写到document下保存。这种保存的机制是永久的,除非你删掉了APP或者是情空APP数据才会消失。
图片压缩就全部结束了。在做图片压缩耗时最多的就是路径处理那一块。
附代码:
#import "ImageCompress.h"
#import
@implementation ImageCompress
- (NSString *)compress:(CDVInvokedUrlCommand *)command {
NSString *fullPath = command.arguments[0];
fullPath = [fullPath stringByReplacingOccurrencesOfString:@"file://" withString:@""];
NSString *imageName = [fullPath lastPathComponent];
// NSString *imagePath = [fullPath stringByReplacingOccurrencesOfString:[@"/" stringByAppendingString:imageName] withString:@""];
UIImage *targetImage = [self getPhotoFromName:imageName filePath:fullPath];
UIImage *newImage = [self imageWithImage:targetImage scaledToSize:CGSizeMake(48, 72)];
return [self saveNewImage:newImage WithImageName:imageName];
}
- (UIImage *)getPhotoFromName:(NSString *)name filePath:(NSString *)filePath {
// NSString *tmpDir = NSTemporaryDirectory();
// NSString *uniquePath=[[paths objectAtIndex:0] stringByAppendingPathComponent:name];
// BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@%@",tmpDir,name]];
BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath: filePath];
if (!blHave) {
return nil;
}else
{
NSData *data = [NSData dataWithContentsOfFile:filePath];
UIImage *img = [[UIImage alloc] initWithData:data];
return img;
}
}
//对图片尺寸进行压缩--
-(UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize {
// Create a graphics image context
UIGraphicsBeginImageContext(newSize);
// Tell the old image to draw in this new context, with the desired
// new size
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Get the new image from the context
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the context
UIGraphicsEndImageContext();
// Return the new image.
return newImage;
}
//保存新的图片 永久保存到沙盒
-(NSString *)saveNewImage:(UIImage *)image WithImageName:(NSString *)imageName{
//xxxx.png
NSString *newName = [imageName stringByReplacingOccurrencesOfString:@".png" withString:@""];
newName = [imageName stringByReplacingOccurrencesOfString:@".jpg" withString:@""];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:@"%@New.png",newName]];
//校验该文件名是否已经存在
if([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:@"%@New02.png",newName]];
}
// UIImageWriteToSavedPhotosAlbum(image, self, nil, NULL);
[UIImagePNGRepresentation(image) writeToFile:filePath atomically:YES];
return filePath;
}
@end
手机拍照上传 出现问题(取不到图片) 解决方案:
由于用手机直接拍照上传传给压缩插件的不再是文件的路径,而是
assets-library://asset/asset.JPG?id=72CABA8E-68C0-413E-A3D5-256585CF3B42&ext=JPG 这种图片的url.
所以原先做的不再通用,需要做判断分开处理:
- (void)compress:(CDVInvokedUrlCommand *)command {
NSString *fullPath = command.arguments[0];
__block UIImage *targetImage = [[UIImage alloc]init];
NSString *imageName = [[NSString alloc]init];
if( [fullPath rangeOfString:@"file://"].location != NSNotFound){
imageName = [fullPath lastPathComponent];
fullPath = [fullPath stringByReplacingOccurrencesOfString:@"file://" withString:@""];
targetImage = [self getPhotoFromName:imageName filePath:fullPath];
} else {
imageName = @"assetTarget";
ALAssetsLibrary *lib = [[ALAssetsLibrary alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
[lib assetForURL:[NSURL URLWithString:fullPath] resultBlock:^(ALAsset *asset) {
//在这里使用asset来获取图片
targetImage = [self fullResolutionImageFromALAsset:asset];
//信号量 通知 +1
dispatch_semaphore_signal(sema);
}
failureBlock:^(NSError *error){
dispatch_semaphore_signal(sema);
}];
});
//阻塞进程 直到 图片处理完毕
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
// NSString *imagePath = [fullPath stringByReplacingOccurrencesOfString:[@"/" stringByAppendingString:imageName] withString:@""];
UIImage *newImage = [self imageWithImage:targetImage scaledToSize:CGSizeMake(480, 720)];
NSString *path = [self saveNewImage:newImage WithImageName:imageName];
// NSString *jsCallback = [NSString stringWithFormat:@"cordova.fireDocumentEvent('compress',%@)", path];
CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:path];
[self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId];
// [self.commandDelegate evalJs:path];
}
- (UIImage *)fullResolutionImageFromALAsset:(ALAsset *)asset
{
ALAssetRepresentation *assetRep = [asset defaultRepresentation];
CGImageRef imgRef = [assetRep fullResolutionImage];
UIImage *img = [UIImage imageWithCGImage:imgRef
scale:assetRep.scale
orientation:(UIImageOrientation)assetRep.orientation];
return img;
}
这里有几点一定要格外注意:
1.拍照的文件名: 不能再直接取了。所以我们给了一个固定的文件名。
2.图片的Url需要经过处理才能转化为UIImage.
3. assetForUrl这个Block是异步的方法。但是不适合我们。这种情况下我们需要同步执行,先获取uiimage才能执行其他的事。所以,此处通过
阻塞线程的方法来控制执行顺序。