Можно ли определить размеры изображения по URL-адресу без загрузки всего изображения?

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

Есть ли способ получить ширину и высоту изображения без загрузки полного изображения?


person mirceapasoi    schedule 13.02.2011    source источник
comment
Вам следует подумать о том, чтобы посмотреть на теги img, как предлагает @gor. Вы можете поспорить, что они используют один и тот же шаблон для публикации каждой новости, поэтому вы, вероятно, можете получить его с помощью div или img id / class.   -  person Brian D    schedule 13.02.2011
comment
Сканируя Интернет, чтобы создать одну гигантскую новостную ленту, да. Отличная идея :) (Нашел ваш summify.com)   -  person Brian D    schedule 13.02.2011
comment
Нет, не будет немедленного ответа, и предложение @Brian D - это вариант, но не забывайте, что css может вступить в игру ... Альтернативой не загружать все изображение является создание HEAD для URL-адреса изображения. Это, вероятно, вернет длину содержимого, которая даст вам размер (но не по высоте / ширине) изображения. Надуманная идея: вы можете даже сделать еще один шаг, если вы знаете тип содержимого и знаете, что вам нужны только первые 128 байтов для определения фактической ширины и высоты, вы перестанете брать байты с сервера после первых 128. байты ...   -  person rene    schedule 13.02.2011
comment
@agerhalls thos 128 байтов, где пример ... Если вы знаете формат файла и высоту / ширину в первых 128 байтах (или 256, или 1024, или первые 4 байта), вам нужно получить только эти байты. если формат файла хранит информацию о размере в последних четырех байтах, у вас нет другой возможности обработать весь файл. Это соответствует твоему ответу.   -  person rene    schedule 13.02.2011
comment
Ну ладно, я понял :) ... мы в очереди, вот что делает мой образец. Он возвращает информацию о размере, как только получает ее из потока ответов. Для JPEG вы не знаете точное положение заголовка. У них могут быть вложенные миниатюры с собственной информацией о размере, которую нужно пропустить в первую очередь, поэтому информация о размере может быть довольно поздно в файле.   -  person asgerhallas    schedule 13.02.2011
comment
@rene, это именно то, чем я хочу заниматься. Интересно, есть ли библиотека Python, которую я могу использовать вместо того, чтобы делать это вручную для каждого формата.   -  person mirceapasoi    schedule 14.02.2011
comment
@mirceapasoi проверьте мою правку моего ответа относительно Python ...   -  person asgerhallas    schedule 14.02.2011
comment
@asgerhallas Большое спасибо! @BrianD Рад, что вам нравится Summify!   -  person mirceapasoi    schedule 14.02.2011
comment
На самом деле, «обрабатывать весь файл» не совсем так, как это бывает. Если вы действительно знаете, где находится информация, вы можете получить ее с помощью осторожного HTTP-запроса с заголовками Range, где вы можете получить любой произвольный диапазон байтов в файле (даже только последние 4 байта, если хотите). Однако файлы JPEG непросты по всем причинам, указанным выше; Я собираю фрагменты файла размером 8 КБ и смотрю, как часто там будет заголовок.   -  person Arantor    schedule 19.10.2011


Ответы (2)


Не знаю, поможет ли это ускорить работу приложения, но это можно сделать. Ознакомьтесь с этими двумя статьями:

http://www.anttikupila.com/flash/getting-jpg-dimensions-with-as3-without-loading-the-entire-file/ для JPEG.

http://www.herrodius.com/blog/265 для PNG

Оба они предназначены для ActionScript, но этот принцип, конечно же, применим и к другим языкам.

Я сделал образец на C #. Это не самый красивый код, он работает только для JPEG, но его можно легко расширить и до PNG:

var request = (HttpWebRequest) WebRequest.Create("http://unawe.org/joomla/images/materials/posters/galaxy/galaxy_poster2_very_large.jpg");
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
{
    int r;
    bool found = false;
    while (!found && (r = responseStream.ReadByte()) != -1)
    {
        if (r != 255) continue;

        int marker = responseStream.ReadByte();

        // App specific
        if (marker >= 224 && marker <= 239)
        {
            int payloadLengthHi = responseStream.ReadByte();
            int payloadLengthLo = responseStream.ReadByte();
            int payloadLength = (payloadLengthHi << 8) + payloadLengthLo;
            for (int i = 0; i < payloadLength - 2; i++)
                responseStream.ReadByte();
        }
        // SOF0
        else if (marker == 192)
        {
            // Length of payload - don't care
            responseStream.ReadByte();
            responseStream.ReadByte();

            // Bit depth - don't care
            responseStream.ReadByte();

            int widthHi = responseStream.ReadByte();
            int widthLo = responseStream.ReadByte();
            int width = (widthHi << 8) + widthLo;

            int heightHi = responseStream.ReadByte();
            int heightLo = responseStream.ReadByte();
            int height = (heightHi << 8) + heightLo;

            Console.WriteLine(width + "x" + height);
            found = true;
        }
    }
}

РЕДАКТИРОВАТЬ: Я не эксперт по Python, но в этой статье описывается библиотека Python, выполняющая именно это (последний пример): http://effbot.org/zone/pil-image-size.htm

person asgerhallas    schedule 13.02.2011
comment
Следует отметить, что этот пример не прерывает загрузку, он просто записывает результат сразу после его получения и продолжает. Но прервать его тривиально, для .NET просто требуется выполнить асинхронный запрос. Еще одно замечание: для прогрессивных JPEG вам также нужно проверить SOF2. - person asgerhallas; 14.02.2011
comment
Спасибо за ответ и за ссылку на Python, это именно то, что я искал! - person mirceapasoi; 14.02.2011

Нет, это невозможно. Но вы можете получить информацию из тегов img, но не из фона.

person gor    schedule 13.02.2011
comment
Согласованный. В любом случае большую часть времени уйдет на загрузку больших изображений. Вы не сэкономите много времени, экономя на маленьких изображениях. (Попробуйте скачать все асинхронно.) - person Natan Yellin; 13.02.2011
comment
Да, асинхронная загрузка может значительно ускорить работу. Но не создавайте много потоков, используйте асинхронные функции. - person gor; 13.02.2011
comment
Почему это невозможно? Не думаю, что можно полагаться на информацию в тегах img, вы можете поставить туда любые значения ширины и высоты. - person mirceapasoi; 14.02.2011
comment
Это возможно. Я только что это сделал :) - person asgerhallas; 14.02.2011