Simplify footer text when everything is identical.
[homepage.git] / lib / imginfo.rb
1 # Nick's web site: imginfo filter.  Generate XML representation of image
2 # metadata which can be further processed into a web page.
3 #
4 # Copyright © 2020 Nick Bowler
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
19 class ImgInfoFilter < Nanoc::Filter
20     identifier :imginfo
21     type :binary => :text
22
23     require 'exifr/jpeg'
24     require 'fastimage'
25
26     def do_variant(xml, name, item = @item, rep: :default)
27         file = item.reps[rep].raw_path
28         unless file.nil?
29             w, h = FastImage.size(file)
30             sz = File.size(file)
31
32             xml.variant {
33                 xml.name(name)
34                 xml.uri(item_uri(item, rep: rep))
35                 xml.width(w)
36                 xml.height(h)
37                 xml.filesize(human_filesize(sz))
38             }
39         end
40     end
41
42     def run(filename, params = {})
43         exif = EXIFR::JPEG.new(filename).to_hash
44
45         b = Nokogiri::XML::Builder.new do |xml|
46             xml.image {
47                 do_variant(xml, "Large", rep: :large)
48                 do_variant(xml, "Medium", rep: :medium)
49                 do_variant(xml, "Original")
50
51
52                 if @item[:description]
53                     xml.description(:xmlns => 'http://www.w3.org/1999/xhtml') {
54                         xml << @item[:description]
55                     }
56                 end
57
58                 xml.exif {
59                     exif.each do |key, value|
60                         # Convert some fields to more useful forms...
61                         case key
62                         when :f_number, :exposure_bias_value
63                             value = sprintf("%.1f", value)
64                         when :focal_length
65                             value = sprintf("%d\n", value)
66                         when :gps_version_id
67                             value = value.bytes.join(".")
68                         when :exposure_program
69                             case value
70                             when 1 then value = "Manual"
71                             when 2 then value = "Normal program"
72                             when 3 then value = "Aperture priority"
73                             when 4 then value = "Shutter priority"
74                             end
75                         when :metering_mode
76                             case value
77                             when 1 then value = "Average"
78                             when 2 then value = "Center weighted average"
79                             when 3 then value = "Spot"
80                             when 4 then value = "Multi-spot"
81                             when 5 then value = "Pattern"
82                             when 6 then vlaue = "Partial"
83                             end
84                         when :flash
85                             tmp = if value & 1 == 1 then "Yes" else "No" end
86                             case (value >> 3) & 3
87                             when 1, 2 then tmp += ", compulsory"
88                             when 3 then tmp += ", auto"
89                             end
90                             case (value >> 1) & 3
91                             when 2 then tmp += ", return light not detected"
92                             when 3 then tmp += ", return light detected"
93                             end
94                             value = tmp
95                         end
96
97                         case value
98                         when String
99                             value.delete!("\x00")
100                             value.strip!
101                         when Time
102                             # EXIF does not do timezones so don't display one
103                             value = value.strftime("%Y-%m-%d %H:%M:%S")
104                         end
105
106                         xml.send((key.to_s << "_").to_sym, value.to_s)
107                     end
108                 }
109             }
110         end
111         b.to_xml
112     end
113 end