Как мы проверяли#
Нам нужен был исходник, который до нас никто не сжимал, иначе мы бы мерили чужие потери вместе со своими. Поэтому взяли снимки из набора Kodak: 24 фотографии размером 768×512 точек, которые компания выложила в свободный доступ, и с тех пор это стандартный набор для проверки алгоритмов сжатия. Мы выбрали три разных сюжета: попугаев с гладким зелёным фоном, разноцветные шляпы и горную речку с камнями, где мелких деталей больше всего.
Каждый снимок сохраняли в JPEG программой на Python с библиотекой Pillow, которая использует libjpeg-turbo — ту же, что стоит в Chrome, Firefox и в редакторах фото. Качество — 75 из 100, как по умолчанию у большинства программ. Сохранили, открыли получившийся файл, сохранили снова — и так двести раз. Сценариев было пять:
- просто пересохранение с одними и теми же настройками;
- поворот на 90 градусов, сохранение и поворот обратно;
- каждый раз случайное качество от 70 до 95, как бывает, когда фото проходит через разные программы;
- уменьшение на 10% и возврат к прежнему размеру перед каждым сохранением;
- обрезка одного пикселя сверху и слева перед каждым сохранением.
Потери мерили в цифрах. Цвет каждой точки на экране задаётся тремя числами — красным, зелёным и синим, каждое от 0 до 255. Мы сравнивали эти числа с оригиналом точка за точкой и считали типичное отклонение (среднеквадратичное, если по-научному). Ошибка в 3–4 ступени на глаз незаметна, 10 ступеней видно при увеличении, а при 50 картинку уже трудно узнать.
200 сохранений подряд: портит только первое#
На фото с попугаями первое сохранение дало ошибку 3,6 ступени. Столько стоит сжатие: из 1,2 МБ несжатой картинки получается файл на 42 КБ. Второе сохранение добавило совсем чуть-чуть, а дальше ошибка дошла до 3,9 и там остановилась. Десятое сохранение совпало с девятым до байта, и вплоть до двухсотого файл больше не менялся. На шляпах и на речке вышло то же: ошибка подросла с 3,7 до 3,9 и с 7,6 до 7,7, а файл замирал после восьмого-девятого раза.
С поворотом получилось так же: двести раз повернули, сохранили, повернули обратно, и итог совпал с обычным пересохранением в пределах десятой доли ступени. Сохранение с высоким качеством 90 сходилось медленнее: файл переставал меняться только на 21-м круге у речки и на 39–40-м у двух других снимков. Но и там после остановки ничего не накапливалось.
Один и тот же фрагмент, увеличен вдвое. Двести сохранений с одними настройками на глаз неотличимы от оригинала, а обрезка на пиксель превратила попугая в шум. Замер «Техпросто»
Так что правило «никогда не пересохраняйте JPEG» не работает. Если вы открыли фото, ничего в нём не меняли и десять раз нажали «Сохранить» в той же программе, вы потеряли почти столько же, сколько за первый раз.
Почему JPEG перестаёт портиться#
JPEG режет снимок на квадраты 8×8 точек и каждый описывает не цветами точек, а набором узоров — от плавной заливки до мелкой ряби. Затем у каждого узора округляет силу, причём мелкую рябь округляет грубее, потому что глаз её почти не замечает. Это округление и есть потеря качества, а заодно главный способ сжать файл: грубо округлённые числа записываются коротко.
Повторное округление ничего не отнимает. Представьте, что вы округляете цену до десятков: 1234 рубля превращаются в 1230, и сколько ни округляй 1230 дальше, останется 1230. При повторном сохранении квадрат уже собран из округлённых узоров: программа раскладывает его на те же узоры и округляет до тех же чисел. Если ничего не менять, новых потерь почти не возникает.
Небольшая добавка в первые сохранения всё же набегает. Когда файл открывают, узоры снова превращаются в точки, и цвет каждой точки приходится округлять до целого числа от 0 до 255, а цвета на краях диапазона ещё и обрезать. Эти мелкие погрешности чуть сдвигают узоры, и следующее сохранение округляет их иначе. Через несколько кругов сдвиг становится меньше шага округления, и файл перестаёт меняться. При качестве 90 шаг мельче, поэтому сдвигов хватает дольше и файл замирает позже.
Что на самом деле портит фото#
Потери копятся, если между сохранениями сдвигается сетка квадратов или меняются настройки качества.
Хуже всего вышло с обрезкой на один пиксель. На попугаях ошибка после пяти кругов выросла до 5,5 ступени — столько же даёт одно сохранение с качеством 30. После двадцати кругов набралось 10,3 ступени, а это уже больше, чем после одного сохранения с качеством 10 из 100, где на вид сплошные квадраты. К двухсотому кругу ошибка дошла до 57 ступеней на попугаях, 61 на шляпах и 84 на речке, и от снимков остался цветной шум, в котором угадываются контуры.
После пяти кругов разница ещё незаметна, после двадцати фон покрывается разводами, к сотому краски уплывают. Замер «Техпросто»
Со случайным качеством от 70 до 95 ошибка росла понемногу на каждом круге: 5 ступеней после десяти сохранений, 8,8 после пятидесяти и 13 после двухсот. Уменьшение на 10% с возвратом размера сначала смягчает картинку, а потом почти перестаёт вредить: на попугаях и шляпах ошибка остановилась на 4,7. Речка с мелкими камнями так и продолжала размываться до 16 ступеней, потому что каждое уменьшение заново съедает мелкие детали.
Шкала сохранений логарифмическая. Синяя и бирюзовая линии почти лежат, жёлтая ползёт вверх, красная уходит вверх круто. Замер «Техпросто»
🔢 Типичная ошибка пикселя на фото с попугаями (ступеней из 255)
| Сценарий |
1 раз |
10 раз |
50 раз |
200 раз |
| Одни и те же настройки |
3,6 |
3,9 |
3,9 |
3,9 |
| Поворот и обратно |
3,5 |
3,9 |
3,9 |
3,9 |
| Уменьшение на 10% и обратно |
3,7 |
4,4 |
4,7 |
4,7 |
| Каждый раз другое качество |
3,6 |
5,0 |
8,8 |
13,2 |
| Обрезка на 1 пиксель |
3,5 |
7,3 |
18,5 |
56,8 |
Для сравнения, одно сохранение того же оригинала с качеством 90 даёт 2,7, с качеством 30 — 5,5, с качеством 10 — 9,2.
Испорченный файл ещё и тяжелее. Снимок с попугаями после двухсот обрезок стал меньше на 200 точек по каждой стороне, а весил 60 КБ вместо 42. Цветной шум сжимается хуже гладкой картинки, поэтому испорченный файл занимает больше места.
📲 Проверяем, а не верим на слово
Мы регулярно берём расхожие советы про технику и проверяем их опытом, а потом объясняем результат простыми словами. Подпишитесь на «Техпросто» в MAX, Telegram или Дзене, и новые эксперименты будут приходить сами.
Почему сдвиг на один пиксель вредит больше, чем двести обычных сохранений#
Виновата сетка квадратов 8×8. Пока картинку не трогают, при каждом сохранении сетка ложится на те же места, и в каждый квадрат попадает то же содержимое, которое уже округлили. Обрезали пиксель слева — и вся сетка уехала на одну точку. Теперь каждый новый квадрат захватывает куски двух старых, в нём сочетаются узоры, которые ни разу не округлялись вместе, и формат округляет их заново.
Мы проверили эту догадку тем же опытом, только обрезали не по одному пикселю, а сразу по 16. Сетка в таком случае сдвигается на два квадрата и ложится на старые места. Двадцать таких обрезок дали на попугаях ошибку 3,6 ступени, как одно-единственное сохранение. А при обрезке по 8 пикселей ошибка выросла до 6,4: сетка яркости совпадает, а сетка цвета нет. Дело в том, что JPEG по умолчанию хранит цвет с половинной чёткостью — одним значением на квадрат 2×2 точки, поэтому цветные квадраты покрывают 16×16 точек снимка. Когда мы отключили эту экономию на цвете, обрезка по 8 пикселей тоже перестала портить фото.
Со сменой качества сетка остаётся на месте, зато меняется шаг округления: каждое новое качество — новый шаг, и число съезжает заново. Поворот на 90 градусов у нас прошёл безвредно, потому что стороны снимка, 768 и 512 точек, делятся на 16 без остатка и после поворота квадраты встают на те же места. Так выходит только с такими размерами, а у многих фотографий стороны на 16 не делятся, поэтому поворачивать их лучше без пересжатия (об этом ниже). Повышение качества от сдвига защищает лишь отчасти: обрезка на пиксель при качестве 90 за пятьдесят кругов дала на попугаях 14 ступеней против 18,5 при качестве 75, и порча всё равно сильная.
Как не испортить свои снимки#
Фото портит цепочка «поправил — сохранил», повторённая десятки раз. Уберечься от неё просто.
Правьте от оригинала. Обрезали фото, сохранили, через неделю захотели обрезать ещё — откройте исходник, а не прошлый результат. Приложение «Фото» на iPhone хранит оригинал, и свои правки в нём можно откатить кнопкой «Вернуть». В Google Фото рядом с кнопкой «Сохранить» есть «Сохранить как копию», и тогда исходник останется нетронутым.
Все правки — за один заход. Яркость, обрезку, поворот и надписи лучше сделать в одной программе и сохранить один раз в конце. Если работа растягивается на несколько дней, промежуточные версии храните в PNG: этот формат сжимает без потерь, а JPEG сделайте в самом конце.
Поворачивайте без пересжатия. На компьютере поворачивать JPEG без потерь умеют XnView MP и IrfanView (только Windows): они переставляют готовые квадраты и не пережимают картинку заново.
💡 Когда отправляете фото в мессенджер
Мессенджеры по умолчанию экономят трафик за ваш счёт: отправка «как фото» означает, что приложение уменьшит снимок и пережмёт его своими настройками. Если снимок нужен для печати или дальнейшей обработки, отправляйте его файлом, и до получателя дойдёт оригинал без изменений.
Повышать качество при каждом сохранении мало помогает: качество 90 от сдвига почти не защищает. Зато первое сохранение лучше делать с запасом. Одно сохранение с качеством 90 дало на попугаях ошибку 2,7 ступени против 3,6 при 75, а файл вырос с 42 до 77 КБ — для фото, которое вы будете ещё обрабатывать, это разумная цена. Где хранить архив оригиналов, чтобы они не съедали память телефона, мы разбирали в подборке облачных хранилищ и в гайде как перенести фото с телефона на компьютер.
⚠️ Где наш опыт не совпадает с жизнью
Мы пересохраняли в одной программе. Другие программы округляют иначе, поэтому у них файл может замереть позже. Но вывод не меняется: после остановки потери перестают копиться, а сдвиг сетки и смена настроек портят снимок в любой программе, различаться будет только скорость.
Частые вопросы#
Портит ли фото простое копирование или перенос? Нет, если файл просто копируют: на флешку или на компьютер он переезжает байт в байт. А вот облако может пережать снимок при загрузке — у Google Фото за это отвечает режим «Экономия места», он уменьшает фото до 16 Мп. Для архива оригиналов выбирайте загрузку в исходном качестве.
А если упаковать фото в архив? Архив сжимает без потерь, и после распаковки файл совпадает с исходным до байта. Правда, места он тоже почти не экономит — это мы проверяли в эксперименте что на самом деле сжимает ZIP.
С видео то же самое? Видео тоже сжимают с потерями, поэтому каждое перекодирование ролика в новый формат или с новыми настройками отнимает часть качества. Сколько места экономят разные форматы, мы замеряли в опыте с H.264, HEVC и AV1.
Почему мемы из интернета такие мутные? Картинку по пути много раз обрезают, подписывают, уменьшают и пересохраняют в разных приложениях. Тут сразу и сдвиг сетки, и смена настроек. Двухсот кругов мему не нужно: в нашем опыте с обрезкой на пиксель заметные разводы появлялись уже за двадцать.
Заведите папку с оригиналами и правьте только копии — этого достаточно, чтобы снимки не превратились в кашу.