整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

如何修改尺寸大小,附下载链接

如何修改尺寸大小,附下载链接

谈论图片处理软件时,我们常常会提到行业领袖和强大的工具,但选择合适的软件不仅仅是使用功能,更是关于学习和成长。Adobe Photoshop、GIMP、Krita等软件不仅提供强大的编辑功能,还能成为您探索和提升技能的平台。无论您是刚入门的新手还是经验丰富的专业人士,理解如何有效地使用这些工具至关重要。通过学习它们的基础和高级功能,您将能够更好地应对各种挑战,创造出令人印象深刻的作品。让我们一起探索和学习,用这些工具来提升我们的创造力和技能吧!看到粉丝当众求助,让写一个关于图片如何修改尺寸的文章,本着授人以鱼不如授人以渔的原则,列举出并简单写了一下图片调整尺寸的方法。

在这个视觉为王的时代,拥有一款得心应手的图片处理软件至关重要。无论您是摄影爱好者、设计师,还是仅仅想要美化日常照片,以下这 10 款软件都能满足您的需求。


1. Adobe Photoshop

官网下载:https://www.adobe.com/cn/

2. Adobe Illustrator

官网下载:https://www.adobe.com/cn/products/illustrator.html

3. GIMP

官网下载:https://www.gimp.org/

4. 美图秀秀

官网下载:https://pc.meitu.com/download

5. 光影魔术手

官网下载:https://www.neoimaging.cn/

8. 改图鸭

官网下载:https://www.gaituya.com/

9. 图片编辑助手

官网下载:https://www.xunjiepdf.com/tupian

10. Fotor

官网下载:http://static.fotor.com.s3-website-us-east-1.amazonaws.com/cn/index.html

以下是使用一些常见软件调整图片尺寸的步骤:

**方法一:使用嗨格式抠图大师** 1. 下载并安装嗨格式抠图大师,打开软件后点击对应抠图功能。 2. 在弹出的窗口中,点击选择需要调整尺寸的图片。 3. 图片添加完成后,点击右边“改尺寸”选择需要的尺寸即可调整图片大小。 小贴士:嗨格式抠图大师还支持批量处理图片,可以一次性调整多张图片大小,大大提高工作效率。

**方法二:使用 Photoshop** 1. 打开 Photoshop,导入需要调整尺寸的图片。 2. 在菜单栏中选择“图像”,然后选择“图像大小”。 3. 在弹出的对话框中,可以修改图片的宽度和高度。注意,需确保“约束比例”是勾选状态,以保持图片的长宽比不变,避免图片变形。若想要自定义长宽比,也可以取消勾选“约束比例”。 4. 修改完成后,点击“确定”按钮即可保存调整大小后的图片。

**方法三:使用画图工具(Windows 系统自带)** 1. 右击图片,选择“打开方式”中的“画图”。 2. 在画图工具的菜单栏中,找到“重新调整大小”选项,点击它。 3. 在弹出的对话框中,选择依据百分比或像素来调整图片大小。若选择像素,则可手动输入新的水平和垂直像素值。勾选“保持纵横比”可使图片在调整大小时保持比例不变,防止图片变形。 4. 点击“确定”后,再点击“文件”菜单,选择“保存”,将调整后的图片保存到本地。

**方法四:使用美图秀秀** 1. 打开美图秀秀,导入需要调整尺寸的照片。 2. 在菜单栏中选择“裁剪”功能。 3. 在弹出的对话框中选择“自定义裁剪”。 4. 输入需要调整的尺寸大小(如 285*385),并点击“确定”按钮。 5. 等待调整完成后,保存照片即可。

**方法五:使用在线图片处理工具改图宝** 1. 打开改图宝的官网(https://www.gaitubao.com/ )。 2. 点击“选择图片”或直接拖放需要调整尺寸的图片到指定区域。 3. 在下方的“目标图像素”处输入想要的图片尺寸(宽度×高度)。 4. 系统会自动调整图片尺寸,调整完成后,可点击“下载”按钮保存图片。 需注意,不同软件的操作界面和具体选项可能会有所差异,但基本思路都是找到调整图片尺寸的相关功能,并输入期望的尺寸数值或通过其他方式进行设置。此外,在调整图片尺寸时,为了保持图片的质量和清晰度,尽量避免过度拉伸或压缩图片。如果需要处理的图片数量较多,可以优先考虑支持批量处理的软件,以提高工作效率。


网盘链接:夸克网盘分享

提取码:pdUF

以上是对每款软件如何调整图片尺寸大小的简要介绍。具体操作可能会因软件版本或用户界面的不同而有所差异,建议在使用时参考软件的官方文档或在线帮助以获取最准确的操作方法。好了,今天就聊到这儿,如果大家在生活中需要用什么软件或者使用方法,欢迎留言。

*CSS基础-06-元素大小(设置元素尺寸height/width、最大值max-height max-width、最小值min-height min-width、设置行间距 line-height)**

在Web前端开发中,对元素大小的精确控制是构建美观且布局合理的网页界面的关键。CSS提供了丰富的属性来帮助我们实现这一目标,包括设置元素的宽高(`height`/`width`)、定义最大与最小尺寸(`max-height`/`max-width`和`min-height`/`min-width`),以及调整文本行间距(`line-height`)。本文将深入探讨这些属性的用法、应用场景及示例代码,助您掌握元素大小调整的核心技巧。

**一、设置元素尺寸:height与width**

**1.1 定义元素高度(height)**

**定义方式:**

```css

element {

height: value;

}

```

其中,`element`代表目标元素的选择器,`value`可以是以下几种类型:

- **绝对单位**:如像素(`px`)、厘米(`cm`)、毫米(`mm`)、英寸(`in`)、点(`pt`)等。

- **相对单位**:如百分比(`%`)、视口宽度(`vw`)、视口高度(`vh`)、字体大小(`em`)等。

- **关键字**:如`auto`(默认值,由内容决定高度)、`initial`(恢复初始值)、`inherit`(继承父元素的值)。

**示例代码:**

```html

<div class="box">

<p>这是一个高度为200px的盒子。</p>

</div>

<style>

.box {

background-color: #f8f9fa;

height: 200px; /* 设置固定高度 */

width: 300px; /* 设置固定宽度,便于观察效果 */

}

</style>

```

**1.2 定义元素宽度(width)**

**定义方式:**

```css

element {

width: value;

}

```

`width`属性的值同样支持绝对单位、相对单位及关键字,其使用方法和`height`相同。

**示例代码:**

```html

<div class="content">

<p>这是一个宽度为80%的自适应容器。</p>

</div>

<style>

.content {

background-color: #f8f9fa;

width: 80%; /* 设置宽度为父元素的80% */

margin: 0 auto; /* 居中显示 */

}

</style>

```

**二、设定元素最大/最小尺寸:max-height/max-width与min-height/min-width**

**2.1 最大高度/宽度(max-height/max-width)**

**定义方式:**

```css

element {

max-height: value;

max-width: value;

}

```

这两个属性用于限制元素的最大尺寸,当元素的实际尺寸超过设定值时,会自动调整到指定的最大值。值的类型与`height`和`width`相同。

**示例代码:**

```html

<div class="image-container">

<img src="large-image.jpg" alt="Large Image">

</div>

<style>

.image-container {

max-width: 100%; /* 图片最大宽度不超过父元素宽度 */

max-height: 500px; /* 图片最大高度不超过500px */

overflow: hidden; /* 隐藏超出部分 */

}

</style>

```

**2.2 最小高度/宽度(min-height/min-width)**

**定义方式:**

```css

element {

min-height: value;

min-width: value;

}

```

`min-height`和`min-width`用于确保元素的最小尺寸,当元素的实际尺寸小于设定值时,会强制扩展到指定的最小值。值的类型与`height`和`width`相同。

**示例代码:**

```html

<div class="sidebar">

<ul>

<li><a href="#">Link 1</a></li>

<li><a href="#">Link 2</a></li>

<!-- 更多链接 -->

</ul>

</div>

<style>

.sidebar {

background-color: #f8f9fa;

min-width: 200px; /* 侧边栏最小宽度为200px */

}

</style>

```

**三、设置行间距:line-height**

**3.1 定义行间距(line-height)**

**定义方式:**

```css

element {

line-height: value;

}

```

`line-height`属性用于设置元素内文本行之间的垂直间距。值的类型包括:

- **数值**:如`1.5`、`2`等,表示相对于当前字体大小的倍数。

- **绝对单位**:如像素(`px`)、厘米(`cm`)等。

- **百分比**:相对于元素本身的字体大小。

- **关键字**:如`normal`(默认值,浏览器默认行间距)、`initial`、`inherit`。

**示例代码:**

```html

<p class="loose-text">这是一段行间距为1.5倍的文本。</p>

<style>

.loose-text {

font-size: 16px;

line-height: 1.5; /* 设置行间距为字体大小的1.5倍 */

}

</style>

```

**四、实战应用与注意事项**

**4.1 响应式设计**

结合`max-height`/`max-width`、`min-height`/`min-width`与媒体查询(`@media`),可以轻松实现响应式布局,确保元素在不同屏幕尺寸下保持合适的大小。

**示例代码:**

```css

@media (max-width: 768px) {

.content {

width: 100%; /* 小于768px时,宽度占满屏幕 */

}

}

@media (min-width: 768px) and (max-width: 1200px) {

.content {

width: 75%; /* 768px至1200px之间,宽度为75% */

}

}

@media (min-width: 1200px) {

.content {

width: 50%; /* 大于1200px时,宽度为50% */

}

}

```

**4.2 注意事项**

- **`height`与`width`设置为`auto`时,元素的尺寸通常由其内容决定。对于块级元素,宽度默认为`auto`,高度则受内部内容影响;对于内联元素,宽度和高度均受内容影响。**

- **使用百分比单位时,`height`的百分比基于包含块的高度,而`width`的百分比基于包含块的宽度。**

- **在设置`min-height`时,确保包含块(父元素)具有足够的高度或自身元素具有足够的内容,否则可能无法达到预期效果。**

- **使用`line-height`时,注意与其他文本相关的属性(如`font-size`、`vertical-align`等)的配合,以保持良好的排版效果。**

通过熟练掌握上述CSS属性,您将能精准地控制网页中元素的大小,实现复杂多样的布局效果。不断实践并结合实际项目需求,您的前端开发技能将更上一层楼。

者:wuwhs

转发链接:https://segmentfault.com/a/1190000023486410

前言

公司的移动端业务需要在用户上传图片是由前端压缩图片大小,再上传到服务器,这样可以减少移动端上行流量,减少用户上传等待时长,优化用户体验。前段时间小编也发布一篇关于《JS 图片简易压缩【实践】 》,有兴趣的小伙伴也可以看看。

插播一下,本文案例已整理成插件,已上传 npm ,可通过 npm install js-image-compressor -D 安装使用,可以从 github 下载。

github:https://github.com/wuwhs/js-image-compressor

JavaScript 操作压缩图片原理不难,已有成熟 API,然而在实际输出压缩后结果却总有意外,有些图片竟会越压缩越大,加之终端(手机)类型众多,有些手机压缩图片甚至变黑。

所以本文将试图解决如下问题:

  • 弄清 Image 对象、data URL、Canvas 和 File(Blob)之间的转化关系;
  • 图片压缩关键技巧;
  • 超大图片压缩黑屏问题。

转化关系

在实际应用中有可能使用的情境:大多时候我们直接读取用户上传的 File 对象,读写到画布(canvas)上,利用 Canvas 的 API 进行压缩,完成压缩之后再转成 File(Blob) 对象,上传到远程图片服务器;不妨有时候我们也需要将一个 base64 字符串压缩之后再变为 base64 字符串传入到远程数据库或者再转成 File(Blob) 对象。一般的,它们有如下转化关系:

具体实现

下面将按照转化关系图中的转化方法一一实现。

file2DataUrl(file, callback)

用户通过页面标签 <input type="file" /> 上传的本地图片直接转化 data URL 字符串形式。可以使用 FileReader 文件读取构造函数。FileReader 对象允许 Web 应用程序异步读取存储在计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。该实例方法 readAsDataURL 读取文件内容并转化成 base64 字符串。在读取完后,在实例属性 result 上可获取文件内容。

function file2DataUrl(file, callback) {
  var reader=new FileReader();
  reader.onload=function () {
    callback(reader.result);
  };
  reader.readAsDataURL(file);
}

Data URL 由四个部分组成:前缀(data:)、指示数据类型的 MIME 类型、如果非文本则为可选的 base64 标记、数据本身:

data:<mediatype>,<data>

比如一张 png 格式图片,转化为 base64 字符串形式:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAgAElEQVR4XuxdB5g。

file2Image(file, callback)

若想将用户通过本地上传的图片放入缓存并 img 标签显示出来,除了可以利用以上方法转化成的 base64 字符串作为图片 src,还可以直接用 URL 对象,引用保存在 File 和 Blob 中数据的 URL。使用对象 URL 的好处是可以不必把文件内容读取到 JavaScript 中 而直接使用文件内容。为此,只要在需要文件内容的地方提供对象 URL 即可。

function file2Image(file, callback) {
  var image=new Image();
  var URL=window.webkitURL || window.URL;
  if (URL) {
    var url=URL.createObjectURL(file);
    image.onload=function() {
      callback(image);
      window.revokeObjectURL(url);
    };
    image.src=url;
  } else {
    inputFile2DataUrl(file, function(dataUrl) {
      image.onload=function() {
        callback(image);
      }
      image.src=dataUrl;
    });
  }
}

注意:要创建对象 URL,可以使用 window.URL.createObjectURL() 方法,并传入 File 或 Blob 对象。如果不再需要相应数据,最好释放它占用的内容。但只要有代码在引用对象 URL,内存就不会释放。要手工释放内存,可以把对象 URL 传给 window.revokeObjectURL()。

url2Image(url, callback)

通过图片链接(url)获取图片 Image 对象,由于图片加载是异步的,因此放到回调函数 callback 回传获取到的 Image 对象。

function url2Image(url, callback) {
  var image=new Image();
  image.src=url;
  image.onload=function() {
    callback(image);
  }
}

image2Canvas(image)

利用 drawImage() 方法将 Image 对象绘画在 Canvas 对象上。

drawImage 有三种语法形式:

void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

参数:

  • image 绘制到上下文的元素;
  • sx 绘制选择框左上角以 Image 为基准 X 轴坐标;
  • sy 绘制选择框左上角以 Image 为基准 Y 轴坐标;
  • sWidth 绘制选择框宽度;
  • sHeight 绘制选择框宽度;
  • dx Image 的左上角在目标 canvas 上 X 轴坐标;
  • dy Image 的左上角在目标 canvas 上 Y 轴坐标;
  • dWidth Image 在目标 canvas 上绘制的宽度;
  • dHeight Image 在目标 canvas 上绘制的高度;
function image2Canvas(image) {
  var canvas=document.createElement('canvas');
  var ctx=canvas.getContext('2d');
  canvas.width=image.naturalWidth;
  canvas.height=image.naturalHeight;
  ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
  return canvas;
}

canvas2DataUrl(canvas, quality, type)

HTMLCanvasElement 对象有 toDataURL(type, encoderOptions) 方法,返回一个包含图片展示的 data URL 。同时可以指定输出格式和质量。

参数分别为:

  • type 图片格式,默认为 image/png。
  • encoderOptions 在指定图片格式为 image/jpeg 或 image/webp 的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92,其他参数会被忽略。
function canvas2DataUrl(canvas, quality, type) {
  return canvas.toDataURL(type || 'image/jpeg', quality || 0.8);
}

dataUrl2Image(dataUrl, callback)

图片链接也可以是 base64 字符串,直接赋值给 Image 对象 src 即可。

function dataUrl2Image(dataUrl, callback) {
  var image=new Image();
  image.onload=function() {
    callback(image);
  };
  image.src=dataUrl;
}

dataUrl2Blob(dataUrl, type)

将 data URL 字符串转化为 Blob 对象。主要思路是:先将 data URL 数据(data) 部分提取出来,用 atob 对经过 base64 编码的字符串进行解码,再转化成 Unicode 编码,存储在Uint8Array(8位无符号整型数组,每个元素是一个字节) 类型数组,最终转化成 Blob 对象。

function dataUrl2Blob(dataUrl, type) {
  var data=dataUrl.split(',')[1];
  var mimePattern=/^data:(.*?)(;base64)?,/;
  var mime=dataUrl.match(mimePattern)[1];
  var binStr=atob(data);
  var arr=new Uint8Array(len);

  for (var i=0; i < len; i++) {
    arr[i]=binStr.charCodeAt(i);
  }
  return new Blob([arr], {type: type || mime});
}

canvas2Blob(canvas, callback, quality, type)

HTMLCanvasElement 有 toBlob(callback, [type], [encoderOptions]) 方法创造 Blob 对象,用以展示 canvas 上的图片;这个图片文件可以被缓存或保存到本地,由用户代理端自行决定。第二个参数指定图片格式,如不特别指明,图片的类型默认为 image/png,分辨率为 96dpi。第三个参数用于针对image/jpeg 格式的图片进行输出图片的质量设置。

function canvas2Blob(canvas, callback, quality, type){
  canvas.toBlob(function(blob) {
    callback(blob);
  }, type || 'image/jpeg', quality || 0.8);
}

为兼容低版本浏览器,作为 toBlob 的 polyfill 方案,可以用上面 data URL 生成 Blob 方法 dataUrl2Blob 作为HTMLCanvasElement 原型方法。

if (!HTMLCanvasElement.prototype.toBlob) {
 Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
  value: function (callback, type, quality) {
    let dataUrl=this.toDataURL(type, quality);
    callback(dataUrl2Blob(dataUrl));
  }
 });
}

blob2DataUrl(blob, callback)

将 Blob 对象转化成 data URL 数据,由于 FileReader 的实例 readAsDataURL 方法不仅支持读取文件,还支持读取 Blob 对象数据,这里复用上面 file2DataUrl 方法即可:

function blob2DataUrl(blob, callback) {
  file2DataUrl(blob, callback);
}

blob2Image(blob, callback)

将 Blob 对象转化成 Image 对象,可通过 URL 对象引用文件,也支持引用 Blob 这样的类文件对象,同样,这里复用上面 file2Image 方法即可:

function blob2Image(blob, callback) {
  file2Image(blob, callback);
}

upload(url, file, callback)

上传图片(已压缩),可以使用 FormData 传入文件对象,通过 XHR 直接把文件上传到服务器。

function upload(url, file, callback) {
  var xhr=new XMLHttpRequest();
  var fd=new FormData();
  fd.append('file', file);
  xhr.onreadystatechange=function () {
    if (xhr.readyState===4 && xhr.status===200) {
      // 上传成功
      callback && callback(xhr.responseText);
    } else {
      throw new Error(xhr);
    }
  }
  xhr.open('POST', url, true);
  xhr.send(fd);
}

也可以使用 FileReader 读取文件内容,转化成二进制上传

function upload(url, file) {
  var reader=new FileReader();
  var xhr=new XMLHttpRequest();

  xhr.open('POST', url, true);
  xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');

  reader.onload=function() {
    xhr.send(reader.result);
  };
  reader.readAsBinaryString(file);
}

实现简易图片压缩

在熟悉以上各种图片转化方法的具体实现,将它们封装在一个公用对象 util 里,再结合压缩转化流程图,这里我们可以简单实现图片压缩了:首先将上传图片转化成 Image 对象,再将写入到 Canvas 画布,最后由 Canvas 对象 API 对图片的大小和尺寸输出调整,实现压缩目的。

/**
 * 简易图片压缩方法
 * @param {Object} options 相关参数
 */
(function (win) {
  var REGEXP_IMAGE_TYPE=/^image\//;
  var util={};
  var defaultOptions={
    file: null,
    quality: 0.8
  };
  var isFunc=function (fn) { return typeof fn==='function'; };
  var isImageType=function (value) { return REGEXP_IMAGE_TYPE.test(value); };

  /**
   * 简易图片压缩构造函数
   * @param {Object} options 相关参数
   */
  function SimpleImageCompressor(options) {
    options=Object.assign({}, defaultOptions, options);
    this.options=options;
    this.file=options.file;
    this.init();
  }

  var _proto=SimpleImageCompressor.prototype;
  win.SimpleImageCompressor=SimpleImageCompressor;

  /**
   * 初始化
   */
  _proto.init=function init() {
    var _this=this;
    var file=this.file;
    var options=this.options;

    if (!file || !isImageType(file.type)) {
      console.error('请上传图片文件!');
      return;
    }

    if (!isImageType(options.mimeType)) {
      options.mimeType=file.type;
    }

    util.file2Image(file, function (img) {
      var canvas=util.image2Canvas(img);
      file.width=img.naturalWidth;
      file.height=img.naturalHeight;
      _this.beforeCompress(file, canvas);

      util.canvas2Blob(canvas, function (blob) {
        blob.width=canvas.width;
        blob.height=canvas.height;
        options.success && options.success(blob);
      }, options.quality, options.mimeType)
    })
  }

  /**
   * 压缩之前,读取图片之后钩子函数
   */
  _proto.beforeCompress=function beforeCompress() {
    if (isFunc(this.options.beforeCompress)) {
      this.options.beforeCompress(this.file);
    }
  }

  // 省略 `util` 公用方法定义
  // ...

  // 将 `util` 公用方法添加到实例的静态属性上
  for (key in util) {
    if (util.hasOwnProperty(key)) {
      SimpleImageCompressor[key]=util[key];
    }
  }
})(window)

这个简易图片压缩方法调用和入参:

var fileEle=document.getElementById('file');

fileEle.addEventListener('change', function () {
  file=this.files[0];

  var options={
    file: file,
    quality: 0.6,
    mimeType: 'image/jpeg',
    // 压缩前回调
    beforeCompress: function (result) {
      console.log('压缩之前图片尺寸大小: ', result.size);
      console.log('mime 类型: ', result.type);
      // 将上传图片在页面预览
      // SimpleImageCompressor.file2DataUrl(result, function (url) {
      //   document.getElementById('origin').src=url;
      // })
    },
    // 压缩成功回调
    success: function (result) {
      console.log('压缩之后图片尺寸大小: ', result.size);
      console.log('mime 类型: ', result.type);
      console.log('压缩率: ', (result.size / file.size * 100).toFixed(2) + '%');

      // 生成压缩后图片在页面展示
      // SimpleImageCompressor.file2DataUrl(result, function (url) {
      //   document.getElementById('output').src=url;
      // })

      // 上传到远程服务器
      // SimpleImageCompressor.upload('/upload.png', result);
    }
  };

  new SimpleImageCompressor(options);
}, false);

如果看到这里的客官不嫌弃这个 demo 太简单可以戳这里试试水。如果你有足够的耐心多传几种类型图片就会发现还存在如下问题:

  • 压缩输出图片寸尺固定为原始图片尺寸大小,而实际可能需要控制输出图片尺寸,同时达到尺寸也被压缩目的;
  • png 格式图片同格式压缩,压缩率不高,还有可能出现“不减反增”现象;
  • 有些情况,其他格式转化成 png 格式也会出现“不减反增”现象;
  • 大尺寸 png 格式图片在一些手机上,压缩后出现“黑屏”现象;

改进版图片压缩

俗话说“罗马不是一天建成的”,通过上述实验,我们发现了很多不足,下面将逐条问题分析,寻求解决方案。

压缩输出图片寸尺固定为原始图片尺寸大小,而实际可能需要控制输出图片尺寸,同时达到尺寸也被压缩目的;

为了避免压缩图片变形,一般采用等比缩放,首先要计算出原始图片宽高比 aspectRatio,用户设置的高层以 aspectRatio,得出等比缩放后的宽,若比用户设置宽的小,则用户设置的高为为基准缩放,否则以宽为基准缩放。

var aspectRatio=naturalWidth / naturalHeight;
var width=Math.max(options.width, 0) || naturalWidth;
var height=Math.max(options.height, 0) || naturalHeight;
if (height * aspectRatio > width) {
  height=width / aspectRatio;
} else {
  width=height * aspectRatio;
}

输出图片的尺寸确定了,接下来就是按这个尺寸创建一个 Canvas 画布,将图片画上去。这里可以将上面提到的 image2Canvas 方法稍微做一下改造:

function image2Canvas(image, destWidth, destHeight) {
  var canvas=document.createElement('canvas');
  var ctx=canvas.getContext('2d');
  canvas.width=destWidth || image.naturalWidth;
  canvas.height=destHeight || image.naturalHeight;
  ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
  return canvas;
}

png 格式图片同格式压缩,压缩率不高,还有可能出现“不减反增”现象

一般的,不建议将 png 格式图片压缩成自身格式,这样压缩率不理想,有时反而会造成自身质量变得更大。

因为我们在“具体实现”中两个有关压缩关键 API:

  • toBlob(callback, [type], [encoderOptions]) 参数 encoderOptions 用于针对image/jpeg 格式的图片进行输出图片的质量设置;
  • toDataURL(type, encoderOptions 参数encoderOptions 在指定图片格式为 image/jpeg 或 image/webp 的情况下,可以从 0 到 1 的区间内选择图片的质量。

均未对 png 格式图片有压缩效果。

有个折衷的方案,我们可以设置一个阈值,如果 png 图片的质量小于这个值,就还是压缩输出 png 格式,这样最差的输出结果不至于质量太大,在此基础上,如果压缩后图片大小 “不减反增”,我们就兜底处理输出源图片给用户。当图片质量大于某个值时,我们压缩成 jpeg 格式。

// `png` 格式图片大小超过 `convertSize`, 转化成 `jpeg` 格式
if (file.size > options.convertSize && options.mimeType==='image/png') {
  options.mimeType='image/jpeg';
}
// 省略一些代码
// ...
// 用户期待的输出宽高没有大于源图片的宽高情况下,输出文件大小大于源文件,返回源文件
if (result.size > file.size && !(options.width > naturalWidth || options.height > naturalHeight)) {
  result=file;
}

大尺寸 png 格式图片在一些手机上,压缩后出现“黑屏”现象;

由于各大浏览器对 Canvas 最大尺寸支持不同



如果图片尺寸过大,再创建同尺寸画布,再画上图片,就会出现异常情况,即生成的画布没有图片像素,而画布本身默认给的背景色为黑色,这样就导致图片“黑屏”情况。

这里可以通过控制输出图片最大宽高防止生成画布越界,并且用透明色覆盖默认黑色背景解决解决“黑屏”问题:

// ...
// 限制最小和最大宽高
var maxWidth=Math.max(options.maxWidth, 0) || Infinity;
var maxHeight=Math.max(options.maxHeight, 0) || Infinity;
var minWidth=Math.max(options.minWidth, 0) || 0;
var minHeight=Math.max(options.minHeight, 0) || 0;

if (maxWidth < Infinity && maxHeight < Infinity) {
  if (maxHeight * aspectRatio > maxWidth) {
    maxHeight=maxWidth / aspectRatio;
  } else {
    maxWidth=maxHeight * aspectRatio;
  }
} else if (maxWidth < Infinity) {
  maxHeight=maxWidth / aspectRatio;
} else if (maxHeight < Infinity) {
  maxWidth=maxHeight * aspectRatio;
}

if (minWidth > 0 && minHeight > 0) {
  if (minHeight * aspectRatio > minWidth) {
    minHeight=minWidth / aspectRatio;
  } else {
    minWidth=minHeight * aspectRatio;
  }
} else if (minWidth > 0) {
  minHeight=minWidth / aspectRatio;
} else if (minHeight > 0) {
  minWidth=minHeight * aspectRatio;
}

width=Math.floor(Math.min(Math.max(width, minWidth), maxWidth));
height=Math.floor(Math.min(Math.max(height, minHeight), maxHeight));

// ...
// 覆盖默认填充颜色 (#000)
var fillStyle='transparent';
context.fillStyle=fillStyle;

到这里,上述的意外问题被我们一一解决了,如需体验改进版的图片压缩 demo 的小伙伴可以戳这里

总结

我们梳理了通过页面标签 <input type="file" /> 上传本地图片到图片被压缩整个过程,也覆盖到了在实际使用中还存在的一些意外情况,提供了相应的解决方案。将改进版图片压缩整理成插件,已上传 npm ,可通过 npm install js-image-compressor -D 安装使用。整理匆忙,如有问题欢迎大家指正,完~

作者:wuwhs

转发链接:https://segmentfault.com/a/1190000023486410