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 57
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 17
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 112
def handle_response(t)
  case t
  when 0 # ----------------------------------------------- FramebufferUpdate
    ret = handle_fb_update
    @cb_mutex.synchronize do
      @cb_cv.broadcast
    end
    ret
  when 1 # --------------------------------------------- SetColourMapEntries
    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 41
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 104
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

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

32bit RGBA pixel data of screen

# File lib/net/rfb/frame_buffer.rb, line 46
def rgba_pixel_data
  px = 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 129
def save_pixel_data_as_png(dest = nil)
  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 29
def send_initial_data
  # set encoding
  raise 'Error while setting encoding' unless set_encodings @encodings

  # set pixel format
  set_pixel_format @vnc_rec_pix_fmt

  # request all pixel data
  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 91
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 82
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 153
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
  unless VNCRec.const_defined? pf
    raise ArgumentError,
          "Unsupported pixel_format '#{pix_fmt}', now supported values are: BGR8, BGRA"
  end

  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