Hướng dẫn javascript image resize library - thư viện thay đổi kích thước hình ảnh javascript

Bạn có biết là mình có thể resize ảnh ngay trên browser mà không cần dùng đến tool hay thư viện nào không .

.

Nội dung chính ShowShow

  • Dùng canvas
  • Dùng const img = new Image[]; img.onload = function[] { const canvas const canvas = newCanvas[width, height]; const ctx = canvas.getContext['2d']; ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450]; document.body.appendChild[canvas]; }; img.src = url; 7
  • Dùng const img = new Image[]; img.onload = function[] { const canvas const canvas = newCanvas[width, height]; const ctx = canvas.getContext['2d']; ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450]; document.body.appendChild[canvas]; }; img.src = url; 7

Dùng canvas

Dùng const img = new Image[]; img.onload = function[] { const canvas const canvas = newCanvas[width, height]; const ctx = canvas.getContext['2d']; ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450]; document.body.appendChild[canvas]; }; img.src = url; 7

Canvas API cho phép chúng ta vẽ đồ họa 2D theo ý muốn trên trình duyệt. Nghĩa là chúng ta hoàn toàn có thể vẽ lại một hình nào đó với kích thước mong muốn. Hay nói cách khác là resize đó . Chúng ta hãy cùng xem method dùng để vẽ lại một hình ảnh trên canvas drawImage.
const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
4 có thể có đến 9 parameter:

. Chúng ta hãy cùng xem method dùng để vẽ lại một hình ảnh trên canvas drawImage.

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
4 có thể có đến 9 parameter:
void ctx.drawImage[image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight];

  • Trong đó:
  • const img = new Image[];
    
    img.onload = function[] {
        const canvas
        const canvas = newCanvas[width, height];
    
        const ctx = canvas.getContext['2d'];
        ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
        document.body.appendChild[canvas];
    };
    
    img.src = url;
    
    6,
    const img = new Image[];
    
    img.onload = function[] {
        const canvas
        const canvas = newCanvas[width, height];
    
        const ctx = canvas.getContext['2d'];
        ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
        document.body.appendChild[canvas];
    };
    
    img.src = url;
    
    7: là vị trí trên cùng bên trái của ảnh gốc mà chúng ta muốn vẽ lại.
  • const img = new Image[];
    
    img.onload = function[] {
        const canvas
        const canvas = newCanvas[width, height];
    
        const ctx = canvas.getContext['2d'];
        ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
        document.body.appendChild[canvas];
    };
    
    img.src = url;
    
    8,
    const img = new Image[];
    
    img.onload = function[] {
        const canvas
        const canvas = newCanvas[width, height];
    
        const ctx = canvas.getContext['2d'];
        ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
        document.body.appendChild[canvas];
    };
    
    img.src = url;
    
    0: là kích thước hình ảnh chúng ta muốn vẽ lại từ ảnh gốc.
  • const img = new Image[];
    
    img.onload = function[] {
        const canvas
        const canvas = newCanvas[width, height];
    
        const ctx = canvas.getContext['2d'];
        ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
        document.body.appendChild[canvas];
    };
    
    img.src = url;
    
    1,
    const img = new Image[];
    
    img.onload = function[] {
        const canvas
        const canvas = newCanvas[width, height];
    
        const ctx = canvas.getContext['2d'];
        ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
        document.body.appendChild[canvas];
    };
    
    img.src = url;
    
    2: là vị trí trên canvas mà chúng ta muốn vẽ lại ảnh gốc.

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
3,
const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
4: là kích thước trên canvas mà chúng ta muốn vẽ lại ảnh gốc.

Vậy là chỉ cần set

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
3 và
const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
4 thành kích thước mà chúng ta muốn resize là sẽ resize được ảnh. Hãy làm thử xem nhé. Ví dụ mình có hình này.

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;

Kích thước ảnh gốc là 1207 x 1800. Giờ mình sẽ resize thành 301 x 450 nhé. Code của chúng ta như này:

Đây là kết quả nè.

Hmm, trông không ổn lắm nhỉ . Hình khá thiếu sắc nét so với ảnh gốc. Đó là do API này vốn không được thiết kế để resize ảnh với những thuật toán xịn như những tool chỉnh sửa ảnh hay thư viện phía server vì lý do performance. Vậy nên khi resize với kích thước khác biệt quá nhiều sẽ khiến cho hình ảnh bị răng cưa như vậy. Để hạn chế, chúng ta sẽ resize từ từ mỗi lần 1 tí để tránh kích thước mỗi lần resize cách nhau quá nhiều. Resize nhiều lần cũng có thể khiến chất lượng giảm đi, nhưng sẽ tránh được tình trạng răng cưa như trên. Mình sửa code 1 tí như này, mỗi lần sẽ resize còn 1 nửa, dần dần tới kích thước mình muốn.

. Hình khá thiếu sắc nét so với ảnh gốc. Đó là do API này vốn không được thiết kế để resize ảnh với những thuật toán xịn như những tool chỉnh sửa ảnh hay thư viện phía server vì lý do performance. Vậy nên khi resize với kích thước khác biệt quá nhiều sẽ khiến cho hình ảnh bị răng cưa như vậy. Để hạn chế, chúng ta sẽ resize từ từ mỗi lần 1 tí để tránh kích thước mỗi lần resize cách nhau quá nhiều. Resize nhiều lần cũng có thể khiến chất lượng giảm đi, nhưng sẽ tránh được tình trạng răng cưa như trên. Mình sửa code 1 tí như này, mỗi lần sẽ resize còn 1 nửa, dần dần tới kích thước mình muốn.

function resize[img, width, height, quality = null] {
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, width, height];

    return canvas;
}

const img = new Image[];

img.onload = function[] {
    let canvas = img;

    while [canvas.width * .5 > 301] {
        canvas = resize[canvas, canvas.width / 2, canvas.height / 2];
    }

    canvas = resize[canvas, 301, 450];
};

img.src = url;

Đây là kết quả:

.

Trông khá hơn nhiều nhỉ .

Cũng có 1 tính năng thử nghiệm hiện mới có trên Chrome có thể tùy chỉnh chất lượng resize là option imageSmoothingQuality của canvas context 2D. Mình thử dùng thì được kết quả ảnh như này:

.

Dùng const img = new Image[]; img.onload = function[] { const canvas const canvas = newCanvas[width, height]; const ctx = canvas.getContext['2d']; ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450]; document.body.appendChild[canvas]; }; img.src = url; 7

Canvas API cho phép chúng ta vẽ đồ họa 2D theo ý muốn trên trình duyệt. Nghĩa là chúng ta hoàn toàn có thể vẽ lại một hình nào đó với kích thước mong muốn. Hay nói cách khác là resize đó . Chúng ta hãy cùng xem method dùng để vẽ lại một hình ảnh trên canvas drawImage.

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
4 có thể có đến 9 parameter:

. Chúng ta hãy cùng xem method dùng để vẽ lại một hình ảnh trên canvas drawImage.
const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
4 có thể có đến 9 parameter:
void ctx.drawImage[image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight];

Trong đó:

Giờ chúng ta dùng thử xem sao, code như này:

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
4

Đây là kết quả:

Trông khá hơn nhiều nhỉ .

Cũng có 1 tính năng thử nghiệm hiện mới có trên Chrome có thể tùy chỉnh chất lượng resize là option imageSmoothingQuality của canvas context 2D. Mình thử dùng thì được kết quả ảnh như này:

Cũng không khác cái trên là mấy nhỉ, mình thấy cái trên còn đẹp hơn ấy .

Dùng const img = new Image[]; img.onload = function[] { const canvas const canvas = newCanvas[width, height]; const ctx = canvas.getContext['2d']; ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450]; document.body.appendChild[canvas]; }; img.src = url; 7

Vẫn là Canvas API nhưng lần này chúng ta có một method khác, vẫn là chỉ support trên chrome [Firefox có support nhưng lại là crop thay vì resize ]. createImageBitmap cho phép tạo

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
8 để lưu dữ liệu ảnh từ ảnh gốc [image hoặc canvas]. Trong quá trình tạo còn support tính năng resize nữa. Và đặc biệt là nó return một
const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
9 nên chúng ta không phải lo nó sẽ làm browser bị lag khi đang render. Resize 1 cái ảnh thì vẫn chưa thấy gì khác biệt, nhưng bạn sẽ thấy sự khác biệt ở đoạn sau khi chúng ta resize một lúc nhiều ảnh. Chắc cũng nhờ vậy nên nó cho phép sử dụng những thuật toán resize xịn hơn.

Giờ chúng ta dùng thử xem sao, code như này:

Đây là ảnh mình thử resize với một tool chỉnh sửa ảnh xịn để thấy chất lượng cũng không khác gì lắm.

.

Đây là code của tất cả các cách trên để bạn so sánh. Bạn mở full example lên so sánh cho dễ nhé. Kết quả có thể khác nhau tùy browser bạn dùng.

Link codepen: //codepen.io/thphuong/pen/qBOeMRb

, code tách file gif thành frame như này nhé.
const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
7

Resize GIF

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
8

Nếu bạn thử cách trên với ảnh GIF sẽ thấy không được. Ví dụ mình resize hình này

Sẽ chỉ được mỗi frame đấu tiên.

Có thể bạn đã biết rồi là ảnh gif được tạo thành từ các frame. Hôm trước mình cũng mới viết một bài tạo ảnh gif ở đây. Vậy nếu chúng ta có thể từ ảnh gif tách ra thành từng frame, rồi resize mỗi frame, sao đó ghép lại như cũ là có ảnh gif đã được resize rồi .

Mình sẽ dùng gif-frames đế tách gif thành cách frame và gif.js để ghép các frame lại thành gif.

Vậy giờ chúng ta có 2 lựa chọn. Tô màu background để không có đoạn viền trong suốt nữa như mình làm bài trước :p. Hoặc là chúng ta fix bằng cách sửa lại những pixel có alpha channel thành không trong suốt đúng theo yêu cầu của gif.

Để sửa data của ảnh vẽ trong canvas, chúng ta dùng

function resize[img, width, height, quality = null] {
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, width, height];

    return canvas;
}

const img = new Image[];

img.onload = function[] {
    let canvas = img;

    while [canvas.width * .5 > 301] {
        canvas = resize[canvas, canvas.width / 2, canvas.height / 2];
    }

    canvas = resize[canvas, 301, 450];
};

img.src = url;
5. Image data sẽ là 1 array các số nguyên 8 bit [0-255]. Mỗi 4 số sẽ là 1 pixel, thể hiện 4 giá trị trong
function resize[img, width, height, quality = null] {
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, width, height];

    return canvas;
}

const img = new Image[];

img.onload = function[] {
    let canvas = img;

    while [canvas.width * .5 > 301] {
        canvas = resize[canvas, canvas.width / 2, canvas.height / 2];
    }

    canvas = resize[canvas, 301, 450];
};

img.src = url;
6. Vậy giờ mình loop trong đống array pixel đấy và thấy cái nào có màu mà giá trị a nhỏ hơn 255 thì sẽ set lại thành 255. Ngoài ra những pixel mà có alpha channel quá nhỏ [< 127] thì mình cũng set = 0 luôn để hình đỡ bị răng cưa. Code tí nữa bạn xem function
function resize[img, width, height, quality = null] {
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, width, height];

    return canvas;
}

const img = new Image[];

img.onload = function[] {
    let canvas = img;

    while [canvas.width * .5 > 301] {
        canvas = resize[canvas, canvas.width / 2, canvas.height / 2];
    }

    canvas = resize[canvas, 301, 450];
};

img.src = url;
7 trong demo nhé.

Kết quả ngon hơn nhiều rồi. So với resize bằng thư viện xịn như Imagemagick thì mình thấy cũng không kém đâu .

.

Đây là code của tất cả các cách trên để bạn so sánh. Bạn mở full example lên so sánh cho dễ nhé. Kết quả có thể khác nhau tùy browser bạn dùng.

Link codepen: //codepen.io/thphuong/pen/qBOeMRb

, code tách file gif thành frame như này nhé.

const img = new Image[];

img.onload = function[] {
    const canvas
    const canvas = newCanvas[width, height];

    const ctx = canvas.getContext['2d'];
    ctx.drawImage[img, 0, 0, img.width, img.height, 0, 0, 301, 450];
    document.body.appendChild[canvas];
};

img.src = url;
7

Resize GIF

Nếu bạn thử cách trên với ảnh GIF sẽ thấy không được. Ví dụ mình resize hình này

Bài Viết Liên Quan

Chủ Đề