kashey
@kashey
Программирую большую половину жизни

Фиксация загрузки изображения до загрузки изображения

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

Onload тут не совсем походит — событие вызывается именно при полной загрузки.

Но на самом деле нужные мне данные доступны немного ранее, на милисекунды или даже полные секунды.
Заголовок формата уже считан, браузер уже выделил ноде нужные размеры, ему уже размеры известны.

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

Пример по проблеме я на всякий случай разместил на сайте.
В консоли можно увидеть что чтение размеров доступно задолго до полной загрузки картинки.
  • Вопрос задан
  • 3389 просмотров
Пригласить эксперта
Ответы на вопрос 5
@ComodoHacker
По правилам хорошей верстки размеры должны быть в разметке. Оттуда и брать.
Ответ написан
@avrelian
Если не найдется решение «в лоб», то можно попробовать обходной маневр — запросить размеры картинки AJAX'ом. Для работы данного варианта нужно, чтобы сервер поддерживал «Range» заголовок в запросе (чтобы не загружать картинку два раза). А также, чтобы картинка была правильно сформирована (с правильными заголовками в файле).

Скажем, мы хотим узнать размеры какой-то картинки. Пусть она, для простоты, будет в формате PNG (узнать формат конкретной картинки можно через заголовки ответа). Для примера возмем картинку с данной страницы. Следующий код, вставленный в консоль, выдаст ее правильные размеры: 82 x 61.

image

function getPngDimensions(bytes) {
    var ihdr = bytes.split(' 49 48 44 52 ')[1].split(' ');
    return {
        width: parseInt(ihdr[0] + ihdr[1] + ihdr[2] + ihdr[3], 16),
        height: parseInt(ihdr[4] + ihdr[5] + ihdr[6] + ihdr[7], 16)
    };
}

function toBytes(str) {
    var bytes = '';
    for(var i = 0, ii = str.length; i < ii; ++i) {
        var byte = str.charCodeAt(i).toString(16);
        bytes += (byte.length == 1 ? ' 0' : ' ') + byte;
    }
    return bytes;
}

$.ajax({
  url: 'http://habrahabr.ru/images/share.icons.png',
  headers: {Range: "bytes=0-29"},
  success: function(data) {
      console.log(getPngDimensions(toBytes(data))); 
  }
});


Иными словами, получаем первые 29 байт (для PNG-картинки этого хватит). Переводим в hex-строку. Находим IHDR-заголовок. Получаем ширину и высоту.
Ответ написан
freeek
@freeek
А
$(document).ready(function() {
//get image size here                                  
});

Не даёт нужного результата?
Ответ написан
@likejavascript
У YUI2, в утилите YAHOO.util.Element есть событие onAvailable, которое вызывается когда элемент может быть получен по id. Не знаю то ли это, но под капотом он все равно использует setInterval()
Ответ написан
Комментировать
azproduction
@azproduction
Думаю получится ускорить в ИЕ, используя onreadystatechange.

Мозиловский MozAfterPaint сейчас не доступен.
watch на свойство DOM элемента повесить нельзя.
Эвент «loading» для изображений только в обсуждениях рабочей группы.
Возможно есть способ подойти со стороны WebGL-ных текстур, но уверенности в этом нет.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы