ios 和 android 中的 whatsapp 和 instagram 等图像优化
Image optimization like whatsapp and instagram in ios and android
任务:-
像 Facebook 和 WhatApp 那样优化图像?
在 android 和 ios 中以优化大小将图像上传到服务器,而不会丢失图像质量和尺寸。
我看过很多代码,比如原生图像压缩 (UIImageJPEGRepresentation(viewImage, 0.8)),但我无法得到正确的结果。
有人可以向我推荐 iOS 和 android 中的任何算法或库,我们可以通过它们在不损失质量的情况下优化图像。
我已经访问过的链接:
iOS
- What's the easiest way to resize/optimize an image size with the iPhone SDK?
Android
试试这个代码:
+(UIImage *)scaleAndRotateImage:(UIImage *)image {
int kMaxResolution = 640; // Or whatever
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat ratio = width/height;
if (ratio > 1) {
bounds.size.width = kMaxResolution;
bounds.size.height = roundf(bounds.size.width / ratio);
}
else {
bounds.size.height = kMaxResolution;
bounds.size.width = roundf(bounds.size.height * ratio);
}
}
CGFloat scaleRatio = bounds.size.width / width;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {
case UIImageOrientationUp: //EXIF = 1
transform = CGAffineTransformIdentity;
break;
case UIImageOrientationUpMirrored: //EXIF = 2
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
break;
case UIImageOrientationDown: //EXIF = 3
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationDownMirrored: //EXIF = 4
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
break;
case UIImageOrientationLeftMirrored: //EXIF = 5
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationLeft: //EXIF = 6
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationRightMirrored: //EXIF = 7
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
case UIImageOrientationRight: //EXIF = 8
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
CGContextScaleCTM(context, -scaleRatio, scaleRatio);
CGContextTranslateCTM(context, -height, 0);
}
else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGFloat scaleSize = 0.2f;
UIImage *smallImage = [UIImage imageWithCGImage:imageCopy.CGImage
scale:scaleSize
orientation:imageCopy.imageOrientation];
return smallImage;
}
这是我在 Android 中使用的:
public class ImageCompresser {
public static void compressImage(String inputFilePath, String outputFilePath) {
try {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(inputFilePath, options);
//options.inSampleSize = calculateInSampleSize(options,400,300);
options.inSampleSize = calculateInSampleSize(options,800,1000);//Specify Minimum Height, Width of the resulting bitmap maintaining the aspect ratio
options.inJustDecodeBounds = false;
Bitmap bm = BitmapFactory.decodeFile(inputFilePath, options);
FileOutputStream fileOutputStream;
fileOutputStream = new FileOutputStream(outputFilePath);
ExifInterface exif;
try {
exif = new ExifInterface(inputFilePath);
Log.d("EXIF", "Make : " + exif.getAttribute(ExifInterface.TAG_MAKE));
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif Orientation : " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
Bitmap scaledBitmap = Bitmap.createBitmap(bm, 0, 0,
bm.getWidth(), bm.getHeight(), matrix,
true);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);//Instead of 100, you can provide any value. But it will reduce the image quality
scaledBitmap.recycle();
} catch (IOException e) {
e.printStackTrace();
}
fileOutputStream.flush();
fileOutputStream.close();
bm.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int imageWidth = options.outWidth;
final int imageHeight = options.outHeight;
Log.d("Test", "imageWidth : " + imageWidth);
Log.d("Test", "imageHeight : " + imageHeight);
int inSampleSize = 1;
if(imageWidth > reqWidth || imageHeight > reqHeight) {
final int halfWidth = imageWidth / 2;
final int halfHeight = imageHeight / 2;
while((halfWidth / inSampleSize) > reqWidth
&& (halfHeight / inSampleSize) > reqHeight) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
}
参考文献:
任务:- 像 Facebook 和 WhatApp 那样优化图像? 在 android 和 ios 中以优化大小将图像上传到服务器,而不会丢失图像质量和尺寸。
我看过很多代码,比如原生图像压缩 (UIImageJPEGRepresentation(viewImage, 0.8)),但我无法得到正确的结果。
有人可以向我推荐 iOS 和 android 中的任何算法或库,我们可以通过它们在不损失质量的情况下优化图像。
我已经访问过的链接:
iOS
- What's the easiest way to resize/optimize an image size with the iPhone SDK?
Android
试试这个代码:
+(UIImage *)scaleAndRotateImage:(UIImage *)image {
int kMaxResolution = 640; // Or whatever
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat ratio = width/height;
if (ratio > 1) {
bounds.size.width = kMaxResolution;
bounds.size.height = roundf(bounds.size.width / ratio);
}
else {
bounds.size.height = kMaxResolution;
bounds.size.width = roundf(bounds.size.height * ratio);
}
}
CGFloat scaleRatio = bounds.size.width / width;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {
case UIImageOrientationUp: //EXIF = 1
transform = CGAffineTransformIdentity;
break;
case UIImageOrientationUpMirrored: //EXIF = 2
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
break;
case UIImageOrientationDown: //EXIF = 3
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationDownMirrored: //EXIF = 4
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
break;
case UIImageOrientationLeftMirrored: //EXIF = 5
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationLeft: //EXIF = 6
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationRightMirrored: //EXIF = 7
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
case UIImageOrientationRight: //EXIF = 8
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
CGContextScaleCTM(context, -scaleRatio, scaleRatio);
CGContextTranslateCTM(context, -height, 0);
}
else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGFloat scaleSize = 0.2f;
UIImage *smallImage = [UIImage imageWithCGImage:imageCopy.CGImage
scale:scaleSize
orientation:imageCopy.imageOrientation];
return smallImage;
}
这是我在 Android 中使用的:
public class ImageCompresser {
public static void compressImage(String inputFilePath, String outputFilePath) {
try {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(inputFilePath, options);
//options.inSampleSize = calculateInSampleSize(options,400,300);
options.inSampleSize = calculateInSampleSize(options,800,1000);//Specify Minimum Height, Width of the resulting bitmap maintaining the aspect ratio
options.inJustDecodeBounds = false;
Bitmap bm = BitmapFactory.decodeFile(inputFilePath, options);
FileOutputStream fileOutputStream;
fileOutputStream = new FileOutputStream(outputFilePath);
ExifInterface exif;
try {
exif = new ExifInterface(inputFilePath);
Log.d("EXIF", "Make : " + exif.getAttribute(ExifInterface.TAG_MAKE));
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif Orientation : " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
Bitmap scaledBitmap = Bitmap.createBitmap(bm, 0, 0,
bm.getWidth(), bm.getHeight(), matrix,
true);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);//Instead of 100, you can provide any value. But it will reduce the image quality
scaledBitmap.recycle();
} catch (IOException e) {
e.printStackTrace();
}
fileOutputStream.flush();
fileOutputStream.close();
bm.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int imageWidth = options.outWidth;
final int imageHeight = options.outHeight;
Log.d("Test", "imageWidth : " + imageWidth);
Log.d("Test", "imageHeight : " + imageHeight);
int inSampleSize = 1;
if(imageWidth > reqWidth || imageHeight > reqHeight) {
final int halfWidth = imageWidth / 2;
final int halfHeight = imageHeight / 2;
while((halfWidth / inSampleSize) > reqWidth
&& (halfHeight / inSampleSize) > reqHeight) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
}
参考文献: