programing

브라우저에서 자바스크립트로 이미지를 압축하는 방법은?

powerit 2023. 9. 25. 23:10
반응형

브라우저에서 자바스크립트로 이미지를 압축하는 방법은?

TL;DR;

업로드하기 전에 이미지(주로 jpeg, png 및 gif)를 브라우저 측에서 직접 압축할 수 있는 방법이 있습니까? 자바스크립트가 할 수 있다고 확신하지만 달성할 수 있는 방법을 찾을 수 없습니다.


구현하고자 하는 전체 시나리오는 다음과 같습니다.

  • 내합니다를 합니다.input type="file"소,
  • 이 이미지는 자바스크립트를 통해 검색되며, 우리는 정확한 파일 형식, 최대 파일 크기 등의 검증을 수행합니다.
  • 모든 것이 정상인 경우, 페이지에 이미지의 미리보기가 표시됩니다.
  • 사용자는 이미지를 90°/-90° 회전하거나 미리 정의된 비율에 따라 잘라내는 등의 기본적인 작업을 수행하거나 다른 이미지를 업로드하고 1단계로 돌아갈 수 있습니다.
  • 사용자가 만족하면 편집된 이미지가 압축되고 로컬에서 "saved"됩니다(파일에 저장되지 않고 브라우저 메모리/페이지에 저장됨).
  • 사용자는 양식에 이름, 나이 등의 데이터를 채웁니다.
  • 사용자가 "Finish" 버튼을 클릭하면 데이터 + 압축 이미지를 포함하는 양식이 서버로 전송됩니다(AJAX는 제외).

마지막 단계까지의 전체 프로세스는 클라이언트 측에서 수행되어야 하며 최신 Chrome 및 Firefox, Safari 5+ 및 IE 8+에서 호환되어야 합니다.가능하다면 자바스크립트만 사용해야 합니다. (하지만 이것은 불가능하다고 확신합니다.)

지금은 코드화한 게 없는데 이미 생각해봤어요.파일 API를 통해 로컬에서 파일 읽기가 가능하고, 캔버스 요소를 사용하여 이미지 미리보기 및 편집이 가능하지만 이미지 압축 부분을 수행할 방법을 찾을없습니다.

html5please.com caniuse.com 에 따르면 IE 덕분에 브라우저 지원이 상당히 어렵지만 FlashCanvasFileReader와 같은 폴리필(polyfill)을 사용하면 가능하다고 합니다.

사실 파일 크기를 줄이는 것이 목표이기 때문에 이미지 압축을 해결책으로 봅니다.그러나 업로드된 이미지가 매번 같은 장소에서 내 웹사이트에 표시된다는 것을 알고 있으며, 이 표시 영역의 크기(예: 200x400)도 알고 있습니다.따라서 이미지 크기를 해당 치수에 맞게 조정할 수 있으므로 파일 크기를 줄일 수 있습니다.이 기술에 대한 압축비가 어떻게 될지 모르겠습니다.

당신은 어떻게 생각하나요?나에게 해줄 조언이 있습니까?자바스크립트에서 이미지 브라우저 쪽을 압축하는 방법을 알고 계십니까?답변 감사합니다.

간단히 말해서:

  • .readAs로 HTML5 FileReader API를 사용하여 파일을 읽습니다.배열 버퍼
  • 파일 데이터로 Blob을 만들고 window로 URL을 가져옵니다.URL.createObjectURL(블롭)
  • 새 이미지 요소를 만들고 src를 파일 bloburl로 설정합니다.
  • 이미지를 캔버스로 보냅니다.캔버스 크기가 원하는 출력 크기로 설정됨
  • canvas.를 통해 축소된 데이터를 canvas.에서 DataURL("image/jpeg", 0.7)로 가져옵니다(출력 형식 및 품질 설정).
  • 원본 양식에 숨겨진 새로운 입력 첨부 및 데이터 전송URI 이미지는 기본적으로 일반 텍스트입니다.
  • 백엔드로 데이터를 읽습니다.URI, Base64에서 디코딩한 후 저장

출처 : 코드.

다른 답변에서 두 가지가 누락된 것 같습니다.

  • canvas.toBlob 가능한 가 우).canvas.toDataURL, 비동기화도 가능합니다.
  • 파일 -> image -> canvas -> 파일 변환은 EXIF 데이터를 손실합니다. 특히 현대 전화기/태블릿에서 일반적으로 설정하는 이미지 회전에 대한 데이터입니다.

다음 스크립트에서는 두 가지 사항을 모두 다룹니다.

// From https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob, needed for Safari:
if (!HTMLCanvasElement.prototype.toBlob) {
    Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
        value: function(callback, type, quality) {

            var binStr = atob(this.toDataURL(type, quality).split(',')[1]),
                len = binStr.length,
                arr = new Uint8Array(len);

            for (var i = 0; i < len; i++) {
                arr[i] = binStr.charCodeAt(i);
            }

            callback(new Blob([arr], {type: type || 'image/png'}));
        }
    });
}

window.URL = window.URL || window.webkitURL;

// Modified from https://stackoverflow.com/a/32490603, cc by-sa 3.0
// -2 = not jpeg, -1 = no data, 1..8 = orientations
function getExifOrientation(file, callback) {
    // Suggestion from http://code.flickr.net/2012/06/01/parsing-exif-client-side-using-javascript-2/:
    if (file.slice) {
        file = file.slice(0, 131072);
    } else if (file.webkitSlice) {
        file = file.webkitSlice(0, 131072);
    }

    var reader = new FileReader();
    reader.onload = function(e) {
        var view = new DataView(e.target.result);
        if (view.getUint16(0, false) != 0xFFD8) {
            callback(-2);
            return;
        }
        var length = view.byteLength, offset = 2;
        while (offset < length) {
            var marker = view.getUint16(offset, false);
            offset += 2;
            if (marker == 0xFFE1) {
                if (view.getUint32(offset += 2, false) != 0x45786966) {
                    callback(-1);
                    return;
                }
                var little = view.getUint16(offset += 6, false) == 0x4949;
                offset += view.getUint32(offset + 4, little);
                var tags = view.getUint16(offset, little);
                offset += 2;
                for (var i = 0; i < tags; i++)
                    if (view.getUint16(offset + (i * 12), little) == 0x0112) {
                        callback(view.getUint16(offset + (i * 12) + 8, little));
                        return;
                    }
            }
            else if ((marker & 0xFF00) != 0xFF00) break;
            else offset += view.getUint16(offset, false);
        }
        callback(-1);
    };
    reader.readAsArrayBuffer(file);
}

// Derived from https://stackoverflow.com/a/40867559, cc by-sa
function imgToCanvasWithOrientation(img, rawWidth, rawHeight, orientation) {
    var canvas = document.createElement('canvas');
    if (orientation > 4) {
        canvas.width = rawHeight;
        canvas.height = rawWidth;
    } else {
        canvas.width = rawWidth;
        canvas.height = rawHeight;
    }

    if (orientation > 1) {
        console.log("EXIF orientation = " + orientation + ", rotating picture");
    }

    var ctx = canvas.getContext('2d');
    switch (orientation) {
        case 2: ctx.transform(-1, 0, 0, 1, rawWidth, 0); break;
        case 3: ctx.transform(-1, 0, 0, -1, rawWidth, rawHeight); break;
        case 4: ctx.transform(1, 0, 0, -1, 0, rawHeight); break;
        case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
        case 6: ctx.transform(0, 1, -1, 0, rawHeight, 0); break;
        case 7: ctx.transform(0, -1, -1, 0, rawHeight, rawWidth); break;
        case 8: ctx.transform(0, -1, 1, 0, 0, rawWidth); break;
    }
    ctx.drawImage(img, 0, 0, rawWidth, rawHeight);
    return canvas;
}

function reduceFileSize(file, acceptFileSize, maxWidth, maxHeight, quality, callback) {
    if (file.size <= acceptFileSize) {
        callback(file);
        return;
    }
    var img = new Image();
    img.onerror = function() {
        URL.revokeObjectURL(this.src);
        callback(file);
    };
    img.onload = function() {
        URL.revokeObjectURL(this.src);
        getExifOrientation(file, function(orientation) {
            var w = img.width, h = img.height;
            var scale = (orientation > 4 ?
                Math.min(maxHeight / w, maxWidth / h, 1) :
                Math.min(maxWidth / w, maxHeight / h, 1));
            h = Math.round(h * scale);
            w = Math.round(w * scale);

            var canvas = imgToCanvasWithOrientation(img, w, h, orientation);
            canvas.toBlob(function(blob) {
                console.log("Resized image to " + w + "x" + h + ", " + (blob.size >> 10) + "kB");
                callback(blob);
            }, 'image/jpeg', quality);
        });
    };
    img.src = URL.createObjectURL(file);
}

사용 예시:

inputfile.onchange = function() {
    // If file size > 500kB, resize such that width <= 1000, quality = 0.9
    reduceFileSize(this.files[0], 500*1024, 1000, Infinity, 0.9, blob => {
        let body = new FormData();
        body.set('file', blob, blob.name || "file.jpg");
        fetch('/upload-image', {method: 'POST', body}).then(...);
    });
};

@Psycho Woods의 대답은 좋습니다.저만의 해결책을 제시하고 싶습니다.이 자바스크립트 기능은 이미지 데이터 URL과 너비를 가져와 새로운 너비로 축척하여 새로운 데이터 URL을 반환합니다.

// Take an image URL, downscale it to the given width, and return a new image URL.
function downscaleImage(dataUrl, newWidth, imageType, imageArguments) {
    "use strict";
    var image, oldWidth, oldHeight, newHeight, canvas, ctx, newDataUrl;

    // Provide default values
    imageType = imageType || "image/jpeg";
    imageArguments = imageArguments || 0.7;

    // Create a temporary image so that we can compute the height of the downscaled image.
    image = new Image();
    image.src = dataUrl;
    oldWidth = image.width;
    oldHeight = image.height;
    newHeight = Math.floor(oldHeight / oldWidth * newWidth)

    // Create a temporary canvas to draw the downscaled image on.
    canvas = document.createElement("canvas");
    canvas.width = newWidth;
    canvas.height = newHeight;

    // Draw the downscaled image on the canvas and return the new data URL.
    ctx = canvas.getContext("2d");
    ctx.drawImage(image, 0, 0, newWidth, newHeight);
    newDataUrl = canvas.toDataURL(imageType, imageArguments);
    return newDataUrl;
}

이 코드는 데이터 URL이 있고 축소된 이미지의 데이터 URL을 원하는 곳에서 사용할 수 있습니다.

이미지 변환, 여기서 해보세요 --> 데모 페이지

enter image description here

사용자 지정이 가능한 순수 JS 샘플을 사용해 보십시오. 90% 이상 압축:

   <div id="root">
        <p>Upload an image and see the result</p>
        <input id="img-input" type="file" accept="image/*" style="display:block" />
    </div>

    <script>
        const MAX_WIDTH = 320;
        const MAX_HEIGHT = 180;
        const MIME_TYPE = "image/jpeg";
        const QUALITY = 0.7;

        const input = document.getElementById("img-input");
        input.onchange = function (ev) {
            const file = ev.target.files[0]; // get the file
            const blobURL = URL.createObjectURL(file);
            const img = new Image();
            img.src = blobURL;
            img.onerror = function () {
                URL.revokeObjectURL(this.src);
                // Handle the failure properly
                console.log("Cannot load image");
            };
            img.onload = function () {
                URL.revokeObjectURL(this.src);
                const [newWidth, newHeight] = calculateSize(img, MAX_WIDTH, MAX_HEIGHT);
                const canvas = document.createElement("canvas");
                canvas.width = newWidth;
                canvas.height = newHeight;
                const ctx = canvas.getContext("2d");
                ctx.drawImage(img, 0, 0, newWidth, newHeight);
                canvas.toBlob(
                    (blob) => {
                        // Handle the compressed image. es. upload or save in local state
                        displayInfo('Original file', file);
                        displayInfo('Compressed file', blob);
                    },
                    MIME_TYPE,
                    QUALITY
                );
                document.getElementById("root").append(canvas);
            };
        };

        function calculateSize(img, maxWidth, maxHeight) {
            let width = img.width;
            let height = img.height;

            // calculate the width and height, constraining the proportions
            if (width > height) {
                if (width > maxWidth) {
                    height = Math.round((height * maxWidth) / width);
                    width = maxWidth;
                }
            } else {
                if (height > maxHeight) {
                    width = Math.round((width * maxHeight) / height);
                    height = maxHeight;
                }
            }
            return [width, height];
        }

        // Utility functions for demo purpose

        function displayInfo(label, file) {
            const p = document.createElement('p');
            p.innerText = `${label} - ${readableBytes(file.size)}`;
            document.getElementById('root').append(p);
        }

        function readableBytes(bytes) {
            const i = Math.floor(Math.log(bytes) / Math.log(1024)),
                sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

            return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i];
        }
    </script>

저는 수용된 답변에 비해 더 간단한 해결책이 있다고 생각합니다.

  • API와 HTML5 FileReader 을 읽습니다. 를..readAsArrayBuffer
  • 하고 하여 Blob URL 로 .window.URL.createObjectURL(blob)
  • 새 이미지 요소를 만들고 src를 파일 bloburl로 설정합니다.
  • 이미지를 캔버스로 보냅니다.캔버스 크기가 원하는 출력 크기로 설정됨
  • 캔버스에서 축소된 데이터 가져오기(출력 형식품질 설정)
  • 원본 양식에 숨겨진 새로운 입력 첨부 및 데이터 전송URI 이미지는 기본적으로 일반 텍스트입니다.
  • 백엔드로 데이터를 읽습니다.URI, Base64에서 디코딩한 저장

질문하신 내용은 다음과 같습니다.

업로드 전에 이미지(주로 jpeg, png, gif)를 브라우저 쪽으로 직접 압축하는 방법이 있습니까?

내 솔루션:

  1. 파일을 사용하여 blob을 직접 만듭니다.URL.createObjectURL(inputFileElement.files[0]).

  2. 승인된 답변과 같습니다.

  3. 승인된 답변과 같습니다.언급할 가치가 있습니다, 캔버스 사이즈는 필요하고 사용합니다.img.width그리고.img.height정하다canvas.width그리고.canvas.height.것은 아니다.img.clientWidth.

  4. 축소 이미지 가져오기:canvas.toBlob(callbackfunction(blob){}, 'image/jpeg', 0.5). 세팅'image/jpg'효과가 없습니다.image/png가 지원됩니다.새로 만들기File안에 있는 물체callbackfunction 몸을 맞대고let compressedImageBlob = new File([blob]).

  5. 숨겨진 입력을 새로 추가하거나 자바스크립트를 통해 전송합니다. 서버는 어떤 것도 해독할 필요가 없습니다.

모든 정보는 https://javascript.info/binary 에서 확인하세요.저는 이 장을 읽고 해결책을 생각해 냈습니다.


코드:

    <!DOCTYPE html>
    <html>
    <body>
    <form action="upload.php" method="post" enctype="multipart/form-data">
      Select image to upload:
      <input type="file" name="fileToUpload" id="fileToUpload" multiple>
      <input type="submit" value="Upload Image" name="submit">
    </form>
    </body>
    </html>

이 코드는 다른 답변들보다 훨씬 덜 무서워 보입니다.

업데이트:

사람은 모든 것을 넣어야 돼요.img.onload.그렇지않으면canvas이미지의 너비와 높이를 시간만큼 정확하게 얻을 수 없습니다.canvas가 할당됩니다.

    function upload(){
        var f = fileToUpload.files[0];
        var fileName = f.name.split('.')[0];
        var img = new Image();
        img.src = URL.createObjectURL(f);
        img.onload = function(){
            var canvas = document.createElement('canvas');
            canvas.width = img.width;
            canvas.height = img.height;
            var ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            canvas.toBlob(function(blob){
                    console.info(blob.size);
                    var f2 = new File([blob], fileName + ".jpeg");
                    var xhr = new XMLHttpRequest();
                    var form = new FormData();
                    form.append("fileToUpload", f2);
                    xhr.open("POST", "upload.php");
                    xhr.send(form);
            }, 'image/jpeg', 0.5);
        }
    }

3.4MB .png파일 압축 테스트:image/jpeg논법을 정했습니다.

    |0.9| 777KB |
    |0.8| 383KB |
    |0.7| 301KB |
    |0.6| 251KB |
    |0.5| 219kB |

문제가 있었습니다.downscaleImage()@daniel- allen- lang던이 위에 올린 함수는.image.width그리고.image.height이미지 로드가 비동기식이므로 속성을 즉시 사용할 수 없습니다.

아래의 업데이트된 TypeScript 예제를 참조하여 이를 고려하여 사용합니다.async기능하고 너비가 아닌 가장 긴 차원을 기준으로 이미지 크기를 조정합니다.

function getImage(dataUrl: string): Promise<HTMLImageElement> 
{
    return new Promise((resolve, reject) => {
        const image = new Image();
        image.src = dataUrl;
        image.onload = () => {
            resolve(image);
        };
        image.onerror = (el: any, err: ErrorEvent) => {
            reject(err.error);
        };
    });
}

export async function downscaleImage(
        dataUrl: string,  
        imageType: string,  // e.g. 'image/jpeg'
        resolution: number,  // max width/height in pixels
        quality: number   // e.g. 0.9 = 90% quality
    ): Promise<string> {

    // Create a temporary image so that we can compute the height of the image.
    const image = await getImage(dataUrl);
    const oldWidth = image.naturalWidth;
    const oldHeight = image.naturalHeight;
    console.log('dims', oldWidth, oldHeight);

    const longestDimension = oldWidth > oldHeight ? 'width' : 'height';
    const currentRes = longestDimension == 'width' ? oldWidth : oldHeight;
    console.log('longest dim', longestDimension, currentRes);

    if (currentRes > resolution) {
        console.log('need to resize...');

        // Calculate new dimensions
        const newSize = longestDimension == 'width'
            ? Math.floor(oldHeight / oldWidth * resolution)
            : Math.floor(oldWidth / oldHeight * resolution);
        const newWidth = longestDimension == 'width' ? resolution : newSize;
        const newHeight = longestDimension == 'height' ? resolution : newSize;
        console.log('new width / height', newWidth, newHeight);

        // Create a temporary canvas to draw the downscaled image on.
        const canvas = document.createElement('canvas');
        canvas.width = newWidth;
        canvas.height = newHeight;

        // Draw the downscaled image on the canvas and return the new data URL.
        const ctx = canvas.getContext('2d')!;
        ctx.drawImage(image, 0, 0, newWidth, newHeight);
        const newDataUrl = canvas.toDataURL(imageType, quality);
        return newDataUrl;
    }
    else {
        return dataUrl;
    }

}

Moderm 브라우저의 경우 다음 대신 사용합니다.img.onload

async function compressImage(blobImg, percent) {
  let bitmap = await createImageBitmap(blobImg);
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  canvas.width = bitmap.width;
  canvas.height = bitmap.height;
  ctx.drawImage(bitmap, 0, 0);
  let dataUrl = canvas.toDataURL("image/jpeg", percent/100);
  return dataUrl;
}

inputImg.addEventListener('change', async(e) => {
  let img = e.target.files[0];
  console.log('File Name: ', img.name)
  console.log('Original Size: ', img.size.toLocaleString())
  
  let imgCompressed = await compressImage(img, 75) // set to 75%
  let compSize = atob(imgCompressed.split(",")[1]).length;
  console.log('Compressed Size: ', compSize.toLocaleString())
  //console.log(imgCompressed)
})
<input type="file" id="inputImg">

편집: 이 답변에 대한 Mr Me 코멘트에 따르면 JPG/WebP 형식에 대해 압축이 가능한 것 같습니다(https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL 참조).

캔버스를 사용하여 이미지를 압축할 수 없고 크기를 조정할 수 있는 것으로 알고 있습니다.canvas.toData(데이터에 canvas.URL에서는 사용할 압축비를 선택할 수 없습니다.당신은 당신이 원하는 것을 정확히 해주는 캔 이미지를 볼 수 있습니다.

실제로 이미지 크기를 줄이기 위해 이미지 크기를 조정하는 것만으로도 충분한 경우가 많지만, 더 나아가려면 새로 도입된 메소드 파일을 사용해야 합니다.영상 데이터를 포함하는 버퍼를 가져오는 ArrayBuffer.

그런 다음 이미지 형식 사양(http://en.wikipedia.org/wiki/JPEG 또는 http://en.wikipedia.org/wiki/Portable_Network_Graphics) 에 따라 데이터 보기를 사용하여 내용을 읽습니다.

이미지 데이터 압축을 처리하는 것은 어렵겠지만, 더 나쁜 시도입니다.반면 PNG 헤더나 JPEG exif 데이터를 삭제하여 이미지를 더 작게 만들 수 있습니다.

다른 버퍼에 다른 DataWiew를 만들어 필터링된 이미지 내용으로 채워야 합니다.그러면 이미지 컨텐츠를 데이터로 인코딩하기만 하면 됩니다.window.btoa를 사용하는 URI.

만약 당신이 비슷한 것을 실행한다면, 코드를 통과하는 것이 흥미로울 것입니다.

Compressor.js

https://github.com/fengyuanchen/compressorjs

import axios from 'axios';
import Compressor from 'compressorjs';

document.getElementById('file').addEventListener('change', (e) => {
  const file = e.target.files[0];

  if (!file) {
    return;
  }

  new Compressor(file, {
    quality: 0.6,

    // The compression process is asynchronous,
    // which means you have to access the `result` in the `success` hook function.
    success(result) {
      const formData = new FormData();

      // The third parameter is required for server
      formData.append('file', result, result.name);

      // Send the compressed image file to server with XMLHttpRequest.
      axios.post('/path/to/upload', formData).then(() => {
        console.log('Upload success');
      });
    },
    error(err) {
      console.log(err.message);
    },
  });
});

저는 다음 패키지를 사용했습니다: https://www.npmjs.com/package/browser-image-compression

npm install browser-image-compression
or
yarn add browser-image-compression

그러면 문서를 따라가면 됩니다.

import imageCompression from 'browser-image-compression';
const options = {
 maxSizeMB: 0.5, // pretty much self-explanatory
 maxWidthOrHeight: 500, // apparently px
}

imageCompression(file, options)
            .then(function(compressedFile) {
                console.log(
                    "compressedFile instanceof Blob",
                    compressedFile instanceof Blob
                ); // true
                console.log(
                    `compressedFile size ${compressedFile.size /
                        1024 /
                        1024} MB`
                ); // smaller than maxSizeMB

                return uploader(compressedFile); // code to actual upload, in my case uploader() is a function to upload to Firebase storage.
            })

요.uploader(), 그것의 코드는 다음과 같습니다.

import { initializeApp } from "firebase/app";

const firebaseConfig = {
    // your config
};

initializeApp(firebaseConfig);
import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage";
const storage = getStorage();
const sRef = ref(storage);

const uploader = async (file) => {
        /* uploads to root */

        // const imageRef = ref(sRef, file.name);
        // console.log(imageRef);
        // await uploadBytes(imageRef, file).then((snapshot) => {
        //  console.log("Uploaded a blob or file!", snapshot);
        // });

        /* upload to folder 'techs/' */
        const folderRef = ref(sRef, "techs/" + file.name);
        await uploadBytes(folderRef, file);

        // get URL
        const url = await getDownloadURL(ref(storage, folderRef));

        console.log("url: ", url);
        return url;
    };

할 수 .<canvas>요소:

function compressImage(imgToCompress, resizingFactor, quality) {
  // resizing the image
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  
  const originalWidth = imgToCompress.width;
  const originalHeight = imgToCompress.height;
  
  const canvasWidth = originalWidth * resizingFactor;
  const canvasHeight = originalHeight * resizingFactor;
  
  canvas.width = canvasWidth;
  canvas.height = canvasHeight;
  
  context.drawImage(
    imgToCompress,
    0,
    0,
    originalWidth * resizingFactor,
    originalHeight * resizingFactor
  );
  
  // reducing the quality of the image
  canvas.toBlob(
    (blob) => {
      if (blob) {
        // showing the compressed image
        resizedImage.src = URL.createObjectURL(resizedImageBlob);
      }
    },
    "image/jpeg",
    quality
  );
}

자세한 설명은 이 블로그 게시물을 참고하세요: https://img.ly/blog/how-to-compress-an-image-before-uploading-it-in-javascript/

나는 이것이 되도록 기능을 개선했습니다.

var minifyImg = function(dataUrl,newWidth,imageType="image/jpeg",resolve,imageArguments=0.7){
    var image, oldWidth, oldHeight, newHeight, canvas, ctx, newDataUrl;
    (new Promise(function(resolve){
      image = new Image(); image.src = dataUrl;
      log(image);
      resolve('Done : ');
    })).then((d)=>{
      oldWidth = image.width; oldHeight = image.height;
      log([oldWidth,oldHeight]);
      newHeight = Math.floor(oldHeight / oldWidth * newWidth);
      log(d+' '+newHeight);

      canvas = document.createElement("canvas");
      canvas.width = newWidth; canvas.height = newHeight;
      log(canvas);
      ctx = canvas.getContext("2d");
      ctx.drawImage(image, 0, 0, newWidth, newHeight);
      //log(ctx);
      newDataUrl = canvas.toDataURL(imageType, imageArguments);
      resolve(newDataUrl);
    });
  };

그것의 용도:

minifyImg(<--DATAURL_HERE-->,<--new width-->,<--type like image/jpeg-->,(data)=>{
   console.log(data); // the new DATAURL
});

즐김 ;)

입력에서 이미지를 가져온 경우 base64 문자열이 필요한 경우 다음을 시도할 수 있습니다.

async function compressImage(input, maxWidth, maxHeight, quality) {
  const file = input.files[0];
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = event => {
      const img = new Image();
      img.src = event.target.result;
      img.onload = () => {
        let width = img.width;
        let height = img.height;

        if (width > height) {
          if (width > maxWidth) {
            height *= maxWidth / width;
            width = maxWidth;
          }
        } else {
          if (height > maxHeight) {
            width *= maxHeight / height;
            height = maxHeight;
          }
        }

        const canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, width, height);
        const base64String = canvas.toDataURL('image/jpeg', quality);
        resolve(base64String);
      };
    };
    reader.onerror = error => reject(error);
  });
}

JPG 이미지 압축은 JIC(Javascript Image Compression)라는 최고의 압축 기법을 사용할 수 있습니다.이것은 분명히 당신에게 도움이 될 것입니다 -->https://github.com/brunobar79/J-I-C

언급URL : https://stackoverflow.com/questions/14672746/how-to-compress-an-image-via-javascript-in-the-browser

반응형