Hatena::Grouprubyist

takuma104のRuby/Rails日記

ツッコミ大歓迎!間違等ありましたらご指摘ください! / はてダはこちらで書いてます。

 | 

2008-05-05

RubyでDP1のRAW画像からサムネイルとかのJPEGを抜き出すコードを書いた

| 01:54 | RubyでDP1のRAW画像からサムネイルとかのJPEGを抜き出すコードを書いた - takuma104のRuby/Rails日記 を含むブックマーク はてなブックマーク - RubyでDP1のRAW画像からサムネイルとかのJPEGを抜き出すコードを書いた - takuma104のRuby/Rails日記 RubyでDP1のRAW画像からサムネイルとかのJPEGを抜き出すコードを書いた - takuma104のRuby/Rails日記 のブックマークコメント

これまたニッチwなのを書きました。SIGMA DP1 というすばらしい絵が撮れるデジカメがあるのですが、この RAW 画像が、なかなか普通の RAW 現像ソフトとかで対応してもらえなくて結構ファイルの取り扱いに困ります。DP1 付属の RAW 現像ソフトはよく出来ているのですが、やっぱり OS のプレビュー使いたいなとかで、JPEG にしたいとかがあると思います。そんな時 RAW の中に JPEG がそのまま格納(オリジナルサイズのも!)されているのを知ったので、それを抜き出せないかと。ちょっと書いてみたらまあまあシンプルだったので貼ってみます。

DP1 の RAW フォーマットである X3F の解説は、こちらから。作者さんthanks!

http://anotherm8.exblog.jp/7838817/

一番下にコードを貼りました。使い方は x3f.rb とかで保存して

 $ ruby x3f.rb SDIM0000.X3F

とかで、同じディレクトリに SDIM0000.X3F.thumb.jpg と SDIM0000.X3F.jpg の2ファイルができます。

.thumb.jpg の方がサムネイル用 (221x147) で、 .jpg のほうが、元サイズとおなじ 2640 x 1780 のサイズの JPEG になります。.jpg のほうは、Flickrとかにまず上げる際とかに、そのまま使えそうですね。もちろんちゃんと現像した方が全然良いですが(たぶんAuto現像でもこれよりいい絵が出来るんじゃないかと思いますが)、とりあえず見れると言えば見れる絵です。

ちなみに、引数にディレクトリを指定すると、それ以下の全フォルダ内のX3Fをスキャンして全部このJPEGを作成します。

module X3F
  class Parser
    def initialize(fn)
      @x3f = open(fn, 'rb')
      @dic_entries = []
    end
    
    def close
      @x3f.close
    end
    
    def parse_dictionary
      len = File.size(@x3f)
      doff = read32u(len - 4)
      raise "Premature end of file" if doff > len
      raise 'SECd not found.' if read4B(doff) != 'SECd'
      raise 'SECd version is not 0x00020000.' if read32u(doff+4) != 0x00020000
      entries = read32u(doff+8)
      entries.times do |i|
        pt = doff + 12 + i * 4 * 3
        @dic_entries <<  {:offset=>read32u(pt), :size=>read32u(pt+4), :tag=>read4B(pt+8)}
      end
    end

    def save_jpeg(fn, thumbnail=false)
      e = nil
      if thumbnail
        e = @dic_entries[4]
      else
        e = @dic_entries[0]
      end

      raise 'JPEG not found' if e[:tag] != 'IMA2'
      open(fn, 'wb') do |f|
        o = e[:offset]; s = e[:size]
        o += 28; s -= 28 # skip head 28 bytes
        @x3f.pos = o
        f.write(@x3f.read(s))
      end
    end

private
    def read4B(offset)
      @x3f.pos = offset
      @x3f.read(4)
    end
    
    def read32u(offset)
      read4B(offset).unpack('V1')[0]
    end
  end
end

if $0 == __FILE__
  def pickjpegs(path)
    x3f = X3F::Parser.new(path)
    x3f.parse_dictionary
    x3f.save_jpeg(path + '.jpg', false) # for full size JPEG
    x3f.save_jpeg(path + '.thumb.jpg', true) # for thumbnail JPEG
    x3f.close
  end
  
  path = ARGV.shift
  case File.ftype(path)
  when 'directory'
    Dir::glob(File.expand_path(path) + "/**/*.X3F") do |fn|
      puts fn
      pickjpegs(fn)
    end
  when 'file'
    pickjpegs(path)
  else
    puts "usage: ruby x3f.rb x3f_filename.x3f"
  end
end

きたしきたし2008/05/11 12:41すばらしい!
実は同じことをやろうとして昨日半日X3FファイルをHexエディタで読んでいました。。。
既にやっておられる方がいらっしゃったとは。

jpeg以外の部分のデータ形式が早く解読(or 公開)されるといいですね。

takuma104takuma1042008/05/11 15:34ありがとうございます。Foveonデータの方ですが、dcraw.cではまだ対応されてないみたいですね...
http://cybercom.net/~dcoffin/dcraw/

SIGMA社のSD9/SD10/SD14には対応しているので、そのうち対応するのかな?作者の人に聞いてみようかと思います.

takuma104takuma1042008/05/11 22:37さきほど作者のdcoffinさんに、サンプルのRAWファイルとともに対応を聞いておきました。何かレスがあったらまたここに書き込みます。

トラックバック - http://rubyist.g.hatena.ne.jp/takuma104/20080505
 |