Add BC1 block encoding tests

This commit is contained in:
Andrew Cassidy 2021-04-05 23:07:33 -07:00
parent 901dcc45df
commit 50d411a349
2 changed files with 77 additions and 64 deletions

@ -1 +1 @@
Subproject commit 0ade526dd1070e6f5b43e0bd58b26828abff86b7 Subproject commit 1023b4934473aef3c2ff24687bef4f41db1f702b

View File

@ -1,7 +1,8 @@
import unittest import unittest
import nose import nose
from parameterized import parameterized, parameterized_class from parameterized import parameterized_class
import quicktex.s3tc.bc1 as bc1 from quicktex.s3tc.bc1 import BC1Block, BC1Texture, BC1Encoder
from tests.images import BC1Blocks
in_endpoints = ((253, 254, 255), (65, 70, 67)) # has some small changes that should encode the same in_endpoints = ((253, 254, 255), (65, 70, 67)) # has some small changes that should encode the same
out_endpoints = ((255, 255, 255, 255), (66, 69, 66, 255)) out_endpoints = ((255, 255, 255, 255), (66, 69, 66, 255))
@ -14,20 +15,20 @@ class TestBC1Block(unittest.TestCase):
def test_size(self): def test_size(self):
"""Test the size and dimensions of BC1Block""" """Test the size and dimensions of BC1Block"""
self.assertEqual(bc1.BC1Block.size, 8, 'incorrect block size') self.assertEqual(BC1Block.size, 8, 'incorrect block size')
self.assertEqual(bc1.BC1Block.width, 4, 'incorrect block width') self.assertEqual(BC1Block.width, 4, 'incorrect block width')
self.assertEqual(bc1.BC1Block.height, 4, 'incorrect block width') self.assertEqual(BC1Block.height, 4, 'incorrect block width')
self.assertEqual(bc1.BC1Block.dimensions, (4, 4), 'incorrect block dimensions') self.assertEqual(BC1Block.dimensions, (4, 4), 'incorrect block dimensions')
def test_buffer(self): def test_buffer(self):
"""Test the buffer protocol of BC1Block""" """Test the buffer protocol of BC1Block"""
block = bc1.BC1Block() block = BC1Block()
mv = memoryview(block) mv = memoryview(block)
self.assertFalse(mv.readonly, 'buffer is readonly') self.assertFalse(mv.readonly, 'buffer is readonly')
self.assertTrue(mv.c_contiguous, 'buffer is not contiguous') self.assertTrue(mv.c_contiguous, 'buffer is not contiguous')
self.assertEqual(mv.ndim, 1, 'buffer is multidimensional') self.assertEqual(mv.ndim, 1, 'buffer is multidimensional')
self.assertEqual(mv.nbytes, bc1.BC1Block.size, 'buffer is the wrong size') self.assertEqual(mv.nbytes, BC1Block.size, 'buffer is the wrong size')
self.assertEqual(mv.format, 'B', 'buffer has the wrong format') self.assertEqual(mv.format, 'B', 'buffer has the wrong format')
mv[:] = block_bytes mv[:] = block_bytes
@ -35,7 +36,7 @@ class TestBC1Block(unittest.TestCase):
def test_constructor(self): def test_constructor(self):
"""Test constructing a block out of endpoints and selectors""" """Test constructing a block out of endpoints and selectors"""
block = bc1.BC1Block(*in_endpoints, selectors) block = BC1Block(*in_endpoints, selectors)
self.assertEqual(block.tobytes(), block_bytes, 'incorrect block bytes') self.assertEqual(block.tobytes(), block_bytes, 'incorrect block bytes')
self.assertEqual(block.selectors, selectors, 'incorrect selectors') self.assertEqual(block.selectors, selectors, 'incorrect selectors')
self.assertEqual(block.endpoints, out_endpoints, 'incorrect endpoints') self.assertEqual(block.endpoints, out_endpoints, 'incorrect endpoints')
@ -43,15 +44,15 @@ class TestBC1Block(unittest.TestCase):
def test_frombytes(self): def test_frombytes(self):
"""Test constructing a block out of raw data""" """Test constructing a block out of raw data"""
block = bc1.BC1Block.frombytes(block_bytes) block = BC1Block.frombytes(block_bytes)
self.assertEqual(block.tobytes(), block_bytes, 'incorrect block bytes') self.assertEqual(block.tobytes(), block_bytes, 'incorrect block bytes')
self.assertEqual(block.selectors, selectors, 'incorrect selectors') self.assertEqual(block.selectors, selectors, 'incorrect selectors')
self.assertEqual(block.endpoints, out_endpoints, 'incorrect endpoints') self.assertEqual(block.endpoints, out_endpoints, 'incorrect endpoints')
self.assertFalse(block.is_3color, 'incorrect color mode') self.assertFalse(block.is_3color, 'incorrect color mode')
def test_eq(self): def test_eq(self):
block1 = bc1.BC1Block.frombytes(block_bytes) block1 = BC1Block.frombytes(block_bytes)
block2 = bc1.BC1Block.frombytes(block_bytes) block2 = BC1Block.frombytes(block_bytes)
self.assertEqual(block1, block2, 'identical blocks not equal') self.assertEqual(block1, block2, 'identical blocks not equal')
@ -64,25 +65,29 @@ class TestBC1Block(unittest.TestCase):
]) ])
class TestBC1Texture(unittest.TestCase): class TestBC1Texture(unittest.TestCase):
def setUp(self): def setUp(self):
self.tex = bc1.BC1Texture(self.w, self.h) self.tex = BC1Texture(self.w, self.h)
self.size = self.wb * self.hb * bc1.BC1Block.size self.size = self.wb * self.hb * BC1Block.size
def test_size(self): def test_size(self):
"""Test size and dimensions of BC1Texture""" """Test size of BC1Texture in bytes"""
self.assertEqual(self.tex.size, self.size, 'incorrect texture size') self.assertEqual(self.tex.size, self.size, 'incorrect texture size')
self.assertEqual(len(self.tex.tobytes()), self.size, 'incorrect texture size from tobytes') self.assertEqual(len(self.tex.tobytes()), self.size, 'incorrect texture size from tobytes')
def test_dimensions(self):
"""Test dimensions of BC1Texture in pixels"""
self.assertEqual(self.tex.width, self.w, 'incorrect texture width') self.assertEqual(self.tex.width, self.w, 'incorrect texture width')
self.assertEqual(self.tex.height, self.h, 'incorrect texture height') self.assertEqual(self.tex.height, self.h, 'incorrect texture height')
self.assertEqual(self.tex.dimensions, (self.w, self.h), 'incorrect texture dimensions') self.assertEqual(self.tex.dimensions, (self.w, self.h), 'incorrect texture dimensions')
def test_dimensions_blocks(self):
"""Test dimensions of BC1Texture in blocks"""
self.assertEqual(self.tex.width_blocks, self.wb, 'incorrect texture width_blocks') self.assertEqual(self.tex.width_blocks, self.wb, 'incorrect texture width_blocks')
self.assertEqual(self.tex.height_blocks, self.hb, 'incorrect texture width_blocks') self.assertEqual(self.tex.height_blocks, self.hb, 'incorrect texture width_blocks')
self.assertEqual(self.tex.dimensions_blocks, (self.wb, self.hb), 'incorrect texture dimensions_blocks') self.assertEqual(self.tex.dimensions_blocks, (self.wb, self.hb), 'incorrect texture dimensions_blocks')
def test_blocks(self): def test_blocks(self):
"""Test getting and setting blocks to BC1Texture""" """Test getting and setting blocks to BC1Texture"""
blocks = [[bc1.BC1Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(self.wb)] for y in range(self.hb)] blocks = [[BC1Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(self.wb)] for y in range(self.hb)]
for x in range(self.wb): for x in range(self.wb):
for y in range(self.hb): for y in range(self.hb):
self.tex[x, y] = blocks[y][x] self.tex[x, y] = blocks[y][x]
@ -90,9 +95,9 @@ class TestBC1Texture(unittest.TestCase):
b = self.tex.tobytes() b = self.tex.tobytes()
for x in range(self.wb): for x in range(self.wb):
for y in range(self.hb): for y in range(self.hb):
index = (x + (y * self.wb)) * bc1.BC1Block.size index = (x + (y * self.wb)) * BC1Block.size
tb = self.tex[x, y] tb = self.tex[x, y]
fb = bc1.BC1Block.frombytes(b[index:index + bc1.BC1Block.size]) fb = BC1Block.frombytes(b[index:index + BC1Block.size])
self.assertEqual(tb, blocks[y][x], 'incorrect block read from texture') self.assertEqual(tb, blocks[y][x], 'incorrect block read from texture')
self.assertEqual(fb, blocks[y][x], 'incorrect block read from texture bytes') self.assertEqual(fb, blocks[y][x], 'incorrect block read from texture bytes')
@ -104,7 +109,6 @@ class TestBC1Texture(unittest.TestCase):
self.assertFalse(mv.readonly, 'buffer is readonly') self.assertFalse(mv.readonly, 'buffer is readonly')
self.assertTrue(mv.c_contiguous, 'buffer is not contiguous') self.assertTrue(mv.c_contiguous, 'buffer is not contiguous')
self.assertEqual(mv.ndim, 1, 'buffer is multidimensional')
self.assertEqual(mv.nbytes, self.size, 'buffer is the wrong size') self.assertEqual(mv.nbytes, self.size, 'buffer is the wrong size')
self.assertEqual(mv.format, 'B', 'buffer has the wrong format') self.assertEqual(mv.format, 'B', 'buffer has the wrong format')
@ -113,52 +117,61 @@ class TestBC1Texture(unittest.TestCase):
self.assertEqual(mv.tobytes(), data, 'incorrect buffer data') self.assertEqual(mv.tobytes(), data, 'incorrect buffer data')
def get_class_name_blocks(cls, num, params_dict): @parameterized_class(
return "%s%s" % (cls.__name__, params_dict['color_mode'].name,) ("name", "color_mode"), [
("4Color", BC1Encoder.ColorMode.FourColor),
("3Color", BC1Encoder.ColorMode.ThreeColor),
("3Color_Black", BC1Encoder.ColorMode.ThreeColorBlack),
])
class TestBC1Encoder(unittest.TestCase):
"""Test BC1 encoder with a variety of inputs with 3 color blocks disabled."""
@classmethod
def setUpClass(cls):
cls.bc1_encoder = BC1Encoder(5, cls.color_mode)
# def test_block_4color(self):
# """Test encoder output with 4 color greyscale testblock."""
# @parameterized_class([ out_tex = self.bc1_encoder.encode(BC1Blocks.greyscale.texture)
# {"color_mode": ColorMode.FourColor},
# {"color_mode": ColorMode.ThreeColor}, self.assertEqual(out_tex.dimensions_blocks, (1, 1), 'encoded texture has multiple blocks')
# {"color_mode": ColorMode.ThreeColorBlack},
# ], class_name_func=get_class_name_blocks) out_block = out_tex[0, 0]
# class TestBC1EncoderBlocks(unittest.TestCase):
# """Test BC1 encoder with a variety of inputs with 3 color blocks disabled.""" self.assertFalse(out_block.is_3color, 'returned 3color mode for greyscale test block')
# self.assertEqual(out_block, BC1Blocks.greyscale.block, 'encoded block is incorrect')
# def setUp(self):
# self.bc1_encoder = bc1.BC1Encoder(5, self.color_mode) def test_block_3color(self):
# """Test encoder output with 3 color test block."""
# def test_block_4color(self): out_tex = self.bc1_encoder.encode(BC1Blocks.three_color.texture)
# """Test encoder output with 4 color greyscale testblock."""
# out = BC1Block.frombytes(self.bc1_encoder.encode_image(Blocks.greyscale, 4, 4)) self.assertEqual(out_tex.dimensions_blocks, (1, 1), 'encoded texture has multiple blocks')
# selectors = [[0, 2, 3, 1]] * 4
# out_block = out_tex[0, 0]
# self.assertFalse(out.is_3color(), "returned block color mode for greyscale test block")
# self.assertEqual(selectors, out.selectors, "block has incorrect selectors for greyscale test block") if self.color_mode != BC1Encoder.ColorMode.FourColor: # we only care about the selectors if we are in 3 color mode
# self.assertTrue(out_block.is_3color, 'returned 4-color block for 3 color test block')
# def test_block_3color(self): self.assertEqual(out_block, BC1Blocks.three_color.block, 'encoded block is incorrect')
# """Test encoder output with 3 color test block.""" else:
# out = BC1Block.frombytes(self.bc1_encoder.encode_image(Blocks.three_color, 4, 4)) self.assertFalse(out_block.is_3color, 'returned 3-color block in 4-color mode')
# selectors = [[1, 2, 2, 0]] * 4
# def test_block_3color_black(self):
# if self.color_mode != ColorMode.FourColor: # we only care about the selectors if we are in 3 color mode """Test encoder output with 3 color test block with black pixels."""
# self.assertTrue(out.is_3color(), "returned 4-color block for 3 color test block") out_tex = self.bc1_encoder.encode(BC1Blocks.three_color_black.texture)
# self.assertEqual(selectors, out.selectors, "block has incorrect selectors for 3 color test block")
# else: self.assertEqual(out_tex.dimensions_blocks, (1, 1), 'encoded texture has multiple blocks')
# self.assertFalse(out.is_3color(), "return 3-color block in 4-color mode")
# out_block = out_tex[0, 0]
# def test_block_3color_black(self): has_black = 3 in [j for row in out_block.selectors for j in row]
# """Test encoder output with 3 color test block with black pixels."""
# out = BC1Block.frombytes(self.bc1_encoder.encode_image(Blocks.three_color_black, 4, 4)) if self.color_mode == BC1Encoder.ColorMode.ThreeColorBlack: # we only care about the selectors if we are in 3 color black mode
# selectors = [[3, 1, 2, 0]] * 4 self.assertTrue(out_block.is_3color, 'returned 4-color block for 3 color test block with black')
# self.assertTrue(has_black, 'block does not have black pixels as expected')
# if self.color_mode == ColorMode.ThreeColorBlack: # we only care about the selectors if we are in 3 color black mode self.assertEqual(out_block, BC1Blocks.three_color_black.block, "encoded block is incorrect")
# self.assertTrue(out.is_3color_black(), "returned 4-color block for 3 color test block with black") elif self.color_mode == BC1Encoder.ColorMode.ThreeColor:
# self.assertEqual(selectors, out.selectors, "block has incorrect selectors for 3 color with black test block") self.assertFalse(has_black and out_block.is_3color, 'returned 3color block with black pixels')
# else: else:
# self.assertFalse(out.is_3color_black(), "returned incorrect block color mode for 3 color with black test block") self.assertFalse(out_block.is_3color, 'returned 3-color block in 4-color mode')
if __name__ == '__main__': if __name__ == '__main__':