JS对图片尺寸和DPI进行编辑修改(1寸照修改为2寸照)

各种报名都对照片有大小限制,鉴于这种情况,网上搜了后拼凑出了如下代码,用于解决1寸照片修改为2寸照片,同时将DPI修改为300,当然也可以根据自己的情况修改代码:

HTML

<input type="file" id="input" accept="image/*">
<div style="display: grid;grid-template-columns: 1fr 5px 1fr;"><div><p>修改前:</p><img id="before-image" src="" style="display: block; max-width:100%;" ></div><div></div><div><p>修改后(点击图片下载):</p><a href="javascript:;" download><img id="after-image" src="" style="display: block;"></a></div>
</div>

JS

<script type="text/javascript">const after_image = document.getElementById('before-image');document.getElementById('input').addEventListener('change', (e) => {const reader = new FileReader();reader.readAsDataURL(e.target.files[0]);reader.onload = (e) => {b64 = e.target.result;after_image.src = b64;//设置目标图片大小var target_width = 413;var target_height = 626;//计算目标图片宽高比例var target_wh_scale = target_width / target_height;//定义一个Image对象var bitmap = new Image();bitmap.src = b64;bitmap.onload = function () {//var cut_width = 0;var cut_height = 0;//var bitmap_wh_scale = bitmap.width / bitmap.height;if (bitmap_wh_scale > target_wh_scale) {cut_width = bitmap.width - bitmap.width / (bitmap_wh_scale / target_wh_scale);}//裁剪宽度else if (bitmap_wh_scale < target_wh_scale) {cut_height = bitmap.height - bitmap.height * (bitmap_wh_scale / target_wh_scale);} else {Console.log("比例一致无需裁剪");}console.log("图片裁剪宽度:" + cut_width + " px");console.log("图片裁剪高度:" + cut_height + " px");const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');canvas.width = target_width;canvas.height = target_height;ctx.drawImage(this, cut_width / 2, cut_height / 2, bitmap.width - cut_width, bitmap.height - cut_height, 0, 0, target_width, target_height);var after_img = document.getElementById('after-image');after_img.src = canvas.toDataURL('image/jpg');var dataUrl = canvas.toDataURL('image/jpeg', 0.9);//修改DPI为300downloadBase64Img(after_img.parentElement, changeDpiDataUrl(dataUrl, 300), "t.jpg");}};})function downloadBase64Img(a, base64URL, fileName) {// 将 a 标签的 download 属性设置为要下载的文件名a.download = fileName || 'image';// 创建 Blob 对象,并获取 base64 数据的 MIME 类型const mimeType = base64URL.match(/:(.*?);/)[1];// 将 base64 数据转换为字节数组const byteCharacters = atob(base64URL.split(',')[1]);const byteNumbers = new Array(byteCharacters.length);// 将字节数组填充到 Uint8Array 中for (let i = 0; i < byteCharacters.length; i++) {byteNumbers[i] = byteCharacters.charCodeAt(i);}const byteArray = new Uint8Array(byteNumbers);// 创建 Blob 对象const blob = new Blob([byteArray], { type: mimeType });// 将 Blob 对象的 URL 赋值给 a 标签的 href 属性a.href = URL.createObjectURL(blob);}function changeDpiDataUrl(base64Image, dpi) {const PNG = 'image/png';const JPEG = 'image/jpeg';const dataSplitted = base64Image.split(',');const format = dataSplitted[0];const body = dataSplitted[1];let type;let headerLength;let overwritepHYs = false;if (format.indexOf(PNG) !== -1) {type = PNG;const b64Index = detectPhysChunkFromDataUrl(body);// 28 bytes in dataUrl are 21bytes, length of phys chunk with everything inside.if (b64Index >= 0) {headerLength = Math.ceil((b64Index + 28) / 3) * 4;overwritepHYs = true;} else {headerLength = 33 / 3 * 4;}}if (format.indexOf(JPEG) !== -1) {type = JPEG;headerLength = 18 / 3 * 4;}// 33 bytes are ok for pngs and jpegs// to contain the information.const stringHeader = body.substring(0, headerLength);const restOfData = body.substring(headerLength);const headerBytes = atob(stringHeader);const dataArray = new Uint8Array(headerBytes.length);for (let i = 0; i < dataArray.length; i++) {dataArray[i] = headerBytes.charCodeAt(i);}const finalArray = changeDpiOnArray(dataArray, dpi, type, overwritepHYs);const base64Header = btoa(String.fromCharCode(...finalArray));return [format, ',', base64Header, restOfData].join('');}function changeDpiOnArray(dataArray, dpi, format, overwritepHYs) {const PNG = 'image/png';const JPEG = 'image/jpeg';if (format === JPEG) {dataArray[13] = 1; // 1 pixel per inch or 2 pixel per cmdataArray[14] = dpi >> 8; // dpiX high bytedataArray[15] = dpi & 0xff; // dpiX low bytedataArray[16] = dpi >> 8; // dpiY high bytedataArray[17] = dpi & 0xff; // dpiY low bytereturn dataArray;}if (format === PNG) {const physChunk = new Uint8Array(13);// chunk header pHYs// 9 bytes of data// 4 bytes of crc// this multiplication is because the standard is dpi per meter.const _P = 'p'.charCodeAt(0);const _H = 'H'.charCodeAt(0);const _Y = 'Y'.charCodeAt(0);const _S = 's'.charCodeAt(0);dpi *= 39.3701;physChunk[0] = _P;physChunk[1] = _H;physChunk[2] = _Y;physChunk[3] = _S;physChunk[4] = dpi >>> 24; // dpiX highest bytephysChunk[5] = dpi >>> 16; // dpiX veryhigh bytephysChunk[6] = dpi >>> 8; // dpiX high bytephysChunk[7] = dpi & 0xff; // dpiX low bytephysChunk[8] = physChunk[4]; // dpiY highest bytephysChunk[9] = physChunk[5]; // dpiY veryhigh bytephysChunk[10] = physChunk[6]; // dpiY high bytephysChunk[11] = physChunk[7]; // dpiY low bytephysChunk[12] = 1; // dot per meter....const crc = calcCrc(physChunk);const crcChunk = new Uint8Array(4);crcChunk[0] = crc >>> 24;crcChunk[1] = crc >>> 16;crcChunk[2] = crc >>> 8;crcChunk[3] = crc & 0xff;if (overwritepHYs) {const startingIndex = searchStartOfPhys(dataArray);dataArray.set(physChunk, startingIndex);dataArray.set(crcChunk, startingIndex + 13);return dataArray;} else {// i need to give back an array of data that is divisible by 3 so that// dataurl encoding gives me integers, for luck this chunk is 17 + 4 = 21// if it was we could add a text chunk contaning some info, untill desired// length is met.// chunk structur 4 bytes for length is 9const chunkLength = new Uint8Array(4);chunkLength[0] = 0;chunkLength[1] = 0;chunkLength[2] = 0;chunkLength[3] = 9;const finalHeader = new Uint8Array(54);finalHeader.set(dataArray, 0);finalHeader.set(chunkLength, 33);finalHeader.set(physChunk, 37);finalHeader.set(crcChunk, 50);return finalHeader;}}}
</script>

以上代码中changeDpiDataUrl()changeDpiOnArray()两个函数来源于开源项目changeDPI。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/140986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

毕业设计项目:基于java+springboot的共享单车信息网站

运行环境 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Ma…

ABAP OpenSQL 分页处理

功能实现 在 ABAP 中&#xff0c;可以使用 OpenSQL 来实现分页功能。下面是一种实现分页的示例方法&#xff1a; 首先&#xff0c;定义一个内部表来存储查询结果数据&#xff1a; DATA lt_data TYPE TABLE OF your_data_type.然后&#xff0c;使用 SELECT 语句将数据查询到内…

Android 10.0 Settings 加载流程

一、系统设置首页 代码路径&#xff1a;packages/app/Settings/ 1 主界面加载&#xff1a; <!-- Alias for launcher activity only, as this belongs to each profile. --><activity-alias android:name"Settings"android:label"string/settings_la…

5. HTML常用标签

5.1 标签语义 学习标签是有技巧的&#xff0c;重点是记住每个标签的语义。简单理解就是指标签的含义。即这个标签是用来干嘛的。 根据标签的语义&#xff0c;在合适的地方给一个最为合理的标签。可以让页面结构给清晰。 5.2 标题标签 <h1>-<h6>(重要) HTML提供了…

【学习辅助】Axure手机时间管理APP原型,告别手机控番茄任务模板

作品概况 页面数量&#xff1a;共 30 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;时间管理、系统工具 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本品为「手机时间管理」APP原型&#xff0c;…

第二座山:万事万物的宇宙规律,一定是站在共赢才能实现

第二座山 真善 实现大众利益 破我执、破小钱关&#xff0c;破小情关&#xff0c;破小事关众生皆苦&#xff0c;十年的目的就是牺牲自己任何那些你的身外之物&#xff0c;它根本不可控 真善 实现大众利益 破我执、破小钱关&#xff0c;破小情关&#xff0c;破小事关 你今天…

Redis集群,你真的学会了吗?

目录 1、为什么引入集群 1.1、先来了解集群是什么 1.2、哨兵模式的缺陷 引入集群解决了什么问题 1.3、使用集群&#xff0c;如何存储数据 2、三种主流的分片方式【经典面试题】 2.1、哈希求余算法 2.1.1、哈希求余算法的介绍 2.1.2、哈希求余算法如何扩容 2.2、一致性…

C# 并发编程

C# 并发编程 前言 对于现在很多编程语言来说&#xff0c;多线程已经得到了很好的支持&#xff0c; 以至于我们写多线程程序简单&#xff0c;但是一旦遇到并发产生的问题就会各种尝试。 因为不是明白为什么会产生并发问题&#xff0c;并发问题的根本原因是什么。 接下来就让…

acwing算法基础之数学知识--筛法求<=n的所有质数

目录 1 基础知识2 模板3 工程化 1 基础知识 核心思想&#xff1a;把2~n中的非质数打上标记&#xff08;也即&#xff0c;筛掉&#xff09;&#xff0c;剩余的就是质数。 一般做法&#xff1a; int primes[N]; //存储所有的质数 int st[N]; //存储是否被排除 int cnt; int n;…

vcomp120.dll丢失怎么办?vcomp120.dll丢失的解决方法分享

vcomp120.dll丢失”。这个错误通常会导致某些应用程序无法正常运行&#xff0c;给用户带来困扰。那么&#xff0c;当我们遇到这个问题时&#xff0c;应该如何修复呢&#xff1f;下面我将为大家介绍四个修复vcomp120.dll丢失的方法。 一、使用dll修复程序修复 可以通过百度或许…

flink的副输出sideoutput单元测试

背景 处理函数中处理输出主输出的数据流数据外,也可以输出多个其他的副输出的数据流数据&#xff0c;当我们的处理函数有副输出时&#xff0c;我们需要测试他们功能的正确性&#xff0c;本文就提供一个测试flink副输出单元测试的例子 测试flink副输出单元测试 首先看一下处理…

基于SWAT-MODFLOW地表水与地下水耦合

耦合模型被应用到很多科学和工程领域来改善模型的性能、效率和结果&#xff0c;SWAT作为一个地表水模型可以较好的模拟主要的水文过程&#xff0c;包括地表径流、降水、蒸发、风速、温度、渗流、侧向径流等&#xff0c;但是对于地下水部分的模拟相对粗糙&#xff0c;考虑到SWAT…

矢量绘图软件Sketch 99 for mac

Sketch是一款为用户提供设计和创建数字界面的矢量编辑工具。它主要用于UI/UX设计师、产品经理和开发人员&#xff0c;帮助他们快速设计和原型各种应用程序和网站。 Sketch具有简洁直观的界面&#xff0c;以及丰富的功能集&#xff0c;使得用户可以轻松地创建、编辑和共享精美的…

NSF服务器

目录 1.简介 1.1 NFS背景介绍 1.2 生产应用场景 2.NFS工作原理 2.1 实例图 2.2 流程 3.NFS的使用 3.1.安装 3.2.配置文件 3.3.主配置文件分析 3.4 实验 服务端&#xff1a; 客户端&#xff1a; 3.5.NFS账户映射 3.5.1.实验2 3.5.2.实验3 4.autofs自动挂载服务…

springboot整合Redis后间歇性io.lettuce.core.RedisCommandTimeoutException

在springboot中引入spring-boot-starter-data-redis依赖时&#xff0c;默认使用的时Lettuce 产生这种问题的原因有如下两点&#xff1a; 1、Lettuce 自适应拓扑刷新&#xff08;Adaptive updates&#xff09;与定时拓扑刷新&#xff08;Periodic updates&#xff09; 是默认关闭…

深入理解 Django 信号机制

Django 信号&#xff08;signals&#xff09;是一种实现解耦的有力工具&#xff0c;它允许某些发生的事件通知其他部分的代码。信号主要用于在 Django 应用中的不同部分之间传递信息&#xff0c;尤其是在模型操作发生时。本文将深入探讨 Django 信号的工作原理、如何定义和接收…

Mysql学习笔记--基础

一&#xff0c;SQL最重要的增删改命令格式 1&#xff0c;insert into 表名&#xff08;不写这个括号里面的内容就默认所有字段都要添加&#xff09; values&#xff08;&#xff09; 插入单条数据 2&#xff0c;insert into 表名 (里面是列名) values&#xff08;根据列名依次…

Java Web——前端HTML入门

目录 HTML&CSS3&JavaScript简述 1. HTML概念 2. 超文本 3. 标记语言 4. HTML基础结构 5. HTML基础词汇 6. HTML语法规则 7. VS Code 推荐使用的插件 8. 在线帮助文档 HTML&CSS3&JavaScript简述 HTML 主要用于网页主体结构的搭建&#xff0c;像一个毛坯…

ImportError: cannot import name ‘HTTPClientFactory‘ from ‘twisted.web.client‘

在scrapy框架下添加爬虫文件&#xff0c;运行时报错&#xff1a; ImportError: cannot import name HTTPClientFactory from twisted.web.client 解决方法&#xff1a; 降低了twisted的版本&#xff0c;开始在Python3.9上降低twisted的版本&#xff0c;全都失败&#xff0c;…

【LeetCode:715. Range 模块 | 线段树】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…