Как узнать размер изображения в Python

Как узнать размер картинки python

Как узнать размер картинки python

Размер изображения – это базовый параметр, от которого зависят масштабирование, обрезка, валидация входных данных и расчёт соотношения сторон. В Python получить ширину и высоту изображения можно разными способами, и выбор подхода напрямую зависит от формата файла, используемой библиотеки и требований к загрузке данных. Ошибка на этом этапе часто приводит к искажению изображений или сбоям в обработке.

Python не имеет встроенных средств для работы с изображениями, поэтому на практике применяются сторонние библиотеки: Pillow, OpenCV, matplotlib и инструменты для чтения метаданных. Каждая из них по-разному загружает файл и предоставляет информацию о размерах, что важно учитывать при работе с большими изображениями или потоковой обработке.

В ряде задач требуется узнать размер изображения без полной загрузки в память, например при валидации пользовательских файлов или обработке тысяч изображений на сервере. В таких случаях используются заголовки файлов, EXIF-данные или режимы частичного чтения, позволяющие получить ширину и высоту с минимальными затратами ресурсов.

Отдельного внимания требуют нестандартные форматы, повреждённые файлы и изображения с ориентацией, заданной через EXIF. Неправильная интерпретация этих данных может привести к перепутанным значениям ширины и высоты. Поэтому при определении размеров важно не только получить числа, но и корректно интерпретировать их в контексте конкретной задачи.

Получение ширины и высоты изображения с помощью Pillow (PIL)

Библиотека Pillow предоставляет прямой доступ к размерам изображения через объект Image. После открытия файла ширина и высота доступны без дополнительных вычислений, что делает этот способ удобным для большинства прикладных задач: ресайза, проверки ограничений и подготовки данных для машинного обучения.

Базовый алгоритм состоит из открытия файла и чтения свойства size, которое возвращает кортеж из двух целых чисел: (width, height). Эти значения соответствуют фактическим пиксельным размерам изображения.

from PIL import Image
with Image.open("example.jpg") as img:
width, height = img.size

Использование контекстного менеджера with освобождает файловый дескриптор сразу после чтения метаданных, что важно при обработке большого количества файлов.

Альтернативный вариант – обращение к отдельным свойствам объекта изображения:

width = img.width
height = img.height

Этот способ полезен, когда значения используются независимо и код должен быть максимально читаемым.

При работе с разными форматами стоит учитывать следующие моменты:

  • Для JPEG и PNG размеры читаются напрямую из заголовка файла.
  • Для изображений с EXIF-ориентацией Pillow возвращает исходные размеры, без учёта поворота.
  • Файлы с повреждённой структурой могут вызвать исключение UnidentifiedImageError.

Чтобы избежать ошибок при массовой обработке, рекомендуется оборачивать открытие изображения в блок try/except и заранее фильтровать файлы по расширению:

from PIL import Image, UnidentifiedImageError
try:
with Image.open(path) as img:
w, h = img.size
except UnidentifiedImageError:
pass

Pillow подходит для серверных и локальных сценариев, где требуется быстро получить ширину и высоту изображения с минимальным объёмом кода и без ручного парсинга форматов.

Определение размера изображения через OpenCV без отображения

Определение размера изображения через OpenCV без отображения

Для загрузки изображения применяется функция cv2.imread, которая возвращает массив с формой (height, width, channels). Ширина и высота извлекаются напрямую из свойства shape.

import cv2
img = cv2.imread("example.jpg")
height, width = img.shape[:2]

Срез [:2] гарантирует корректное получение размеров независимо от количества цветовых каналов, включая изображения в оттенках серого.

Если изображение не удалось загрузить, cv2.imread возвращает None. Проверка этого условия обязательна при работе с пользовательскими файлами или внешними источниками.

img = cv2.imread(path)
if img is None:
raise ValueError("Файл не является изображением")

OpenCV всегда загружает изображение полностью в память, поэтому этот способ подходит для сценариев, где дальнейшая обработка массива неизбежна. Для экономии ресурсов можно отключить чтение цветовых каналов, загрузив изображение в градациях серого.

img = cv2.imread("example.jpg", cv2.IMREAD_GRAYSCALE)
height, width = img.shape

При таком режиме отсутствует третье измерение массива, что упрощает извлечение размеров и снижает объём используемой памяти.

Важно учитывать, что OpenCV не применяет EXIF-ориентацию. Возвращаемые ширина и высота соответствуют исходной матрице пикселей, а не визуальному отображению изображения после поворота.

Этот способ оптимален для проектов, где OpenCV уже используется для детекции, фильтрации или анализа изображений, и нет необходимости подключать дополнительные библиотеки.

Чтение размеров изображения с использованием matplotlib.imread

Функция matplotlib.imread загружает изображение в виде массива NumPy, что позволяет сразу определить его размер через форму массива. Этот способ часто применяется в аналитических и научных сценариях, где matplotlib уже используется для визуализации данных.

После чтения файла массив имеет форму (height, width) для изображений в градациях серого или (height, width, channels) для цветных изображений. Ширина и высота извлекаются из первых двух значений.

import matplotlib.image as mpimg
img = mpimg.imread("example.png")
height, width = img.shape[:2]

Важно учитывать, что matplotlib.imread корректно работает не со всеми форматами. Для файлов PNG данные загружаются без сторонних декодеров, тогда как JPEG обрабатывается через Pillow, если он установлен в системе.

Тип данных массива зависит от формата изображения. Для PNG значения пикселей представлены числами с плавающей точкой в диапазоне от 0.0 до 1.0, а для JPEG – целыми числами от 0 до 255. Это не влияет на извлечение размеров, но важно при последующей обработке.

При невозможности прочитать файл будет выброшено исключение, поэтому при пакетной обработке рекомендуется явно обрабатывать ошибки и проверять расширение файла перед загрузкой.

Проверка размеров изображения без полной загрузки файла в память

В серверных и потоковых сценариях часто требуется узнать размеры изображения до его сохранения или обработки, не загружая весь файл в память. Это снижает нагрузку на систему при работе с большими изображениями и массовыми загрузками.

Наиболее универсальный способ – использование Pillow в режиме отложенной загрузки. При вызове Image.open библиотека читает только заголовки файла, содержащие информацию о ширине и высоте, не декодируя все пиксели.

from PIL import Image
img = Image.open("example.jpg")
width, height = img.size
img.close()

Декодирование изображения происходит только при обращении к пиксельным данным, поэтому чтение свойства size не приводит к загрузке всего содержимого файла.

Для строгой валидации файлов можно принудительно остановить обработку до полной загрузки, избегая вызовов методов, связанных с преобразованием изображения:

with Image.open(path) as img:
w, h = img.size

Если требуется минимальный контроль формата, Pillow позволяет проверить корректность структуры файла без чтения пикселей с помощью метода verify.

with Image.open(path) as img:
img.verify()

Метод verify подтверждает, что файл является валидным изображением, но после его вызова объект изображения нельзя использовать повторно.

Альтернативный подход – чтение размеров напрямую из бинарных заголовков формата. Например, для PNG ширина и высота хранятся в чанке IHDR, а для JPEG – в сегментах SOF. Такой метод требует ручного парсинга байтов и применяется только в узкоспециализированных системах.

Проверка размеров без полной загрузки файла особенно актуальна для API загрузки изображений, систем модерации и очередей обработки, где важно отсеивать неподходящие файлы на самом раннем этапе.

Извлечение размеров из метаданных и EXIF в Python

Метаданные и EXIF позволяют получить информацию о размере изображения без анализа массива пикселей. Этот подход применяется при работе с фотографиями, полученными с камер и мобильных устройств, где часть параметров хранится отдельно от графических данных.

В Python доступ к EXIF чаще всего осуществляется через библиотеку Pillow. После открытия изображения можно получить словарь метаданных с помощью метода _getexif(). В нём содержатся теги, связанные с ориентацией, разрешением и параметрами съёмки.

from PIL import Image, ExifTags
with Image.open("photo.jpg") as img:
exif = img._getexif()

Фактические ширина и высота изображения берутся из заголовка файла, но EXIF может содержать тег ориентации, влияющий на визуальное отображение. Для корректной интерпретации размеров важно учитывать это значение.

На практике используются следующие EXIF-теги:

Orientation Определяет поворот изображения (90°, 180°, 270°)
XResolution Горизонтальное разрешение, DPI
YResolution Вертикальное разрешение, DPI

Теги разрешения не задают размер в пикселях напрямую, но используются при расчётах физического размера изображения при печати. Для задач верстки и экспорта это критично.

Если изображение имеет EXIF-ориентацию, ширина и высота могут визуально меняться местами. Для устранения несоответствий рекомендуется нормализовать ориентацию перед чтением размеров:

from PIL import ImageOps
with Image.open("photo.jpg") as img:
img = ImageOps.exif_transpose(img)
w, h = img.size

Не все форматы поддерживают EXIF. PNG, GIF и WebP обычно содержат минимальные метаданные, поэтому для них размеры почти всегда извлекаются только из заголовка файла.

Извлечение размеров через метаданные оправдано в задачах анализа фотографий, предварительной проверки пользовательских загрузок и обработки изображений с учётом ориентации камеры.

Обработка ошибок и нестандартных форматов при определении размеров изображения

Обработка ошибок и нестандартных форматов при определении размеров изображения

При определении размеров изображений в Python важно учитывать некорректные файлы, неподдерживаемые форматы и частично повреждённые данные. Без явной обработки таких случаев код может завершаться исключениями или возвращать неверные значения ширины и высоты.

from PIL import Image, UnidentifiedImageError
try:
with Image.open(path) as img:
w, h = img.size
except UnidentifiedImageError:
pass
except OSError:
pass

Некоторые файлы имеют корректное расширение, но не содержат изображение. Проверка только по имени файла недостаточна, поэтому попытка открытия должна быть основным способом валидации.

В OpenCV функция cv2.imread не выбрасывает исключения, а возвращает None. Отсутствие проверки этого значения приводит к ошибкам при обращении к свойству shape.

img = cv2.imread(path)
if img is None:
raise ValueError("Невозможно определить размер изображения")

Нестандартные форматы, такие как TIFF, PSD или многослойные изображения, могут содержать несколько страниц или каналов. Pillow в таких случаях возвращает размер активного кадра, что не всегда соответствует ожидаемому результату.

Для многостраничных TIFF-файлов рекомендуется явно выбирать кадр перед чтением размеров:

with Image.open("file.tiff") as img:
img.seek(0)
w, h = img.size

Повреждённые изображения могут иметь читаемый заголовок, но вызывать ошибку при дальнейшей работе. Метод verify позволяет выявить такие файлы до извлечения размеров, не загружая пиксели.

Отдельную проблему создают изображения с некорректными EXIF-данными, где указана ориентация, не соответствующая реальному содержимому. В таких случаях нормализация EXIF может привести к искажённым значениям, поэтому для строгой валидации предпочтительно использовать исходные размеры без трансформаций.

Корректная обработка ошибок и учёт особенностей форматов позволяют надёжно определять размеры изображений даже при работе с непредсказуемыми входными данными и внешними источниками.

Вопрос-ответ:

Почему при использовании Pillow ширина и высота иногда оказываются «перепутанными»?

Чаще всего причина связана с EXIF-ориентацией. Файл может храниться в горизонтальном виде, а визуально отображаться повернутым на 90 или 270 градусов. Свойство img.size возвращает исходные размеры матрицы пикселей. Если нужны размеры так, как изображение выглядит на экране, требуется применить ImageOps.exif_transpose перед чтением width и height.

Можно ли узнать размер изображения, не читая его полностью с диска?

Да. При открытии файла через Image.open Pillow читает только заголовки и метаданные. Пока код не обращается к пиксельным данным, файл не декодируется полностью. Это подходит для проверки ограничений по ширине и высоте при загрузке изображений пользователями.

Почему cv2.imread иногда возвращает None вместо массива?

Так происходит, если файл повреждён, путь указан неверно или формат не поддерживается сборкой OpenCV. В отличие от Pillow, OpenCV не выбрасывает исключение. Перед обращением к img.shape всегда нужно проверять, что результат чтения не равен None.

Какой способ лучше подходит для обработки тысяч изображений на сервере?

Если требуется только проверка размеров, удобнее использовать Pillow без загрузки пикселей. При необходимости дальнейшего анализа изображения OpenCV подходит лучше, так как данные сразу представлены в виде массива NumPy. Выбор зависит от того, нужен ли доступ к пикселям после получения размеров.

Можно ли доверять данным о размере из EXIF?

EXIF не хранит размеры в пикселях напрямую, а содержит параметры ориентации и разрешения. Для расчёта физического размера при печати эти данные полезны, но для задач верстки и обработки изображений всегда следует опираться на width и height, полученные из заголовка файла.

Почему размеры изображения, полученные через Pillow и OpenCV, совпадают, но результат масштабирования отличается?

Обе библиотеки возвращают одинаковые значения ширины и высоты, однако используют разный порядок цветовых каналов и разные алгоритмы изменения размера по умолчанию. OpenCV работает в формате BGR и применяет собственные методы интерполяции, а Pillow использует RGB и другие фильтры ресайза. При одинаковых размерах итоговое изображение может выглядеть по-разному, поэтому при сравнении результатов нужно учитывать используемую библиотеку и явно задавать параметры масштабирования.

Ссылка на основную публикацию