Skip to content

Commit

Permalink
Improved precision when converting RGB565 colors to 16 bit per channel.
Browse files Browse the repository at this point in the history
  • Loading branch information
Lars committed Jan 11, 2016
1 parent 364b834 commit 4de252a
Showing 1 changed file with 27 additions and 10 deletions.
37 changes: 27 additions & 10 deletions fb.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,11 @@ func (rgb565ColorModel) Convert(c color.Color) color.Color {
}

// toRGB565 helps convert a color.Color to rgb565. In a color.Color each
// channel is represented as a uint32 but the maximum value is 0xFFFF. This
// simply uses the highest 5 or 6 bits of each channel as the RGB values.
// channel is represented by the lower 16 bits in a uint32 so the maximum value
// is 0xFFFF. This function simply uses the highest 5 or 6 bits of each channel
// as the RGB values.
func toRGB565(r, g, b uint32) rgb565 {
// RRRRRGGGGGGBBBBB
return rgb565((r & 0xF800) +
((g & 0xFC00) >> 5) +
((b & 0xF800) >> 11))
Expand All @@ -153,14 +155,29 @@ type rgb565 uint16

// RGBA implements the color.Color interface.
func (c rgb565) RGBA() (r, g, b, a uint32) {
// The conversion from 5 and 6 bit channels to 16 bits is lossy. It simply
// shifts each channel's bits to the highest position which means that the
// maximum value of 0xFFFF can never be reached for example. The low 15 or
// 16 bits of the channels will always be 0.
// Alpha is always 100% opaque since this model does not support it.
r = uint32(c & 0xF800)
g = uint32((c & 0x7E0) << 5)
b = uint32((c & 0x1F) << 11)
// To convert a color channel from 5 or 6 bits back to 16 bits, the short
// bit pattern is duplicated to fill all 16 bits.
// For example the green channel in rgb565 is the middle 6 bits:
// 00000GGGGGG00000
//
// To create a 16 bit channel, these bits are or-ed together starting at the
// highest bit:
// GGGGGG0000000000 shifted << 5
// 000000GGGGGG0000 shifted >> 1
// 000000000000GGGG shifted >> 7
//
// These patterns map the minimum (all bits 0) and maximum (all bits 1)
// 5 and 6 bit channel values to the minimum and maximum 16 bit channel
// values.
//
// Alpha is always 100% opaque since this model does not support
// transparency.
rBits := uint32(c & 0xF800) // RRRRR00000000000
gBits := uint32(c & 0x7E0) // 00000GGGGGG00000
bBits := uint32(c & 0x1F) // 00000000000BBBBB
r = uint32(rBits | rBits>>5 | rBits>>10 | rBits>>15)
g = uint32(gBits<<5 | gBits>>1 | gBits>>7)
b = uint32(bBits<<11 | bBits<<6 | bBits<<1 | bBits>>4)
a = 0xFFFF
return
}

0 comments on commit 4de252a

Please sign in to comment.