Skip to content

Instantly share code, notes, and snippets.

@pedrocr
Created December 15, 2021 23:22
Show Gist options
  • Save pedrocr/37bdd976df98ae785566314c763206f1 to your computer and use it in GitHub Desktop.
Save pedrocr/37bdd976df98ae785566314c763206f1 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'nokogiri'
if ARGV.size != 1
$stderr.puts "Usage: get_defs <file>"
exit 2
end
COLORS = {
"0"=>"R",
"1"=>"G",
"2"=>"B",
"3"=>"E",
"4"=>"M",
"5"=>"Y",
}
@rawspeed_info = {}
xml_doc = Nokogiri::XML(File.open("../rawspeed/data/cameras.xml"))
xml_doc.css("Camera").each do |c|
maker = canonical_maker = c.attribute("make").value
model = canonical_model = c.attribute("model").value
if c.css("ID")[0]
canonical_maker = c.css("ID")[0].attribute("make").value
canonical_model = c.css("ID")[0].attribute("model").value
end
mode = ""
mode = c.attribute("mode").value if c.attribute("mode")
x = y = width = height = 0;
c.css("Crop").each do |a|
x = a.attribute("x").value.to_i
y = a.attribute("y").value.to_i
width = a.attribute("width").value.to_i
height = a.attribute("height").value.to_i
end
@rawspeed_info[[maker,model,mode]] = [canonical_maker,canonical_model,x,y,width,height]
@rawspeed_info[[maker,model,""]] = [canonical_maker,canonical_model,x,y,width,height]
c.css("Alias").each do |a|
model = a.content
canonical_model = a.attribute("id").value if a.attribute("id")
@rawspeed_info[[maker,model,mode]] = [canonical_maker,canonical_model,x,y,width,height]
@rawspeed_info[[maker,model,""]] = [canonical_maker,canonical_model,x,y,width,height]
end
end
$file=ARGV[0];
def get_key(key)
line = IO.popen("exiv2 -Pkt \"#{$file}\" 2>/dev/null | grep '#{key} ' ","r").read
return "" if line == ""
line.split(" ")[1..-1].join(" ")
end
def get_key_rational(key)
v = get_key(key)
parts = v.split("/")
return 0 if parts == []
if parts.size() == 1
parts[0].to_i
else
((parts[0].to_f)/(parts[1].to_f)).to_i
end
end
maker = get_key("Exif.Image.Make")
model = get_key("Exif.Image.Model")
width = get_key("Exif.SubImage1.ImageWidth").to_i
length = get_key("Exif.SubImage1.ImageLength").to_i
def calculate_crops(width, length, x, y, cropwidth, cropheight)
if cropwidth > 0
[y,width-cropwidth-x,length-cropheight-y,x]
else
[y,-cropwidth,-cropheight,x]
end
end
canonical_maker,canonical_model,x,y,cropwidth,cropheight = @rawspeed_info[[maker,model,""]]
crops = if canonical_maker
calculate_crops(width, length, x, y, cropwidth, cropheight)
else
canonical_maker = maker
canonical_model = model
[0,0,0,0]
end
canonical_maker = "Sony" if canonical_maker == "SONY"
canonical_maker = "Phase One" if canonical_maker == "Phase One A/S"
canonical_maker = "Leica" if canonical_maker == "LEICA"
if canonical_model[0..canonical_maker.size-1] == canonical_maker
canonical_model = canonical_model[canonical_maker.size..-1].strip
end
matrix = get_key("Exif.Image.ColorMatrix2")
matrix = get_key("Exif.Image.ColorMatrix1") if matrix == ""
matrix = matrix.split(" ").map{|v| v.split("/")[0].to_i}
white = get_key_rational("Exif.SubImage1.WhiteLevel")
black = get_key_rational("Exif.SubImage1.BlackLevel")
pattern = get_key("Exif.SubImage1.CFAPattern")
pattern = pattern.split(" ").map{|c| COLORS[c]}.join
# The DNG's CFA pattern is mysteriously shifted horizontally for
# 14-bit x-trans chips (despite it being stored unshifted in the raw
# file). Identify 14-bit cips by their max white value.
if maker == "FUJIFILM" && pattern.size() == 36 && white.to_i > 16000
new_pattern = " "*36
(0...6).each do |row|
(0...6).each do |col|
new_pattern[row*6+col] = pattern[row*6+((col+2)%6)]
end
end
pattern = new_pattern
end
# Fuji often has broken CFA patterns, at least make them 4 wide so it doesn't
# just generate a parsing error
if maker == "FUJIFILM" && pattern.size() == 8
pattern = pattern[0..3]
end
puts "make = \"#{maker}\""
puts "model = \"#{model}\""
puts "clean_make = \"#{canonical_maker}\""
puts "clean_model = \"#{canonical_model}\""
if maker[0..4] != "NIKON"
puts "blackpoint = #{black}"
puts "whitepoint = #{white}"
end
puts "color_matrix = #{matrix.inspect}"
puts "color_pattern = \"#{pattern}\""
if maker != "Panasonic" && maker != "LEICA"
puts "crops = [#{crops.join(",")}]"
end
puts "bps = 8" if maker == "SONY"
if maker == "Panasonic" || maker == "LEICA"
["1:1", "4:3", "3:2", "16:9"].each do |mode|
vals = @rawspeed_info[[maker,model,mode]]
if vals
canonical_maker,canonical_model,x,y,cropwidth,cropheight = vals
crops = if cropwidth > 1000
["Needs attention"]
else
calculate_crops(width, length, x, y, cropwidth, cropheight)
end
puts
puts "[[cameras.modes]]"
puts "mode = \"#{mode}\""
puts "crops = [#{crops.join(",")}]"
end
end
end
if maker[0..4] == "NIKON"
bps = if white < 4096
12
else
14
end
puts
puts "[[cameras.modes]]"
puts "mode = \"#{bps}bit\""
puts "blackpoint = #{black}"
puts "whitepoint = #{white}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment