class DiscreetProxy::Proxy
This class represents a proxy.
Attributes
Image dimensions, standard is 126x92
Array of rows with each row being an array of packed color integers (you can unpack them with ChunkyPNG::Color)
Image dimensions, standard is 126x92
Public Class Methods
# File lib/discreet_proxy.rb, line 57 def initialize(w = DEFAULT_WIDTH, h = DEFAULT_HEIGHT) @width, @height = w.to_i, h.to_i # Blank out the pixel values with black generate_black end
Public Instance Methods
Get an array of the [r,g,b] pixel values at the specific coordinate
# File lib/discreet_proxy.rb, line 75 def [](left, top) png_color_int = @rows[top][left] unpack_rgb(png_color_int) end
Set the color value at the specific coordinate. If the passed value is a single integer, it gets interpreted as a PNG color value. If a triplet array with three components is passed it's interpreted as RGB
# File lib/discreet_proxy.rb, line 83 def []=(x, y, *rgb) color = rgb.flatten # Check for raw pixel value if color.length == 1 && color[0].is_a?(Numeric) @rows[y][x] = color[0] else r, g, b = color.map{|e| e.to_i } @rows[y][x] = pack_rgb(r, g ,b) end end
Once the proxy metadata is known, this method can parse out the actual pixel data from the passed IO
# File lib/discreet_proxy.rb, line 119 def fill_pixbuf(io) @rows = [] # Data comes in row per row, starting on bottom left because of endianness per_row = (@width.to_i + row_pad) * 3 total_size = ((per_row + row_pad) * @height) + 1 blob = StringIO.new(io.read(total_size)) @height.times do row = [] row_data = blob.read(@width.to_i * 3) row_data = StringIO.new(row_data.to_s) # Read 3x8bit for each pixel @width.times do rgb = (row_data.read(3) || "AAA").unpack("CCC") row.push(pack_rgb(*rgb)) end # At the end of each row (thus at the beginning byteswap), # 2 bytes contain garbage since rows are aligned # to start at 8-complement byte offsets. If they are not discarded this disturbs # the RGB cadence of the other values. blob.seek(blob.pos + row_pad) # Since the file is actually BE, the rows are ordered top to bottom in the file @rows.unshift(row) end end
Save out the .p file
# File lib/discreet_proxy.rb, line 150 def save(filename) File.open(filename, 'wb') { |io| io.write(to_dotp) } end
Save out the PNG version of the file
# File lib/discreet_proxy.rb, line 155 def save_png(filename) to_png.save(filename) end
Compose a string with the entire contents of a proxy file
# File lib/discreet_proxy.rb, line 96 def to_dotp # Pack the header buf = StringIO.new(0xFF.chr * 40) byteswap_version = [PROXY_VERSION].pack("e").reverse header = [MAGIC, VERSION_BSWAP, width, height, PROXY_DEPTH].pack("na6nnn") buf.write(header) buf.seek(40) # Write out all the rows starting with the last one @rows.reverse.each do | row | row.each do | pix | rgb = unpack_rgb(pix).pack("CCC") buf.write(rgb) end # Then write the padding buf.write(0x00.chr * row_pad) end buf.string end
# File lib/discreet_proxy.rb, line 63 def to_png png = ChunkyPNG::Image.new(@width, @height) png.metadata["Software"] = "Ruby DiscreetProxy converter/chunky_png" @rows.each_with_index do | row, y | png.replace_row!(y, row) end # Bump it to the default icon size png.resample_bilinear!(DEFAULT_WIDTH, DEFAULT_HEIGHT) png end
Private Instance Methods
# File lib/discreet_proxy.rb, line 175 def generate_black @rows = [] row = [0] * @width @height.times{ @rows.push(row.dup) } end
# File lib/discreet_proxy.rb, line 167 def pack_rgb(r,g,b) ChunkyPNG::Color.rgb(r.to_i, g.to_i, b.to_i) end
Rows start at 8-byte aligned boundaries. BUT due to the fact that this is a BDSM Silicon Graphics format the start of the row is END of the image.
# File lib/discreet_proxy.rb, line 163 def row_pad @row_pad ||= ((@width * 3) % 8) end
# File lib/discreet_proxy.rb, line 171 def unpack_rgb(rgb) [ChunkyPNG::Color.r(rgb), ChunkyPNG::Color.g(rgb), ChunkyPNG::Color.b(rgb)] end