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