当前位置: 首页 > 编程日记 > 正文

PC端、移动端手机竖拍原图压缩上传顺时针旋转90°的解决方案

问题背景

最近在做的项目中,不管是移动端还是后台系统都涉及到了手机照片压缩上传的问题,做完功能测试的时候发现图片回显的时候有些顺时针旋转了90°(竖拍照片,不管是ios还是android都存在这问题),后来百度了一下才知道是跟图片的EXIF(可交换图像文件格式)中的Orientation(旋转参数)有关,那么问题就好处理了,我们可以获取上传图片的Orientation值,根据不同的值对图片做旋转处理。

Orientation旋转参数的介绍与获取

可交换图像文件格式(Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。只要是数码相机(包括手机)拍出来的照片都带有这个参数,旋转的方向有四种情况。exif.js可以帮助我们获取Orientation值(exif.js读取图像的元数据),后来我以import EXIF from './exif.js'方式引入发现文件中的EXIF方法并没有对外暴露出来,因此稍稍改写了一下。这是新的exif.js(你们可以引用这个exif.js)
图片描述
引用exif.js后,获取Orientation的核心代码,记得先var Orientation声明Orientation

EXIF.getData(img, function () {//获取照片Orientation,主要是修复竖拍照片顺时针旋转90°的问题(Orientation:6)EXIF.getAllTags(this);Orientation = EXIF.getTag(this, 'Orientation');
});

canvas 的 rotate() 方法对不同的Orientation值旋转处理

ctx.rotate(angle);

方法介绍参照canvas rotate()

旋转的中心点默认是canvas 的起点,即圆点位置(0, 0)。旋转的原理如下图:
图片描述

旋转之后,如果从圆点(0, 0)进行 drawImage(),那么画出来的位置就是在左图中的旋转90°后的位置,不在可视区域。旋转之后,坐标轴也跟着旋转了,想要显示在可视区域呢,需要将 ( 0, 0 ) 点往 y 轴的反方向移 y 个单位,此时的起始点则为 ( x, -y )(这种情况就是我们使用手机竖拍图片上传后顺时针旋转90°的情况)。

同理,可以获得旋转 -90°后的起始点为 ( -x, y ),旋转 180 度后的起始点为 ( -x, -y )。
核心代码如下

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// 设置 canvas 的宽度和高度  
// canvas.width = w;
// canvas.height = h;
// ctx.drawImage(img, 0, 0, w, h);
if (Orientation == 3) {canvas.width = w;canvas.height = h;ctx.rotate(Math.PI);ctx.drawImage(img, 0, 0, -w, -h);
} else if (Orientation == 8) {canvas.width = h;canvas.height = w;ctx.rotate(Math.PI * 3 / 2);ctx.drawImage(img, 0, 0, -w, h);
} else if (Orientation == 6) {canvas.width = h;canvas.height = w;ctx.rotate(Math.PI / 2);ctx.drawImage(img, 0, 0, w, -h);
} else {canvas.width = w;canvas.height = h;ctx.drawImage(img, 0, 0, w, h);
}

图片压缩

随着手机拍照像素越来越高,照片大小越来越大。图片上传的压缩一般是:第一是对上传的图片宽高做大小限制。

// 不要超出最大宽度  
var w = Math.min(_this.maxWidth, img.width);
// 高度按比例计算  
var h = img.height * (w / img.width);

第二是通过canvas.toDataURL(type, encoderOptions)方法设置压缩比,方法参考canvas.toDataUrl()

核心代码如下:

setQuality: function (file) {
//alert(file.size+','+this.maxSize);
if (file.size < 1024 * 1024) {//0-1mbthis.quality = 0.4;
}
if (file.size < 1024 * 1024 && file.size > 1024 * 1024 * 2) {//1-2mbthis.quality = 0.3;
}
if (file.size < 1024 * 1024 * 3 && file.size > 1024 * 1024 * 2) {//2-3mbthis.quality = 0.2;
}
if (file.size < 1024 * 1024 * 4 && file.size > 1024 * 1024 * 3) {//3-4mbthis.quality = 0.15;
}
if (file.size < 1024 * 1024 * 5 && file.size > 1024 * 1024 * 4) {//4-5mbthis.quality = 0.12;
}
if (file.size < 1024 * 1024 * 6 && file.size > 1024 * 1024 * 5) {//5-6mbthis.quality = 0.11;
}
if (file.size < 1024 * 1024 * 7 && file.size > 1024 * 1024 * 6) {//6-7mbthis.quality = 0.1;
}
if (file.size < 1024 * 1024 * 8 && file.size > 1024 * 1024 * 7) {//7-8mbthis.quality = 0.08;
}
if (file.size < 1024 * 1024 * 10 && file.size > 1024 * 1024 * 8) {//8-10mbthis.quality = 0.06;
}
}
var base64 = canvas.toDataURL('image/jpeg', _this.quality);
setTimeout(function () {_this.imgData[id].uploadFiles.push(base64);_this.imgData[id].filesLength = _this.imgData[id].uploadFiles.length;
}, 100);

小结

拍照上传功能可拆分为图片压缩以及对获取到数码图片Orientation值进行相应的处理。这是小白第一次写技术贴,可能我写得并不是我想表达的,写得不好的地方请各位大神指点,有疑问的可以留言交流。

相关文章:

perl:cpanm安装方式的一种取代方法

笔者现在有一个cpanfile&#xff0c;里面需要安装的perl模块&#xff0c;github的作者给出的指令是 cpanm --installdeps . 而笔者的服务器没有cpanm&#xff0c;因为不是管理员也无法用apt安装 经过一番搜索&#xff0c;发现以下的替代方式&#xff1a; 依次在命令行输入 1…

elementUI源码修改的爬坑之旅

今天由于项目需要&#xff0c;想在Tree组件的前面增加一个icon图标&#xff0c;根据不同类型增加不同的图标&#xff0c;我修改了elementUI的源代码&#xff0c;发布到npm上去成功使用&#xff0c;记录下过程中所碰到的问题&#xff0c;首先看下最后的效果&#xff1a; 下面简单…

Sublime text3 快捷方式(windows平台)

1.Goto Anything-快速查找&#xff08;ctrl P&#xff09; 输入函数名可以快速找到函数输入#文本可以快速进行文件内文本匹配2.命令模式CtrlShiftP&#xff1a;打开命令面板 CtrlP&#xff1a;搜索项目中的文件 CtrlW&#xff1a;关闭当前打开文件 CtrlShiftW&#xf…

(已解决)ubuntu20.04 jar xvf XXX.zip报错-java.io.EOFException:Unexpected end of ZLIB input stream

报错截图 如下 我在服务器上解压缩defects4j-repos.zip&#xff0c;但是出现了如上错误。通过SFTP我把这个压缩包传到了本地win10上面&#xff0c;进行解压缩。本地解压缩软件(有图形界面的好处显现了)告诉我这个文件已经损坏。 原因分析 由于运行脚本涉及到一堆的文件下载&am…

Linux上传和下载

下载&#xff1a;sz 上传&#xff1a;rz

joomla网页无任何显示输出

joomla配置环境&#xff1a;LAMP 先打开php.ini display_errorsOn 网页显示报错 Class DOMDocument not found *********** 解决方法&#xff1a; 1.安装php-xml #yum install php-xml 2.重启apache&#xff08;CentOS&#xff09; #service httpd restart转载于:https://www…

【mysql的编程专题⑤】自定义函数

用户自定义函数(user-defined function,UDF) 是一种对mysql的扩展途径&#xff0c;其用法与内置函数相同 创建自定义函数 语法 create function function_name returns {string|integer|real|decimal} routine_body Example1 delimiter $ create function f1(gdate datetime) …

配深度学习环境要注意的不多,也就

1. 使用nvcc -V命令查看cuda版本&#xff0c;再在官网选择对应版本的pytorch。(是的不要根据python的版本去选择pytorch指令) 2. 用conda安装pytorch可能一直有cpuonly的玄学问题。(哪怕选择的是CUDA版本的pytorch安装命令)改用pip安装。 3. torchtext不会被顺带安装&#xf…

整理的一点MD5资料(第一部分)

MD5加密算法研究MD5简介&#xff1a; MD5的全称是Message-Digest Algorithm 5&#xff0c;在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明&#xff0c;经MD2、MD3和MD4发展而来。 Message-Digest泛指字节串(Message)的Hash变换&#xff0c;就是把一个任意长度的…

SQL学习(六)

1. INSERT 通用形式&#xff1a; INSERT INTO tablename [colname {,colname...}] {VALUES (expr &#xff5c;NULL &#xff5c; Subquery)} 例&#xff1a;1. insert into orders (ordno,month) values (1107.aug); 2. insert into swcusts select * from customers wh…

百练,4103,踩方格

百练&#xff0c;4103&#xff0c;踩方格 普通做法&#xff1a;&#xff08;也可以找规律&#xff09; #include #include//要调用memset函数&#xff0c;头文件 using namespace std; int visited[50][50];//开辟50*50的方格 int num0;//num为方案数 void ways(int i,int j,i…

BZOJ1747 [Usaco2005 open]Expedition 探险

首先我们可以发现如果错过了一个加油站&#xff0c;而继续往前走的时候没有油了&#xff0c;可以再假装之前经过加油站的时候加过油 于是我们维护一个大根堆&#xff0c;表示错过的加油站是哪些&#xff0c;每当没有油的时候从堆顶取出最大值加上去即可 1 /*******************…

Netty - ByteBuf索引管理

2019独角兽企业重金招聘Python工程师标准>>> 之前写过一篇文章介绍过JDK里面InputStream的mark(readlimit)和reset()方法&#xff0c;Java IO&#xff1a;使用mark/reset实现替换文件中字符串。相应的&#xff0c;可以通过调用markReaderIndex()/markWriterIndex()/…

DB2 9 利用开辟(733 测验)认证指南,第 1 部分: 数据库工具与编程步调(6)

运用基泉源基本理构建根本完毕语总结本教程向您引见了 DB2 利用挨次开辟的根本常识。在中缀任何开辟变乱之前&#xff0c;必须熟习差别规范的数据库工具。在本教程中&#xff0c;引见了几种初级的数据库工具。别名、序列工具和且则表凡是用于简化利用挨次代码。存储历程、函数和…

PHP 设计模式 笔记与总结(9)数据对象映射模式

【数据对象映射模式】 是将对象和数据存储映射起来&#xff0c;对一个对象的操作会映射为对数据存储的操作。例如在代码中 new 一个对象&#xff0c;使用数据对象映射模式就可以将对象的一些操作比如设置一些属性&#xff0c;就会自动保存到数据库&#xff0c;跟数据库中表的一…

inet_pton和inet_ntop函数

Linux下这2个IP地址转换函数&#xff0c;可以在将IP地址在“点分十进制”和“整数”之间转换 而且&#xff0c;inet_pton和inet_ntop这2个函数能够处理ipv4和ipv6。算是比较新的函数了。 inet_pton函数原型如下[将“点分十进制” &#xff0d;> “整数”] #include <sys/…

Firefox3 RC1颁布各种新特征发扬阐发更平定

作者: Dailon 出自: http://www.linuxdiyf.com Mozilla项目曾经颁布了Firefox 3 RC1。Firefox 3的新特征包罗对Javascript 1.8的支持、DOM和HTML的转变、微技俩&#xff08;microformats&#xff09;支持及一个扩展的Canvass完成。 Mozilla公司颠末对Javascript 1.8特征…

java中判断两个字符(或者字符串相等)

string a,b;//两字符串 在java中判断两个字符&#xff08;字符串&#xff09;相等&#xff0c;用a.equals(b); if(a.equals(b)){ //如果相等&#xff0c;返回值为true }else{ //如果不相等&#xff0c;返回值为false } 不能用if(ab)来进行判断,这里比较的是两数据的内存

初学Hadoop之图解MapReduce与WordCount示例分析

Hadoop的框架最核心的设计就是&#xff1a;HDFS和MapReduce。HDFS为海量的数据提供了存储&#xff0c;MapReduce则为海量的数据提供了计算。HDFS是Google File System&#xff08;GFS&#xff09;的开源实现&#xff0c;MapReduce是Google MapReduce的开源实现。HDFS和MapReduc…

cnblogs不愧为cnblogs

在cnblogs落脚3天了&#xff0c;写了一些很实践的文章&#xff0c;很有成就感&#xff0c;为什么&#xff1f;我第一次为是否发表这篇文章而作出思考&#xff0c;以前在别的地方&#xff0c;总是转别人的文章居多&#xff0c;到了cnblogs&#xff0c;感受到了原创的精神——即使…

Debian刊行版3晋级到4

作者: rincess 出自: http://www.linuxdiyf.com 前些天把供职器从Debian 3 sarge晋级到Debian 4 etch&#xff0c;经过议定考察这几天的运转浮现&#xff0c;感受非常满意。新的体系包孕了新的WWW供职器Apache 2.2和PHP 5.2.0&#xff0c;SVN也从1.1晋级到了1.4&#xff0c;Tr…

简单五子棋问题,java实现

**题目要求&#xff1a;**实现一个控制台下五子棋的程序。用一个二维数组模拟一个15*15路的五子棋棋盘&#xff0c;把每个元素赋值位“┼”可以画出棋盘&#xff0c; “○”代表该交叉点下了一颗白棋子&#xff0c;“●”代表该交叉点下了一颗黑棋子。每次用户输入要下棋的坐标…

Singleton 单例模板

1 // singleton.h2 3 #ifndef SINGLETON_H4 #define SINGLETON_H5 6 // 单例基类模板7 template <class T>8 class Singleton9 { 10 public: 11 static T& give_me() 12 { 13 static T s_inst; 14 return s_inst; 15 } 16 17 private: …

Oracle 7.3.4 for OpenServer 5 装配

起原&#xff1a;网海拾贝 1.建立oracle用户、dba组&#xff1b;2.调整系统中央参数&#xff1a;#./idtune SHMMAX 409600000#./idtune SEMMNI 153.装配SCO补丁文件 oss459A&#xff0c;重新毗连中央并重新启动&#xff1a;#/etc/conf/cf.d/link_unix -y#init 6   4.编纂oracl…

sql server中的hash应用优化

sql server很多地方用到hash&#xff0c;计划缓存查找&#xff0c;hash连接&#xff0c;hash聚合等。 hash查找mssql很多设计中都应用了&#xff0c;不过我们能在开发设计中&#xff0c;也可以利用这个特性。 将如果有需求对大文本进行完全匹配&#xff0c;比如查找产品型号&am…

JAVA猴子选大王问题

题目要求 猴子选大王。输入猴子的个数n&#xff0c;所有的猴子从1-n编号排成一圈&#xff0c;从1号猴子开始数数&#xff0c;数到3的倍数猴子被淘汰&#xff0c;最后剩下的是大王。输出是大王的猴子的编号&#xff08;提示&#xff1a;使用数组&#xff0c;每个数组元素相当于一…

POJ 1185 炮兵阵地 (状压DP)

炮兵阵地Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 14869 Accepted: 5575Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成&#xff0c;地图的每一格可能是山地&#xff08;用"H" 表示&#xff09;…

不雅测发挥分析Android在美智能机市场凌驾黑莓及苹果

网易科技讯 3月4日动静&#xff0c;根据尼尔森公司比来宣布的陈诉发挥分析&#xff0c;Android操纵体系以29%的市占率在美国智好手机市场凌驾黑莓(27%)和苹果(27%)。其中&#xff0c;宏达电占12%&#xff0c;摩托罗拉占10%&#xff0c;三星占5%。但从厂商角度来看&#xff0c;苹…

Java基础-常量,变量,成员变量,局部变量

在java中&#xff0c;数据是以常量和变量两种方法形式进行存储和表示的&#xff08;实际上&#xff0c;所有程序的数据都是这两种形式&#xff09;。 变量 变量代表程序的状态。程序通过改变变量的值来改变整个程序的状态&#xff0c;或者说得更大一些&#xff0c;也就是实现程…

把eclipse从英文调整为中文

鼠标右键单击桌面上的快捷方式&#xff0c;选择文件所在位置 选择配置设置 eclipse.ini 在最后加上 -Duser.languageen 然后重启eclipse即可