Class: ImageContent

Inherits:
DocumentContent show all
Includes:
Zena::Use::Upload::UploadedFile
Defined in:
app/models/image_content.rb

Overview

Used by Image to store image data. See the documentation on this class for more information.

Attributes

Provides the following attributes/methods to Image :

size(format)

file size for the image using the given format

ext

file extension

content_type

file content_type

width(format)

image width in pixel using the given format

height(format)

image height in pixel using the given format

ImageContent also provides a crop pseudo attribute to crop an image. See crop=.

Instance Method Summary collapse

Methods inherited from DocumentContent

#can_destroy?, #changed?, #clone, #filepath, #size=

Instance Method Details

#can_crop?(format) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
32
33
34
# File 'app/models/image_content.rb', line 29

def can_crop?(format)
  x, y, w, h = [format['x'].to_i, 0].max, [format['y'].to_i, 0].max, [format['w'].to_i, width].min, [format['h'].to_i, height].min
  (format['max_value'] && (format['max_value'].to_f * (format['max_unit'] == 'Mb' ? 1024 : 1) * 1024) < self.size) ||
  (format['format'] && format['format'] != self.ext) ||
  ((x < width && y < height && w > 0 && h > 0) && !(x==0 && y==0 && w == width && h == height))
end

#crop=(format) ⇒ Object

Crop the image using the ‘crop’ hash with the top left corner position (:x, :y) and the width and height (:width, :heigt). Example:

@node.crop = {:x=>10, :y=>10, :width=>30, :height=>60}

Be carefull as this method changes the current file. So you should make a backup version before croping the image (the popup editor displays a warning).



39
40
41
42
43
44
45
46
47
# File 'app/models/image_content.rb', line 39

def crop=(format)
  if can_crop?(format)
    # do crop
    if file = self.cropped_file(format)
      # crop can return nil, check first.
      self.file = file
    end
  end
end

#cropped_file(format) ⇒ Object

Return a cropped image using the ‘crop’ hash with the top left corner position (:x, :y) and the width and height (:width, :heigt).



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'app/models/image_content.rb', line 51

def cropped_file(format)
  original   = format['original'] || @loaded_file || self.file
  x, y, w, h = format['x'].to_f, format['y'].to_f, format['w'].to_f, format['h'].to_f
  new_type   = format['format'] ? Zena::EXT_TO_TYPE[format['format'].downcase][0] : nil
  max        = format['max_value'].to_f * (format['max_unit'] == 'Mb' ? 1024 : 1) * 1024

  # crop image
  img = Zena::Use::ImageBuilder.new(:file=>original)
  img.crop!(x, y, w, h) if x && y && w && h
  img.format       = format['format'] if new_type && new_type != content_type
  img.max_filesize = max if format['max_value'] && max

  file = Tempfile.new(name)
  File.open(file.path, "wb") { |f| f.syswrite(img.read) }

  ctype = Zena::EXT_TO_TYPE[img.format.downcase][0]
  fname = "#{name}.#{Zena::TYPE_TO_EXT[ctype][0]}"
  uploaded_file(file, fname, ctype)
end

#exifObject



146
147
148
# File 'app/models/image_content.rb', line 146

def exif
  @exif ||= ExifData.new(self[:exif_json])
end

#exif_gps_latitudeObject

FIXME: remove when RubyLess is here !



151
152
153
# File 'app/models/image_content.rb', line 151

def exif_gps_latitude
  exif.gps_latitude
end

#exif_gps_longitudeObject

FIXME: remove when RubyLess is here !



156
157
158
# File 'app/models/image_content.rb', line 156

def exif_gps_longitude
  exif.gps_longitude
end

#file(format = nil) ⇒ Object

Return a file with the data for the given format. It is the receiver’s responsability to close the file.



121
122
123
124
125
126
127
128
129
130
131
# File 'app/models/image_content.rb', line 121

def file(format=nil)
  if format.nil? || format.size == :keep
    super
  else
    if File.exist?(filepath(format)) || make_image(format)
      File.new(filepath(format))
    else
      nil
    end
  end
end

#file=(file) ⇒ Object

Set content file, will refuse to accept the file if it is not an image.



72
73
74
75
76
77
78
79
# File 'app/models/image_content.rb', line 72

def file=(file)
  super
  return unless Zena::Use::ImageBuilder.image_content_type?(file.content_type)
  img = image_with_format(nil)
  self[:width ] = img.width
  self[:height] = img.height
  self[:exif_json] = img.exif.to_json rescue nil
end

#height(format = nil) ⇒ Object

Return the height in pixels for an image at the given format.



108
109
110
111
112
113
114
115
116
117
118
# File 'app/models/image_content.rb', line 108

def height(format=nil)
  if format.nil? || format.size == :keep
    self[:height]
  else
    if img = image_with_format(format)
      img.height
    else
      nil
    end
  end
end

#image_with_format(format = nil) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
# File 'app/models/image_content.rb', line 133

def image_with_format(format=nil)
  if @new_file
    Zena::Use::ImageBuilder.new(:file => @new_file).transform!(format)
  elsif !new_record?
    format   ||= Iformat['full']
    @formats ||= {}
    @formats[format[:name]] ||= Zena::Use::ImageBuilder.new(:path => filepath,
            :width => self[:width], :height => self[:height]).transform!(format)
  else
    raise StandardError, "No image to work on"
  end
end

#size(format = nil) ⇒ Object

Return the size for an image at the given format.



82
83
84
85
86
87
88
89
90
91
92
# File 'app/models/image_content.rb', line 82

def size(format=nil)
  if format.nil? || format.size == :keep
    super
  else
    if File.exist?(filepath(format)) || make_image(format)
      File.stat(filepath(format)).size
    else
      nil
    end
  end
end

#width(format = nil) ⇒ Object

Return the width in pixels for an image at the given format.



95
96
97
98
99
100
101
102
103
104
105
# File 'app/models/image_content.rb', line 95

def width(format=nil)
  if format.nil? || format.size == :keep
    self[:width]
  else
    if img = image_with_format(format)
      img.width
    else
      nil
    end
  end
end

#would_edit?(new_attrs) ⇒ Boolean

Returns:

  • (Boolean)


25
26
27
# File 'app/models/image_content.rb', line 25

def would_edit?(new_attrs)
  super || (new_attrs['crop'] && can_crop?(new_attrs['crop']))
end