Откройте файл WebP в hex-редакторе. Первые двенадцать байт:
52 49 46 46 ?? ?? ?? ?? 57 45 42 50
Это заголовок контейнера в стиле RIFF/WAVE. 52 49 46 46 — ASCII-коды букв "RIFF". Следующие четыре байта — размер файла в формате uint32 little-endian. 57 45 42 50 — ASCII-коды букв "WEBP". Файл WebP — это не сырой битовый поток. Это контейнер, как WAV-аудио или AVI-видео, построенный по той же спецификации RIFF, которую Microsoft представила в 1991 году. Внутри этого контейнера находится кадр видео VP8, переориентированный для статичного изображения. Использовать видеокодек для фотографий — вот главная особенность WebP.
Google анонсировал WebP 30 сентября 2010 года. Предложение было простым: такое же визуальное качество, как у JPEG, но на 25-34% меньше размер файла. Для PNG заявление было ещё смелее — на 26% меньше для изображений без потерь. В вебе, где изображения составляют примерно половину всех передаваемых данных, этих цифр должно было хватить для массового внедрения. Не хватило.
Приобретение, положившее начало WebP
WebP появился не из лаборатории изображений. Он пришёл из видеокодека.
В феврале 2010 года Google приобрёл On2 Technologies примерно за 124 миллиона долларов. On2 занималась видеокомпрессией — их кодеки обеспечивали видео в Flash, видеозвонки Skype и стриминг AOL. Флагманский продукт — VP8, видеокодек, созданный для конкуренции с H.264 без патентных отчислений.
Google открыл исходный код VP8 в мае 2010 года под названием WebM, объединив его с аудиокодеком Vorbis и контейнером Matroska. Цель была ясна: построить свободный от патентов видеостек для борьбы с пулом лицензирования H.264 от MPEG-LA, который начал требовать отчисления за веб-видео.
Но у Google была параллельная идея. Внутрикадровое сжатие VP8, то есть сжатие отдельного кадра без ссылки на другие кадры, по сути работало как кодек для статичных изображений. Те же режимы предсказания, преобразующее кодирование и энтропийное кодирование, которые делали VP8 эффективным для видео, срабатывали и для фотографий. Google выделил внутрикадровый режим, обернул его в контейнер RIFF и назвал WebP.
Название было маркетинговым ходом. "Web" — потому что создан для веба. "P" — потому что форматы изображений заканчиваются на P: JPEG, PNG, BMP, TIFF. Получился формат, который по сути был видеокадром, выдающим себя за фотографию.
Зачем вообще создавать новый формат?
К 2010 году JPEG было восемнадцать лет, а PNG — четырнадцать. Оба были прочно укоренены. Зачем создавать что-то новое?
JPEG к тому моменту уже страдал от вполне конкретных ограничений:
- Нет прозрачности. Пиксель JPEG либо полностью непрозрачен, либо нужна отдельная маска.
- Нет анимации. Анимированный JPEG как стандарт не существует.
- Только с потерями. Базовая спецификация JPEG не предусматривает режим без потерь. (JPEG-LS и JPEG 2000 существуют, но ни один не совместим с вебом.)
- 8-битная глубина цвета на канал. Базовая спецификация не поддерживает wide-gamut и HDR.
- Блочные артефакты при низком качестве. Сетка DCT 8 x 8 заметна при качестве ниже 75.
У PNG ограничения были не менее серьёзными:
- Нет режима с потерями. PNG всегда кодирует без потерь. Фотография 12 МП в PNG занимает 15-25 МБ.
- Большие файлы для фотографий. DEFLATE-компрессия PNG не может конкурировать с DCT-based psycho-visual discard.
- Нет анимации в базовой спецификации. APNG существует, но годами набирал поддержку браузеров.
Google увидел пробел: единый формат, способный на компрессию с потерями и без потерь, прозрачность и анимацию, при этом дающий файлы меньше, чем у конкурентов. Таким было предложение WebP.
Как WebP работает на самом деле
У WebP два принципиально разных внутренних формата: WebP с потерями (внутрикадровый VP8) и WebP без потерь (отдельный кодек, также выросший из исследований VP8).
WebP с потерями: внутрикадровый VP8
WebP с потерями хранит битовый поток VP8 внутри контейнера RIFF. Конвейер кодирования концептуально похож на JPEG, но с ключевыми отличиями:
| Этап | JPEG | WebP с потерями |
|---|---|---|
| Преобразование | 8 x 8 DCT | 4 x 4 или 16 x 16 integer DCT-like transform |
| Предсказание | Нет (только внутрикадровое) | 4 режима внутрикадрового предсказания на блок 4 x 4 |
| Chroma subsampling | 4:2:0 default | 4:2:0 default |
| Энтропийное кодирование | Хаффман | Binary arithmetic coding |
| Глубина цвета | 8-bit | 8-bit |
Главный выигрыш даёт внутрикадровое предсказание. JPEG кодирует каждый блок 8 x 8 независимо. WebP предсказывает каждый блок 4 x 4 на основе уже закодированных соседей, сверху, слева или с обеих сторон, и кодирует только ошибку предсказания. Для плавных градиентов и больших однородных областей ошибка минимальна, и коэффициент компрессии значительно растёт.
Арифметический кодировщик также эффективнее кодирования Хаффмана в JPEG (обычно дополнительная экономия 5-10% при том же качестве).
Собственные бенчмарки Google из 2010 года утверждали:
| Метрика | WebP против JPEG |
|---|---|
| Среднее уменьшение размера файла | 25-34% при эквивалентном SSIM |
| Скорость кодирования | ~в 8 раз медленнее libjpeg |
| Скорость декодирования | Сопоставима с libjpeg |
Скорость кодирования была скрытой платой. Создание файла WebP требовало значительно больше CPU, чем JPEG. Для фотографов, экспортирующих сотни изображений, это имело значение.
WebP без потерь
WebP без потерь использует совершенно другой кодек. Это не VP8. Это кастомный формат, в основе которого лежат предиктивное кодирование с 14 режимами пространственного предсказания на пиксель, хеш-таблица недавно встреченных цветов для локальных повторов, LZ77-ссылки назад с двумерным spatial-aware matching и гибрид Хаффмана с арифметическим кодированием, адаптирующийся к локальной статистике.
Google заявлял о файлах на 26% меньше, чем PNG в среднем. На практике экономия сильно варьируется: простая графика с большими однородными областями получает мало выгоды, а фотографии с мелкой текстурой могут ужиматься на 30-40%.
Расширенный WebP (VP8X)
Чанк VP8X расширяет возможности WebP: он добавляет 8-битный альфа-канал, кодируемый отдельно и сжимаемый энтропийным кодировщиком WebP без потерь; анимацию через несколько кадров с метаданными о тайминге; метаданные EXIF и XMP; а также ICC-профиль для управления цветом.
Файл VP8X начинается с заголовка чанка VP8X, за которым следуют флаги, указывающие, какие расширения присутствуют.
Формат файла
WebP — это контейнер RIFF. Понять байтовую структуру просто, если вы знаете RIFF.
Структура контейнера RIFF
Bytes 0-3: "RIFF" (0x52 0x49 0x46 0x46)
Bytes 4-7: File size - 8 (little-endian uint32)
Bytes 8-11: "WEBP" (0x57 0x45 0x42 0x50)
Bytes 12-15: Chunk FourCC — "VP8 ", "VP8L", или "VP8X"
Bytes 16-19: Chunk size (little-endian uint32)
Bytes 20+: Chunk data
Расширенный заголовок VP8X
Если FourCC в байтах 12-15 равен "VP8X" (0x56 0x50 0x38 0x58):
Bytes 20-23: Chunk size = 10 (little-endian uint32)
Bytes 24: Flags byte
Bit 0: Animation present
Bit 1: XMP metadata present
Bit 2: EXIF metadata present
Bit 3: Alpha channel present
Bit 4: ICC profile present
Bits 5-7: Reserved
Bytes 25-27: Canvas width - 1 (little-endian uint24)
Bytes 28-30: Canvas height - 1 (little-endian uint24)
Размеры canvas хранятся как width - 1 и height - 1, поэтому изображение 1200 x 675 хранит 1199 и 674. Максимальный размер canvas — 16 777 215 x 16 777 215 пикселей.
Типы чанков
| FourCC | Содержимое | Компрессия |
|---|---|---|
VP8 | Битовый поток VP8 (с потерями) | Внутрикадровый VP8 |
VP8L | Битовый поток VP8L (без потерь) | Пользовательский кодек без потерь |
VP8X | Расширенный заголовок + флаги | Отсутствует |
ALPH | Данные альфа-канала | Энтропийное кодирование WebP без потерь |
ANMF | Кадр анимации | VP8/VP8L на кадр |
ICCP | ICC-профиль | Отсутствует |
EXIF | Метаданные EXIF | Отсутствует |
XMP | Метаданные XMP | Отсутствует |
Определение WebP по сигнатуре файла
Не доверяйте расширению .webp. Прочитайте первые 16 байт и разберите заголовок RIFF.
Точная байтовая раскладка простого WebP с потерями:
Bytes 0-3: "RIFF"
Bytes 4-7: File size (little-endian uint32)
Bytes 8-11: "WEBP"
Bytes 12-15: "VP8 " (lossy) или "VP8L" (lossless) или "VP8X" (extended)
TypeScript в браузере:
interface WebPInfo {
valid: boolean
type: "lossy" | "lossless" | "extended" | "unknown"
width?: number
height?: number
hasAlpha?: boolean
isAnimated?: boolean
}
async function inspectWebP(file: File): Promise<WebPInfo> {
const buffer = await file.slice(0, 30).arrayBuffer()
const bytes = new Uint8Array(buffer)
if (bytes.length < 12) return { valid: false, type: "unknown" }
const riff = String.fromCharCode(...bytes.slice(0, 4))
const webp = String.fromCharCode(...bytes.slice(8, 12))
if (riff !== "RIFF" || webp !== "WEBP") {
return { valid: false, type: "unknown" }
}
const type = String.fromCharCode(...bytes.slice(12, 16))
if (type === "VP8 ") {
// Lossy: width/height в байтах 26-29
const w = bytes[26] | (bytes[27] << 8)
const h = bytes[28] | (bytes[29] << 8)
return { valid: true, type: "lossy", width: w, height: h, hasAlpha: false }
}
if (type === "VP8L") {
// Lossless: размеры упакованы в биты байтов 21-24
const bits =
bytes[21] | (bytes[22] << 8) | (bytes[23] << 16) | (bytes[24] << 24)
const w = (bits & 0x3fff) + 1
const h = ((bits >> 14) & 0x3fff) + 1
const alpha = ((bits >> 28) & 0x01) !== 0
return {
valid: true,
type: "lossless",
width: w,
height: h,
hasAlpha: alpha,
}
}
if (type === "VP8X") {
const flags = bytes[20]
const w = (bytes[24] | (bytes[25] << 8) | (bytes[26] << 16)) + 1
const h = (bytes[27] | (bytes[28] << 8) | (bytes[29] << 16)) + 1
return {
valid: true,
type: "extended",
width: w,
height: h,
hasAlpha: (flags & 0x10) !== 0,
isAnimated: (flags & 0x02) !== 0,
}
}
return { valid: false, type: "unknown" }
}
Python
import struct
from typing import TypedDict
class WebPInfo(TypedDict):
valid: bool
type: str
width: int | None
height: int | None
has_alpha: bool | None
is_animated: bool | None
def inspect_webp(path: str) -> WebPInfo:
with open(path, "rb") as f:
header = f.read(30)
if len(header) < 12:
return {"valid": False, "type": "unknown"}
if header[:4] != b"RIFF" or header[8:12] != b"WEBP":
return {"valid": False, "type": "unknown"}
chunk_type = header[12:16]
if chunk_type == b"VP8 ":
w, h = struct.unpack("<HH", header[26:30])
return {"valid": True, "type": "lossy", "width": w, "height": h,
"has_alpha": False, "is_animated": None}
if chunk_type == b"VP8L":
bits = struct.unpack("<I", header[21:25])[0]
w = (bits & 0x3FFF) + 1
h = ((bits >> 14) & 0x3FFF) + 1
alpha = ((bits >> 28) & 0x01) != 0
return {"valid": True, "type": "lossless", "width": w, "height": h,
"has_alpha": alpha, "is_animated": None}
if chunk_type == b"VP8X":
flags = header[20]
w = struct.unpack("<I", header[24:27] + b"\x00")[0] + 1
h = struct.unpack("<I", header[27:30] + b"\x00")[0] + 1
return {"valid": True, "type": "extended", "width": w, "height": h,
"has_alpha": bool(flags & 0x10), "is_animated": bool(flags & 0x02)}
return {"valid": False, "type": "unknown"}
Вариант высокого уровня с Pillow:
from PIL import Image
with Image.open("image.webp") as img:
print(img.format) # WEBP
print(img.mode) # RGB или RGBA
print(img.size) # (width, height)
print(img.is_animated) # True если анимировано
Или с библиотекой webp:
import webp
info = webp.WebPInfo("image.webp")
print(info.width, info.height, info.has_alpha)
Go
package main
import (
"encoding/binary"
"fmt"
"os"
)
type WebPInfo struct {
Valid bool
Type string
Width int
Height int
HasAlpha bool
IsAnimated bool
}
func inspectWebP(path string) (WebPInfo, error) {
f, err := os.Open(path)
if err != nil {
return WebPInfo{}, err
}
defer f.Close()
buf := make([]byte, 30)
if _, err := f.Read(buf); err != nil {
return WebPInfo{}, err
}
if string(buf[:4]) != "RIFF" || string(buf[8:12]) != "WEBP" {
return WebPInfo{Valid: false, Type: "unknown"}, nil
}
typeStr := string(buf[12:16])
switch typeStr {
case "VP8 ":
w := int(binary.LittleEndian.Uint16(buf[26:28]))
h := int(binary.LittleEndian.Uint16(buf[28:30]))
return WebPInfo{Valid: true, Type: "lossy", Width: w, Height: h, HasAlpha: false}, nil
case "VP8L":
bits := binary.LittleEndian.Uint32(buf[21:25])
w := int(bits&0x3FFF) + 1
h := int((bits>>14)&0x3FFF) + 1
alpha := ((bits >> 28) & 0x01) != 0
return WebPInfo{Valid: true, Type: "lossless", Width: w, Height: h, HasAlpha: alpha}, nil
case "VP8X":
flags := buf[20]
w := int(binary.LittleEndian.Uint32(append(buf[24:27], 0))) + 1
h := int(binary.LittleEndian.Uint32(append(buf[27:30], 0))) + 1
return WebPInfo{
Valid: true, Type: "extended", Width: w, Height: h,
HasAlpha: (flags & 0x10) != 0, IsAnimated: (flags & 0x02) != 0,
}, nil
}
return WebPInfo{Valid: false, Type: "unknown"}, nil
}
PHP
function inspectWebP(string $path): array {
$header = file_get_contents($path, false, null, 0, 30);
if (strlen($header) < 12) {
return ["valid" => false, "type" => "unknown"];
}
if (substr($header, 0, 4) !== "RIFF" || substr($header, 8, 4) !== "WEBP") {
return ["valid" => false, "type" => "unknown"];
}
$type = substr($header, 12, 4);
if ($type === "VP8 ") {
$w = unpack("v", substr($header, 26, 2))[1];
$h = unpack("v", substr($header, 28, 2))[1];
return ["valid" => true, "type" => "lossy", "width" => $w, "height" => $h, "has_alpha" => false];
}
if ($type === "VP8L") {
$bits = unpack("V", substr($header, 21, 4))[1];
$w = ($bits & 0x3FFF) + 1;
$h = (($bits >> 14) & 0x3FFF) + 1;
$alpha = (($bits >> 28) & 0x01) !== 0;
return ["valid" => true, "type" => "lossless", "width" => $w, "height" => $h, "has_alpha" => $alpha];
}
if ($type === "VP8X") {
$flags = ord($header[20]);
$w = unpack("V", substr($header, 24, 3) . "\x00")[1] + 1;
$h = unpack("V", substr($header, 27, 3) . "\x00")[1] + 1;
return [
"valid" => true, "type" => "extended",
"width" => $w, "height" => $h,
"has_alpha" => (bool)($flags & 0x10),
"is_animated" => (bool)($flags & 0x02),
];
}
return ["valid" => false, "type" => "unknown"];
}
С fileinfo:
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file('image.webp');
// image/webp
ImageMagick CLI
magick identify -verbose image.webp | grep "Format:"
# Format: WEBP (WebP Image Format)
Полное извлечение метаданных:
magick identify -verbose image.webp
Выводит ширину, высоту, глубину цвета, наличие альфа-канала, тип компрессии и информацию о ICC-профиле.
Или просто:
file image.webp
# image.webp: RIFF (little-endian) data, Web/P image
Сильные стороны
WebP в некоторых местах действительно хорош.
На эталонном корпусе Google WebP с потерями в среднем давал файлы на 25-34% меньше JPEG при том же SSIM, а WebP без потерь — на 26% меньше PNG. Для сайтов с высоким трафиком эта экономия напрямую превращается в снижение расходов на трафик и ускорение загрузки страниц.
Один формат покрывает большинство сценариев: режим с потерями для фотографий, режим без потерь для графики, альфа-канал для прозрачности, анимация для коротких последовательностей. Веб-разработчику нужно знать один формат вместо трёх.
Chrome, Firefox, Safari и Edge поставляются с аппаратно ускоренными или высокооптимизированными программными декодерами WebP. Скорость декодирования сопоставима с JPEG на десктопе и отличается в пределах 10-20% на мобильных устройствах.
WebP поддерживает инкрементальное отображение по мере поступления данных, аналогично прогрессивному режиму JPEG. На медленных соединениях узнаваемое изображение появляется после получения примерно 30% файла.
Анимированные файлы WebP обычно на 60-80% меньше анимированных GIF при эквивалентном визуальном качестве, с полным 24-битным цветом и 8-битным альфа-каналом на кадр.
Слабые стороны
Проблемы WebP, в основном, не технические, а экосистемные.
В 2010 году кодирование WebP было примерно в 8 раз медленнее libjpeg. Разрыв сократился: libwebp в 2026 году примерно в 2-3 раза медленнее libjpeg-turbo. Но для пакетной обработки это всё ещё заметно. Фотограф, экспортирующий 1000 изображений, будет ждать дольше.
WebP строго 8-bit на канал. Для wide-gamut фотографии, медицинской визуализации или HDR-контента он непригоден. HEIC, AVIF и JPEG XL поддерживают большую битовую глубину.
WebP не умеет пережимать существующий JPEG без потерь. JPEG XL может это делать, обеспечивая экономию около 20%. Конвертация JPEG в WebP требует полного перекодирования, что приводит к деградации качества при повторном сжатии.
Photoshop не поддерживал WebP нативно до 2022 года. Поддержка WebP в ImageMagick долго требовала компиляции с плагином libwebp, который многие дистрибутивы не включали по умолчанию. Многие системы управления контентом до сих пор генерируют JPEG/PNG по умолчанию.
Google выпустил VP8 с обещанием патентной индемнификации, но патентный ландшафт кодека никогда не был таким чистым, как у PNG или JPEG. Некоторые организации избегали WebP именно потому, что не доверяли, что юридическое прикрытие Google выдержит в суде.
Почему победил «устаревший» формат
JPEG существует уже тридцать четыре года. В нём нет прозрачности, анимации и режима без потерь, а при качестве 75 заметны артефакты. WebP выглядит лучше почти по всем параметрам. Тем не менее Web Almanac за 2025 год оценивает долю JPEG примерно в 46% всех веб-изображений против 19% у WebP.
Причина не в технологиях, а в сетевых эффектах и издержках переключения.
JPEG — это QWERTY среди форматов изображений. Любая камера сохраняет JPEG по умолчанию, любой телефон отображает его нативно, любой принтер принимает его. Социальные сети, CMS, CDN и почтовые клиенты работают с JPEG без плагинов, кодеков или конвертации. Формат настолько универсален, что для большинства пользователей "изображение" и "JPEG" стали функциональными синонимами.
Хронология внедрения WebP выглядит так:
| Год | Веха |
|---|---|
| 2010 | Google анонсирует WebP (Chrome 8) |
| 2012 | Chrome 23 добавляет поддержку изображений без потерь и альфа-канала |
| 2013 | Chrome добавляет анимированный WebP |
| 2014 | Android 4.0+ добавляет нативную поддержку WebP |
| 2015 | Facebook конвертирует все мобильные фото в WebP |
| 2016 | Safari 14 добавляет поддержку WebP |
| 2020 | Достигнута универсальная поддержка браузерами |
| 2022 | Photoshop добавляет нативный экспорт WebP |
| 2025 | WebP занимает 19% веб-изображений по данным Web Almanac |
Chrome агрессивно продвигал WebP, потому что Google контролировал и браузер, и формат. Facebook внедрил его, потому что экономил петабайты трафика. Но длинный хвост веба (блоги на WordPress, мелкие интернет-магазины, корпоративные CMS, email-рассылки) двигался медленно или не двигался вовсе.
Слабое место — экосистема Apple. iPhone сохраняет HEIC по умолчанию, а не WebP. macOS Preview не поддерживал WebP до macOS 11 Big Sur (2020). iOS share sheet не предлагал экспорт в WebP. Для фотографов, дизайнеров и авторов социальных сетей, работающих преимущественно на устройствах Apple, WebP был невидим.
Тем временем AVIF появился в 2019 году с лучшей компрессией, чем у WebP, и бесплатным лицензированием от Alliance for Open Media. Chrome, Firefox и Safari поставляют AVIF. Cloudflare и Cloudinary автоматически отдают AVIF. WebP стал ступенькой, лучше JPEG, но уже перепрыгиваемой следующим поколением.
Где WebP находится сегодня
WebP не провалился, но и не захватил рынок.
Для веб-разработчиков, строящих новые проекты в 2026 году, WebP — прагматичный выбор по умолчанию для изображений, которым нужна прозрачность или анимация. Он меньше PNG для графики без потерь и меньше JPEG для фотографий. Поддержка браузерами универсальна. Инструменты кодирования зрелые.
Но WebP не заменил JPEG. Он выкроил нишу рядом с ним, ту же нишу, которую уже занимал PNG, просто с файлами меньше. Видение "одного формата для всех изображений" не материализовалось.
Практическая реальность 2026 года:
| Сценарий | Лучший формат | Почему |
|---|---|---|
| Фотографии (legacy) | JPEG | Универсален, быстрое кодирование, достаточно мал |
| Фотографии (новые) | AVIF | На 30% меньше WebP, royalty-free |
| Фотографии (резервный вариант) | WebP | На 25% меньше JPEG, универсальная поддержка |
| Графика без потерь | WebP или PNG | WebP меньше; PNG — безопасный резервный вариант |
| Прозрачность | WebP или PNG | WebP даёт меньшие файлы; PNG — безопасный резервный вариант |
| Анимация | WebP или AVIF | Оба обгоняют GIF на 60-80%; AVIF новее |
| Wide-gamut / HDR | AVIF или JPEG XL | 10+ bit depth, поддержка ICC/ICC v4 |
| Полиграфические рабочие процессы | TIFF или JPEG XL | CMYK, 16 бит, пересжатие JPEG без потерь |
Главный урок WebP в том, что веб способен принимать новые форматы изображений, если крупный вендор браузеров давит достаточно настойчиво. WebP помог AVIF набрать инерцию, заставил Apple нативно поддерживать форматы помимо JPEG/PNG и показал, что прозрачность с анимацией могут жить в одном контейнере.
Вместе с тем WebP продемонстрировал, что одних коэффициентов компрессии мало. Повсеместность, инерция и выравнивание экосистемы важнее. JPEG переживёт WebP не потому, что лучше, а потому, что он уже везде.
Вместо вывода
WebP создан на основе видеокодека для решения проблемы пропускной способности. Он решил её для Google, для Facebook и для любого сайта, готового переделать свой конвейер обработки изображений. Компрессия реальна, возможности полезны, поддержка браузерами полная.
Но веб не переключается на формат только потому, что техническая документация утверждает, что новый формат на 25% меньше. Переключение происходит, когда новый формат удобнее старого, или когда старый проваливается настолько сильно, что миграция неизбежна. JPEG не провалился настолько сильно. WebP не был достаточно удобен. А к тому времени, как WebP стал удобным, AVIF уже появился с большей цифрой в спецификации.
WebP похож на Betamax среди форматов изображений: технически прочный, хорошо поддерживаемый и в итоге обогнанный тем, что вышло чуть позже с лучшим маркетингом и более широкой поддержкой. Он не исчезнет. Он будет сосуществовать с JPEG, PNG, AVIF и всем, что появится дальше, выполняя ту же роль, что сегодня выполняет PNG: формат, который открывается везде.
Если у вас есть PNG-файлы, которым нужен меньший размер для веба, PNG to WebP конвертирует их локально в браузере — без загрузок, без серверной обработки. Для JPEG, которым нужна прозрачность или анимация, JPG to WebP справится с конвертацией с контролем качества. А когда нужен универсальный резервный вариант, WebP to PNG и WebP to JPG вернут файлы WebP к форматам, которые открываются в любом просмотрщике.



