Understand ChunkyPNG's memory-efficient pixel representation
masterChunkyPNG optimizes memory usage by representing pixels as single 32-bit integers (Fixnums) rather than individual objects for each color channel. This approach avoids the high overhead of Ruby object instances and floating-point numbers.
How it works:
- Bit Packing: Each pixel stores Red, Green, Blue, and Alpha channels in a single integer using bitwise shifts.
- Channel Layout: The channels are packed as
r << 24 | g << 16 | b << 8 | a. - On-demand Wrapping: To provide a developer-friendly API, the
Imageclass wraps the raw integer in aPixelobject only when a specific pixel is accessed via[]. When setting a pixel via[]=, thePixelobject is unwrapped back into its integer representation.
# Conceptual representation of how ChunkyPNG handles pixels
class Pixel
def self.rgba(r, g, b, a = 255)
self.new(r << 24 | g << 16 | b << 8 | a)
end
def r; (@value & 0xff000000) >> 24; end
def g; (@value & 0x00ff0000) >> 16; end
def b; (@value & 0x0000ff00) >> 8; end
def a; (@value & 0x000000ff); end
end
# How the Image class manages memory
class Image
def [](x, y)
Pixel.new(@pixels[y * width + x]) # Wrap integer in object for access
end
def []=(x, y, pixel)
@pixels[y * width + x] = pixel.to_i # Unwrap object to integer for storage
end
end