cool-bun-demo/image_converter.rb

91 lines
1.7 KiB
Ruby
Executable File

#!/usr/bin/env ruby
require 'rmagick'
# [ ] load the image
# [ ] map each pixel to a 12 bit color, with pixels less than 25% transparent as mask
# [ ] sort the color counts
# [ ] transparent pixels become the mask
# [ ] turn the big color counts into three bitplames worth of data
# [ ] turn the little color counts into up to 8 sprites worth of data strips & color changes
image = Magick::Image.read('topaz.png').first
rows = []
class MaskPixel
def initialize; end
def color? = false
end
class Color
attr_reader :red, :green, :blue
def initialize(red:, green:, blue:)
@red = red
@green = green
@blue = blue
end
def ==(other)
red == other.red && green == other.green && blue == other.blue
end
alias eql? ==
def hash
red * 256 + green * 16 + blue
end
end
class BitplanePixel
attr_reader :color
def initialize(color:)
@color = color
end
def color? = true
end
MAX_ALPHA = Magick::QuantumRange * 0.25
BIT_SHIFT = Math.log2(Magick::QuantumRange + 1) - 4
class PixelRow
def initialize
@row = []
end
def add(pixel:, x:)
@row[x] = pixel
end
def colors_with_usage
@row.find_all(&:color?).each_with_object({}) do |pixel, obj|
obj[pixel.color] ||= 0
obj[pixel.color] += 1
end
end
end
image.each_pixel do |px, x, y|
rows[y] ||= PixelRow.new
pixel = if px.alpha < MAX_ALPHA
MaskPixel.new
else
BitplanePixel.new(
color: Color.new(
red: px.red >> BIT_SHIFT,
green: px.green >> BIT_SHIFT,
blue: px.blue >> BIT_SHIFT
)
)
end
rows[y].add(pixel:, x:)
end
pp rows[50].colors_with_usage