Почему мой алгоритм Scaling-Pixelated(без интерполяции / сглаживания) работает медленно? Оптимизация?

Я решил серьезно отнестись к веб-дизайну, уделяя основное внимание клиентской части. Я работал над некоторыми дизайнами, включающими изображения с низким разрешением и масштабирование, чтобы получить пиксельный вид. Проблема в том, что я продолжаю сталкиваться с переменным качеством при тестировании в разных браузерах и на разных машинах. До сих пор я обнаружил 2 довольно простых способа (см. Ниже), чтобы получить пиксельный результат, который работает 90% времени: один путем изменения свойств CSS, а другой путем изменения переменных контекста холста в js. Оба этих решения обеспечивают четкую пикселизацию в последних версиях Firefox, Chrome, Safari, Opera и Vivaldi; хотя при тестировании на моем старом компьютере у меня были разные уровни размытия, тестирование в разных браузерах. После дальнейшего поиска я нашел третье решение (см. Ниже), включающее вызов ImageData() для контекста холста, применение этих данных к новому изображению, а затем рисование этого изображения на холсте и изменение масштаба. Это решение делает все возможное для создания четкого изображения во всех моих тестах. Проблема в том, что мой алгоритм работает примерно в 100 раз медленнее, чем первые 2 решения. Эта доля секунды едва заметна, хотя я вижу, что это может вызвать проблемы при разработке адаптивного веб-приложения. Есть ли способ сделать мой алгоритм быстрее? Или стоит отказаться от поддержки старых машин и альтернативных браузеров?

  1. CSS решение

    <html>
        <head>
            <title>css image-rendering...</title>
            <style>
                #myimg {
                    image-rendering: optimizeSpeed;             /* STOP SMOOTHING, GIVE ME SPEED  */
                    image-rendering: -moz-crisp-edges;          /* Firefox                        */
                    image-rendering: -o-crisp-edges;            /* Opera                          */
                    image-rendering: -webkit-optimize-contrast; /* Chrome (and eventually Safari) */
                    image-rendering: pixelated;                 /* Chrome */
                    image-rendering: optimize-contrast;         /* CSS3 Proposed                  */
                    -ms-interpolation-mode: nearest-neighbor;   /* IE8+                           */
                }
            </style>
        </head>
        <body>
            <img id="myimg"/>
        </body>
        <script>
            var imgin = new Image();
            imgin.src = "./bill64.png";
            var imgframe = document.getElementById("myimg");
            imgin.onload = function(){
                var magnfctn = 16; //magnify by this
                imgframe.width = imgin.width*magnfctn;
                imgframe.height = imgin.height*magnfctn;
                imgframe.src = "./bill64.png";
            }
        </script>
    </html>
    

  1. ImageSmoothingEnabled= ложь

    <html>
        <head>
            <title>ImageSmoothingEnabled=false</title>
        </head>
        <body>
            <canvas width="256" height="256" id="myCanvas"></canvas>
        </body>
        <script>
            var c = document.getElementById("myCanvas");
            var ctx = c.getContext("2d");
            var imgin = new Image();
            imgin.src = "./pig64.png";
            imgin.onload = function(){//**Edit: Thanks Kaiido, performance slightly improved**
                var magnfctn = 16; //magnify by this
                //ctx.drawImage(imgin, 0, 0);
                //var imgData = ctx.getImageData(0, 0, imgin.width, imgin.height);
                c.width = imgin.width*magnfctn;
                c.height = imgin.height*magnfctn;
                ctx.msImageSmoothingEnabled = false;
                ctx.mozImageSmoothingEnabled = false;
                ctx.webkitImageSmoothingEnabled = false;
                ctx.imageSmoothingEnabled = false;
                ctx.scale(magnfctn,magnfctn);
                //ctx.putImageData(imgData, 0, 0);
                ctx.drawImage(imgin, 0, 0);
            }
        </script>
    </html>
    

  1. Пользовательский JavaScript

    <html>
        <head>
            <title>No Interpol...</title>
        </head>
        <body>
            <canvas width="256" height="256" id="myCanvas"></canvas>
        </body>
        <script>
            var c = document.getElementById("myCanvas");
            var ctx = c.getContext("2d");
            var imgin = new Image();
            imgin.src = "./macaque64.png";
            imgin.onload = function(){
                var magnfctn = 16; //magnify by this
                ctx.drawImage(imgin, 0, 0);
                var imgData = ctx.getImageData(0, 0, imgin.width, imgin.height);
                var largeData = ctx.createImageData(imgin.width*magnfctn, imgin.height*magnfctn);
                for (var i=0;i<imgData.data.length;i+=4) {
                    for(var x=0;x<magnfctn;x++){
                        for(var y=0;y<magnfctn;y++){
                            largeData.data[magnfctn*i+4*x +
                                           magnfctn*imgin.width*4*y +
                                           4*imgin.width*magnfctn*(magnfctn-1)*Math.floor(i/4/imgin.width)] =
                                           imgData.data[i];//red
                            largeData.data[magnfctn*i+4*x +
                                           magnfctn*imgin.width*4*y +
                                           1+4*imgin.width*magnfctn*(magnfctn-1)*Math.floor(i/4/imgin.width)] =
                                           imgData.data[i+1];//green
                            largeData.data[magnfctn*i+4*x +
                                           magnfctn*imgin.width*4*y +
                                           2+4*imgin.width*magnfctn*(magnfctn-1)*Math.floor(i/4/imgin.width)] =
                                           imgData.data[i+2];//blue
                            largeData.data[magnfctn*i+4*x +
                                           magnfctn*imgin.width*4*y +
                                           3+4*imgin.width*magnfctn*(magnfctn-1)*Math.floor(i/4/imgin.width)] =
                                           imgData.data[i+3];//alpha
                        }
                    }
                }
                c.width = imgin.width*magnfctn;
                c.height = imgin.height*magnfctn;
                ctx.putImageData(largeData, 0, 0);
            }
        </script>
    </html>
    

Примечание(проблема с несколькими источниками): некоторые браузеры требуют отключения безопасности для обработки локальных файлов.

FireFox: работает по умолчанию

Safari: сначала вам нужно включить меню разработки. Щелкните меню "Разработка". Выберите "Отключить локальные ограничения для файлов".

Chrome: терминал: "open -a" Google Chrome "--args --allow-file-access-from-files"

Opera: терминал: "open -a Opera --args --allow-file-access-from-files"

Vivaldi: терминал: "open -a Vivaldi --args - доступ к файлам из файлов"

0 ответов

Другие вопросы по тегам