FileReader
FileReader 对象 允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
readAsDataURL
readAsDataURL 方法 会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成 DONE,并触发 loadend 事件,同时 result 属性将包含一个 data:URL 格式的字符串(base64 编码)以表示所读取文件的内容。
示例:
function previewFile() {
var preview = document.querySelector("img");
var file = document.querySelector("input[type=file]").files[0];
var reader = new FileReader();
reader.addEventListener(
"load",
function () {
preview.src = reader.result;
},
false
);
if (file) {
reader.readAsDataURL(file);
}
}
canvas
Canvas 提供了一个通过 JavaScript 和 HTML 的<canvas>
元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。
drawImage
Canvas 2D API 中的 CanvasRenderingContext2D.drawImage() 方法提供了多种在画布(Canvas)上绘制图像的方式。
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
getImageData
CanvasRenderingContext2D.getImageData() 返回一个 ImageData 对象,用来描述 canvas 区域隐含的像素数据,这个区域通过矩形表示,起始点为(sx, sy)、宽为 sw、高为 sh。
参数:
- sx
- 将要被提取的图像数据矩形区域的左上角 x 坐标。
- sy
- 将要被提取的图像数据矩形区域的左上角 y 坐标。
- sw
- 将要被提取的图像数据矩形区域的宽度。
- sh
- 将要被提取的图像数据矩形区域的高度。
返回值:
- 一个 ImageData 对象,包含 canvas 给定的矩形图像数据。
UPNG
一个小型,快速和先进的 PNG / APNG 编码器和解码器。开源地址:github.com/photopea/UP…
完整代码
declare var UPNG: {
encode: (
imgs: ArrayBuffer[],
w: number,
h: number,
cnum: number,
dels?: number[]
) => ArrayBuffer;
};
interface Options {
file: File;
cnum?: number;
success?: (base64: string) => void;
}
// 定义一个函数,参数是一个 ArrayBuffer 对象
function arrayBufferToBase64(buffer) {
// 初始化一个空字符串,用于存储二进制数据
var binary = "";
// 创建一个新的 Uint8Array 对象,它的内容是参数 buffer 的一个浅拷贝
// Uint8Array 是一个类型化数组,用于表示 8 位无符号整数的数组
var bytes = new Uint8Array(buffer);
// 获取这个 Uint8Array 的长度(即字节数)
var len = bytes.byteLength;
// 遍历这个 Uint8Array
for (var i = 0; i < len; i++) {
// 将每个字节转换为字符,然后添加到 binary 字符串中
// String.fromCharCode 函数接收一个 Unicode 值,然后返回一个字符串
binary += String.fromCharCode(bytes[i]);
}
// 使用 window.btoa 函数将 binary 字符串转换为 Base64 格式
// btoa 是 "binary to ASCII" 的缩写
return window.btoa(binary);
}
/**
* 适用于png
*/
class CompressImage {
options: Options;
fileReader = new FileReader();
constructor(options: Options) {
this.options = options;
this.createBase64();
}
createBase64() {
this.fileReader.readAsDataURL(this.options.file);
this.fileReader.onload = (e) => {
this.compress(e.target.result as string);
};
}
compress(base64: string) {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const img = new Image();
img.src = base64;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
const dta = ctx.getImageData(0, 0, img.width, img.height).data;
const png = UPNG.encode(
[dta.buffer],
img.width,
img.height,
this.options.cnum
);
const newBase64 = "data:image/png;base64," + arrayBufferToBase64(png);
this.options.success(newBase64);
};
}
}
const file = document.querySelector("#file") as HTMLInputElement;
file.addEventListener("change", (e) => {
const target = e.target as HTMLInputElement;
const fileObject = target.files[0];
if (fileObject) {
new CompressImage({
file: fileObject,
cnum: 256, // 将其设置为零以进行无损压缩,或写入图像中允许的颜色数。较小的值生成较小的文件。0表示无损,256表示有损。
success: (base64) => {
document.body.innerHTML = `<img src='${base64}' />`;
},
});
}
});