Module: Przn::ImageUtil
- Defined in:
- lib/przn/image_util.rb
Constant Summary collapse
- PNG_MAGIC =
"\x89PNG\r\n\x1a\n".b.freeze
Class Method Summary collapse
- .image_size(path) ⇒ Object
-
.kitty_icat(path, cols:, rows:, x:, y:) ⇒ Object
Display image using kitten icat with –place for positioning.
-
.kitty_place(image_id:, cols:, rows:) ⇒ Object
Kitty Graphics Protocol: place a previously-uploaded image at the current cursor position, scaled to fit ‘cols` x `rows` cells.
- .kitty_terminal? ⇒ Boolean
-
.kitty_upload_png(path, image_id:) ⇒ Object
Kitty Graphics Protocol: upload a PNG file by path with the given id.
- .png?(path) ⇒ Boolean
-
.sixel_available? ⇒ Boolean
Sixel via img2sixel.
- .sixel_encode(path, width: nil, height: nil) ⇒ Object
Class Method Details
.image_size(path) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 |
# File 'lib/przn/image_util.rb', line 7 def image_size(path) return nil unless File.exist?(path) File.open(path, 'rb') do |f| header = f.read(8) return nil unless header && header.size >= 4 # PNG if header.b == "\x89PNG\r\n\x1a\n".b f.seek(16) w = f.read(4)&.unpack1('N') h = f.read(4)&.unpack1('N') return [w, h] if w && h end # JPEG f.seek(0) if header.b[0..1] == "\xFF\xD8".b f.seek(2) loop do marker = f.read(2) break unless marker && marker.size == 2 && marker.getbyte(0) == 0xFF type = marker.getbyte(1) if [0xC0, 0xC1, 0xC2].include?(type) f.read(3) h = f.read(2)&.unpack1('n') w = f.read(2)&.unpack1('n') return [w, h] if w && h end len = f.read(2)&.unpack1('n') break unless len && len >= 2 f.seek(len - 2, IO::SEEK_CUR) end end # GIF f.seek(0) sig = f.read(6) if sig&.start_with?("GIF8") w = f.read(2)&.unpack1('v') h = f.read(2)&.unpack1('v') return [w, h] if w && h end end nil rescue nil end |
.kitty_icat(path, cols:, rows:, x:, y:) ⇒ Object
Display image using kitten icat with –place for positioning
57 58 59 60 61 62 |
# File 'lib/przn/image_util.rb', line 57 def kitty_icat(path, cols:, rows:, x:, y:) args = ['kitten', 'icat', '--transfer-mode', 'stream', '--place', "#{cols}x#{rows}@#{x}x#{y}", File.(path)] IO.popen(args, 'r', err: File::NULL) { |io| io.read } end |
.kitty_place(image_id:, cols:, rows:) ⇒ Object
Kitty Graphics Protocol: place a previously-uploaded image at the current cursor position, scaled to fit ‘cols` x `rows` cells.
88 89 90 |
# File 'lib/przn/image_util.rb', line 88 def kitty_place(image_id:, cols:, rows:) "\e_Ga=p,i=#{image_id},c=#{cols},r=#{rows},q=2\e\\" end |
.kitty_terminal? ⇒ Boolean
64 65 66 |
# File 'lib/przn/image_util.rb', line 64 def kitty_terminal? ENV['TERM'] == 'xterm-kitty' || ENV['TERM_PROGRAM'] == 'kitty' end |
.kitty_upload_png(path, image_id:) ⇒ Object
Kitty Graphics Protocol: upload a PNG file by path with the given id. Kitty reads the file directly from disk; we just send a small APC control sequence with the base64-encoded path. Use this once per image; subsequent renders only need a placement command. sw.kovidgoyal.net/kitty/graphics-protocol/
81 82 83 84 |
# File 'lib/przn/image_util.rb', line 81 def kitty_upload_png(path, image_id:) encoded = [File.(path)].pack('m0') "\e_Ga=t,t=f,f=100,i=#{image_id},q=2;#{encoded}\e\\" end |
.png?(path) ⇒ Boolean
70 71 72 73 74 |
# File 'lib/przn/image_util.rb', line 70 def png?(path) File.open(path, 'rb') { |f| f.read(8)&.b == PNG_MAGIC } rescue Errno::ENOENT false end |
.sixel_available? ⇒ Boolean
Sixel via img2sixel
93 94 95 96 |
# File 'lib/przn/image_util.rb', line 93 def sixel_available? @sixel_available = system('command -v img2sixel > /dev/null 2>&1') if @sixel_available.nil? @sixel_available end |
.sixel_encode(path, width: nil, height: nil) ⇒ Object
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/przn/image_util.rb', line 98 def sixel_encode(path, width: nil, height: nil) return nil unless sixel_available? return nil unless File.exist?(path) args = ['img2sixel'] args += ['-w', width.to_s] if width args += ['-h', height.to_s] if height args << path IO.popen(args, 'r', err: File::NULL) { |io| io.read } end |