Получение размеров изображения без загрузки всего изображения

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

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

Есть ли еще способы оптимизировать это?


person Aen Tan    schedule 10.05.2011    source источник
comment
Это полностью зависит от типа изображений, которые вы обрабатываете. Не все изображения имеют метаданные в заголовке.   -  person Matthew Scharley    schedule 10.05.2011
comment
возможный дубликат Быстрый способ получить размеры удаленного изображения   -  person the Tin Man    schedule 10.05.2011
comment
Пожалуйста, не повторяйте свои вопросы.   -  person the Tin Man    schedule 10.05.2011
comment
@Железный человечек. Это другой вопрос. Я бреюсь.   -  person Aen Tan    schedule 10.05.2011


Ответы (2)


Я считаю, что если вы используете исходный сокет (выдаете простой HTTP-запрос), нет необходимости загружать более нескольких байтов (и прерывать соединение), чтобы определить размеры изображений.

require 'uri'
require 'socket'
raise "Usage: url [bytes-to-read [output-filename]]" if ARGV.length < 1
uri   = URI.parse(ARGV.shift)
bytes = (ARGV.shift || 50).to_i
file  = ARGV.shift
$stderr.puts "Downloading #{bytes} bytes from #{uri.to_s}"
Socket.tcp(uri.host, uri.port) do |sock|
  # http request
  sock.print "GET #{uri.path} HTTP/1.0\r\nHost: #{uri.host}\r\n\r\n"
  sock.close_write
  # http response headers
  while sock.readline.chomp != ""; end
  # http response body, we need first N bytes
  if file
    open(file,"wb") {|f| f.write(sock.read(bytes)) }
  else
    puts sock.read(bytes)
  end
end

например если я вставлю первые 33 байта файла PNG (13 байтов для GIF) в exiftool, он даст мне размер изображения

$ ruby download_partial.rb http://yardoc.org/images/ss5.png 33 | exiftool - | grep ^Image
Downloading 33 bytes from http://yardoc.org/images/ss5.png
Image Width                     : 1000
Image Height                    : 300
Image Size                      : 1000x300
person choonkeat    schedule 11.05.2011
comment
Является ли размер байта стандартным для форматов изображений? например 33 для PNG и 13 для GIF. - person Aen Tan; 12.05.2011
comment
Я получаю неопределенный метод `tcp' для Socket:Class (NoMethodError). Я что-то упускаю? - person Aen Tan; 12.05.2011
comment
извините, не видел комментарии ожидания. я использую рубин 1.9. что касается смещения размера байта, я не совсем уверен, что просто взял образец из GIF и PNG на моем жестком диске - person choonkeat; 28.06.2011

Я не знаю, как указать, сколько байтов нужно загрузить с помощью обычного HTTPd-запроса. Это ситуация «все или ничего».

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

Прошло много времени с тех пор, как я играл на этом уровне, но теоретически вы могли бы использовать блок с Net::HTTP или Open-URI и считать байты, пока не получите соответствующее число, чтобы добраться до блока размера изображения. , затем закройте соединение. Ваш стек TCP, вероятно, не был бы слишком доволен вами, особенно если бы вы делали это много. Если я правильно помню, он не будет избавляться от памяти до тех пор, пока не истечет время ожидания соединения, и съест доступные соединения либо на вашей стороне, либо на сервере. И, если бы я запустил сайт и обнаружил, что производительность моего сервера скомпрометирована вашим приложением, преждевременно закрывающим соединения, я бы вас забанил.

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

person the Tin Man    schedule 10.05.2011