Skip to content

Commit

Permalink
Fix some bb conversion so that white stays white (#590)
Browse files Browse the repository at this point in the history
Blitting pure white from RGB32 and RGB16 to BB8 (which is the framebuffer
format on Kindle) would result in some light gray.
  • Loading branch information
poire-z authored and Frenzie committed Jan 28, 2018
1 parent 05dd09d commit 6769d0c
Show file tree
Hide file tree
Showing 2 changed files with 245 additions and 11 deletions.
22 changes: 11 additions & 11 deletions ffi/blitbuffer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,12 @@ L = 0.299*Red + 0.587*Green + 0.114*Blue
--]]
function ColorRGB16_mt.__index:getColor4L()
local r = rshift(self.v, 11)
local g = band(rshift(self.v, 5, 0x3F))
local g = band(rshift(self.v, 5), 0x3F)
local b = band(self.v, 0x001F)
return Color4L(rshift(39190*r + 38469*g + 14942*b, 18))
return Color4L(rshift(39919*r + 39185*g + 15220*b, 18))
end
function ColorRGB24_mt.__index:getColor4L()
return Color4L(rshift(4897*self.r + 9617*self.g + 1868*self.b, 18))
return Color4L(rshift(4898*self.r + 9618*self.g + 1869*self.b, 18))
end
ColorRGB32_mt.__index.getColor4L = ColorRGB24_mt.__index.getColor4L

Expand All @@ -257,12 +257,12 @@ function Color8_mt.__index:getColor4U() return Color4U(band(0xF0, self.a)) end
function Color8A_mt.__index:getColor4U() return Color4U(band(0xF0, self.a)) end
function ColorRGB16_mt.__index:getColor4U()
local r = rshift(self.v, 11)
local g = band(rshift(self.v, 5, 0x3F))
local g = band(rshift(self.v, 5), 0x3F)
local b = band(self.v, 0x001F)
return Color4U(band(0xF0, rshift(39190*r + 38469*g + 14942*b, 14)))
return Color4U(band(0xF0, rshift(39919*r + 39185*g + 15220*b, 14)))
end
function ColorRGB24_mt.__index:getColor4U()
return Color4U(band(0xF0, rshift(4897*self.r + 9617*self.g + 1868*self.b, 14)))
return Color4U(band(0xF0, rshift(4898*self.r + 9618*self.g + 1869*self.b, 14)))
end
ColorRGB32_mt.__index.getColor4U = ColorRGB24_mt.__index.getColor4U

Expand All @@ -281,10 +281,10 @@ function ColorRGB16_mt.__index:getColor8()
local r = rshift(self.v, 11)
local g = band(rshift(self.v, 5), 0x3F)
local b = band(self.v, 0x001F)
return Color8(rshift(39190*r + 38469*g + 14942*b, 14))
return Color8(rshift(39919*r + 39185*g + 15220*b, 14))
end
function ColorRGB24_mt.__index:getColor8()
return Color8(rshift(4897*self:getR() + 9617*self:getG() + 1868*self:getB(), 14))
return Color8(rshift(4898*self:getR() + 9618*self:getG() + 1869*self:getB(), 14))
end
ColorRGB32_mt.__index.getColor8 = ColorRGB24_mt.__index.getColor8

Expand All @@ -303,13 +303,13 @@ function ColorRGB16_mt.__index:getColor8A()
local r = rshift(self.v, 11)
local g = band(rshift(self.v, 5), 0x3F)
local b = band(self.v, 0x001F)
return Color8A(rshift(39190*r + 38469*g + 14942*b, 14), 0)
return Color8A(rshift(39919*r + 39185*g + 15220*b, 14), 0)
end
function ColorRGB24_mt.__index:getColor8A()
return Color8A(rshift(4897*self:getR() + 9617*self:getG() + 1868*self:getB(), 14), 0)
return Color8A(rshift(4898*self:getR() + 9618*self:getG() + 1869*self:getB(), 14), 0)
end
function ColorRGB32_mt.__index:getColor8A()
return Color8A(rshift(4897*self:getR() + 9617*self:getG() + 1868*self:getB(), 14), self:getAlpha())
return Color8A(rshift(4898*self:getR() + 9618*self:getG() + 1869*self:getB(), 14), self:getAlpha())
end

-- to ColorRGB16:
Expand Down
234 changes: 234 additions & 0 deletions spec/unit/blitbuffer_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ describe("Blitbuffer unit tests", function()
local cRGB24 = Blitbuffer.ColorRGB24(0xFF, 0xAA, 0x55) -- luacheck: ignore 211
local cRGB24_32 = cRGB32:getColorRGB24() -- luacheck: ignore 211

local whiteRGB32 = Blitbuffer.ColorRGB32(0xFF, 0xFF, 0xFF, 0x00)
local whiteRGB32a = Blitbuffer.ColorRGB32(0xFF, 0xFF, 0xFF, 0xFF)
local whiteRGB24 = Blitbuffer.ColorRGB24(0xFF, 0xFF, 0xFF)
local whiteRGB16 = Blitbuffer.ColorRGB16(0xFFFF)
local whiteBB8A = Blitbuffer.Color8A(0xFF, 0x00)
local whiteBB8Aa = Blitbuffer.Color8A(0xFF, 0xFF)
local whiteBB8 = Blitbuffer.Color8(0xFF)
local whiteBB4L= Blitbuffer.Color4L(0x0F)
local whiteBB4U= Blitbuffer.Color4U(0xF0)
local blackRGB32 = Blitbuffer.ColorRGB32(0x00, 0x00, 0x00, 0x00)
local blackRGB32a = Blitbuffer.ColorRGB32(0x00, 0x00, 0x00, 0xFF)
local blackRGB24 = Blitbuffer.ColorRGB24(0x00, 0x00, 0x00)
local blackRGB16 = Blitbuffer.ColorRGB16(0x0000)
local blackBB8A = Blitbuffer.Color8A(0x00, 0x00)
local blackBB8Aa = Blitbuffer.Color8A(0x00, 0xFF)
local blackBB8 = Blitbuffer.Color8(0x00)
local blackBB4L= Blitbuffer.Color4L(0x00)
local blackBB4U= Blitbuffer.Color4U(0x00)

it("should convert RGB32 to RGB16", function()
local c16_32 = cRGB32:getColorRGB16()
assert.are.equals(0xFD4A, c16_32.v)
Expand All @@ -31,6 +50,221 @@ describe("Blitbuffer unit tests", function()
local c4u_32 = cRGB32:getColor4U()
assert.are.equals(0xB0, c4u_32.a)
end)

describe("should have pure white stay pure white when converting", function()
it("from RGB32 with alpha 0x00", function()
assert.True(whiteRGB32:getColorRGB32() == whiteRGB32)
assert.True(whiteRGB32:getColorRGB24() == whiteRGB24)
assert.True(whiteRGB32:getColorRGB16() == whiteRGB16)
assert.True(whiteRGB32:getColor8() == whiteBB8)
assert.True(whiteRGB32:getColor8A() == whiteBB8A)
assert.True(whiteRGB32:getColor4L() == whiteBB4L)
assert.True(whiteRGB32:getColor4U() == whiteBB4U)
end)
it("from RGB32 with alpha 0xFF", function()
assert.True(whiteRGB32a:getColorRGB32() == whiteRGB32a)
assert.True(whiteRGB32a:getColorRGB24() == whiteRGB24)
assert.True(whiteRGB32a:getColorRGB16() == whiteRGB16)
assert.True(whiteRGB32a:getColor8() == whiteBB8)
assert.True(whiteRGB32a:getColor8A() == whiteBB8Aa)
assert.True(whiteRGB32a:getColor4L() == whiteBB4L)
assert.True(whiteRGB32a:getColor4U() == whiteBB4U)
end)
it("from RGB24", function()
assert.True(whiteRGB24:getColorRGB32() == whiteRGB32a)
assert.True(whiteRGB24:getColorRGB24() == whiteRGB24)
assert.True(whiteRGB24:getColorRGB16() == whiteRGB16)
assert.True(whiteRGB24:getColor8() == whiteBB8)
assert.True(whiteRGB24:getColor8A() == whiteBB8A)
assert.True(whiteRGB24:getColor4L() == whiteBB4L)
assert.True(whiteRGB24:getColor4U() == whiteBB4U)
end)
it("from RGB16", function()
assert.True(whiteRGB16:getColorRGB32() == whiteRGB32a)
assert.True(whiteRGB16:getColorRGB24() == whiteRGB24)
assert.True(whiteRGB16:getColorRGB16() == whiteRGB16)
assert.True(whiteRGB16:getColor8() == whiteBB8)
assert.True(whiteRGB16:getColor8A() == whiteBB8A)
assert.True(whiteRGB16:getColor4L() == whiteBB4L)
assert.True(whiteRGB16:getColor4U() == whiteBB4U)
end)
it("from BB8A with alpha 0x00", function()
assert.True(whiteBB8A:getColorRGB32() == whiteRGB32)
assert.True(whiteBB8A:getColorRGB24() == whiteRGB24)
assert.True(whiteBB8A:getColorRGB16() == whiteRGB16)
assert.True(whiteBB8A:getColor8() == whiteBB8)
assert.True(whiteBB8A:getColor8A() == whiteBB8A)
assert.True(whiteBB8A:getColor4L() == whiteBB4L)
assert.True(whiteBB8A:getColor4U() == whiteBB4U)
end)
it("from BB8A with alpha 0xFF", function()
assert.True(whiteBB8Aa:getColorRGB32() == whiteRGB32a)
assert.True(whiteBB8Aa:getColorRGB24() == whiteRGB24)
assert.True(whiteBB8Aa:getColorRGB16() == whiteRGB16)
assert.True(whiteBB8Aa:getColor8() == whiteBB8)
assert.True(whiteBB8Aa:getColor8A() == whiteBB8Aa)
assert.True(whiteBB8Aa:getColor4L() == whiteBB4L)
assert.True(whiteBB8Aa:getColor4U() == whiteBB4U)
end)
it("from BB8", function()
assert.True(whiteBB8:getColorRGB32() == whiteRGB32a)
assert.True(whiteBB8:getColorRGB24() == whiteRGB24)
assert.True(whiteBB8:getColorRGB16() == whiteRGB16)
assert.True(whiteBB8:getColor8() == whiteBB8)
assert.True(whiteBB8:getColor8A() == whiteBB8A)
assert.True(whiteBB8:getColor4L() == whiteBB4L)
assert.True(whiteBB8:getColor4U() == whiteBB4U)
end)
it("from BB4L", function()
assert.True(whiteBB4L:getColorRGB32() == whiteRGB32a)
assert.True(whiteBB4L:getColorRGB24() == whiteRGB24)
assert.True(whiteBB4L:getColorRGB16() == whiteRGB16)
assert.True(whiteBB4L:getColor8() == whiteBB8)
assert.True(whiteBB4L:getColor8A() == whiteBB8A)
assert.True(whiteBB4L:getColor4L() == whiteBB4L)
assert.True(whiteBB4L:getColor4U() == whiteBB4U)
end)
it("from BB4U", function()
assert.True(whiteBB4U:getColorRGB32() == whiteRGB32a)
assert.True(whiteBB4U:getColorRGB24() == whiteRGB24)
assert.True(whiteBB4U:getColorRGB16() == whiteRGB16)
assert.True(whiteBB4U:getColor8() == whiteBB8)
assert.True(whiteBB4U:getColor8A() == whiteBB8A)
assert.True(whiteBB4U:getColor4U() == whiteBB4U)
assert.True(whiteBB4U:getColor4U() == whiteBB4U)
end)
end)

describe("should have pure black stay pure black when converting", function()
it("from RGB32 with alpha 0x00", function()
assert.True(blackRGB32:getColorRGB32() == blackRGB32)
assert.True(blackRGB32:getColorRGB24() == blackRGB24)
assert.True(blackRGB32:getColorRGB16() == blackRGB16)
assert.True(blackRGB32:getColor8() == blackBB8)
assert.True(blackRGB32:getColor8A() == blackBB8A)
assert.True(blackRGB32:getColor4L() == blackBB4L)
assert.True(blackRGB32:getColor4U() == blackBB4U)
end)
it("from RGB32 with alpha 0xFF", function()
assert.True(blackRGB32a:getColorRGB32() == blackRGB32a)
assert.True(blackRGB32a:getColorRGB24() == blackRGB24)
assert.True(blackRGB32a:getColorRGB16() == blackRGB16)
assert.True(blackRGB32a:getColor8() == blackBB8)
assert.True(blackRGB32a:getColor8A() == blackBB8Aa)
assert.True(blackRGB32a:getColor4L() == blackBB4L)
assert.True(blackRGB32a:getColor4U() == blackBB4U)
end)
it("from RGB24", function()
assert.True(blackRGB24:getColorRGB32() == blackRGB32a)
assert.True(blackRGB24:getColorRGB24() == blackRGB24)
assert.True(blackRGB24:getColorRGB16() == blackRGB16)
assert.True(blackRGB24:getColor8() == blackBB8)
assert.True(blackRGB24:getColor8A() == blackBB8A)
assert.True(blackRGB24:getColor4L() == blackBB4L)
assert.True(blackRGB24:getColor4U() == blackBB4U)
end)
it("from RGB16", function()
assert.True(blackRGB16:getColorRGB32() == blackRGB32a)
assert.True(blackRGB16:getColorRGB24() == blackRGB24)
assert.True(blackRGB16:getColorRGB16() == blackRGB16)
assert.True(blackRGB16:getColor8() == blackBB8)
assert.True(blackRGB16:getColor8A() == blackBB8A)
assert.True(blackRGB16:getColor4L() == blackBB4L)
assert.True(blackRGB16:getColor4U() == blackBB4U)
end)
it("from BB8A", function()
assert.True(blackBB8A:getColorRGB32() == blackRGB32)
assert.True(blackBB8A:getColorRGB24() == blackRGB24)
assert.True(blackBB8A:getColorRGB16() == blackRGB16)
assert.True(blackBB8A:getColor8() == blackBB8)
assert.True(blackBB8A:getColor8A() == blackBB8A)
assert.True(blackBB8A:getColor4L() == blackBB4L)
assert.True(blackBB8A:getColor4U() == blackBB4U)
end)
it("from BB8", function()
assert.True(blackBB8:getColorRGB32() == blackRGB32a)
assert.True(blackBB8:getColorRGB24() == blackRGB24)
assert.True(blackBB8:getColorRGB16() == blackRGB16)
assert.True(blackBB8:getColor8() == blackBB8)
assert.True(blackBB8:getColor8A() == blackBB8A)
assert.True(blackBB8:getColor4L() == blackBB4L)
assert.True(blackBB8:getColor4U() == blackBB4U)
end)
it("from BB4L", function()
assert.True(blackBB4L:getColorRGB32() == blackRGB32a)
assert.True(blackBB4L:getColorRGB24() == blackRGB24)
assert.True(blackBB4L:getColorRGB16() == blackRGB16)
assert.True(blackBB4L:getColor8() == blackBB8)
assert.True(blackBB4L:getColor8A() == blackBB8A)
assert.True(blackBB4L:getColor4L() == blackBB4L)
assert.True(blackBB4L:getColor4U() == blackBB4U)
end)
it("from BB4U", function()
assert.True(blackBB4U:getColorRGB32() == blackRGB32a)
assert.True(blackBB4U:getColorRGB24() == blackRGB24)
assert.True(blackBB4U:getColorRGB16() == blackRGB16)
assert.True(blackBB4U:getColor8() == blackBB8)
assert.True(blackBB4U:getColor8A() == blackBB8A)
assert.True(blackBB4U:getColor4U() == blackBB4U)
assert.True(blackBB4U:getColor4U() == blackBB4U)
end)
end)

describe("should have non-pure white stay non-pure white when converting", function()
it("from RGB32", function()
assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFF, 0xFE, 0x00):getColorRGB32() ~= whiteRGB32)
assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFE, 0xFF, 0x00):getColorRGB32() ~= whiteRGB32)
assert.True(Blitbuffer.ColorRGB32(0xFE, 0xFF, 0xFF, 0x00):getColorRGB32() ~= whiteRGB32)
assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFF, 0xFE, 0x00):getColorRGB24() ~= whiteRGB24)
assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFE, 0xFF, 0x00):getColorRGB24() ~= whiteRGB24)
assert.True(Blitbuffer.ColorRGB32(0xFE, 0xFF, 0xFF, 0x00):getColorRGB24() ~= whiteRGB24)
-- These ones do fail and may (or not) need fixing (the simple conversion
-- method take the most significant bits, so it misses the one we change)
-- assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFF, 0xFE, 0x00):getColorRGB16() ~= whiteRGB16)
-- assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFE, 0xFF, 0x00):getColorRGB16() ~= whiteRGB16)
-- assert.True(Blitbuffer.ColorRGB32(0xFE, 0xFF, 0xFF, 0x00):getColorRGB16() ~= whiteRGB16)
assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFF, 0xFE, 0x00):getColor8() ~= whiteBB8)
assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFE, 0xFF, 0x00):getColor8() ~= whiteBB8)
assert.True(Blitbuffer.ColorRGB32(0xFE, 0xFF, 0xFF, 0x00):getColor8() ~= whiteBB8)
assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFF, 0xFE, 0xFF):getColor8A() ~= whiteBB8A)
assert.True(Blitbuffer.ColorRGB32(0xFF, 0xFE, 0xFF, 0xFF):getColor8A() ~= whiteBB8A)
assert.True(Blitbuffer.ColorRGB32(0xFE, 0xFF, 0xFF, 0xFF):getColor8A() ~= whiteBB8A)
end)

-- RGB24 should use the same rules than RGB32, no need to check

it("from RGB16", function()
-- hex((31<<11)+(63<<5)+31) = '0xffff' = pure white
-- hex((30<<11)+(63<<5)+31) = '0xf7ff'
-- hex((31<<11)+(62<<5)+31) = '0xffdf'
-- hex((31<<11)+(63<<5)+30) = '0xfffe'
assert.True(Blitbuffer.ColorRGB16(0xF7FF):getColorRGB16() ~= whiteRGB16)
assert.True(Blitbuffer.ColorRGB16(0xFFDF):getColorRGB16() ~= whiteRGB16)
assert.True(Blitbuffer.ColorRGB16(0xFFFE):getColorRGB16() ~= whiteRGB16)
assert.True(Blitbuffer.ColorRGB16(0xF7FF):getColorRGB24() ~= whiteRGB24)
assert.True(Blitbuffer.ColorRGB16(0xFFDF):getColorRGB24() ~= whiteRGB24)
assert.True(Blitbuffer.ColorRGB16(0xFFFE):getColorRGB24() ~= whiteRGB24)
assert.True(Blitbuffer.ColorRGB16(0xF7FF):getColorRGB16() ~= whiteRGB16)
assert.True(Blitbuffer.ColorRGB16(0xFFDF):getColorRGB16() ~= whiteRGB16)
assert.True(Blitbuffer.ColorRGB16(0xFFFE):getColorRGB16() ~= whiteRGB16)
assert.True(Blitbuffer.ColorRGB16(0xF7FF):getColor8() ~= whiteBB8)
assert.True(Blitbuffer.ColorRGB16(0xFFDF):getColor8() ~= whiteBB8)
assert.True(Blitbuffer.ColorRGB16(0xFFFE):getColor8() ~= whiteBB8)
assert.True(Blitbuffer.ColorRGB16(0xF7FF):getColor8A() ~= whiteBB8A)
assert.True(Blitbuffer.ColorRGB16(0xFFDF):getColor8A() ~= whiteBB8A)
assert.True(Blitbuffer.ColorRGB16(0xFFFE):getColor8A() ~= whiteBB8A)
end)

it("from BB8", function()
assert.True(Blitbuffer.Color8(0xFE):getColorRGB32() ~= whiteRGB32a)
assert.True(Blitbuffer.Color8(0xFE):getColorRGB24() ~= whiteRGB24)
-- This one does fail and may (or not) need fixing (the simple conversion method
-- does some rshift then lshift, the bit we changed is lost in the process)
-- assert.True(Blitbuffer.Color8(0xFE):getColorRGB16() ~= whiteRGB16)
assert.True(Blitbuffer.Color8(0xFE):getColor8() ~= whiteBB8)
assert.True(Blitbuffer.Color8(0xFE):getColor8A() ~= whiteBB8A)
end)
end)
end)

describe("basic BB API", function()
Expand Down

0 comments on commit 6769d0c

Please sign in to comment.