Знакомьтесь, это Маня. Маню поразил страшный недуг и теперь она нуждается в вашей помощи. Маня росла обычной девочкой, жизнерадостным счастливым ребенком. Но чуть больше года назад врачи поставили ей страшный диагноз — алиазинг. И она стала выглядеть вот так.
Как выяснилось, виной тому стала жадность и алчность производителей браузеров, которые решили сэкономить на алгоритмах ресайза изображений и применить самые низкокачественные фильтры. Тогда Маню удалось спасти — она прошла курс последовательных не кратных двум уменьшений, что снизило алиазинг и вернуло её былую резкость. Но теперь ей снова угрожает опасность.
Что изменилось за этот год? Хорошие новости в том, что появился стандарт, призванный управлять качеством растеризации изображений на канвасе. Новости еще лучше: этот стандарт реализован в браузере: мобильном Сафари с версии 9.3 и десктопном с версии 9.1. И судя по получающимся результатам, значению high
соответствует метод сверток с бикубическим или очень похожим фильтром. Т.е. результат действительно очень хорош. Казалось бы, можно обернуть код, вымученный в предыдущей статье, в if ('imageSmoothingQuality' in context)
и ждать появления этого же свойства в остальных браузерах. Но что-то пошло не так.
Что-то пошло не так и на Маню напала другая напасть — Маня стала мыльной. Оказалось, что Гугл тоже готовит для Машеньки сюрприз, реализовав нужное свойство и пока что спрятав его за флагом chrome://flags/#enable-experimental-canvas-features
. Вот только реализовано оно не добросовестно, а чем попало. Вместо правильных, четких, православных сверток, в нем для значения high
используется техника, применяющаяся в играх: с помощью суперсэмплинга для изображения создаются mip-уровни, а потом ближайший по размеру уровень ресайзится все тем же дешевым методом с фиксированным количеством исходных точек.
Почему этот метод работает в играх? По двум причинам. Первая: в динамичной игре у вас нет времени рассматривать каждую текстуру по-отдельности, мыльная она или не очень. Гораздо больше на восприятие влияет общая картинка и спецэффекты, чем такие мелочи. Вторая: очень жесткие временные ограничения, для которых очень кстати приходится постоянная сложность этого метода относительно размеров конечного изображения (разрешения экрана в случае игр).
Почему этот метод не годится для ресайза в приложениях для работы с графикой? Да потому что это вообще не метод ресайза, алло. Это аппликация из двух решений, ни одно из которых не способно удовлетворить требования к качеству — а уж вдвоем и подавно. Оно не обладает ни математическим обоснованием, ни стабильностью результата относительно входных параметров. Например, картинка, отресайженая до 244 пикселей в ширину может получиться ничего так, а отресайженая до 243 вся будет в мыле. Тем более это не приемлемо для специально созданного по этому случаю свойства imageSmoothingQuality
. Уж если я ставлю high
, то наверное я имею в виду, что мне нужно именно хорошее качество. Зачем вообще реализовывать новое свойство, если оно дает результат хуже, чем можно добиться, повозившись с существующим решением? Вот, например, справа Маня отресайженая последовательными не кратными двум уменьшениями. Абсолютно здоровый и счастливый ребенок.
Если вы вдруг не испытываете сочувствия и симпатии к маленьким детям, то вот вам Манечкин друг, мандрил Пупуся. Его постигла та же беда. Слева направо:
- заблюреная картинка после ресайза в Хроме с
imageSmoothingQuality = 'high'
- качественная картинки из Сафари
- более-менее качественная картинка после ресайза в Хроме методом последовательных уменьшений без
imageSmoothingQuality
Как тут можно помочь? Ну например, пойти поставить звездочку в созданном для этого баг-репорте. Не уверен, насколько это эффективно, но ничего другого придумать не могу.
Что же будет, если эта фича перекочует в стабильную версию Хрома? Вместо простой проверки на наличие фичи, придется либо городить проверку по юзер-агенту, либо отключать эту функциональность для всех пользователей, даже в Сафари. В голову пришла правильная идея: нужно пойти и прямо сейчас поставить дополнительную проверку на то, что в юзерагенте нет слова Хром. Если Хром исправится и в стабильной версии не будет этого позорища, можно будет включить. Зато если кто-то из клиентов скачает код сейчас, при выходе бажного Хрома Маня не пострадает.
Для получения использовались изображения раз и два, тестовый стенд, а также виджет для последовательных уменьшений.
Комментарии (80)
ChALkeRx
08.06.2016 18:43У вас на тестовом стенде
<img>
ровно в два раза меньше<canvas>
-а. Наверное, из-за HiDPI.homm
08.06.2016 18:45После того как подвинете рычажок, всё должно стать одинаково.
ChALkeRx
08.06.2016 19:01До того, как я подвинул рычажок — там вообще ничего не рисуется.
После того, как подвинул — нижняя картинка из четырёх ровно в два раза меньше остальных трёх.
Причём это ещё и не зависит от масштаба.
Wesha
08.06.2016 19:19-36Сдаётся мне, homm только что напостил себе 10 лет без права УДО...
Вы уж выбирайте там тестовые изображения поаккуратнее, а?
VoidEx
09.06.2016 00:30+12«Доктор, а откуда у вас такие картинки?»
Alexufo
09.06.2016 01:43-4первый комментарий который пытается возразить не молча. Вы про то что человек проецирует чтоли?
VoidEx
09.06.2016 01:47+5Просто напомнило анекдот, так как не вижу на фотографии в посте «несовершеннолетнего, совершающего либо имитирующего половое сношение или иные действия сексуального характера» или что-то ещё из списка по приведённой ссылке (в том числе хентай).
Wesha
09.06.2016 02:40-15Я к тому, что
Дайте мне всего шесть строк, написанных рукой самого честного человека, и я найду, за что его можно повесить.
Картиночка есть? Есть. Юная девочка на ней есть? Есть. Осталась самая мелочь — правильные™ эксперты, которые найдут в картинке всё, что требуется. Пример их работы уже имеется.
— Арман Жан дю Плесси Ришелье.
VoidEx
09.06.2016 02:48+6Вы всерьёз полагаете, что за картинку в посте автора могут привлечь? Сколько на это поставите и с каким коэффициентом?
Если же невсерьёз, а лишь как повод пообсуждать, то, может, сам закон стоит обсуждать в более уместных постах?
Wesha
09.06.2016 00:34-25Чегой-то я не понимаю в этом мире: закон предложила Мизулина, а минусА — мне… =o.O=
burjui
09.06.2016 11:55+8Потому что бред несёте. На картинке — одетая счастливая девочка, это разрешено законом. А мизулопетросянство к этому посту не имеет вообще никакого отношения.
gogolinsky
08.06.2016 19:24-8Ну не, нельзя в таком контексте про детей писать: "«Это Маня», «Врачи поставили диагноз». Плохая шутка
dmitrmax
08.06.2016 19:54+11Предполагаете, что возможен сглаз?
ExplosiveZ
08.06.2016 21:58+8<сарказм> Это сотрудник полиции мыслей. Людей уже набрали, скоро законопроект о такой полиции введут. </сарказм>
Alexufo
08.06.2016 22:03-3предполагаем, что в глазах людей знакомых с этой болью выглядит как издевка.
burjui
09.06.2016 11:58+4Вы так шутите или в самом деле подумали, будто существует болезнь "алиасинг" ("лесенка")? Иногда поражаюсь уровню дискуссии на Хабре. Такое ощущение, что половина комментирующих даже не читают пост.
Alexufo
09.06.2016 12:24-3Про алиасинг я на втором курсе выбрал себе тему для пересказа для английского в 5000 знаков. Сама формулировка поста высмеивает спам письма с поиском денег для неизлечимо больных детей.
Что говорит об отсутствии какого либо участия или ознакомления с этой бедой или наличии знакомых, собирающих деньги для своего ребенка, а то и знакомых потерявших ребенка в моем случае. Если никогда зуб не болел, сочувствовать человеку с зубной болью сложно. Тем более понять что тут может обидеть. Обратите внимание, нет ни одного комментария раскрывающего противоположное мнение кроме вашего. Есть молчаливое несогласие, отсутствие диалога. Так что спасибо. Раз уж спросили может кто и задумается плевать ли ему на то что его слова могут значить что-то большее, чем он ожидает или нет. Возможно это только мои проблемы.
Статья хорошая, только ресайз на стороне клиента давно для себя закрыл. Кому нужен ресайз на клиенте если изображения сейчас на входе минимум от 5 MP закинутых пачкой вешают на долго браузер среднего компа.dmitrmax
09.06.2016 12:27+1> Кому нужен ресайз на клиенте
Очевидно тому, кто делает client-side облачный редактор картинок, например.Alexufo
09.06.2016 12:41-1Как и очевидно, что это решение не рабочее.
Я игрался этими экспериментальными свойствами интерполяции при ресайзе img и при transform: rotate(). Результат пляшет от версии к версии от браузера к браузеру. Сегодня нормально, завтра мыло и т.пdmitrmax
09.06.2016 12:48+1Вы должны ещё помнить (если ваш ДР в профиле правильный), что во времена IE 3.0 существующий вэб был вообще невозможен. Так что речь скорее не о том, возможно ли это right now. А на ближайшую перспективу. В конце концов технологии развиваются потому что на них есть спрос, а не потому что кто-то придумывает никому ненужную технологию, а потом начинается придумка мест, куда бы её впендюрить.
mark_slepkov
09.06.2016 13:52Вангую для таких целей либу на JS, которая будет реализовывать нужный алгоритм ресайза, беря за исходные данные значения пикселей и не будет полагаться на встроенные алгоритмы. Но да, ресурсов это все равно будет кушать немало.
homm
09.06.2016 13:53Разработчики браузеров уже постарались, чтобы этот вариант был практически невозможен.
mark_slepkov
09.06.2016 14:26Я так сильно с этим не сталкивался, но что мешает сначала отобразить img в canvas в пропорции 1:1 (на этом этапе потери качества быть не должно), а затем применить нужный нам алгоритм ресайза оперируя только лишь значениями пикселей? по вашей же ссылке сходу пытаются ресайзить. лично я не замечал, чтобы при отображении 1:1 браузер косячил (хотя может быть я просто не работал с большими и качественными изображениями)
UPD: прочитал внимательнее, понял. спасибо.
lorc
08.06.2016 19:40+5Хм, а что насчет энергоэфективности? Картинки не только на десктопах смотрят. Я не хотел бы, что бы мой телефон жрал батарейку только потому что горе-дизайнер решил поставит везде high вместо того что бы отресайзить картинки на сервере.
lorc
08.06.2016 19:53Интересно, что я не так сказал? Мипмапы прекрасно ложатся на GPU, соотвественно, композицию можно делать прямо там, не напрягая лишний раз CPU. Меньше напрягаем CPU -> дольше живет батарейка. Всё логично, как мне кажется.
mayorovp
08.06.2016 20:03+2GPU — тоже тот еще энергожрун. Лучше всего ресайзить картинки во время билда :) Жаль, не всегда возможно.
Но, вообще говоря, пока картинка одна — то в плане энергоэфективности получается экономия на спичках.
lorc
08.06.2016 20:12+2Ну дело в том, что GPU на таких задачах жрет меньше энергии, чем CPU. Косвенным подверждением тому явяется например тот факт, что libskia в Андроиде сейчас используется как последняя мера, когда с композицией не справляется ни аппаратный композитор (где он есть), ни GPU. И это при том что libskia по максимуму оптимизированна под различные варианты ARM'ов и x86-тых. Всю работу с графикой пытаются вынести на GPU, и поверьте — это не от хорошей жизни.
homm
08.06.2016 20:10+3Ну представьте, что разработчики Хрома бы реализовали скругленые уголки аппроксимацией из трех отрезков, потому что так на железо оучше ложится, и сказали бы, что фичу поддерживают. Тут то же самое.
К тому же для картинок же как-то все используют более качественный ресемплинг и никто не поднимает вопроса об энергоэффективности, а картинки явно чаще встречаются чем канвас, да еще и не всегда требуют особого качества. А тут специальное апи специально для этого, для тех, кто специально хочет получить хорошее качество и такая лажа. Батарейка пользователя будет страдать больше, если вместо хорошего ресайза на клиенте придется слать огромные фотографии на сервер целиком.
dmitrmax
08.06.2016 20:15+1Да тут разрабы Хрома отрезали серпом одно место, что HTTP/2 перестал много где работать, который они же и рожали (через SPDY). А вы тут про картинки ))))
mychaelo
09.06.2016 14:04+2Ну представьте, что разработчики Хрома бы реализовали скругленые уголки аппроксимацией из трех отрезков, потому что так на железо оучше ложится, и сказали бы, что фичу поддерживают. Тут то же самое.
Забавно, что вы вспомнили об этом, т. к. Хром до сих пор не научился правильно рисовать border, отличный от solid. См. https://www.impressivewebs.com/comparison-css-border-style/
dmitrmax
08.06.2016 19:57Я думаю, что авторы браузера для мобильного устройства вплоне понимают такие аспекты и могут игнорировать волю, как вы выразились, горе-дизайнера. Впрочем я не совсем уверен, что ресайз картинок на сервере, это вообще удел дизайнера, ровно как и в необходимости делать это, когда речь идет об использовании канваса.
korzunin
08.06.2016 20:01+2Это как запретить делать острые ножи, а то вдруг какой-то горе повар кого-то зарезать решит.
Ресайз может быть нужен не только для отображения картинки с сервера, но и например для отображения миниатюр фоточек перед загрузкой на сервер. Да много чего придумать можно.
artyfarty
08.06.2016 20:03+1Насколько я понял – речь о canvas, а не об обычных картинках в DOM. А канвас в нос на мобильниках вроде и так пока не тычут везде.
artyfarty
08.06.2016 19:58+5Вам стоило бы уточнить в начале статьи, что речь идет о canvas, а то у меня поначалу начала подступать паника, что это происходит в обычных img или css background.
homm
08.06.2016 20:02+1В том-то и дело, что если бы это происходило в картинках, было бы пофиг. Если пользователю не нравится, как выглядит img в браузере, можно взять другой браузер. А вот результат работы канваса потом и на сервер может попасть, а оттуда уже будут страдать глаза всех, кто его увидит.
PaulZi
09.06.2016 10:08Для обычных картинок и background тоже проблема есть в хроме — ужасно мылит, но помогает:
image-rendering: -webkit-optimize-contrast;
serg199627
08.06.2016 20:02-22Мне кажется не есть хорошо сравнивать якобы болезнь с ребенком, когда в стране итак не мало реально больных детей
dmitrmax
08.06.2016 20:09+33Автор, если бы вместо Мани вы использовали Лену, то претензий от моралистов было бы меньше, а ваша статья выглядела бы более «весомо» что ли в глазах знатоков. Но это не критика, а так — мысль вслух )
Halt
09.06.2016 08:06+7Есть еще каноничный шакал, как эталон оценки качества сжатия изображения. Он стерпит все.
PavelMSTU
09.06.2016 09:04+1если бы вместо Мани вы использовали Лену, то претензий от моралистов было бы меньше
Я так не думаю… Вот оригинал из Playpoy.
P.S. Правда модель уже совершеннолетняя и в настоящее время ей уже 65…dmitrmax
09.06.2016 12:24+7Дружище, не передергивай факты. Леной называется кусок оригинала из постера размером 512x512 пикселей, не содержащий никаких непристойностей. Так что моралисты идут лесом.
PavelMSTU
09.06.2016 13:56-3Виноват, забыл добавить <ирония>… </ирония>
;))
занудствоЛеной называется кусок оригинала из постера размером 512x512 пикселей, не содержащий никаких непристойностей.
В том то и дело, что оригинал как раз таки и содержит!
Я же дал ссылку ранее: http://fatcats.ru/uploads/posts/2014-02/1391417934_1972_11_lenna_sjooblom_playboy_centerfold.jpgdmitrmax
09.06.2016 14:32+4Не содежащий по правилам русского языка относится к слову кусок, а не к слову оригинала.
sergehog
09.06.2016 10:55+1Не кроется ли здесь проблема в том что браузер — неподходящий инструмент для таких операций? Если редактируете и грузите фотки с мобильных устройств — нужно делать мобильные аппликухи, которые все сделают правильно и как надо. HTML+JS как бэ не для этого был создан.
Потом опять же, надо определиться что важнее — качество картинок или экономия трафика. Если качество картинок важнее то пусть уж сервер ресайзит.Alexufo
09.06.2016 12:43Это очевидно. Если важнее экономия трафика, то пилится приложение. Браузеры трафик слабо экономят. А при зоопарке браузеров ожидать одинакового результата…
REPISOT
09.06.2016 13:55-4Чем «алиазинг» отличается от «элайзинга»?
1. Искажения, связанные с дискретизацией исходного аналогового сигнала во времени. В результате этого в спектре дискретизированного во времени сигнала появляются дополнительные спектральные составляющие. Следствием этого может быть появление «Эффекта наложения частот» или элайзинга (aliasing) при дискретизации сигнала с достаточно широким частотным спектром.
www.google.ru/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwj6_f3G45rNAhWKlCwKHTwRDdcQFggbMAA&url=http%3A%2F%2Fwww.autex.spb.su%2Fcgi-bin%2Fdownload.cgi%3Fdspa2007_1_18&usg=AFQjCNEpbyYhPrzvFmzWzGU5VoV2sBmECQ&bvm=bv.124088155,d.bGg&cad=rja
REPISOT
09.06.2016 13:59Ссылка почему-то подсвечивается не вся.
0x9d8e
09.06.2016 17:06С определением ссылок в комментариях вечная проблема, если считать запятые частью ссылки, то в комментарии «Посмотрите на https://example.com, там есть подробная документация с примерами» ссылкой будет и часть после запятой. Можно считать окончанием ссылки запятую, перед которой есть пробел, но не каждый этот пробел поставит т.к. пробела там быть и не должно. Можно считать окончанием ссылки пробел как таковой, но тогда в приведённом мною примере запятая становится частью ссылки, что не корректно. Относительно приемлемым для себя определил вариант, когда концом ссылки считается 0 или более спецсимволов (запятая, точка, двоеточие, восклицательный и вопросительный знаки, любые кавычки, апострофы и скобки), не отделённых буквой или цифрой от пробела справа. Просто потому, что ссылки крайне редко _оканчиваются_ на знак вопроса (и даже в этом случае чаще всего его можно безболезненно убрать), точку или запятую (ибо зачем их использовать не в качестве разделителя). Проблема же ссылок, содержащих пробелы (вставленных без замены на %20) кажется вовсе неразрешимой.
qweqwa
09.06.2016 18:38-1И что. Не ресайзить. А сразу отдавать как надо?
0x9d8e
09.06.2016 19:39+1Речь про ресайзинг, например, загружаемых пользователем картинок на клиенте. Для экономии трафика, ресурсов сервера. А также каких-то других произвольных манипуляций, например наложения фильтров, которое при любом другом способе, кроме как «отресайзить на клиенте и на клиенте же наложить фильтр» либо в крайнем случае «отресайзить на клиенте, наложить фильтр на сервере и показать на клиенте что получилось» будет крайне неотзывчиво и недружелюбно.
qweqwa
10.06.2016 22:17С каких пор сразу отданная нужная картинка будет хуже чем та, на которую клиент тратит время. И которую качает в полном размере, чтобы потом уменьшить.
Itachi261092
14.06.2016 11:23-1Я не очень понял мотив автора. Первым делом надо было писать в багрепорт хрома, или отправить им вариант более правильного решения на гитхабе. А потом уже пилить статью. А то весь такой крутой «я знаю как правильнее»… А ребятам их хрома сложно что ли подсказать это? Вряд ли они сами будут специально искать эту статью и разбирать её. А на багрепорты скорее всего отреагируют.
dmitrmax
14.06.2016 11:55+1Ребята из хрома местами весьма упертые осталопы. Тем более ссылка на багрепорт в посте присутствует.
Itachi261092
14.06.2016 12:01-3Ребята из хрома местами весьма упертые осталопы.
А вот это, в таком случае, тема для отдельного поста с примерами и скриншотами.
Вообще я это написал к тому, что с багрепорта надо было начинать. А автор представил информацию в виде «вот всё сейчас плохо. я давно знал как надо сделать чтобы стало лучше, но уже долгое время просто жду что они реализуют это сами. вот терпение вышло — пошёл написал багрепорт»
Я бы с бОльшим удовольствием прочитал статью в стиле «год назад я нашёл проблему ресайза и отправил багрепорт с указаниями и правками как сделать лучше. проблему до сих пор пытаются исправить/не исправили и т.п.»dmitrmax
14.06.2016 13:24+2Почему вы считаете, что все обязаны знать с++, чтобы коммитить фиксы в хром, например? В конце концов, найти баг и нормально его документировать — это тоже большая работа.
Писать отдельный пост с примерами и скриншотами о том, что в каком-то open source проекте разработчики — упёртые осталопы? Вы шутите, наверное?Itachi261092
14.06.2016 13:26-1Вы правы. Писать пост о том что «вот как плохо хром работает с картинками. надо исправлять» — гораздо продуктивнее и интереснее.
dmitrmax
14.06.2016 13:38+2Давайте оценим ваш сарказм численно. Данная статья набрала +72. А, например, ваша статья о том «как надо» про Битрикс набрала -9. Думаю, что в этом месте вам нужно задуматься на тему, что:
а) все пидорасы, один вы — д'Артаньян
б) вы читаете и пишите не в то сообщество, где ценят ваши принципы
alltiptop
Загрузил большую картинку Плутона на jsbin.com — при всех вариантах канваса меньше 300px граница планетоида — лесенка, никакого сглаживания и в помине.
homm
Уверены, что включили флаг:
chrome://flags/#enable-experimental-canvas-features
?Черт, Хабр кушает ссылки на флаги. Сейчас в статье поправлю.
alltiptop
Ага, теперь одна лесенка и 2 мыла