Class: Juli::Macro::Photo

Inherits:
Base
  • Object
show all
Includes:
Visitor::Html::TagHelper
Defined in:
lib/juli/macro/photo.rb

Overview

embed photo(image) in juli wiki text with minimum maintenance cost

See ‘doc/photo(macro).txt’ for the detail.

Defined Under Namespace

Classes: ConfigNoMount, DirNameConflict

Constant Summary collapse

PUBLIC_PHOTO_DIR_DEFAULT =
'public_photo'
SEED_DEFAULT =
'-- Juli seed default!! --'
CONF_DEFAULT =
{
  'mount'     => '/home/YOUR_NAME/Photos',
  'small'     => {
    'width'   => 512,           # default small width in pixel
    'style'   => 'float: right'
  },
  'large'     => {
    'width'   => 1024           # default large width in pixel
  }
}

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Visitor::Html::TagHelper

#content_tag, #tag

Methods inherited from Base

#after_root, #initialize, #on_root

Methods included from Util

#camelize, conf, find_template, in_filename, juli_repo, mkdir, out_filename, str_limit, str_trim, to_wikiname, underscore, usage, visitor, visitor_list

Constructor Details

This class inherits a constructor from Juli::Macro::Base

Class Method Details

.conf_templateObject



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/juli/macro/photo.rb', line 30

def self.conf_template
  "# Photo macro setup sample is as follows.\n#\n#photo:\n# mount:    '\#{CONF_DEFAULT['mount']}'\n# small:\n#   width:  \#{CONF_DEFAULT['small']['width']}\n#   style:  '\#{CONF_DEFAULT['small']['style']}'\n# large:\n#   width:  \#{CONF_DEFAULT['large']['width']}\n"
end

Instance Method Details

#conf_photoObject



148
149
150
# File 'lib/juli/macro/photo.rb', line 148

def conf_photo
  @conf_photo ||= conf['photo']
end

#intern(path, size = :small, url = true) ⇒ Object

create resized, rotated, and ‘exif’ eliminated cache when:

  1. not already created, or

  2. cache is obsolete

and return the path.

INPUTS

path

photo-macro path argument

size

:small, or :large

url

when true, return url, else, return physical file-system path



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/juli/macro/photo.rb', line 113

def intern(path, size = :small, url = true)
  protected_path    = File.join(conf_photo['mount'], path)
  if !File.exist?(protected_path)
    warn("WARN: no source photo path(#{protected_path})")
    return ''
  end

  public_phys_path  = photo_path(path, size, false)
  if !File.exist?(public_phys_path) ||
      File::Stat.new(public_phys_path).mtime < File::Stat.new(protected_path).mtime

    img     = Magick::ImageList.new(protected_path)
    width   = (s = conf_photo[size.to_s]) && s['width']
    img.resize_to_fit!(width, img.rows * width / img.columns)
    self.rotate(img).
        strip!.
        write(public_phys_path).destroy!
  end
  photo_path(path, size, url)
end

#photo_name(path, size) ⇒ Object

simplify path to the non-directory name with size.

Example

path

a/b/c.jpg

photo_name

a_b_c_#size.jpg



87
88
89
90
91
# File 'lib/juli/macro/photo.rb', line 87

def photo_name(path, size)
  flat = path.gsub(/\//, '_')
  sprintf("%s_%s%s",
      File.basename(flat, '.*'), size, File.extname(flat))
end

#photo_path(path, size, url = true) ⇒ Object

cached photo path

INPUTS

path

photo-macro path argument

size

:small, or :large

url

when true, return url, else, return physical file-system path



99
100
101
# File 'lib/juli/macro/photo.rb', line 99

def photo_path(path, size, url = true)
  File.join(public_photo_dir(url), photo_name(path, size))
end

#public_photo_dir(url = true) ⇒ Object

public photo directory is used to:

  • store converted photo from original one

  • protect private photo in ‘mount’ directory from public web access by copying (with conversion) to it on demand.

INPUTS

url

when true, return url, else, return physical file-system path

Raises:



72
73
74
75
76
77
78
79
80
# File 'lib/juli/macro/photo.rb', line 72

def public_photo_dir(url = true)
  dir = File.join(conf['output_top'], PUBLIC_PHOTO_DIR_DEFAULT)
  raise DirNameConflict if File.file?(dir)

  if !File.directory?(dir)
    FileUtils.mkdir(dir)
  end
  url ? PUBLIC_PHOTO_DIR_DEFAULT : dir
end

#rotate(img) ⇒ Object

rotate image to fit orientation



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/juli/macro/photo.rb', line 49

def rotate(img)
  exif = img.get_exif_by_entry(:Orientation)
  return img if !(exif && exif[0] && exif[0][0] == :Orientation)
  case exif[0][1]
  when '1'  # Normal
    img
  when '6'  #  90 degree
    img.rotate(90)    # 90[deg] to clock direction
  when '8'  # 270 degree
    img.rotate(-90)   # 90[deg] to reversed-clock direction
  else
    img
  end
end

#run(*args) ⇒ Object

return <img…> HTML tag for the photo with this macro features.



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/juli/macro/photo.rb', line 135

def run(*args)
  path      = args[0].gsub(/\.\./, '')     # sanitize '..'
  style     = conf_photo['small']['style']
  small_url = intern(path)
  large_url = intern(path, :large)
  (:a, :href=>large_url) do
    tag(:img,
        :src    => intern(path),
        :class  => 'juli_photo_small',
        :style  => style)
  end
end

#set_conf_default(conf) ⇒ Object



44
45
46
# File 'lib/juli/macro/photo.rb', line 44

def set_conf_default(conf)
  set_conf_default_sub(conf, 'photo', CONF_DEFAULT)
end