ツッコミ大歓迎!間違等ありましたらご指摘ください! / はてダはこちらで書いてます。
これまたニッチ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
実は同じことをやろうとして昨日半日X3FファイルをHexエディタで読んでいました。。。
既にやっておられる方がいらっしゃったとは。
jpeg以外の部分のデータ形式が早く解読(or 公開)されるといいですね。
http://cybercom.net/~dcoffin/dcraw/
SIGMA社のSD9/SD10/SD14には対応しているので、そのうち対応するのかな?作者の人に聞いてみようかと思います.