Class: Aspera::Preview::Terminal
- Inherits:
-
Object
- Object
- Aspera::Preview::Terminal
- Defined in:
- lib/aspera/preview/terminal.rb
Overview
Display a picture in the terminal, either using coloured characters or iTerm2
Class Method Summary collapse
-
.build(blob, reserve: 3, text: false, double: true, font_ratio: DEFAULT_FONT_RATIO) ⇒ String
The image as text, or the iTerm2 escape sequence.
-
.iterm_display_image(blob) ⇒ Object
display image in iTerm2 iterm2.com/documentation-images.html.
-
.iterm_supported? ⇒ Boolean
True if the terminal supports iTerm2 image display.
Class Method Details
.build(blob, reserve: 3, text: false, double: true, font_ratio: DEFAULT_FONT_RATIO) ⇒ String
Returns the image as text, or the iTerm2 escape sequence.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/aspera/preview/terminal.rb', line 28 def build(blob, reserve: 3, text: false, double: true, font_ratio: DEFAULT_FONT_RATIO) return iterm_display_image(blob) if iterm_supported? && !text begin # do not require statically, as the package is optional require 'rmagick' # https://rmagick.github.io/index.html rescue LoadError => e Log.log.error('Install missing gem: gem install rmagick') # fallback to iterm, if supported return iterm_display_image(blob) if iterm_supported? Log.log.error('Cant display picture.') raise e end image = Magick::ImageList.new.from_blob(blob) (term_rows, term_columns) = IO.console.winsize term_rows -= reserve # compute scaling to fit terminal fit_term_ratio = [term_rows.to_f * font_ratio / image.rows.to_f, term_columns.to_f / image.columns.to_f].min height_ratio = double ? 2.0 : 1.0 image = image.scale((image.columns * fit_term_ratio).to_i, (image.rows * fit_term_ratio * height_ratio / font_ratio).to_i) # quantum depth is 8 or 16, see: `convert xc: -format "%q" info:` shift_for_8_bit = Magick::MAGICKCORE_QUANTUM_DEPTH - 8 # get all pixel colors, adjusted for Rainbow pixel_colors = [] image.each_pixel do |pixel, col, row| pixel_rgb = [pixel.red, pixel.green, pixel.blue] pixel_rgb = pixel_rgb.map { |color| color >> shift_for_8_bit } unless shift_for_8_bit.eql?(0) # init 2-dim array pixel_colors[row] ||= [] pixel_colors[row][col] = pixel_rgb 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
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/aspera/preview/terminal.rb', line 76 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.encode64(blob)}\a" end |
.iterm_supported? ⇒ Boolean
Returns true if the terminal supports iTerm2 image display.
92 93 94 95 96 97 |
# File 'lib/aspera/preview/terminal.rb', line 92 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 |