当前位置: 首页 > news >正文

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。

相关文章:

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

各种报名都对照片有大小限制&#xff0c;鉴于这种情况&#xff0c;网上搜了后拼凑出了如下代码&#xff0c;用于解决1寸照片修改为2寸照片&#xff0c;同时将DPI修改为300&#xff0c;当然也可以根据自己的情况修改代码&#xff1a; HTML <input type"file" id&…...

EDA实验----四选一多路选择器设计(QuartusII)

目录 一&#xff0e;实验目的 二&#xff0e;实验仪器设备 三&#xff0e;实验原理&#xff1a; 四&#xff0e;实验要求 五&#xff0e;实验内容及步骤 1.实验内容 2.实验步骤 六&#xff0e;实验报告 七.实验过程 1.创建Verilog文件&#xff0c;写代码 2.波形仿真 …...

从windows iso文件中提取install.wim

1、首先从微软官方下载需要的windows镜像 https://www.microsoft.com/zh-cn/software-download/windows10/ 2、在下载的iso文件右键&#xff0c;打开压缩包&#xff0c;在sources文件夹下&#xff0c;应该就可以看到install.wim了。但似乎在最新的win10版本&#xff0c;微软采…...

Python的flask网页编程的GET和POST方法的区别

关于flask网页编程的GET及POST方法之间存在哪些区别问题&#xff0c;我们主要从以下六个关键点予以详细阐述&#xff1a; 首先需要明确的是&#xff0c;GET与POST两种不同类型的HTTP方法所采用的请求模式有所差别。其中&#xff0c;GET方法采用的是基于URL请求的机制&#xff…...

15 # 手写 throttle 节流方法

什么是节流 节流是限制事件触发的频率&#xff0c;当持续触发事件时&#xff0c;在一定时间内只执行一次事件&#xff0c;这个效果跟英雄联盟里的闪现技能释放差不多。 函数防抖关注一定时间连续触发的事件只在最后执行一次&#xff0c;而函数节流侧重于一段时间内只执行一次…...

puzzle(1612)拼单词、wordlegame

目录 拼单词 wordlegame 拼单词 在线play 找出尽可能多的单词。 如果相邻的话&#xff08;在任何方向上&#xff09;&#xff0c;你可以拖拽鼠标从一个字母&#xff08;方格&#xff09;到另一个字母&#xff08;方格&#xff09;。在一个单词中&#xff0c;你不能多次使用…...

【解决方案】pytion 运行时提示 import psutil ModuleNotFoundError: No module named ‘psutil‘

报错原因分析 import psutil ModuleNotFoundError: No module named psutil报错原因分析 当前环境pytion中缺少了psutil包&#xff0c;使用pip命令进行安装 解决方案 pip install psutil...

CSS3 过度效果、动画、多列

一、CSS3过度&#xff1a; CSS3过渡是元素从一种样式逐渐改变为另一种的效果。要实现这一点&#xff0c;必须规定两相内容&#xff1a;指定要添加效果的CSS属性&#xff1b;指定效果的持续时间。如果为指定持续时间&#xff0c;transition将没有任何效果。 <style> div…...

java使用geotools解析矢量数据kml、geojson、shp文件

geotools解析kml、geojson geotools环境准备公共获取属性方法解析kml解析geojson解析shp geotools环境准备 这里使用的是maven引用geotools包&#xff0c;引用geotools包需要添加maven仓库&#xff0c;pom.xml文件如下&#xff1a; <properties><!-- geotools版本 -…...

原生 JS DOM 常用操作大全

DOM DOM文档对象模型 又称为DOM树 DOM树 由文档、元素、节点 组成文档&#xff1a;一个页面就是一个文档&#xff0c;元素&#xff1a;文档中的所有标签都称为元素。DOM中使用Element表示节点&#xff1a;文档中的所有内容&#xff0c;在文档中都是节点&#xff08;标签、属性…...

昇腾CANN 7.0 黑科技:DVPP硬件加速训练数据预处理,友好解决Host CPU预处理瓶颈

在NPU/GPU上进行模型训练计算&#xff0c;为了充分使用计算资源&#xff0c;一般采用批量数据处理方式&#xff0c;因此一般情况下为提升整体吞吐率&#xff0c;batch值会设置的比较大&#xff0c;常见的batch数为256/512&#xff0c;这样一来&#xff0c;对数据预处理处理速度…...

Aria2 任意文件写入漏洞复现

漏洞描述 Aria2 是一款轻量级、多协议、多源下载工具&#xff08;支持 HTTP/HTTPS、FTP、BitTorrent、Metalink&#xff09;&#xff0c;内置 XML-RPC 和 JSON-RPC 接口。 我们可以使用 RPC 接口来操作 aria2 并将文件下载到任意目录&#xff0c;从而造成任意文件写入漏洞。 …...

思维模型 多看效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。越熟悉&#xff0c;越喜欢。 1 多看效应的应用 1.1 多看效应在广告和营销领域的应用 1 可口可乐之歌 可口可乐公司在 20 世纪 60 年代推出了“可口可乐之歌”广告&#xff0c;这个广告通…...

持续集成交付CICD:Jenkins Pipeline与远程构建触发器

目录 一、实验 1.Jenkins Pipeline本地构建触发器 2.Jenkins Pipeline与远程构建触发器&#xff08;第一种方式&#xff09; 3.Jenkins Pipeline与远程构建触发器&#xff08;第二种方式&#xff09; 4.Jenkins Pipeline与远程构建触发器&#xff08;第三种方式&#xff0…...

【无标题(PC+WAP)花卉租赁盆栽绿植类pbootcms站模板

(PCWAP)花卉租赁盆栽绿植类pbootcms网站模板 PbootCMS内核开发的网站模板&#xff0c;该模板适用于盆栽绿植网站等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b; PCWAP&#xff0c;同一个后台&#xff0c;数据即时同步&…...

pytorch 学习率衰减策略

##学习率衰减策略 import torch.nn.functional as F import torch import torch.nn as nn import matplotlib.pyplot as plt#初始化模型 class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Co…...

Flink SQL -- 概述

1、Flink SQL中的动态表和连续查询 1、动态表&#xff1a; 因为Flink是可以做实时的&#xff0c;数据是在不断的变化的&#xff0c;所以动态表指的是Flink中一张实时变换的表&#xff0c;表中会不断的有新的数据。但是这张表并不是真正的物理表。 2、连续查询&#xff1a; 连续…...

Spring RabbitMQ那些事(1-交换机配置消息发送订阅实操)

目录 一、序言二、配置文件application.yml三、RabbitMQ交换机和队列配置1、定义4个队列2、定义Fanout交换机和队列绑定关系2、定义Direct交换机和队列绑定关系3、定义Topic交换机和队列绑定关系4、定义Header交换机和队列绑定关系 四、RabbitMQ消费者配置五、RabbitMQ生产者六…...

C++动态库

C动态库 动态库文件&#xff08;Dynamic Link Library&#xff0c;DLL&#xff09;是程序在运行时所需要调用的库。静态库文件是程序在编译时所需要调用的库。 1 环境介绍 VS版本&#xff1a;VS2017 编程语言&#xff1a;C 2 功能介绍 使用VS2017项目模板创建C动态库生成…...

【教3妹学编程-算法题】2923. 找到冠军 I

3妹&#xff1a;2哥2哥&#xff0c;你看到新闻了吗&#xff1f;襄阳健桥医院院长 公然“贩卖出生证明”&#xff0c; 真是太胆大包天了吧。 2哥 : 我也看到新闻了&#xff0c;7人被采取刑事强制措施。 就应该好好查查他们&#xff0c; 一查到底&#xff01; 3妹&#xff1a;真的…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001

qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类&#xff0c;直接把源文件拖进VS的项目里&#xff0c;然后VS卡住十秒&#xff0c;然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分&#xff0c;导致编译的时候找不到了。因…...