Class: Galleruby::Album

Inherits:
Object
  • Object
show all
Defined in:
lib/galleruby/album.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(directory, name) ⇒ Album

Album representing the passed in name in the passed in directory.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/galleruby/album.rb', line 13

def initialize(directory, name)
    @name = name
    @path = "#{directory}/#{name}"
    @settings_file = "#{@path}/.galleruby.yml"
    @skip_file = "#{@path}/.galleruby.skip"


    skiplist_file = "#{@skip_file}list"
    if File.exist? skiplist_file then
        @skiplist = YAML::load(File.read(skiplist_file))
    end
    @skiplist ||= []

    if valid? then
        @info = YAML::load(File.read(@settings_file))
        # YAML serializes DateTime as Time, so we convert back.
        @info['first'] = @info['first'].to_datetime if @info.has_key?('first')
    end

    @info ||= {}

    @images_by_date = nil
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/galleruby/album.rb', line 10

def name
  @name
end

Instance Method Details

#file_needs_updating?(output_filename, original_mtime) ⇒ Boolean

Whether or not the passed in filename needs to be generated from its input, given when the input was last updated.



79
80
81
82
83
84
85
86
# File 'lib/galleruby/album.rb', line 79

def file_needs_updating?(output_filename, original_mtime)
    return true if not File.exist? output_filename
    return true if File.mtime(output_filename) < original_mtime

    # TODO: Check for 'first' etc in @info.

    return false
end

#last_updated(output_directory) ⇒ Object

When the output HTML was last generated.



50
51
52
53
54
55
56
57
# File 'lib/galleruby/album.rb', line 50

def last_updated output_directory
    output_file = "#{output_directory}/#{@info['link']}/index.html"
    if File.exist? output_file then
        File.mtime output_file
    else
        Time.at(0)
    end
end


222
223
224
# File 'lib/galleruby/album.rb', line 222

def link
  @info['link']
end

#needs_updating?(output_directory, templates_modified) ⇒ Boolean

Whether or not the album needs to update the generated HTML file and possibly the resized images, based on when the input images were modified and when the input HAML templates were last modified.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/galleruby/album.rb', line 62

def needs_updating?(output_directory, templates_modified)
    updated = last_updated output_directory

    # If the template is more recent, we need to update.
    return true if templates_modified > updated

    # If any of the images are more recent, we need to update.
    Dir.new(@path).each do |entry|
        next if not entry.match /\.jpe?g$/i
        return true if updated < File.mtime("#{@path}/#{entry}")
    end

    return false
end

#process(config, output_directory) ⇒ Object

Process generates any resized images for the album as needed, and also generates metadata about the album that’s cached in .galleruby.yml inside the albums source directory



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/galleruby/album.rb', line 91

def process(config, output_directory)
    to_process = []
    Dir.new(@path).each { |entry|
        next if not entry.match /\.jpe?g$/i
        next if @skiplist.include? entry

        to_process << entry
    }

    return false if to_process.empty?

    output_album = "#{output_directory}/#{@info['link']}"
    output_thumb = "#{output_album}/small"
    output_medium = "#{output_album}/medium"
    output_large = "#{output_album}/large"

    FileUtils.mkdir_p [output_thumb, output_medium, output_large]

    @images_by_date = Hash.new {|hash, key| hash[key] = [] }
    first_taken, last_taken = nil, nil

    # We go over each (loosely defined) valid image in the directory, and
    # generate any thumbnail, medium or large versions needed. In addition, we
    # find the range of the EXIF DateTime header for the album, so that we
    # can store that as metadata for the album.
    to_process.each do |entry|
        filename = "#{@path}/#{entry}"
        thumb_filename = "#{output_thumb}/#{entry}"
        medium_filename = "#{output_medium}/#{entry}"
        large_filename = "#{output_large}/#{entry}"

        image = LazyObject.new { o = Magick::Image.read(filename).first; o.auto_orient!; o }
        original_mtime = File.mtime filename

        if file_needs_updating?(large_filename, original_mtime) then
            new_image = image.resize_to_fit(*config[:large])
            new_image.write(large_filename)
            image.destroy!

            image = new_image
        end

        if file_needs_updating?(medium_filename, original_mtime) then
            medium_image = image.resize_to_fit(*config[:medium])
            medium_image.write(medium_filename)
            medium_image.destroy!
        end

        if file_needs_updating?(thumb_filename, original_mtime) then
            thumb_image = image.resize_to_fit(*config[:thumb])
            thumb_image.write(thumb_filename)
        else
            thumb_image = Magick::Image.ping(thumb_filename).first
        end

        taken = thumb_image.get_exif_by_entry('DateTimeOriginal').first[1]
        taken = DateTime.strptime(taken, EXIF_DATE_FORMAT)

        if last_taken.nil? then
            last_taken = taken
        else
            last_taken = taken if taken > last_taken
        end

        if first_taken.nil? then
            first_taken = taken
        else
            first_taken = taken if taken < first_taken
        end

        @images_by_date[taken.strftime('%F')] << {
            :taken => taken,
            :data => {
                :filename => entry,
                :thumb_width => thumb_image.columns,
                :thumb_height => thumb_image.rows
            }
        }

        thumb_image.destroy!
        if not image.nil? and (image.is_a?(LazyObject) and image.was_initialized?) then
            image.destroy!
        end

        if TRACK_ALLOCATIONS and num_allocated > 0 then
            puts "#{name}: Num allocated: #{num_allocated}"
        end
    end

    @info['first'] = first_taken
    if first_taken.strftime('%F') == last_taken.strftime('%F') then
        @info['date'] = first_taken.strftime('%e. %b, %Y').lstrip
    else
        range_start = first_taken.strftime('%e').lstrip
        if first_taken.year == last_taken.year then
            if first_taken.month != last_taken.month then
                range_start << first_taken.strftime('. %b')
            end
        else
            range_start << first_taken.strftime('. %b, %Y')
        end

        date_range = "#{range_start} - #{last_taken.strftime('%e. %b, %Y').lstrip}"
        @info['date'] = date_range
    end

    # Here we write out the original metadata + the EXIF date range we've
    # identified.
    File.open(@settings_file, 'w') { |file| file.write(YAML.dump(@info)) }

    return true
end

#render_to(config, output_directory) ⇒ Object

Create a HTML-file for the album.



205
206
207
208
209
210
211
212
213
214
215
# File 'lib/galleruby/album.rb', line 205

def render_to(config, output_directory)
    images_by_date = @images_by_date.sort.map do |day, images|
        {
            :date => Date.strptime(day),
            :images => images.sort_by {|image| image[:taken]}.map {|image| image[:data]}
        }
    end

    output_file = "#{output_directory}/#{@info['link']}/index.html"
    Template.new('album', config).render_to(output_file, {:title => @info['title'], :images_by_date => images_by_date}, output_directory)
end

#template_infoObject

Data needed for generation of the index document.



227
228
229
# File 'lib/galleruby/album.rb', line 227

def template_info
    {:name => @info['title'], :link => @info['link'], :date => @info['date'], :first => @info['first']}
end

#valid?Boolean

Whether or not the input directory is considered a valid Galleruby album, i.e. if it has the metadata-file, is not a ‘hidden’ directory and does not have a blacklist (.galleruby.skip) file.



40
41
42
43
44
45
46
47
# File 'lib/galleruby/album.rb', line 40

def valid?
    return false if @name.start_with? '.'
    return false if not File.directory? @path
    return false if not File.exist? @settings_file
    return false if File.exist? @skip_file

    return true
end

#yearObject

The year that the first photo was taken in.



218
219
220
# File 'lib/galleruby/album.rb', line 218

def year
    @info['first'].strftime('%Y')
end