Изменение размера изображений в JS БЫСТРО! (Используя многопоточность браузера)

Сегодня мы погрузимся в offscreen canvas с небольшими знаниями о canvas, которые вы должны иметь, так что, пожалуйста, проверьте другие ресурсы, если это необходимо, и посмотрите, как мы играем между blob, image_data (canvas), Bitmap Image и data-url (base64), мы можем рендерить JS IMAGE FILTERS (https://dev.to/vipertechofficial/22-javascript-canvas-filters-just-like-instagram-smarthack-55b) вне основного потока, используя это, и это работает отлично! Также просто проверьте код, он не такой длинный и хорошо прокомментирован, обратите внимание, что проект, который я собрал (https://pixa.pics/) использует https://www.npmjs.com/package/workerpool, чтобы все эти вещи распространялись на рабочих…

1) Мы создаем растровое изображение, которое будет перенесено на наш холст, созданный для растровых изображений.
2) Мы конвертируем растровое изображение в формат файла, который мы выбираем при создании blob-файла (файлоподобного объекта)
3) Мы конвертируем этот файлоподобный объект в dataurl, который представляет собой изображение в кодировке base64 (data:image/png;base64,… и некоторые base64).
ЭТО МАГИЯ

// CONST:
// imgd_data (you get img_data using a canvas, please get familiar with canvas)
// no_transparent (Boolean to know which file format to use)
// pxl_width (Simply width of the image)
// pxl_height (Simply height of the image)
// resize_width (Which size of width will it get at the end?)

try { // Can work in Web Worker so you can run it on a CPU thread different from the main one which doesn't freeze the UI

    var imgd = null;
    // imgd = new ImageData(pxl_width, pxl_height);
    // imgd.data = imgd_data;

    var canvas = new OffscreenCanvas(pxl_width, pxl_height);
    var ctx = canvas.getContext('2d');
    imgd = ctx.getImageData(0, 0, pxl_width, pxl_height);


    var resize_ratio = resize_width / pxl_width;
    var resizeWidth = parseInt(pxl_width * resize_ratio);
    var resizeHeight = parseInt(pxl_height * resize_ratio);

    var canvas2 = new OffscreenCanvas(resizeWidth, resizeHeight);
    var ctx2 = canvas2.getContext("bitmaprenderer"); // "bitmaprenderer" context is available in web worker which isn't true for "2d" context

    // Of course with a bitmaprenderer context we may need to create a bitmap image, this is how we do :
    // 1) We create a Bitmap Image which will be transferred onto our canvas made for bitmap images
    // 2) We convert the raster image into a file format we choose when we create a blob file (a file-like object)
    // 3) We convert that file-like object into a dataurl which is base64 encoded image (data:image/png;base64,...and some base64)
    // THIS IS MAGIC
    return createImageBitmap(imgd, {
        premultiplyAlpha: 'none',
        colorSpaceConversion: 'none',
        resizeWidth: resizeWidth,
        resizeHeight: resizeHeight,
        resizeQuality: "pixelated", // One of pixelated, low (default), medium, or high
    }).then((btmp_i) => {

        // And at once, we resized it before transfering it now onto the canvas context responsible for exporting it
        ctx2.transferFromImageBitmap(btmp_i);

        var blob_params = no_transparent ? {type: "image/jpeg", quality: 0.3}: {type: "image/png"}; // We can also export the image in webp format but just wrap it into a try catch because it isn't supported everywhere

        // We call the canvas of our second context (canvas2) and ask the browser to create a blob (which is a file-like object of immutable, raw data)
        return ctx2.canvas.convertToBlob(blob_params).then((blob) => {

            // With it, we read the blob file as a data url you know (data:image/png;base64,...and some base64)
            function blob_to_base64(blob) { 
              return new Promise((resolve, _) => { 
                var reader = new FileReader();
                reader.onloadend = () => resolve(reader.result);
                reader.readAsDataURL(blob);
              })
            }

            return blob_to_base64(blob).then((data_url) => { // This we get a promise so we can call ".then()" to this function

                 return data_url;
            });
        });
    });

}catch(e) { // Hopefully if OffscreenCanvas or such isn't supported we can use the classical method but it won't work in Web Worker my friend

    var canvas = document.createElement("canvas");
    canvas.width = pxl_width;
    canvas.height = pxl_height;
    var ctx = canvas.getContext('2d');

    var imgd = null;
    // imgd = new ImageData(pxl_width, pxl_height);
    // imgd.data = imgd_data;
    // ctx.putImageData(image_data, 0, 0);

    var resize_ratio = resize_width / pxl_width;
    var resizeWidth = parseInt(pxl_width * resize_ratio);
    var resizeHeight = parseInt(pxl_height * resize_ratio);

    // THIS IS NOT MAGIC, we just draw an image on our simple secondary canvas (but again it doesn't work off the main thread since it can't work in Web Worker)
    var canvas2 = document.createElement("canvas");
    canvas2.width = resizeWidth;
    canvas2.height = resizeHeight;
    var ctx2 = canvas2.getContext("2d");
    ctx2.drawImage(canvas, 0, 0, resizeWidth, resizeHeight);

    if(no_transparent){

        return canvas2.toDataURL("image/jpeg", 0.3); 
    }else {

        return canvas2.toDataURL("image/png");
    }

    // We can also export the image in webp format but just wrap it into a try catch because it isn't supported everywhere
}

// USEFULL TIPS: Use https://www.npmjs.com/package/workerpool combined with THIS ENSOULEMENT:
new Function(`return async function(param1, param2){}`)()(param1, param2)
Вход в полноэкранный режим Выход из полноэкранного режима

Оцените статью
Procodings.ru
Добавить комментарий