cli_pix 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e54d55ea153abfef0d9d3539c52da6e645bc89c418036396a717bfdcd8483008
4
+ data.tar.gz: 073eac82290bebb0ca48d29b65bc6500d6033151f5a06e42a422691560957293
5
+ SHA512:
6
+ metadata.gz: 150b4e897881168a54ef351362e1ac2595dc3c3e16f2020fc06f065b38a996b4ce17412fa8adad6cad6aa925c6d3dd93481c36753d536e96a6207c7a4e3d479b
7
+ data.tar.gz: d25743adeada14fd4aa91fd4a501f5385aab4de7190c60a4cf9fa236a9cc483bca3c4166b059213b1760fcb8e394d1106e01599a9e510afc3ea166e06a832532
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.6.3
6
+ before_install: gem install bundler -v 2.1.4
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at ianholla@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cli_pix.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "rspec", "~> 3.0"
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cli_pix (0.1.0)
5
+ mini_magick (~> 4.10)
6
+ paint (~> 2.2)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.4.4)
12
+ mini_magick (4.10.1)
13
+ paint (2.2.0)
14
+ rake (12.3.3)
15
+ rspec (3.9.0)
16
+ rspec-core (~> 3.9.0)
17
+ rspec-expectations (~> 3.9.0)
18
+ rspec-mocks (~> 3.9.0)
19
+ rspec-core (3.9.2)
20
+ rspec-support (~> 3.9.3)
21
+ rspec-expectations (3.9.2)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.9.0)
24
+ rspec-mocks (3.9.1)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.9.0)
27
+ rspec-support (3.9.3)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ cli_pix!
34
+ rake (~> 12.0)
35
+ rspec (~> 3.0)
36
+
37
+ BUNDLED WITH
38
+ 2.1.4
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 ihollander
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,113 @@
1
+ # CliPix
2
+
3
+ A Ruby library to display and animate images in your terminal.
4
+
5
+ ## Requirements
6
+
7
+ This library uses the MiniMagick gem, which requires ImageMagick or GraphicsMagick to be installed on your system.
8
+
9
+ You can install it for OS X with homebrew:
10
+
11
+ ```
12
+ brew install imagemagick
13
+ ```
14
+
15
+ See the [requirements](https://github.com/minimagick/minimagick#requirements) from MiniMagick for more installation info.
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```rb
22
+ gem 'cli_pix'
23
+ ```
24
+
25
+ And then execute:
26
+
27
+ $ bundle install
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install cli_pix
32
+
33
+ ## Usage
34
+
35
+ Display an image from a file:
36
+
37
+ ```rb
38
+ file_path = "demos/image.png"
39
+ image = CliPix::Image.from_file(file_path)
40
+ image.display
41
+ ```
42
+
43
+ Display an image from a URL:
44
+
45
+ ```rb
46
+ url = "https://f0.pngfuel.com/png/980/847/ruby-on-rails-logo-programming-language-rubygems-ruby-png-clip-art.png"
47
+ image = CliPix::Image.from_url(url)
48
+ image.display
49
+ ```
50
+
51
+ Display animated gifs:
52
+
53
+ ```rb
54
+ url = "https://media3.giphy.com/media/dXLnSpMDt7CvzRwMa9/giphy.gif?cid=ecf05e47nkii9rn5xq6uc0tsoyc53rowe8zjnwrcydkfbw6w&rid=giphy.gif"
55
+ image = CliPix::Image.from_url(url)
56
+ image.animate
57
+ ```
58
+
59
+ Display data from a blob (to capture a webcam image, for example):
60
+
61
+ ```rb
62
+ require "av_capture"
63
+
64
+ # uses av_capture gem to access webcam (OSX only)
65
+ session = AVCapture::Session.new
66
+ device = AVCapture.devices.find(&:video?)
67
+
68
+ session.run_with(device) do |connection|
69
+ # give a little time for the camera to warm up...
70
+ sleep 1
71
+
72
+ # run a loop continuously
73
+ loop do
74
+ # connection.capture returns a blob
75
+ image = CliPix::Image.from_blob(connection.capture, flop: true)
76
+ image.display
77
+ # wait for next capture
78
+ sleep 0.2
79
+ end
80
+ end
81
+ ```
82
+
83
+ The `CliPix::Image#display` and `CliPix::Image#animate` methods will both output the image directly to your terminal. If you want more control, you can also use the `CliPix::Image#read` method to return a string representation of the image a block:
84
+
85
+ ```rb
86
+ url = "https://media3.giphy.com/media/dXLnSpMDt7CvzRwMa9/giphy.gif?cid=ecf05e47nkii9rn5xq6uc0tsoyc53rowe8zjnwrcydkfbw6w&rid=giphy.gif"
87
+ image = CliPix::Image.from_url(url, preprocess: true)
88
+ # read will yield an image_string of each frame of the image to the block
89
+ image.read do |image_string|
90
+ print `clear`
91
+ puts image_string
92
+ sleep 0.5
93
+ end
94
+ ```
95
+
96
+ ### Options
97
+
98
+ When creating an image, you can pass an options hash as a second argument. It takes the following options:
99
+
100
+ ```rb
101
+ {
102
+ autoscale: true, # default: true. resize the image to fit the console window.
103
+ size: nil, # default: nil. you can provide an array of width and height [50, 30] or a string "50x30" to resize the image
104
+ flip: false, # default: false. if true, flip the image vertically
105
+ flop: false, # default: false. if true, flip the image horizontally
106
+ mode: :color, # default: :color. you can also use :ascii to display the image in ASCII mode.
107
+ preprocess: false # default: false. if true, process all frames of the image before displaying. useful for animated gifs.
108
+ }
109
+ ```
110
+
111
+ ## License
112
+
113
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "cli_pix"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,31 @@
1
+ require_relative 'lib/cli_pix/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "cli_pix"
5
+ spec.version = CliPix::VERSION
6
+ spec.authors = ["ihollander"]
7
+ spec.email = ["ianholla@gmail.com"]
8
+
9
+ spec.summary = %q{A gem to help display images and animation in your terminal.}
10
+ spec.homepage = "https://github.com/ihollander/cli_pix"
11
+ spec.license = "MIT"
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
13
+
14
+ spec.metadata["homepage_uri"] = spec.homepage
15
+ spec.metadata["source_code_uri"] = "https://github.com/ihollander/cli_pix"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ # dependencies
27
+ spec.add_development_dependency "rspec", "~> 3.9"
28
+
29
+ spec.add_dependency "paint", "~> 2.2"
30
+ spec.add_dependency "mini_magick", "~> 4.10"
31
+ end
@@ -0,0 +1,5 @@
1
+ require_relative "../lib/cli_pix"
2
+
3
+ url = "https://media3.giphy.com/media/dXLnSpMDt7CvzRwMa9/giphy.gif?cid=ecf05e47nkii9rn5xq6uc0tsoyc53rowe8zjnwrcydkfbw6w&rid=giphy.gif"
4
+ image = CliPix::Image.from_url(url, preprocess: true)
5
+ image.animate
Binary file
@@ -0,0 +1,5 @@
1
+ require_relative "../lib/cli_pix"
2
+
3
+ file_path = "demos/image.png"
4
+ image = CliPix::Image.from_file(file_path)
5
+ image.display
@@ -0,0 +1,20 @@
1
+ # NOTE
2
+ # You'll need to install the av_capture gem to run this demo!
3
+ require "av_capture"
4
+ require_relative "../lib/cli_pix"
5
+
6
+ # uses av_capture gem to access webcam (OSX only)
7
+ session = AVCapture::Session.new
8
+ device = AVCapture.devices.find(&:video?)
9
+
10
+ session.run_with(device) do |connection|
11
+ # give a little time for the camera to warm up...
12
+ sleep 1
13
+
14
+ # run a loop continuously
15
+ loop do
16
+ CliPix::Image.from_blob(connection.capture, flop: true).display
17
+ # wait for next capture
18
+ sleep 0.2
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ require_relative "cli_pix/version"
2
+
3
+ module CliPix
4
+ class Error < RuntimeError; end
5
+ end
6
+
7
+ require_relative "cli_pix/image"
@@ -0,0 +1,158 @@
1
+ require "io/console"
2
+ require "mini_magick"
3
+ require "paint"
4
+
5
+ module CliPix
6
+ class Image
7
+
8
+ DEFAULT_OPTIONS = {
9
+ autoscale: true,
10
+ size: nil,
11
+ flop: false,
12
+ flip: false,
13
+ mode: :color,
14
+ preprocess: false
15
+ }
16
+
17
+ class << self
18
+
19
+ def read(blob, options = {})
20
+ image = MiniMagick::Image.read(blob)
21
+ self.new(image, options)
22
+ end
23
+ alias :from_blob :read
24
+
25
+ def open(url, options = {})
26
+ image = MiniMagick::Image.open(url)
27
+ self.new(image, options)
28
+ end
29
+ alias :from_url :open
30
+ alias :from_file :open
31
+
32
+ end
33
+
34
+ attr_reader :image, :options
35
+
36
+ def initialize(image, options = {})
37
+ @image = image
38
+ @options = DEFAULT_OPTIONS.merge options
39
+ end
40
+
41
+ def display
42
+ self.read do |text|
43
+ # clear terminal
44
+ clear_screen!
45
+ puts text
46
+ end
47
+ end
48
+
49
+ def animate(framerate = 0.2)
50
+ self.read do |text|
51
+ # clear terminal
52
+ clear_screen!
53
+ puts text
54
+ # wait
55
+ sleep framerate
56
+ end
57
+ end
58
+
59
+ # yields each text frame to the block
60
+ def read
61
+ process_image!
62
+ if options[:preprocess]
63
+ # | / - \
64
+ spinner = "|/-\\"
65
+ text_frames = image.frames.map.with_index do |frame, index|
66
+ print "Loading frame #{index + 1}/#{image.frames.length}... #{spinner[index % 4]} \r"
67
+ if options[:mode] == :color
68
+ convert_to_color(frame.get_pixels)
69
+ else
70
+ convert_to_ascii(frame.get_pixels)
71
+ end
72
+ end
73
+
74
+ text_frames.each do |text_frame|
75
+ yield text_frame
76
+ end
77
+ else
78
+ image.frames.each do |frame|
79
+ if options[:mode] == :color
80
+ yield convert_to_color(frame.get_pixels)
81
+ else
82
+ yield convert_to_ascii(frame.get_pixels)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def clear_screen!
91
+ print "\e[2J\e[f"
92
+ end
93
+
94
+ def process_image!
95
+ if options[:autoscale]
96
+ width, height = get_scaled_dimensions
97
+ image.resize "#{width}x#{height}"
98
+ elsif options[:size]
99
+ if options[:size].is_a? Array
100
+ width, height = options[:size]
101
+ image.resize "#{width}x#{height}"
102
+ else
103
+ image.resize "#{options[:size]}"
104
+ end
105
+ end
106
+
107
+ image.colorspace "Gray" if options[:mode] == :ascii
108
+
109
+ image.flip if options[:flip]
110
+ image.flop if options[:flop]
111
+ end
112
+
113
+ def convert_to_ascii(pixels)
114
+ ascii_chars = " .:oO8@"
115
+
116
+ text_image = ""
117
+
118
+ pixels.each do |row|
119
+ row.each do |rgb|
120
+ char_index = ((rgb.first.to_f / 255) * ascii_chars.length).to_i
121
+ text_image += (ascii_chars[char_index] || " ") * 2
122
+ end
123
+ text_image += "\n"
124
+ end
125
+
126
+ text_image
127
+ end
128
+
129
+ def convert_to_color(pixels)
130
+ text_image = ""
131
+
132
+ pixels.each do |row|
133
+ row.each do |rgb|
134
+ text_image += Paint[" ", nil, rgb]
135
+ end
136
+ text_image += "\n"
137
+ end
138
+
139
+ text_image
140
+ end
141
+
142
+ def get_scaled_dimensions
143
+ # image width & height
144
+ image_aspect_ratio = image.width.to_f / image.height
145
+
146
+ # terminal width & height
147
+ terminal_height, terminal_width = IO.console.winsize
148
+ terminal_aspect_ratio = terminal_width.to_f / terminal_height
149
+
150
+ # constrain (max width)
151
+ photo_width = terminal_width > 50 ? 50 : terminal_width
152
+ photo_height = photo_width / image_aspect_ratio
153
+ # return [width, height]
154
+ [ photo_width.to_i, photo_height.to_i ]
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,3 @@
1
+ module CliPix
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cli_pix
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ihollander
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-08-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: paint
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mini_magick
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.10'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.10'
55
+ description:
56
+ email:
57
+ - ianholla@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - CODE_OF_CONDUCT.md
66
+ - Gemfile
67
+ - Gemfile.lock
68
+ - LICENSE.txt
69
+ - README.md
70
+ - Rakefile
71
+ - bin/console
72
+ - bin/setup
73
+ - cli_pix.gemspec
74
+ - demos/gif.rb
75
+ - demos/image.png
76
+ - demos/image.rb
77
+ - demos/webcam.rb
78
+ - lib/cli_pix.rb
79
+ - lib/cli_pix/image.rb
80
+ - lib/cli_pix/version.rb
81
+ homepage: https://github.com/ihollander/cli_pix
82
+ licenses:
83
+ - MIT
84
+ metadata:
85
+ homepage_uri: https://github.com/ihollander/cli_pix
86
+ source_code_uri: https://github.com/ihollander/cli_pix
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 2.3.0
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubygems_version: 3.0.6
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: A gem to help display images and animation in your terminal.
106
+ test_files: []