2011-12-21 10 views
3

旅行用のウェブサイトに数千枚の高解像度JPEG写真が保存されています。いくつかの重要なEXIFメタを抽出するRubyコードを書きたいと考えています画像のデータ値はで、各画像ファイルの内容全体がダウンロードされていません(サイズは大きく、たくさんあります)。Rubyを使用したリモート画像からの効率的なEXIFメタデータの読み取り

EXIFデータを読み込むために 'exifr' gemを使用しています。ローカルファイルだけでなく、あらゆるタイプのIOオブジェクトで動作するように設計されています。ただし、ブロックread_bodyメソッドを渡すとインクリメンタルな読み取りが可能ですが、Net::HTTPResponseオブジェクトは実際にはIOオブジェクトではありません。しかし、このインクリメンタルリードが実際にファイルの一部だけをダウンロードできるかどうか、または効率を上げるためにコンテンツをまとめて読み取ることができるかどうかについて(つまり、コンテンツ全体がダウンロードされる)矛盾するレポートを読んでいます。

私は可能なことをしようとしていますか? Net::HTTPの代替案を調べるべきか、または、低レベルのTCPソケット(IOオブジェクトでなければならない)を取得して、取得するイメージを十分に読み取るための 'exifr'コードに渡す方法がいくつかありますEXIFデータ?その他のソリューション?

+0

私は、[JPEG圧縮のWikipediaの記事](http://en.wikipedia.org/wiki/JPEG#Syntax_and_structure)の迅速なスキムミルクを取り、EXIFパケットがさえ 'に位置しているのだろうか信頼性の高いファイルの位置?特定のカメラが予測可能かもしれませんが、EXIFデータがファイルの最後または最初にあると確信できるとは思いません...あなたがヒューリスティックのために十分似ている場合に見なければならないファイルのEXIFデータ... – sarnold

答えて

1

私は写真の私の山に、EXIFデータが格納されている、の迅速なテーブル生成:

$ find . -type f -exec grep -a -bo Exif {} \; > /tmp/exif 
$ sort /tmp/exif | uniq -c | sort -n 
     1 12306:Exif 
     1 3271386:Exif 
     1 8210:Exif 
     1 8234:Exif 
     1 9234:Exif 
     2 10258:Exif 
    24 449:Exif 
    30 24:Exif 
    8975 6:Exif 
$ 

過半数をファイルにわずか数バイトを。一握りは他の場所に散在していますが、最悪の場合はファイルにわずか3メガバイトしかありません。 (与えてください。)

私は、単一のURLに必要なことを行うように見える小さなテストスクリプトを書いています。 (私が利用していた巨大なバイナリファイルの塊で文字列AAを探してテストしました)これは私が書いた最も良いプログラムではありませんが、解決策として適切なスタートになるかもしれません。 Exifテキストがチャンクにまたがる場合は、ファイル全体を取得することに注意してください。それは残念です。私はそれが頻繁に起こらないことを望む。 66000は、JPEG AAP1ブロックのサイズが64キロバイトに制限されているため、もう少し小さくするのはおそらく少し少なくするよりもおそらく良いでしょう。

#!/usr/bin/ruby 

require 'net/http' 
require 'uri' 

url = URI.parse("http://....") 

begin 
    looking = true 
    extra_size = 0 
    File.open("/tmp/output", "w") do |f| 
      Net::HTTP.start(url.host, url.port) do |http| 
        request = Net::HTTP::Get.new url.request_uri 
        http.request request do |resp| 
          resp.read_body do |chunk| 
            f.write chunk 
            if (looking) 
              if (chunk.match(/Exif/)) 
                looking = false 
              end 
            elsif (extra_size < 66000) 
              extra_size += chunk.length 
            else 
              throw "done" 
            end 
          end 
        end 
      end 
    end 
rescue 
    puts "done" 
    exit(0) 
end 
関連する問題