module CatpixMini

Provides a function to print images in the terminal. A range of different formats is supported (check out what ImageMagick supports). Under the hood, this module uses two components:

Some other minor features like centering and handling background colours are supplied directly by this module.

Copyright © 2015 Radek Pazdera <me@radek.io> Distributed under the MIT License (see LICENSE.txt)

Constants

MAX_OPACITY
VERSION

Version of the gem

Public Class Methods

print_image(path, options={}) click to toggle source

Print an image to the terminal.

All formats supported by ImageMagick are supported. The image's colours will be mapped onto the extended 256 colour palette. Also by default, it will be scaled down to fit the width of the terminal while keeping its proportions. This can be changed using the `options` parameter.

@param [Hash] options Adjust some parameters of the image when printed. @option options [Float] :limit_x A factor of the terminal window's width.

If present, the image will be scaled down
to fit (proportions are kept). Using 0
will disable the scaling. [default: 1.0]

@option options [Float] :limit_y A factor of the terminal window's height.

If present, the image will be scaled down
to fit (proportions are kept). Using 0
will disable the scaling. [default: 0]

@option options [Boolean] :center_x Center the image horizontally in the

terminal window. [default: false]

@option options [Boolean] :center_y Center the image vertically in the

terminal window. [default: false]

@option options [String] :bg Background colour to use in case there are

any fully transparent pixels in the image.
This can be a RGB value '#c0ffee' or a tco
alias 'red' or 'blue'. [default: nil]

@option options [Boolean] :bg_fill Fill the margins around the image with

background colour. [default: false]

@option options [String] :resolution Determines the pixel size of the

rendered image. Can be set to `high`,
`low` or `auto` (default). If set to
`auto` the resolution will be picked
automatically based on your terminal's
support of unicode.

Private Class Methods

can_use_utf8?() click to toggle source
# File lib/catpix_mini/private.rb, line 31
def self.can_use_utf8?
  ENV.values_at("LC_ALL", "LC_CTYPE", "LANG").compact.first.include?("UTF-8")
end
default_options() click to toggle source
# File lib/catpix_mini/private.rb, line 13
def self.default_options
  {
    limit_x: 1.0,
    limit_y: 0,
    center_x: false,
    center_y: false,
    bg: nil,
    bg_fill: false,
    resolution: 'auto'
  }
end
do_print_image_hr(img, margins, options) click to toggle source

Print the image in high resolution (using unicode's upper half block)

# File lib/catpix_mini/private.rb, line 185
def self.do_print_image_hr(img, margins, options)
  pixels = img.get_pixels
  rows = img[:height]
  cols = pixels[0].length


  print prep_vert_margin margins[:top], margins[:colour]

  0.step(rows - 1, 2) do |row|
    # line buffering makes it about 20% faster
    buffer = prep_horiz_margin margins[:left], margins[:colour]
    0.upto(cols - 1) do |col|
      top_pixel = pixels[row][col]
      colour_top = top_pixel

      bottom_pixel = pixels[row+1][col]
      colour_bottom = bottom_pixel

      buffer += prep_hr_pixel colour_top, colour_bottom
    end
    buffer += prep_horiz_margin margins[:right], margins[:colour]
    puts buffer
  end

  print prep_vert_margin margins[:bottom], margins[:colour]

end
do_print_image_lr(img, margins, options) click to toggle source

Print the image in low resolution

# File lib/catpix_mini/private.rb, line 162
def self.do_print_image_lr(img, margins, options)
  pixels = img.get_pixels
  rows = img[:height]
  cols = pixels[0].length

  print prep_vert_margin margins[:top], margins[:colour]

  0.upto(rows - 1) do |row|
    buffer = prep_horiz_margin margins[:left], margins[:colour]
    0.upto(cols - 1) do |col|
      pixel = pixels[row][col]
      buffer += prep_lr_pixel pixel
    end
    buffer += prep_horiz_margin margins[:right], margins[:colour]
    puts buffer
  end

  print prep_vert_margin margins[:bottom], margins[:colour]

end
get_margins(img, center_x, center_y) click to toggle source

Determine the margins based on the centering options

# File lib/catpix_mini/private.rb, line 96
def self.get_margins(img, center_x, center_y)
  margins = {}
  tw, th = get_screen_size

  x_space = tw - img[:width]
  if center_x
    margins[:left] = x_space / 2
    margins[:right] = x_space / 2 + x_space % 2
  else
    margins[:left] = 0
    margins[:right] = x_space
  end

  y_space = th - img[:height]
  if center_y
    margins[:top] = y_space / 2
    margins[:bottom] = y_space / 2 + y_space % 2
  else
    margins[:top] = 0
    margins[:bottom] = 0
  end

  if high_res? and margins[:top] % 2 and margins[:bottom] % 2
    margins[:top] -= 1
    margins[:bottom] += 1
  end

  margins
end
get_screen_size() click to toggle source

Returns normalised size of the terminal window

Catpix can use either two blank spaces to approximate a pixel in the temrinal or the 'upper half block' and 'bottom half block' characters.

Depending on which of the above will be used, the screen size must be normalised accordingly.

# File lib/catpix_mini/private.rb, line 71
def self.get_screen_size
  th, tw = TermInfo.screen_size
  if high_res? then [tw, th * 2] else [tw / 2, th] end
end
high_res?() click to toggle source
# File lib/catpix_mini/private.rb, line 27
def self.high_res?
  @@resolution == 'high'
end
load_image(path) click to toggle source
# File lib/catpix_mini/private.rb, line 76
def self.load_image(path)
  MiniMagick::Image.open(path)
end
prep_horiz_margin(size, colour) click to toggle source
# File lib/catpix_mini/private.rb, line 150
def self.prep_horiz_margin(size, colour)
  buffer = ""
  if high_res?
    size.times { buffer += prep_hr_pixel nil, nil }
  else
    size.times { buffer += prep_lr_pixel nil }
  end
  buffer.bg colour
end
prep_hr_pixel(colour_top, colour_bottom) click to toggle source
# File lib/catpix_mini/private.rb, line 43
def self.prep_hr_pixel(colour_top, colour_bottom)
  upper = "\u2580"
  lower = "\u2584"

  return " " if colour_bottom.nil? and colour_top.nil?
  return lower.fg colour_bottom if colour_top.nil?
  return upper.fg colour_top if colour_bottom.nil?

  c_top = Tco::match_colour colour_top
  c_bottom = Tco::match_colour colour_bottom
  if c_top == c_bottom
    return " ".bg "@#{c_top}"
  end

  upper.fg("@#{c_top}").bg("@#{c_bottom}")
end
prep_lr_pixel(colour) click to toggle source
# File lib/catpix_mini/private.rb, line 35
def self.prep_lr_pixel(colour)
  colour ? "  ".bg(colour) : "  "
end
prep_vert_margin(size, colour) click to toggle source

“DRAWING” METHODS

# File lib/catpix_mini/private.rb, line 130
def self.prep_vert_margin(size, colour)
  tw, th = get_screen_size

  buffer = ""
  if high_res?
    (size / 2).times do
      sub_buffer = ""
      tw.times { sub_buffer += prep_hr_pixel nil, nil }
      buffer += sub_buffer.bg(colour) + "\n"
    end
  else
    size.times do
      sub_buffer = ""
      tw.times { sub_buffer += prep_lr_pixel nil }
      buffer += sub_buffer.bg(colour) + "\n"
    end
  end
  buffer
end
print_hr_pixel(colour_top, colour_bottom) click to toggle source
print_lr_pixel(colour) click to toggle source
resize!(img, limit_x=0, limit_y=0) click to toggle source

Scale the image down based on the limits while keeping the aspect ratio

# File lib/catpix_mini/private.rb, line 81
def self.resize!(img, limit_x=0, limit_y=0)
  tw, th = get_screen_size
  iw = img[:width]
  ih = img[:height]

  width = limit_x > 0 ? (tw * limit_x).to_i : iw
  height = limit_y > 0 ? (th * limit_y).to_i : ih

  # Resize the image if it's bigger than the limited viewport
  if iw > width or ih > height
    img.resize "#{width}x#{height}"
  end
end