pebble/tools/img2packbits.rb

103 lines
2.4 KiB
Ruby
Raw Permalink Normal View History

#!/usr/bin/env ruby
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'RMagick'
im = Magick::ImageList.new(ARGV[0]).first
current_data = 0
current_alpha = 0
data = []
alpha = []
0.upto(im.rows - 1) do |r|
0.upto(maxcol = (im.columns - 1)) do |c|
pix = im.pixel_color(c, r)
if pix.intensity == 0 # black
current_data |= (1 << (c % 8))
end
if pix.opacity == 0 # opaque
current_alpha |= (1 << (c % 8))
end
if c % 8 == 7 or c == maxcol
data << current_data
alpha << current_alpha
current_data = 0
current_alpha = 0
end
end
end
packed_data, packed_alpha = [data, alpha].map do |raw|
i = 0
packet_start = 0
out = []
while i < raw.size
if i < raw.size - 1 and raw[i] == raw[i+1]
# output literal packet
if i > packet_start
out << (i - packet_start - 1)
out += raw[packet_start..i-1]
end
# start a run
packet_start = i
while raw[i] == raw[i+1] and (i - packet_start) < 127
i += 1
end
out << -(i - packet_start)
out << raw[i]
# next packet starts at next byte
packet_start = i + 1
elsif (i - packet_start) == 127 or i == raw.size - 1
# too many literal bytes, output and move to next packet
out << (i - packet_start)
out += raw[packet_start..i]
packet_start = i + 1
end
i += 1
end
unpacked_size = 0
i = 0
while i < out.size
if out[i] > 0
unpacked_size += out[i] + 1
i += out[i] + 2
else
unpacked_size += 1 - out[i]
i += 2
end
end
#puts unpacked_size
#puts out.size
out
end
ARGV[0] =~ /(.*)\..*$/
file_name = "#{$1}.packbits"
puts "Wrote #{file_name}"
puts "Compressed image size is: " + packed_data.size.to_s
File.open(file_name, 'w') do |file|
file.print 'PBPB'
file.print [im.columns, im.rows].pack('n*')
file.print [packed_data.size].pack('N*')
file.print packed_data.pack('c*')
end