Class: RRTF::ImageNode

Inherits:
Node
  • Object
show all
Defined in:
lib/rrtf/node/image_node.rb

Overview

This class represents an image within a RTF document. Currently only the PNG, JPEG and Windows Bitmap formats are supported. Efforts are made to identify the file type but these are not guaranteed to work.

Author:

  • Peter Wood

  • Wesley Hileman

Since:

  • legacy

Constant Summary

TYPE_DICTIONARY =

Supported image types.

Since:

  • legacy

{
  :png => 'pngblip',
  :jpeg => 'jpegblip',
  :bmp => 'dibitmap0' # device independent bitmap
}.freeze
SIZING_MODE_DICTIONARY =

Supported sizing modes.

Since:

  • legacy

{
  # Size the image absolutely according to the given width and height.
  "ABSOLUTE" => "ABSOLUTE",
  # Fit the image in the box specified by the given width and height,
  # preserving the aspect ratio.
  "FIX_ASPECT_RATIO" => "FIX_ASPECT_RATIO"
}.freeze

Instance Attribute Summary collapse

Attributes inherited from Node

#parent

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Node

#is_root?, #next_node, #previous_node, #root

Constructor Details

#initialize(parent, source, id, options = {}) ⇒ ImageNode

This is the constructor for the ImageNode class.

Parameters:

  • parent (Node)

    a reference to the node that owns the new image node.

  • source (String, File)

    a reference to the image source; this must be a String, String URL, or a File.

  • id (Integer)

    a unique 32-bit identifier for the image.

  • options (Hash) (defaults to: {})

    a hash of options.

Options Hash (options):

  • "width" (String) — default: nil

    the display width of the image in twips (can be a string, see Utilities.value2twips).

  • "height" (String) — default: nil

    the display height of the image in twips (can be a string, see Utilities.value2twips).

  • "sizing_mode" (String) — default: "ABSOLUTE"

    the method used to size the image (see SIZING_MODE_DICTIONARY).

Raises:

  • (RTFError)

    whenever the image specified is not recognised as a supported image type, something other than a String or File or IO is passed as the source parameter or if the specified source does not exist or cannot be accessed.

Since:

  • legacy



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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
# File 'lib/rrtf/node/image_node.rb', line 74

def initialize(parent, source, id, options = {})
   super(parent)
   @source = source
   @id     = id

   # load default options
   options = {
     "width" => nil,
     "height" => nil,
     "sizing_mode" => "ABSOLUTE",
     "border" => nil
   }.merge(options)

   # extract options
   @displayed_width    = Utilities.value2twips(options.delete("width"))
   @displayed_height   = Utilities.value2twips(options.delete("height"))
   @sizing_mode        = SIZING_MODE_DICTIONARY[options.delete("sizing_mode")]
   @border             = self.class.parse_border_array(options.delete("border"))

   # store border colours in colour table
   @border.each do |b|
     b.push_colours(root.colours)
   end

   # Store path to image.
   if @source.is_a?(String)
     begin
       @source = open(@source)
     rescue OpenURI::HTTPError => error
       response = error.io
       RTFError.fire("Could not open '#{@source}'. Server responded with #{response.status.join(',')}.")
     rescue Exception => error
       RTFError.fire("Could not open '#{@source}'. #{error.message}.")
     end # rescue block
   elsif !@source.respond_to?(:each_byte)
     RTFError.fire("A string or object that responds to :each_byte must be supplied - '#{@source}' given.")
   end # unless

   # Attempt to determine image type and dimensions.
   @type, @width, @height = self.class.inspect(@source)
   if @type.nil?
      RTFError.fire("The #{File.basename(@source)} file contains an unknown or unsupported image type.")
   elsif @width.nil? || @height.nil?
     RTFError.fire("Could not determine the dimensions of #{File.basename(@source)}.")
   end # if

   @displayed_width, @displayed_height = size_image
end

Instance Attribute Details

#borderObject

Since:

  • legacy



28
29
30
# File 'lib/rrtf/node/image_node.rb', line 28

def border
  @border
end

#displayed_heightObject

Since:

  • legacy



28
29
30
# File 'lib/rrtf/node/image_node.rb', line 28

def displayed_height
  @displayed_height
end

#displayed_widthObject

Since:

  • legacy



28
29
30
# File 'lib/rrtf/node/image_node.rb', line 28

def displayed_width
  @displayed_width
end

#heightObject (readonly)

Since:

  • legacy



28
29
30
# File 'lib/rrtf/node/image_node.rb', line 28

def height
  @height
end

#sizing_modeObject

Since:

  • legacy



28
29
30
# File 'lib/rrtf/node/image_node.rb', line 28

def sizing_mode
  @sizing_mode
end

#typeObject (readonly)

Since:

  • legacy



28
29
30
# File 'lib/rrtf/node/image_node.rb', line 28

def type
  @type
end

#widthObject (readonly)

Since:

  • legacy



28
29
30
# File 'lib/rrtf/node/image_node.rb', line 28

def width
  @width
end

Class Method Details

.inspect(source) ⇒ Array<Object>

Attempts to extract the type, width, and height of an image using FastImage.

Parameters:

  • source (String)

    the file path to the source image.

Returns:

  • (Array<Object>)

    a 3-tuple containing the type, width, and height of the image, respectively (type is a symbol, dimensions in pixels).

Since:

  • legacy



37
38
39
40
41
42
43
44
# File 'lib/rrtf/node/image_node.rb', line 37

def self.inspect(source)
  type, width, height = nil

  type = TYPE_DICTIONARY[FastImage.type(source)]
  width, height = FastImage.size(source) unless type.nil?

  [type, width, height]
end

.parse_border_array(border) ⇒ Object

inspect()

Since:

  • legacy



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rrtf/node/image_node.rb', line 46

def self.parse_border_array(border)
  case border
  when nil
    []
  when BorderStyle
    [border]
  when Hash
    [BorderStyle.new(border)]
  when Array
    border.collect{ |b| parse_border_array(b) }.flatten.compact
  else
    RTFError.fire("Invalid border #{b}.")
  end
end

Instance Method Details

#to_rtfObject

This method generates the RTF for an ImageNode object.

Since:

  • legacy



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
# File 'lib/rrtf/node/image_node.rb', line 124

def to_rtf
  text  = StringIO.new
  count = 0

  text << '{\pict'
  @border.each{ |b| text << " #{b.prefix(self.root)}" }
  text << "\\picwgoal#{@displayed_width}" if @displayed_width != nil
  text << "\\pichgoal#{@displayed_height}" if @displayed_height != nil
  text << "\\picw#{@width}\\pich#{@height}\\bliptag#{@id}"
  text << "\\#{@type}\n"

  @source.each_byte do |byte|
    hex_str = byte.to_s(16)
    hex_str.insert(0,'0') if hex_str.length == 1
    text << hex_str
    count += 1
    if count == 40
      text << "\n"
      count = 0
    end # if
  end # each_byte
  text << "\n}"

  text.string
end