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