Class: Aspera::Preview::Terminal

Inherits:
Object
  • Object
show all
Defined in:
lib/aspera/preview/terminal.rb

Overview

Display a picture in the terminal. Either use coloured characters or iTerm2 protocol.

Class Method Summary collapse

Class Method Details

.build(blob, text: false, reserve: 3, double: true, font_ratio: DEFAULT_FONT_RATIO) ⇒ String

Returns The image as text, or the iTerm2 escape sequence.

Parameters:

  • blob (String)

    The image as a binary string

  • text (Boolean) (defaults to: false)

    true to display the image as text, false to use iTerm2 if supported

  • reserve (Integer) (defaults to: 3)

    Number of lines to reserve for other text than the image

  • double (Boolean) (defaults to: true)

    true to use colors on half lines, false to use colors on full lines

  • font_ratio (Float) (defaults to: DEFAULT_FONT_RATIO)

    ratio = font height / font width

Returns:

  • (String)

    The image as text, or the iTerm2 escape sequence



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
# File 'lib/aspera/preview/terminal.rb', line 106

def build(blob, text: false, reserve: 3, double: true, font_ratio: DEFAULT_FONT_RATIO)
  return '[Image display requires a terminal]' unless Environment.terminal?
  return iterm_display_image(blob) if iterm_supported? && !text
  pixel_colors =
    begin
      Log.log.debug('Trying chunky_png')
      Backend::ChunkyPNG.new(blob, reserve: reserve, double: double, font_ratio: font_ratio).terminal_pixels
    rescue => e
      Log.log.debug(e.message)
      begin
        Log.log.debug('Trying rmagick')
        Backend::RMagick.new(blob, reserve: reserve, double: double, font_ratio: font_ratio).terminal_pixels
      rescue => e
        Log.log.debug(e.message)
        nil
      end
    end
  if pixel_colors.nil?
    return iterm_display_image(blob) if iterm_supported?
    raise 'Cannot decode picture.'
  end
  # now generate text
  text_pixels = []
  pixel_colors.each_with_index do |row_data, row|
    next if double && (row.odd? || row.eql?(pixel_colors.length - 1))
    row_data.each_with_index do |pixel_rgb, col|
      text_pixels.push("\n") if col.eql?(0) && !row.eql?(0)
      if double
        text_pixels.push(Rainbow('▄').background(pixel_rgb).foreground(pixel_colors[row + 1][col]))
      else
        text_pixels.push(Rainbow(' ').background(pixel_rgb))
      end
    end
  end
  return text_pixels.join
end

.iterm_display_image(blob) ⇒ Object

display image in iTerm2 iterm2.com/documentation-images.html



145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/aspera/preview/terminal.rb', line 145

def iterm_display_image(blob)
  # image = Magick::ImageList.new.from_blob(blob)
  # parameters for iTerm2 image display
  arguments = {
    inline:              1,
    preserveAspectRatio: 1,
    size:                blob.length
    # width:               image.columns,
    # height:              image.rows
  }.map{ |k, v| "#{k}=#{v}"}.join(';')
  # \a is BEL, \e is ESC : https://github.com/ruby/ruby/blob/master/doc/syntax/literals.rdoc#label-Strings
  # escape sequence for iTerm2 image display
  return "\e]1337;File=#{arguments}:#{Base64.strict_encode64(blob)}\a"
end

.iterm_supported?Boolean

Returns true if the terminal supports iTerm2 image display.

Returns:

  • (Boolean)

    true if the terminal supports iTerm2 image display



161
162
163
164
165
166
# File 'lib/aspera/preview/terminal.rb', line 161

def iterm_supported?
  TERM_ENV_VARS.each do |env_var|
    return true if ITERM_NAMES.any?{ |term| ENV[env_var]&.include?(term)}
  end
  false
end