class Net::RFB::FrameBuffer

Manage FrameBuffer pixel data for RFB protocol This is a little wrapper for the `Proxy` class in vncrec-ruby github.com/d-theus/vncrec-ruby

Public Class Methods

convert_raw_pixel_data_to_rgba(px, pix_fmt) click to toggle source

convert raw pixel data to 32bit RGBA values according to VNC pixel format @param px [String] binary pixel data @param pix_fmt [String] pixel format (bgra, bgr8) @return [Array<Integer>] array of 32bit pixel data

# File lib/net/rfb/frame_buffer.rb, line 60
def self.convert_raw_pixel_data_to_rgba(px, pix_fmt)
  # see https://github.com/d-theus/vncrec-ruby/blob/master/lib/vncrec/constants.rb
  case pix_fmt.to_s
  when 'bgra'
    # convert 32bit BGRA -> 32bit RGBA
    px = px.unpack("V*")
    px.map! { |p| (p << 8) | 0xff }
  when 'bgr8'
    # convert 8bit BGR -> 32bit RGBA
    px = px.unpack("C*")
    px.map! do |p|
      r = (p & 0b00000111)
      g = (p & 0b00111000) >> 3
      b = (p & 0b11000000) >> 6
      ((r * 36) << 24) | ((g * 36) << 16) | ((b * 85) << 8) | 0xff
    end
  else
    raise "unknown pixel format #{pix_fmt.inspect}"
  end
end
new(io, w, h, bpp, encodings=nil) click to toggle source

@param io [IO, read, sysread, syswrite, read_nonblock] string stream from VNC server. @param w [Integer] width of the screen area @param h [Integer] height of the screen area @param bpp [Symbol] bits per pixel (BGR8 or BGRA) @param encodings [Array<Symbol>] encoding (RAW or HEXTILE or ZRLE) default: RAW

# File lib/net/rfb/frame_buffer.rb, line 19
def initialize(io, w, h, bpp, encodings=nil)
  @cb_mutex = Monitor.new
  @cb_cv = @cb_mutex.new_cond

  @encodings = encodings

  @vnc_rec_pix_fmt = convert_to_vnc_rec_pix_fmt bpp

  @proxy = VNCRec::RFB::Proxy.new(io, nil, nil, nil, [VNCRecAuthStub, nil])
  @proxy.prepare_framebuffer w, h, @vnc_rec_pix_fmt[:bpp]
end

Public Instance Methods

handle_response(t) click to toggle source
# File lib/net/rfb/frame_buffer.rb, line 117
def handle_response(t)
  case t
  when 0 # ----------------------------------------------- FramebufferUpdate
    ret = handle_fb_update
    @cb_mutex.synchronize do
      @cb_cv.broadcast
    end
    return ret
  when 1 # --------------------------------------------- SetColourMapEntries
    return handle_set_colormap_entries
  end
end
pixel_data() click to toggle source

raw pixel data of screen

# File lib/net/rfb/frame_buffer.rb, line 45
def pixel_data
  @proxy.data
end
request_update_fb(incremental: true, x: nil, y: nil, w: nil, h: nil, wait_for_response: false) click to toggle source

Send request for update framebuffer.

if block given, called it with pixel data after the response received.

@param [Boolean] incremental incremental, request just difference

between previous and current framebuffer state.

@param x [Integer] @param y [Integer] @param w [Integer] @param h [Integer] @param wait_for_response [Boolean] if true, wait for a FramebufferUpdate response

# File lib/net/rfb/frame_buffer.rb, line 107
def request_update_fb(incremental: true, x: nil, y: nil, w: nil, h: nil, wait_for_response: false)
  @cb_mutex.synchronize do
    @proxy.fb_update_request incremental ? 1 : 0, x||0, y||0, w||@proxy.w, h||@proxy.h

    if wait_for_response
      @cb_cv.wait
    end
  end
end
rgba_pixel_data() click to toggle source

32bit RGBA pixel data of screen

# File lib/net/rfb/frame_buffer.rb, line 50
def rgba_pixel_data
  px = self.pixel_data
  raise 'Error in get raw pixel_data.' unless px
  self.class.convert_raw_pixel_data_to_rgba px, @vnc_rec_pix_fmt[:string]
end
save_pixel_data_as_png(dest=nil) click to toggle source

save current screen pixel data as PNG image @param dest [String|IO|nil] destination file path, or IO-object, or nil @return [String] PNG binary data as string when dest is null

[true]   else case
# File lib/net/rfb/frame_buffer.rb, line 134
def save_pixel_data_as_png(dest=nil)
  self.request_update_fb(wait_for_response: true)

  image = ChunkyPNG::Image.new(@proxy.w, @proxy.h, rgba_pixel_data)

  if dest.is_a? IO
    # write to IO-object
    image.write dest
  elsif dest.is_a?(String) || dest.is_a?(Pathname)
    # write to file
    image.save dest.to_s
  elsif dest.nil?
    # return binary data as string
    return image.to_blob
  else
    raise ArgumentError, "Unsupported destination type #{dest.inspect}"
  end
  true
end
send_initial_data() click to toggle source
# File lib/net/rfb/frame_buffer.rb, line 31
def send_initial_data
  # set encoding
  unless self.set_encodings @encodings
    raise 'Error while setting encoding'
  end

  # set pixel format
  self.set_pixel_format @vnc_rec_pix_fmt

  # request all pixel data
  self.request_update_fb incremental: false
end
set_encodings(*encodings) click to toggle source

Set way of encoding video frames. @param encodings [Symbol|String] list of encoding of video data used to transfer.

* :RAW
* :HEXTILE
* :ZRLE
# File lib/net/rfb/frame_buffer.rb, line 94
def set_encodings(*encodings)
  @proxy.set_encodings [encodings].flatten.compact.map{|sym| VNCRec::const_get "ENC_#{sym}"}
end
set_pixel_format(format) click to toggle source

Set a way that server should use to represent pixel data @param [Symbol|String] pixel format:

* :BGR8
* :BGRA
# File lib/net/rfb/frame_buffer.rb, line 85
def set_pixel_format(format)
  @proxy.set_pixel_format convert_to_vnc_rec_pix_fmt(format)
end

Private Instance Methods

convert_to_vnc_rec_pix_fmt(pix_fmt) click to toggle source

convert pixel_format symbol to VNCRec::PIX_FMT_XXX symbol. @param pix_fmt [Symbol|String] bits per pixel (BGR8 or BGRA)

# File lib/net/rfb/frame_buffer.rb, line 158
def convert_to_vnc_rec_pix_fmt(pix_fmt)
  return pix_fmt if pix_fmt.is_a?(Hash)
  pf = pix_fmt.to_s.prepend('PIX_FMT_').upcase.to_sym
  raise ArgumentError, "Unsupported pixel_format '#{pix_fmt}', now supported values are: BGR8, BGRA" unless VNCRec.const_defined? pf
  VNCRec.const_get(pf)
end
handle_fb_update() click to toggle source

Receives data and applies diffs(if incremental) to the @data

# File lib/net/rfb/frame_buffer.rb, line 166
def handle_fb_update
  @proxy.handle_fb_update
end
handle_set_colormap_entries() click to toggle source

@return [Array] palette

# File lib/net/rfb/frame_buffer.rb, line 171
def handle_set_colormap_entries
  @proxy.handle_colormap_update
end