1. IOS压缩示例
/*
像素修改策略:
宽高均 <= 期望短边,尺寸保持不变
宽高均 > 期望短边,取较短边压缩为期望短边,较长边等比例压缩
宽或高 > 期望短边 && 宽图(宽高比 > 2),尺寸保持不变
宽或高 > 期望短边 && 长图(宽高比 < 0.5),尺寸保持不变
宽或高 > 期望短边 && 宽长(1 <= 宽高比 < 2),取宽压缩为期望短边,高等比例压缩
宽或高 > 期望短边 && 高长(0.5 <= 宽高比 < 1),取高压缩为期望短边,宽等比例压缩
图片压缩策略:
先修改图片像素(期望短边:1100),再进行质量压缩(压缩质量:0.7)
*/
#import <UIKit/UIKit.h>
static CGFloat const CompressShortPixelWidth = 1100.0f;
static CGFloat const CompressQuality = 0.7f;
@implementation ImageCompressTool
// 质量压缩
+ (NSData *)dataWithOriginalImage:(UIImage *)image {
return UIImageJPEGRepresentation([self imageWithOriginalImage:image], CompressQuality);
}
// 像素修改
+ (UIImage *)imageWithOriginalImage:(UIImage *)image {
CGFloat ratio = image.size.width / image.size.height;
CGFloat targetW = CompressShortPixelWidth;
CGFloat targetH = CompressShortPixelWidth;
// 宽高均 <= 期望短边,尺寸保持不变
if (image.size.width <= CompressShortPixelWidth && image.size.height <= CompressShortPixelWidth) {
return image;
}
// 宽高均 > 期望短边,取较短边压缩为期望短边,较长边等比例压缩
else if (image.size.width > CompressShortPixelWidth && image.size.height > CompressShortPixelWidth) {
if (ratio > 1.0f) {
targetH = CompressShortPixelWidth;
targetW = targetH * ratio;
}
else {
targetW = CompressShortPixelWidth;
targetH = targetW / ratio;
}
}
// 宽或高 > 期望短边
else {
// 宽图(宽高比 > 2),尺寸保持不变
if (ratio > 2.0f) {
targetW = image.size.width;
targetH = image.size.height;
}
// 长图(宽高比 < 0.5),尺寸保持不变
else if (ratio < 0.5f) {
targetW = image.size.width;
targetH = image.size.height;
}
// 宽长,取宽压缩为期望短边,高等比例压缩
else if (ratio > 1.0f) {
targetW = CompressShortPixelWidth;
targetH = CompressShortPixelWidth / ratio;
}
// 高长,取高压缩为期望短边,宽等比例压缩
else {
targetH = CompressShortPixelWidth;
targetW = CompressShortPixelWidth * ratio;
}
}
image = [self redrawImage:image targetW:targetW targetH:targetH];
return image;
}
// 重绘
+ (UIImage *)redrawImage:(UIImage *)sourceImage targetW:(CGFloat)targetW targetH:(CGFloat)targetH {
UIGraphicsBeginImageContext(CGSizeMake(targetW, targetH));
[sourceImage drawInRect:CGRectMake(0.0f, 0.0f, targetW, targetH)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
@end
2. Android压缩示例
/***
* 以下是我们图片压缩库的基本的算法
*
* 下面的压缩算法的最终结果是:
* 1).短边在 1000~2000 之间(经过设置相机的参数,通常短边取值是1080、1200等值)
* 2).压缩的质量为 75%
*
* @return
* @throws IOException
*/
File compress() throws IOException {
BitmapFactory.Options options = new BitmapFactory.Options();
// 这里我们通过我们的计算算法来得到一个采样率
options.inSampleSize = myComputeSize();
Bitmap tagBitmap = BitmapFactory.decodeStream(srcImg.open(), null, options);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
if (Checker.SINGLE.isJPG(srcImg.open())) {
tagBitmap = rotatingImage(tagBitmap, Checker.SINGLE.getOrientation(srcImg.open()));
}
// 这里使用了固定的压缩比75,可以通过为构建者模式增加字段来修改库,动态为其赋值
tagBitmap.compress(focusAlpha ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, 75, stream);
tagBitmap.recycle();
FileOutputStream fos = new FileOutputStream(tagImg);
fos.write(stream.toByteArray());
fos.flush();
fos.close();
stream.close();
return tagImg;
}
/**
* 这里的算法是以短边压缩到1000~2000之间为目标,通过计算到1000的比值,然后需要将采样率控制为2的倍数
* 所以需要使用方法{@link #calInSampleSize(int)}进行计算
*
* @return 采样率
*/
private int myComputeSize() {
srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;
srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;
int shortSide = Math.min(srcWidth, srcHeight);
int rate = (int) Math.floor(shortSide / 1000.0);
return calInSampleSize(rate);
}
/**
* 通过移位操作计算采样率,是某个整数对应的二进制数保留最高位为1,其他位置为0的结果
*
* @param rate 比例
* @return 采样率
*/
private int calInSampleSize(int rate) {
int i = 0;
while ((rate >> (++i)) != 0) ;
return 1 << --i;
}
3. js压缩示例
//需要先引入exif.js文件(下载地址:https://fapiao.glority.cn/dist/js/exif.js)
//将大小大于500kb的图片进行压缩,将图片最短边调整成1280,压缩质量比是0.98
ImageCompress(){
var thiz = this,
file = $("#imagefile")[0].files[0],
reader = new FileReader(),
image = new Image(),
needCompress = false,
type = null;
var name = file.name;
type = (name.substr(name.lastIndexOf("."))).toLowerCase();
if (type != ".jpg"&& type != ".png"&& type != ".jpeg"&& type != ".pdf") {
return false;
}
var fileSize = file.size;
if (fileSize > 500*1024) { //如果文件大于500kb,就需要进行压缩
needCompress = true;
}
if (file && type != ".pdf" && needCompress) {
var Orientation = null;
EXIF.getData(file, function() {
Orientation = EXIF.getTag(this, 'Orientation');
});
reader.onload = function (ev) {
image.src = ev.target.result;
image.onload = function () {
var imgWidth = this.width,
imgHeight = this.height;
// 控制上传图片的宽高
if (imgWidth > imgHeight && imgHeight > 1280) {
imgWidth = 1280;
imgHeight = Math.ceil(1280 * this.height / this.width);
} else if (imgWidth < imgHeight && imgWidth > 1280) {
imgWidth = Math.ceil(1280 * this.width / this.height);
imgHeight = 1280;
}
var canvas = document.createElement("canvas"),
ctx = canvas.getContext('2d');
canvas.width = imgWidth;
canvas.height = imgHeight;
if (Orientation && Orientation != 1) {
switch(Orientation) {
case 6: // 旋转90度
canvas.width = imgHeight;
canvas.height = imgWidth;
ctx.rotate(Math.PI / 2);
// (0,-imgHeight) 从旋转原理图那里获得的起始点
ctx.drawImage(this, 0, -imgHeight, imgWidth, imgHeight);
break;
case 3: // 旋转180度
ctx.rotate(Math.PI);
ctx.drawImage(this, -imgWidth, -imgHeight, imgWidth, imgHeight);
break;
case 8: // 旋转-90度
canvas.width = imgHeight;
canvas.height = imgWidth;
ctx.rotate(3 * Math.PI / 2);
ctx.drawImage(this, -imgWidth, 0, imgWidth, imgHeight);
break;
}
} else {
ctx.drawImage(this, 0, 0, imgWidth, imgHeight);
}
var ndata = canvas.toDataURL("image/jpeg", 0.98); // 压缩质量为0.98
var blob = thiz.dataURItoBlob(ndata);
return blob;
}
}
}
}