精华内容
下载资源
问答
  • TIFF图片压缩工具

    2018-11-13 16:13:21
    支持对tiff格式图片进行压缩,也可将图片转换其他格式后进行压缩
  • 阿里巴巴SimpleImage图片压缩相关jar

    热门讨论 2015-07-18 11:56:24
    图片压缩,阿里巴巴SimpleImage 相关jar文件。其中包含依赖jar: commons-io-2.4.jar;commons-lang.jar;commons-logging-1.1.1.jar jai_codec-1.1.3.jar;jai_core-1.1.3.jar; 包含jar:aliSimpleImage.jar。...
  • html5前端图片压缩上传

    热门讨论 2016-03-03 12:40:31
    利用html5 canvas处理图片,得到图片字节流,上传。前端canvas压缩,代码简洁亲测可用,参考博客 :https://blog.csdn.net/jialiuyang/article/details/50787636;
  • ffmpeg 图片压缩成视频

    2016-06-08 09:47:50
    利用ffmpeg将图片压缩成视频,c++源码
  • android经典图片压缩算法 永不失真

    千次下载 热门讨论 2013-12-19 10:21:56
    对各种大图片进行压缩,压缩不失真。大图片压缩后大小在100k以内,可以根据自己的需求进行设置压缩大小。
  • WEB前端大图片压缩并上传例子

    千次下载 热门讨论 2014-12-01 15:47:39
    手机上传图片到服务器时,如果是大文件图片肯定会很慢而且费流量,用户体验不好。本人用html5的canvas解决了这个问题,好东西一定要分享
  • js图片压缩

    热门讨论 2013-07-24 10:34:49
    很好用的图片压缩,不会影响图片质量,好用,希望能帮到某些朋友
  • Android开发中上传图片很常见,一般为了节省流量会进行压缩的操作,Android下的图片压缩及图片和视频的上传
  • 图片压缩节约内存

    2012-11-12 22:51:44
    实现图片压缩,可以节约内存,应用场合:ListView异步加载大量网络图片时,可以适当压缩显示,可以有效防止内存溢出,适合新手学习之用,gb编码
  • 可以压缩市面上大部分图片格式的图片压缩软件,一个2M的jpg数码照片,通图片压缩后可以压缩到200KB左右,压缩后的图片比之前缩小了10倍左右,而且压缩后的图片质量基本没什么变化,实现无损压缩。
  • WinForm批量图片压缩工具源代码

    热门讨论 2013-08-09 22:22:21
    WinForm批量图片压缩工具源代码,一个非常好的WinForm学习例子。
  • 首先通过尺寸压缩,压缩到手机常用的一个分辨率(1280*960 微信好像是压缩到这个分辨率),然后我们要把图片压缩到100KB以内,通过质量压缩来计算options需要设置为多少,最后调用JNI压缩,这边我测试了下,压缩出来的...
  • 在项目开发过程中遇到一个需要从小程序上传图片的需求,此需求实现起来并不难,只需要调用chooseImage接口拿到图片的临时路径然后调用uploadFile接口进行上传。到这里这个功能已经实现了,可是这样简单实现了之后...

    一、概述

    在项目开发过程中遇到一个需要从小程序上传图片的需求,此需求实现起来并不难,只需要调用chooseImage接口拿到图片的临时路径然后调用uploadFile接口进行上传。到这里这个功能已经实现了,可是这样简单实现了之后用户在使用时体验非常差。因为现在手机摄像头像素非常高,拍出来的照片体积都很大,上传时不做处理就会导致上传耗时长,用户消耗流量大,查看图片时加载非常慢等体验问题。

    二、图片压缩的方法及优缺点

    为了消除影响用户体验的这些问题就必须在上传之前对图片做压缩处理减小图片的体积。微信小程序图片压缩总的来说有三种方法,一种是使用官方提供的接口 wx.compressImage(Object object);一种是利用canvas重绘来得到压缩图片;最后一种安装第三方图片压缩包。三种方法各有各的优点与缺点,由于各种原因未对使用第三方压缩包的方式进行验证,所以只对前两种方式进行说明。

    1、wx.compressImage

    优点:官方提供的接口在微信的背景下姑且认为它的压缩实现是最好的。官方接口对小于3MB的图片进行压缩时速度较快,耗时较少。

    缺点:官方接口对于大于3MB的图片压缩较慢,耗时长。另外,当quality参数设置为较大值时压缩效果不

    展开全文
  • 前端图片压缩上传(压缩篇)

    千次阅读 2020-02-14 21:25:43
    为什么说这是一篇比较适合小白的前端图片压缩文章呢?因为我也是一个刚工作半年的前端小白,最近接到了一个前端图片压缩上传的任务,通过各种百度博客完成了这项任务,但是任务完成后对各种技术细节却...

    为什么说这是一篇比较适合小白的前端图片压缩文章呢?因为我也是一个刚工作半年的前端小白,最近接到了一个前端图片压缩上传的任务,通过各种百度博客完成了这项任务,但是任务完成后对各种技术细节却还不是特别理解,所以我针对我不理解的每一个技术细节都进行了记录和学习,最后形成本篇博客,我觉得我不了解的地方可能也会有别的同学不是很了解,所以本篇博客科普向比较重,技术深度可能达不到大佬们的眼界,但也是自己的记录和学习,加油!!!

    1. 前言

    如果您只是为了copy代码实现功能,建议您不要看这篇博客了。如果您是copy了代码实现了功能,想回来了解具体的实现流程、实现原理以及部分科普,我觉得本篇博客能给你带来不小的收获。

    2. 任务背景

    最近的项目有一个技术场景,简单来说就是用户需要上传图片至服务器。就是这么一个简单的技术场景,但是用户是不可控的,他们可能上传的图片会是几M甚至十几M的大小,如此大的图片必然会导致上传时间过长,用户感知不好,服务器压力大等不良影响。

    作为组里唯一一个前端,老大就给了我一个任务,在用户上传图片前把图片压缩了再上传。那么本篇博客主要讲解的就是图片压缩中我是如何进行压缩的,之后的博客会讲解如何将压缩的图片进行上传。

    3. 流程说明

    本文实现的功能流程如下:

    1. 用户通过input框选择图片

    2. 使用FileReader进行图片预览

    3. 将图片绘制到canvas画布上

    4. 使用canvas画布的能力进行图片压缩

    5. 将压缩后的Base64(DataURL)格式的数据转换成Blob对象进行上传

    简要流程图如下:

    各位同学们看到这里,不知道会不会有跟我当时一样的疑惑?什么是 FileReader?我知道 canvas是画布,但是具体是怎么样用它进行图片压缩的呢?Base64我知道但是什么是DataURL格式的数据呢?Blob对象又是什么?

    同学们,不着急,对于这些我都会进行一一讲解,因为这也是作为一个小白的我初次见到这些陌生名词时的疑惑。

    4. 效果预览

    5. FileReader

    FileReader这个对象是做什么的?在本次图片压缩中起到了什么作用?

    5.1 FileReader是什么

    我们先来看看MDN上对它的解释:FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 FileBlob对象指定要读取的文件或数据。

    通俗来讲,就是这个对象是用来读取 File对象或 Blob对象的。File对象就是 <inputtype="file">获取到的对象,而 Blob(二进制)对象在本文的第5点有讲解。

    5.2 FileReader的钩子与方法

    作为一个js原生的用于读取文件的对象, FileReader本身就有较为完整的钩子函数以及一些实例方法,但是本文主要介绍图片压缩,所以在这里只重点讲本文使用到的1个钩子函数和1个实例方法,对其它的钩子和方法都不做详细介绍。

    FileReader.onload:处理 load事件。即该钩子在读取操作完成时触发,通过该钩子函数可以完成例如读取完图片后进行预览的操作,或读取完图片后对图片内容进行二次处理等操作。

    FileReader.readAsDataURL:读取方法,并且读取完成后, result属性将返回 DataURL 格式(Base64 编码)的字符串,代表图片内容。

    除了用到的这个钩子和这个实例方法外, FileReader对象还有 onabortonerroronloadstartonloadendonprogress等钩子;也有 abort()readAsArrayBufferreadAsBinaryString等实例方法,在次就不过多描述。

    5.3 FileReader在图片压缩中的作用

    onload这个钩子对上传的图片实现了预览,并且进行了图片压缩处理。通过 readAsDataURL()方法进行了文件的读取,并且通过 result属性拿到了图片的 Base64(DataURL)格式的数据,然后通过该数据实现了图片预览的功能。有的同学看到这里是不是有点好奇,为什么拿到了这个 Base64(DataURL)格式的数据就能直接展示处图片了呢?不要紧,往下看,我会在后文中解释这个 DataURL格式的神奇。

    FileReader部分代码如下:

    function canvasDataURL(file,item,callback) { //压缩转化为base64
                var reader = new FileReader();      //读取文件的对象
                reader.readAsDataURL(file);         //对文件读取,读取完成后会将内容以base64的形式赋值给result属性
                reader.onload = function (e) {      //读取完成的钩子
                    console.log("原始二进制字符串:",this.result.toString());
                    const img = new Image();
                    const quality = 0.2; // 图像质量
                    const canvas = document.createElement('canvas');
                    const drawer = canvas.getContext('2d');
                    img.src = this.result;
                    console.log("FileReader对象:",this);
                    //图片预览
                    var picDom = $(item.item).find("img");  
                    picDom.attr('src', this.result); //图片链接(base64)
                    //图片压缩转码
                    img.onload = function () {
                        canvas.width = img.width;
                        canvas.height = img.height;
                        drawer.drawImage(img, 0, 0, canvas.width, canvas.height);
                        convertBase64UrlToBlob(canvas.toDataURL(file.type, quality), callback);
                    }
                }
            }
    

    6. canvas(图片压缩的核心)

    canvas元素众所周知是画布,那么 canvas在图片压缩中起到了什么作用?实现图片压缩的核心内容主要是使用到了 canvas的什么方法?

    6.1 Canvas在图片压缩中的作用

    实现图片压缩最核心的地方就在 canvas这里,我们先使用 CanvasRenderingContext2D.drawImage()方法将选中的图片文件在画布上绘制出来,再使用 Canvas.toDataURL()将画布上的图片信息转换成base64(DataURL)格式的数据。有同学会问,那么是在哪儿实现的压缩?其实压缩的核心就在 Canvas.toDataURL()方法的 quality参数上了,下面我们会具体介绍本文中使用到的2个 canvas画布上的方法。

    6.2 CanvasRenderingContext2D.drawImage()

    语法如下:

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

    这个方法是 CanvasRenderingContext2D上的绘制图片的方法,如果有朋友想了解 CanvasRenderingContext2Dcanvas之间的联系和区别的话可以自行了解,这里不过多赘述。

    首先介绍一下该方法所接受的9个参数:

    image:Object;绘制在Canvas上的元素,可以是各类Canvas图片资源),如图片,SVG图像,Canvas元素本身等。

    dx:Number;在Canvas画布上规划一片区域用来放置图片,dx就是这片区域的左上角横坐标。

    dy:Nmuber;在Canvas画布上规划一片区域用来放置图片,dy就是这片区域的左上角纵坐标。

    dWidth:Number;在Canvas画布上规划一片区域用来放置图片,dWidth就是这片区域的宽度。

    dHeight:Number;在在Canvas画布上规划一片区域用来放置图片,dHeight就是这片区域的高度。

    sx:Number;表示图片元素绘制在Canvas画布上起始横坐标。

    sy:Number;表示图片元素绘制在Canvas画布上起始纵坐标。

    sWidth:Number;表示图片元素从坐标点开始算,多大的宽度内容绘制Canvas画布上。

    sHeight;表示图片元素从坐标点开始算,多大的高度内容绘制Canvas画布上。

    很多同学看到这里这么多个参数是不是有点懵逼了?不用慌,我也很懵逼,其实我对canvas也不是很了解,不过没关系我们直接看看本文中使用到这个方法时我们传递了什么参数

    //代码
    //先创建canvas画布,再获取canvas画布上的2d绘图环境,通过这个2d绘图环境才可使用绘制API
    const canvas = document.createElement('canvas');  
    //返回一个在画布上绘制2d图的环境对象,该对象上包含有canvas绘制2d图形的API
    const drawer = canvas.getContext('2d');
    canvas.width = img.width;
    canvas.height = img.height;
    drawer.drawImage(img, 0, 0, canvas.width, canvas.height);
    //实际传递的参数
    drawer.drawImage(image, dx, dy, dWidth, dHeight)
    

    结合上面列举的9个参数,我们可以知道我们实际上只使用到了5个参数。我们传递了1个图片,紧接着我们定义了canvas上的起始区域坐标点以及这个canvas上放置图片的区域的宽高。

    实质上,我们设置的canvas放置图片区域的宽高大小跟图片本身是一模一样的,因为在本文中,使用该方法的目的不在于在canvas上展示一张图片给用户看,而是在于在canvas上绘制出这张图片,这样我们才能使用接下来的的这个 Canvas.toDataURl()方法

    6.3 Canvas.toDataURl()

    咚!咚!咚!敲重点了,这个方法才是本文中实现图片压缩的核心。

    语法如下:

    canvas.toDataURL(mimeType, quality);
    

    Canvas.toDataURl()方法可以将canvas画布上的信息转换为base64(DataURL)格式的图像信息,纯字符的图片表示形式。该方法接收2个参数:

    mimeType(可选):String;表示需要转换的图像的mimeType类型。默认值是image/png,还可以是image/jpeg,甚至image/webp(前提浏览器支持)等。

    quailty(可选):Number;quality表示转换的图片质量。范围是0到1。此参数要想有效,图片的mimeType需要是image/jpeg或者image/webp,其他mimeType值无效。默认压缩质量是0.92。

    到这里,很多同学就可以知道了,前端图片压缩的核心方法,是不是就在这个方法的 quailty参数上面呢?好了,让我们看看本文使用到该方法的地方:

    const canvas = document.createElement('canvas'); 
    const quality = 0.2; //设置压缩比例
    canvas.toDataURL(file.type, quality)
    

    可以看到,本文中设置了压缩质量为0.2,需要注意的是不是说压缩质量设置为0.2实际压缩效果就为5倍压缩(在本文中,压缩质量设置成了0.2但实际压缩效果确实7-9倍),简单的说,当到达了这一步以后,其实图片已经完成了压缩,我们已经可以直接拿着返回的base64(DataURL)格式的数据去渲染图片,但是,如果你的目的是将图片先进行压缩,压缩后再上传给服务器,并且服务器只接受二进制的图片信息的话,那就得好好考虑怎么将base64转换成二进制Blob对象了,关于Blob,不要着急,我会在下一篇上传篇中对它进行科普。

    小tips:该方法为同步方法,如果需要转换的Canvas尺寸很大,则会阻塞脚本的运行,因此需要注意控制Canvas的尺寸。

    6.4 Canvas.toBlob()

    语法如下:

    canvas.toBlob(callback, mimeType, quality)
    

    如果看了6.3小节的同学应该会觉得,这2个方法长得差不多,参数也差不多,那么它们的效果是否也是差不多的呢?

    当然,该方法的作用是将canvas画布上的信息转换为Blob对象。该方法接收的参数基本与6.3的方法相同,区别在于,该方法多接受一个参数,该参数为:

    callback:Function;toBlob()方法执行成功后的回调方法,支持一个参数,表示当前转换的Blob对象。

    6.3小节的最后说过, toDataURL()方法是同步方法,那么我们 toBlob()与此不同,它是一个异步的方法,所以该方法会多接受一个参数 callback,该参数就是 toBlob()的回调函数。

    好了,既然本文最终目的是将file压缩后,再转换成Blob对象上传至后端,那么为什么不直接使用 toBlob()方法,而是使用 toDataURL()方法呢?对于这点的解释我会在下一篇上传篇中进行详解,各位同学可以持续关注我的博客。

    7.DataUrl格式

    不知道有心的同学发现了吗?本文中多次提到了 DataURL格式的数据,那究竟什么才是 DataURL格式的数据呢?

    在下面对 DataURL展开了解之前,我们可以先来复习一下常见的 img标签的src是什么样的?

    那么src除了这种赋值方式之外,还有什么形式能够展示图片吗?

    当然有,那就是我们的 DataURL,详见下图:

    可以看到,同样的图片,2种不同的src。那么 DataURL在实际中有什么用处呢?它的定义是什么?什么场景下需要用到它?带着这个疑问看下去吧。

    7.1 DataURL格式的定义

    先来看看我从网上找到的比较官方的定义:DataURL是由RFC2397定义的一种把小文件直接嵌入文档的方案。格式如下:

    其实整体可以视为三部分,即声明:参数+数据,逗号左边的是各种参数,右边的是数据。举个例子:

    <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAS...">
    

    我们将例子与格式一一对照来看

    MIME type:表示数据呈现的格式,简单来说就是这个数据的类型是什么?是png还是jpg甚至是html,结合实例来看,在实例中我们的这段数据它的类型就是一个图片,而且是个jpg格式的图片。

    character:字符集;这个是可选项,默认为 charset=US-ASCII,如果指定的是图片的话,就不再使用字符集了。在实例中,我们的这段数据代表的就是一张图片,随意是没有这个字段的。

    base64:这一部分将表明数据编码方式,当然我们可以不使用base64的编码方式,那样我们将使用标准的URL编码方式。在本实例中,我们的图片就是采取base64的编码方式。

    enconded data:这就是实际的数据了,在实例中,这就是这张图片的base64编码。

    好了, DataURL的定义讲完了,那么 DataURL只能在图片里使用吗?当然不是,它能表示的东西有很多很多,比如你们可以复制下面的这段代码到浏览器地址栏中粘贴看一看

    data:text/html;charset=UTF-8,<html><body><p>欢迎看刘伟C的博客</p></body></html>
    

    下面会讲下 DataURL的优缺点。

    7.2DataURL的优缺点

    这里就不做铺垫直接说

    优点:

    1. 当我们访问外部资源很麻烦的时候比如跨域限制的时候,可以直接使用 DataURL,因为他不需要向外界发起访问。

    2. 如果看过我Chrome调试工具NetWork模块这篇博客的朋友可能会注意到,浏览器都有默认的同一时间最多同时加载的资源数量限制,比如Chrome,最多允许同时加载6个资源,其它起源就得排队等待,但是对于 DataURL来说,它并不需要向服务器发送Http请求,它就自然不会占用一个http会话资源。

    3. 当图片是在服务器端用程序动态生成,每个访问用户显示的都不同时(emmm,这个我也不是很理解,目前暂时没碰到过这种场景)

    缺点:

    1. 有心的同学如果去尝试就会知道, base64的数据体积实际上会比原数据大,也就是Data URL形式的图片会比二进制格式的图片体积大1/3。所以如果图片较小,使用 DataURL形式的话是比较有利的,图片较小即使比原图片大一些也不会大很多,相比发起一个Http会话这点开销算什么。但是如果图片较大的情况下,使用 DataURL的开销就会相应增大了,具体如何取舍还得各位同学结合实际场景考量。

    2. Data URL形式的图片不会被浏览器缓存,这意味着每次访问这样页面时都被下载一次。这是一个使用效率方面的问题——尤其当这个图片被整个网站大量使用的时候。(这个缺点可以规避,具体可以自行百度或看其它的博客,这里不细说)

    那么总结一下, DataURL带来的便利原因就是一个:它不需要发起http请求;而它的缺点归纳起来就是两个:体积比原有还要大不会被缓存

    7.3 本文为何使用DataURL

    看完上面的科普,同学们是不是都了解了 DataURL的优缺点,那么不知道各位是否会好奇,本次前端压缩为何使用的是 DataURL呢?

    答案其实在第一小节中有,因为我们想做图片预览,而图片预览是通过 FileReader对象实现的, FileReader会去读文件,并且返回文件的内容,但是返回的内容要么就是二进制字符串,要么就是二进制字节数组,这些都不能直接用于图片展示,只有调用 FileReader.readAsDataURL()返回的 DataURL格式的数据可以直接使用。

    8. 代码

    因为公司使用的前端框架比较非主流,是layUI框架的,所以我的代码也是基于layUI的前端压缩(所以你们直接copy我的代码大概率是跑不起来的),不过核心思想核心方法核心原理在博客中都有体现,只要理解了思想,其实不难将它复刻到你们自己的项目中去。

    代码如下:

    //这是layUI的文件上传组件,不了解的朋友也没必要去看文档,理解思想就行了
    var upload1 = upload.render({
            elem: '.uploadImg',
            url: releaseUrl,
            accept: 'images',
            auto: false,
            //选择文件后的钩子函数
            choose: function (obj) {
                var that = this;
                //预读本地文件示例,不支持ie8
                obj.preview(function (index, file, result) {
                    console.log("选中的文件:", file);
                    var index = layer.load(1, {
                        content: '图片上传中....',
                        shade: 0.2,
                        success: function (layer) {
                            layer.find('.layui-layer-content').css({
                                'paddingTop': '40px',
                                'width': '60px',
                                'textAlign': 'center',
                                'backgroundPositionX': 'center'
                            });
                        }
                    });
                    //这段开始才是压缩的重点,所以关注这段代码即可
                    //若图片超过1M则启动压缩
                    if (file.size > (1024 * 1024)) {
                        // console.log("大于1m");
                        canvasDataURL(file, that, function (blob) {
                            // console.log("压缩后的二进制Blob对象:",blob);
                            console.log("压缩前:" + (file.size / 1024 / 1024) + "M");
                            console.log("压缩后:" + (blob.size / 1024 / 1024) + "M");
                            var compresFile = new File([blob], file.name, {
                                type: file.type
                            })
                            obj.upload(1, compresFile);
                        })
                    }
                    //若图片不超过1M则无需压缩,直接传
                    else {
                        var picDom = $(that.item).find("img");
                        picDom.attr('src', result);
                        obj.upload(1, file);
                    }
                });
            },
        })
        //下面是压缩部分的核心代码
        /**
         * 通过canvas画布实现压缩,并转化为base64格式的图片
         * @param {File} file : 图片
         * @param {Object} item :通过item找到当前对象的img标签
         * @param {Function} callback :回调函数
         */
        function canvasDataURL(file,item,callback) { //压缩转化为base64
            var reader = new FileReader();      //读取文件的对象
            reader.readAsDataURL(file);         //对文件读取,读取完成后会将内容以base64的形式赋值给result属性
            reader.onload = function (e) {      //读取完成的钩子
                const img = new Image();
                const quality = 0.2; // 图像质量
                //先创建canvas画布,再获取canvas画布上的2d绘图环境,通过这个2d绘图环境才可使用绘制API
                const canvas = document.createElement('canvas');        //创建canvas画布
                const drawer = canvas.getContext('2d');                 //返回一个在画布上绘制2d图的环境对象,该对象上包含有canvas绘制2d图形的API
                img.src = this.result;
                // console.log("FileReader对象:",this);
                //图片预览
                var picDom = $(item.item).find("img");  
                picDom.attr('src', this.result); //图片链接(base64)
                //图片压缩代码,需要注意的是,img图片渲染是异步的,所以必须在img的onlaod钩子中再进行相应操作
                img.onload = function () {
                    canvas.width = img.width;
                    canvas.height = img.height;
                    drawer.drawImage(img, 0, 0, canvas.width, canvas.height);
                    convertBase64UrlToBlob(canvas.toDataURL(file.type, quality), callback);
                }
            }
        }
        //下面是上传部分的核心代码
        /**
         * 将base64格式转化为Blob格式
         * @param {string} urlData : urlData格式的数据,通过这个转化为Blob对象
         * @param {Function} callback : 回调函数
         */
        function convertBase64UrlToBlob(urlData, callback) { //将base64转化为文件格式
            // console.log("压缩成base64的对象:",urlData);
            const arr = urlData.split(',')
            // console.log("arr",arr);
            const mime = arr[0].match(/:(.*?);/)[1]
            const bstr = atob(arr[1])   //atob方法用于解码base64
            // console.log("将base64进行解码:",bstr);
            let n = bstr.length
            const u8arr = new Uint8Array(n)
            while (n--) {
            u8arr[n] = bstr.charCodeAt(n)
            }
            // console.log("Uint8Array:",u8arr);
            callback(new Blob([u8arr], {
            type: mime
            }));
        }
    

    9. 总结

    关于前端图片压缩的压缩篇告一段落,下一篇博客将介绍前端图片压缩的上传篇,重点是

    1. Blob对象

    2. Base64转Blob的方法

    3. Uint8Array

    4. 为什么要先压缩为Base64(DataURL)?再将Base64(DataURL)转化为Blob对象?)

    也欢迎大佬在评论区留言指正博客错误的地方,也欢迎像我一样的小白前端一起在评论区讨论。

    10.参考文章

    1. 玩转图片流

    2. MDN_FileReader相关文档

    3. canvasApi中文网

    4. DataURL与base64

    • 作者:刘伟C

    • https://juejin.im/post/5e42523ae51d4527031358f4

    展开全文
  • android bitmap图片压缩

    热门讨论 2012-07-25 12:12:59
    缩小尺寸可不是指在layout中设置一下宽高使图片缩小(其实质还是一张占内存大图),而是实实在在的将图片本身缩小,减小内存占用。
  • android 图片压缩,bitmap压缩总结

    千次阅读 2019-06-13 21:10:07
    1. 图片压缩相关概念 在android开发中,图片加载到内存中通常需要占用大量的内存,导致app性能过度消耗,严重的话可能会导致OOM异常,所以对图片进行优化就尤为重要。 android图片压缩的格式可以通过以下一张图进行...

    1.    图片压缩相关概念

    在android开发中,图片加载到内存中通常需要占用大量的内存,导致app性能过度消耗,严重的话可能会导致OOM异常,所以对图片进行优化就尤为重要。
    android图片压缩的格式可以通过以下一张图进行概括,这张图摘自官方API文档:
     
    对于各个参数的含义,通过以下一张表格总结一下

    ALPHA_8每个像素存储为单个半透明(alpha)通道,占用1字节内存,用来存储遮罩非常有用
    ARGB_4444 每个像素占用2字节存储空间,由于在这个配置下的图片质量比较差,官方建议使用ARGB_8888,官方已提示ARGB_4444不推荐使用
    ARGB_8888  每个像素占用4字节存储空间,每个通道(A,R,G,B)都以8位精度进行存储,这种格式下图片质量最佳,官方推荐尽可能使用这种格式存储
    HARDWARE    一种特殊的存储格式,当位图仅仅存储在图形内存中时,位图始终保持不变
    RGBA_F16   每个像素存储在8个字节上,很少用
    RGB_565  每个像素存储在2个字节上,没有透明度,只包括了红,绿,蓝三个通道,当使用不需要透明度图片时,可以使用该格式存储

    android图片加载到内存,bitmap所占内存的大小可以由下列公式进行计算:
    bitmap所占内存 = 图片分辨率 * 一个像素所占的字节数
    上述公式其实是不严谨的,对于从SD卡,assests目录或者网络中加载图片所占用的内存,是可以通过上述的公式计算出来的。但是如果图片存储在res目录中,当图片加载进内存时,会经过一次分辨率的转换,然后在计算内存占用多少,这时图片的分辨率应该是转换之后的分辨率,而不是原图的分辨率。
    这里只讨论常规图片压缩方式,图片都是存储在SD卡或者assests目录中,对于存储在res目录下的情况忽略。
    bitmap的压缩方式主要有:
    1.    采样率压缩
    2.    缩放压缩
    3.    质量压缩
    4.    设置RGB_565
    5.    使用createScaledBitmap
    下面简单讨论下各种压缩方式

    2. 采样率压缩

    通过设置BitmapFactory.Options的inSampleSize参数,达到压缩图片的目的。该参数表示压缩为原图的几分之一,必须大于1,小于1按照1处理。
    下面通过加载原图和设置inSampleSize来对比设置inSampleSize加载图片之后的效果。
    把一张原图不经过压缩直接加载到内存中:

    Bitmap bitmap =
    BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png");
    if(bitmap != null) {
        String info = "原始图片大小: " + (bitmap.getByteCount()) + " 宽度: " + bitmap.getWidth() + " 高度: " + bitmap.getHeight();
        Log.v("sample", info);
        tvOrgin.setText(info);
        imgvOrgin.setImageBitmap(bitmap);
    }

    设置inSampleSize参数,加载一张图片到内存中:

    BitmapFactory.Options options = new BitmapFactory.Options();
    String str = edtvSample.getText().toString();
    int sample = 2;
    try {
        sample = Integer.parseInt(str);
    } catch (Exception e) {
        Toast.makeText(this, "请输入有效数字内容", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
        return ;
    }
    options.inSampleSize = sample;
    
    Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png", options);
    if(bitmap != null) {
        String info = "压缩图片大小: " + (bitmap.getByteCount()) + " 宽度: " + bitmap.getWidth() + " 高度: " + bitmap.getHeight();
        Log.v("sample", info);
        tvCompress.setText(info);
        imgvCompress.setImageBitmap(bitmap);
    }

    其中inSampleSize通过界面动态设置,以此来查看不同inSampleSize加载图片的具体效果。
    例如把inSampleSize设置成4,宽度和高度都变为了原来的1/4,图片内存整整缩小为原来的1/16。
     
    下面是我测试的一张效果:

    3. 缩放压缩

    通过Martix变换,设置缩放值以此来达到图片压缩的目的。

    Bitmap bitmap =
    BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png");
    String strx = edtvSx.getText().toString();
    String stry = edtvSy.getText().toString();
    
    float sx = 0.5f;
    float sy = 0.5f;
    try {
        sx = Float.parseFloat(strx);
        sy = Float.parseFloat(stry);
    } catch (Exception e) {
        Toast.makeText(this, "请输入有效数字内容", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
        return ;
    }
    if(bitmap != null) {
        Matrix matrix = new Matrix();
        matrix.setScale(sx, sy);
        Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        String info = " sx: " + sx + " sy: " + sy + " 压缩图片大小: " + (newBitmap.getByteCount()) + " 宽度为: " + newBitmap.getWidth() + " 高度为: " + newBitmap.getHeight();
        Log.v("martix", info);
        tvCompress.setText(info);
        imgvCompress.setImageBitmap(newBitmap);
    }

    把x,y缩放值分别设置成0.5f,可以看到压缩后的图片宽,高都是原图宽高的1/2,图片整体大小是原图的1/4.
     
    效果图:

    4. 质量压缩

    质量压缩并不会减少bitmap占用的内存,bitmap的分辨率会和原图保持一致。质量压缩的原理是通过算法扣掉(同化)了 图片中的一些某个点附近相近的像素,以此介绍图片中的颜色数量,达到减少文件大小的目的。
    质量压缩测试代码:

            Bitmap bitmap =
    BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            String str = edtvQuality.getText().toString();
            int quality = 100;
            try {
                quality = Integer.parseInt(str);
            } catch (Exception e) {
                Toast.makeText(this, "请输入有效数字内容", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
                return ;
            }
            if(bitmap != null) {
    //            bitmap.compress(Bitmap.CompressFormat.PNG, quality, baos); // 设置Bitmap.CompressFormat.PNG,quality将不起作用,PNG是无损压缩
                bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
                byte[] bytes = baos.toByteArray();
                Bitmap newBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                String info = " quality: " + quality + " 压缩图片大小: " + (newBitmap.getByteCount()) + " 压缩后文件大小: " + (bytes.length) + " 宽度为: " + newBitmap.getWidth() + " 高度为: " + newBitmap.getHeight();
                Log.v("quality", info);
                tvCompress.setText(info);
                imgvCompress.setImageBitmap(newBitmap);
            }
    关键代

    码是:

    bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);

    其中quality是压缩质量,100表示保持最佳质量压缩效果,值越小表示压缩效果越差。
    如果上述方法的CompressFormat参数设置成Bitmap.CompressFormat.PNG,那么后面的quality参数将会失效,无论怎样改变quality的值,压缩后的文件都不会改变这是因为PNG是无损压缩。
    把quality设置成5,可以看下压缩效果:
     
    效果图:
     

    5. 设置RGB_565

    设置RGB_565相比ARGB_8888减少了一半内存,这是因为RGB_565每个像素是2个字节存储的,但是bitmap的宽和高并不会改变。

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = config;
    Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png", options);
    if(bitmap != null) {
        String info = " 压缩图片大小: " + (bitmap.getByteCount()) + " 宽度为: " + bitmap.getWidth() + " 高度为: " + bitmap.getHeight();
        Log.v("rgb", info);
        tvCompress.setText(info);
        imgvCompress.setImageBitmap(bitmap);
    }

    以下是使用RGB_565压缩的输出:

     效果图:

    6. 使用createScaledBitmap

    使用createScaledBitmap()方法可以把图片压缩成用户期望任意尺寸的图片,如果期望尺寸和图片相差太大,会导致图片失真。

    Bitmap bitmap =
    BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/compresstest/test.png");
    String strx = edtvWidth.getText().toString();
    String stry = edtvHeight.getText().toString();
    
    int width = 200;
    int height = 200;
    try {
        width = Integer.parseInt(strx);
        height = Integer.parseInt(stry);
    } catch (Exception e) {
        Toast.makeText(this, "请输入有效数字内容", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
        return ;
    }
    if(bitmap != null) {
        Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
        String info = " width: " + width + " height: " + height + " 压缩图片大小: " + (newBitmap.getByteCount()) + " 宽度为: " + newBitmap.getWidth() + " 高度为: " + newBitmap.getHeight();
        Log.v("scale", info);
        tvCompress.setText(info);
        imgvCompress.setImageBitmap(newBitmap);
    }

    把宽高设置成200之后的效果:
     
     
    可以看到,如果不按比例进行缩放设置,图片是会拉伸,失真的。

    本文的源码比较简单,就不上传了,需要的留下邮箱私发。


     

    展开全文
  • 之前文章已经介绍了 MinIO 的环境搭建,已经对文件的上传下载方法,本篇文章一起与大家来学习图片压缩上传的方法 1、背景 最近客户总抱怨 APP 中图片显示较慢, 升级服务器带宽又没有多的预算,查看原因,是因为现在...

    之前文章已经介绍了 MinIO 的环境搭建,已经对文件的上传下载方法,本篇文章一起与大家来学习图片压缩上传的方法

    1、背景

    最近客户总抱怨 APP 中图片显示较慢, 升级服务器带宽又没有多的预算。查看原因,是因为现在大家都是用的智能手机拍照,拍出来的照片小则 2-3 M,大则十几 M,所以导致图片显示较慢。思考再三,决定将图片进行压缩再上传图片服务器来解决图片显示慢的问题

    2、开发前戏

    1、引入 maven 依赖

    <!-- 图片压缩 -->
    <dependency>
        <groupId>net.coobird</groupId>
        <artifactId>thumbnailator</artifactId>
        <version>0.4.8</version>
    </dependency>
    

    本次我们选择了使用 thumbnailator 来作为压缩的工具

    2、thumbnailator 简介

    • Thumbnailator 是一个用来生成图像缩略图的 Java 类库,通过很简单的代码即可生成图片缩略图,也可直接对一整个目录的图片生成缩略图
    • 支持图片缩放,区域裁剪,水印,旋转,保持比例

    3、压缩前戏

    • 判断是否是图片方法
    /**
     * 判断文件是否为图片
     */
    public boolean isPicture(String imgName) {
        boolean flag = false;
        if (StringUtils.isBlank(imgName)) {
            return false;
        }
        String[] arr = {"bmp", "dib", "gif", "jfif", "jpe", "jpeg", "jpg", "png", "tif", "tiff", "ico"};
        for (String item : arr) {
            if (item.equals(imgName)) {
                flag = true;
                break;
            }
        }
        return flag;
    }
    

    3、压缩上传

    /**
     * 上传文件
     *
     * @param file 文件
     * @return
     */
    public JSONObject uploadFile(MultipartFile file) throws Exception {
        JSONObject res = new JSONObject();
        res.put("code", 500);
        // 判断上传文件是否为空
        if (null == file || 0 == file.getSize()) {
            res.put("msg", "上传文件不能为空");
            return res;
        }
        // 判断存储桶是否存在
        if (!client.bucketExists("test")) {
            client.makeBucket("test");
        }
        // 拿到文件后缀名,例如:png
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        // UUID 作为文件名
        String uuid = String.valueOf(UUID.randomUUID());
        // 新的文件名
        String fileName = DateUtils.getYyyymmdd() + "/" + uuid + "." + suffix;
        /**
         * 判断是否是图片
         * 判断是否超过了 100K
         */
        if (isPicture(suffix) && (1024 * 1024 * 0.1) <= file.getSize()) {
            // 在项目根目录下的 upload 目录中生成临时文件
            File newFile = new File(ClassUtils.getDefaultClassLoader().getResource("upload").getPath() + uuid + "." + suffix);
            // 小于 1M 的
            if ((1024 * 1024 * 0.1) <= file.getSize() && file.getSize() <= (1024 * 1024)) {
                Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.3f).toFile(newFile);
            }
            // 1 - 2M 的
            else if ((1024 * 1024) < file.getSize() && file.getSize() <= (1024 * 1024 * 2)) {
                Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.2f).toFile(newFile);
            }
            // 2M 以上的
            else if ((1024 * 1024 * 2) < file.getSize()) {
                Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.1f).toFile(newFile);
            }
            // 获取输入流
            FileInputStream input = new FileInputStream(newFile);
            // 转为 MultipartFile
            MultipartFile multipartFile = new MockMultipartFile("file", newFile.getName(), "text/plain", input);
            // 开始上传
            client.putObject("test", fileName, multipartFile.getInputStream(), file.getContentType());
            // 删除临时文件
            newFile.delete();
            // 返回状态以及图片路径
            res.put("code", 200);
            res.put("msg", "上传成功");
            res.put("url", minioProp.getEndpoint() + "/" + "test" + "/" + fileName);
        }
        // 不需要压缩,直接上传
        else {
            // 开始上传
            client.putObject("test", fileName, file.getInputStream(), file.getContentType());
            // 返回状态以及图片路径
            res.put("code", 200);
            res.put("msg", "上传成功");
            res.put("url", minioProp.getEndpoint() + "/" + "test" + "/" + fileName);
        }
        return res;
    }
    
    • 这里我们判断了当文件为图片的时候,且当它大小超过了 (1024 * 1024 * 0.1),约为 100K 的时候,才进行压缩
    • 我们首先在根目录下的 upload 目录中创建了一个临时文件 newFile
    • Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.3f).toFile(newFile);将压缩后的文件输出到临时文件中
    • 然后将 FileInputStream 转为 MultipartFile 上传
    • 最后删除临时文件 newFile.delete();
    • 完成图片压缩上传

    4、测试

    • 原图 706K

    原图

    • 压缩后 120K

    压缩后

    5、总结

    • 综合以上代码,可以看出 Thumbnails 对图片的处理是很方便的,且代码量也非常少
    • 通过测试,可以看出压缩后的图片质量也很高
    • thumbnailator 对图片的处理支持全面,缩放,裁剪等

    如您在阅读中发现不足,欢迎留言!!!

    展开全文
  • 前端实现图片压缩

    千次阅读 2020-08-07 17:47:19
    图片压缩在许多交互场景下具有广泛的应用,html5标准还没有普及之前图片压缩主要通过服务器端编程实现,而随着浏览器的快速发展对许多先进属性的支持致使前端技术也可以实现相同的功能.本篇文章以实战角度去深入研究...
  • Android之图片压缩

    千次阅读 多人点赞 2016-09-09 16:09:54
    在开发中,对于图片的操作,稍有不慎,可能就会消耗大量的内存,导致程序崩溃,所以了解一种通用的技术去处理和加载图片,同时保证UI流畅避免OOM现象,是非常有必要的。那么为什么在Android中对于图片的处理会如此...
  • React图片压缩上传统一处理

    千次阅读 2020-04-13 16:50:33
    最近项目需要对上传的图片文件进行压缩后才上传到服务器中,于是研究了一番,下面给出详细的压缩方法,笔者使用的是React Ant Design前端框架的Upload组件上传图片: 通过查看Ant Design官网文档,在上传文件前可以...
  • 本项目主要基于 Android 自带的图片压缩 API 进行实现,提供了开源压缩方案 Luban 和 Compressor 的实现,解决了单一 Fie 类型数据源的问题,并在它们的基础之上进行了功能上的拓展。该项目的主要目的在于:提供一个...
  • Android中图片压缩分析(上)

    千次阅读 2017-11-12 11:50:17
    此文章首发:https://mp.weixin.qq.com/s/QZ-XTsO7WnNvpnbr3DWQmg一、前言在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩。前者是在不改变图片尺寸的情况...
  • TP5 图片压缩

    千次阅读 2019-06-18 17:59:33
    * 图片压缩类:通过缩放来压缩。 * 如果要保持源图比例,把参数$percent保持为1即可。 * 即使原比例压缩,也可大幅度缩小。数码相机4M图片。也可以缩为700KB左右。如果缩小比例,则体积会更小。 * Author @...
  • Vue 图片压缩并上传至服务器

    千次阅读 2020-01-15 11:12:23
    本文主要讲解基于 Vue + Vant ,实现移动端图片选择,并用 Canvas 压缩图片,... * 图片压缩工具类 * 最大高度和最大宽度都为 500,如果超出大小将等比例缩放。 * * 注意可能出现压缩后比原图更大的情况,在调用...
  • Python图片压缩

    千次阅读 2019-05-19 21:03:53
    Python图片压缩 原图片: 压缩后: 压缩后效果图: 使用方法: 在桌面文件夹新建名为“img”文件夹,将要压缩的图片放在里面即可,记得改变一下DIR路径。 第三方库:PIL glob 可自行选择分辨率 正常实现5M/JPG –...
  • flutter图片压缩库对比

    千次阅读 2020-06-11 13:43:14
    flutter图片压缩库对比flutter图片压缩库对比flutter_luban压缩介绍 flutter图片压缩库对比 最近在做flutter的项目的时候用到了图片上传和图片压缩,开始使用的压缩库是flutter_luban,压缩的效果不错,但是在一些...
  • java图片压缩处理(可以压缩为任意大小
  • 前端实现图片压缩上传功能

    千次阅读 2019-04-12 21:49:16
    以移动端为例,在H5上传图片时,由于机型 / 网速 / 流量等限制,在低版本机型上经常会出现上传的图片太大导致上传很慢甚至崩溃的情况,所以需要对在某些情况下需要对上传的图片进行压缩上传。 以下以移动端使用Vue...
  • * 压缩图片,将图片压缩后以二进制的形式输出 * * @param file * 将要压缩的图片 * @param width * 压缩宽(长度短的做宽) * @param height * 压缩长(长度长的做长) * @return byte[]二进制流 */
  • JS前端图片压缩上传-纯js

    千次阅读 2021-02-24 20:11:57
    JS前端图片压缩上传-纯js 最近在做一个手机端的图片上传,写了一个比较符合自己要求的方法,可供参考 在做这个功能模块时,我遇到了以下问题,都花费了大量时间: 1. 不知道怎么压缩图片,(代码和方法) 2. 得到...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 313,985
精华内容 125,594
关键字:

图片压缩