#javascript #html #jquery #math #compression
#javascript #HTML #jquery #математика #сжатие
Вопрос:
Размер моего файла составляет 500 КБ (он будет динамически приходить в любом размере). И моя цель — 150 КБ.
По некоторым причинам я могу выбрать только качество
new Compressor(selectedFile1, {
quality: targetRatio,
т.Е., Если я передам targetRatio на 0.7, это уменьшит изображение до 159 КБ ~
Чтобы динамически находить целевое значение, я сделал следующее
var targetRatio = fileSize / 150;
Но я не могу понять, как найти целевое значение, чтобы получить точное значение, т. Е. Уменьшить до 150 КБ
Ответ №1:
Изменение качества до 150 КБ не будет работать для каждого изображения.
Степень сжатия JPEG обычно измеряется в процентах от уровня качества. Изображение со 100% качеством не имеет (почти) потерь, а качество 1% — это изображение очень низкого качества. В общем, уровни качества 90% или выше считаются «высоким качеством», 80% -90% — «среднее качество», а 70% -80% — низкое качество.
Если вы будете использовать формат jpg размером 15,594 x 3,936 (пример), который может составлять ~ 2,5 Мб в зависимости от сохраненной информации, вы не сможете достичь 150 КБ в формате jpg.
Таким образом, таргетинг на 150 КБ будет 150.000 / 2.500.000 = 0.06
.
Как вы можете видеть из размера результата на скриншоте, это невозможно, вам нужно выполнить несколько преобразований и проверить, соответствует ли размер результата точно или меньше 150 КБ, уменьшив ширину и высоту. Но сжатие исходного изображения из моего примера с использованием качества 0,06 приведет к получению изображения размером около 800 КБ.
fetch('https://i.imgur.com/mw7BsYS.jpg')
.then(response => response.blob())
.then(async blob => {
let {
size
} = blob;
console.log("Startingsize", size, 'B');
let img = document.createElement("img");
img.src = URL.createObjectURL(blob);
await new Promise((r) => img.onload = r);
let {
naturalWidth,
naturalHeight
} = img;
console.log(naturalWidth, naturalHeight, size);
const targetByte = 150 * 1024;
// in case first picture is smaller than 150kb
let compressed = { result: blob };
// speeds up large pictures
if (targetByte / size < 0.15) {
naturalWidth *= 0.15;
naturalHeight *= 0.15;
} else if (targetByte / size < 0.25) {
naturalWidth *= 0.25;
naturalHeight *= 0.25;
} else if (targetByte / size < 0.5) {
naturalWidth *= 0.5;
naturalHeight *= 0.5;
} else if (targetByte / size < 0.75) {
naturalWidth *= 0.75;
naturalHeight *= 0.75;
}
// generate thumbnails
while (size > targetByte) {
if (blob.size > targetByte) {
// the bigger the steps, the faster it will be.
naturalWidth *= 0.99;
naturalHeight *= 0.99;
}
let res = await new Promise((resolve, reject) => {
const res = new Compressor(blob, {
maxWidth: naturalWidth,
maxHeight: naturalHeight,
success(blob) {
size = blob.size;
console.log(naturalWidth, naturalHeight, size);
compressed = res;
resolve();
},
error: reject
})
});
}
// replace the compressed with the original image from above
const original = img.src;
img.onclick = () => { if (confirm("sure?")) img.src = original; };
// compressed.result contains the final blob now
img.src = URL.createObjectURL(compressed.result);
await new Promise((r) => img.onload = r);
console.log(compressed.result, img.naturalWidth, img.naturalHeight)
document.body.append(img);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/compressorjs/1.1.1/compressor.js"></script>