pica
浏览器中的高质量图像大小调整
在浏览器中调整图像大小,无需像素化,速度相当快。自动选择最好的可用技术:webworkers、webassembly、createImageBitmap、纯JS。
简单使用
<script src="./plugins/pica.min.js"></script>
<script>
function resizeImage(img_path, file_name) {
const img = new Image();
img.src = img_path;
img.onload = function () {
const canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
const pica = window.pica({ features: ["all"] });
pica
.resize(img, canvas)
.then((result) => pica.toBlob(result, "image/jpeg", 0.9))
.then((blob) => {
const blob_obj = new Blob([blob], {
type: "image/jpeg",
});
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob_obj);
link.download = file_name + ".jpg";
link.click();
window.URL.revokeObjectURL(link.href);
});
};
}
resizeImage("./images/1.jpg", "download");
</script>
批量压缩文件域选择的图片并打包下载
<script src="./plugins/pica.min.js"></script>
<script src="./plugins/jszip.min.js"></script>
<script src="./plugins/FileSaver.js"></script>
<input type="file" id="files" multiple onchange="previewImages(this)" accept="image/*" />
<div id="con-obj" class="container"></div>
<div id="con-data" class="container"></div>
<div id="con-resize" class="container"></div>
<script>
function previewImages(this_obj) {
const elem_con_obj = document.querySelector("#con-obj");
const elem_con_data = document.querySelector("#con-data");
const elem_con_resize = document.querySelector("#con-resize");
const file_list = [];
for (let i in this_obj.files) {
const file = this_obj.files[i];
if (["image/jpeg", "image/png"].indexOf(file.type) < 0) continue;
file_list.push(file);
}
Promise.all(
file_list.map((file) => {
return new Promise((resolve, reject) => {
//预览
const elem_img = document.createElement("img");
elem_img.src = window.URL.createObjectURL(file);
elem_con_obj.append(elem_img);
console.log(elem_img.src);//blob:http://localhost:3000/80e8fa2c-caa1-4a23-a6d2-01bdac2843e2
const file_reader = new FileReader();
file_reader.readAsDataURL(file);
file_reader.onload = (e) => {
const img = new Image();
img.src = e.target.result;
img.onload = function () {
//预览
elem_con_data.append(img);
console.log(img.src);//data:image/png;base64,iVBORw0...
const canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
//压缩
const pica = window.pica({ features: ["all"] });
pica
.resize(img, canvas)
.then((result) => pica.toBlob(result, "image/jpeg", 0.9))
.then((blob) => {
resolve({ blob: blob, file_name: file.name });
//预览
const elem_img_resize = document.createElement("img");
elem_img_resize.src = window.URL.createObjectURL(blob);
elem_con_resize.append(elem_img_resize);
console.log(elem_img_resize.src);//blob:http://localhost:3000/d2868663-aef0-48a2-8bdc-5e6d9f168a2e
});
};
img.onerror = function () {
reject("not a image");
};
};
file_reader.onerror = function () {
reject("read error");
};
});
})
)
.then((images) => {
console.log(images);
const zip = new JSZip();
for (let i in images) {
zip.file(images[i]["file_name"], images[i]["blob"]);
}
zip.generateAsync({ type: "blob" }).then((blob) => {
saveAs(blob, "compress.zip");
});
})
.catch((err) => {
console.error("Error packaging images:", err);
});
}
</script>
以上方法由于使用了Promise.all 保证了所有图片压缩完成后进行打包下载,然而由于Promise.all的特性,若图片中出现伪装成图片的文件会导致当前Promise走向reject,进一步导致了Promise.all 的失败。
尝试解决这个问题,使用Promise.allSettled 改写上面的代码。
<script>
function previewImages(this_obj) {
const elem_con_obj = document.querySelector("#con-obj");
const elem_con_data = document.querySelector("#con-data");
const elem_con_resize = document.querySelector("#con-resize");
const file_list = [];
for (let i in this_obj.files) {
const file = this_obj.files[i];
if (["image/jpeg", "image/png"].indexOf(file.type) < 0) continue;
file_list.push(file);
}
Promise.allSettled(
file_list.map((file) => {
return new Promise((resolve, reject) => {
//预览
const elem_img = document.createElement("img");
elem_img.src = window.URL.createObjectURL(file);
elem_con_obj.append(elem_img);
const file_reader = new FileReader();
file_reader.readAsDataURL(file);
file_reader.onload = (e) => {
const img = new Image();
img.src = e.target.result;
img.onload = function () {
//预览
elem_con_data.append(img);
const canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
//压缩
const pica = window.pica({ features: ["all"] });
pica
.resize(img, canvas)
.then((result) => pica.toBlob(result, "image/jpeg", 0.9))
.then((blob) => {
resolve({ blob: blob, file_name: file.name });
//预览
const elem_img_resize = document.createElement("img");
elem_img_resize.src = window.URL.createObjectURL(blob);
elem_con_resize.append(elem_img_resize);
});
};
img.onerror = function () {
reject("not a image");
};
};
file_reader.onerror = function () {
reject("read error");
};
});
})
)
.then((images) => {
console.log(images);
const zip = new JSZip();
for (let i in images) {
if (images[i]["status"] == "rejected") continue;
const image = images[i]["value"];
zip.file(image["file_name"], image["blob"]);
}
zip.generateAsync({ type: "blob" }).then((blob) => {
saveAs(blob, "compress.zip");
});
})
.catch((err) => {
console.error("Error packaging images:", err);
});
}
</script>
即可保证所有真正的图片可以正常压缩和打包下载。
标签:const,img,前端,elem,js,blob,file,pica,con From: https://www.cnblogs.com/caroline2016/p/18359242