Получение размеров изображения без загрузки всего изображения - PullRequest
0 голосов
/ 10 мая 2011

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

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

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

Ответы [ 2 ]

2 голосов
/ 11 мая 2011

Я полагаю, что если вы используете необработанный сокет (выполняете 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
0 голосов
/ 10 мая 2011

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

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

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

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

...