diff --git a/PVRTCEncoder/src/Pixel.cpp b/PVRTCEncoder/src/Pixel.cpp index 9c85c32..c4bfe86 100644 --- a/PVRTCEncoder/src/Pixel.cpp +++ b/PVRTCEncoder/src/Pixel.cpp @@ -108,6 +108,44 @@ namespace PVRTCC { } } + void Pixel::ToBits(uint8 *bits, uint32 numBytes, uint32 bitOffset) const { +#ifndef NDEBUG + uint32 bitDepthSum = bitOffset; + for(int i = 0; i < 4; i++) { + bitDepthSum += m_BitDepth[i]; + } + assert((bitDepthSum / 8) < numBytes); +#endif + + uint8 byteIdx = 0; + while(bitOffset > 8) { + byteIdx++; + bitOffset -= 8; + } + + uint8 bitIdx = bitOffset; + for(int i = 3; i >= 0; i--) { + uint8 val = Component(i); + uint8 depth = m_BitDepth[i]; + + if(depth + bitIdx > 8) { + uint8 nextBitIdx = depth - (8 - bitIdx); + uint16 v = static_cast(val); + bits[byteIdx++] |= (v << bitIdx) & 0xFF; + bitIdx = nextBitIdx; + bits[byteIdx] = (v >> (depth - bitIdx)) & 0xFF; + } else { + bits[byteIdx] |= (val << bitIdx) & 0xFF; + bitIdx += depth; + } + + if(bitIdx == 8) { + bitIdx = 0; + byteIdx++; + } + } + } + uint8 Pixel::ChangeBitDepth(uint8 val, uint8 oldDepth, uint8 newDepth) { assert(newDepth <= 8); assert(oldDepth <= 8); diff --git a/PVRTCEncoder/src/Pixel.h b/PVRTCEncoder/src/Pixel.h index f87d79d..3fe7e2b 100644 --- a/PVRTCEncoder/src/Pixel.h +++ b/PVRTCEncoder/src/Pixel.h @@ -82,6 +82,13 @@ class Pixel { const uint8 channelDepth[4] = static_cast(0), uint8 bitOffset = 0); + // This function is the converse of FromBits. It will pack a pixel + // into a specified buffer based on the bit depth of the pixel. The + // bitOffset determines at which bit to start from. The bits are written + // starting from the LSB of bits[0]. numBytes is a sanity check and isn't + // used in release mode. + void ToBits(uint8 *bits, uint32 numBytes, uint32 bitOffset = 0) const; + // Changes the depth of each pixel. This scales the values to // the appropriate bit depth by either truncating the least // significant bits when going from larger to smaller bit depth diff --git a/PVRTCEncoder/test/PixelTest.cpp b/PVRTCEncoder/test/PixelTest.cpp index 99a9c67..decab5b 100644 --- a/PVRTCEncoder/test/PixelTest.cpp +++ b/PVRTCEncoder/test/PixelTest.cpp @@ -133,6 +133,32 @@ TEST(Pixel, FromBitsAndAssociatedConstructor) { } } +TEST(Pixel, ToBits) { + PVRTCC::Pixel p; + + uint8 bitDepth[4] = { 2, 8, 1, 7 }; + p.ChangeBitDepth(bitDepth); + + p.A() = 0x2; + p.R() = 0x56; + p.G() = 0; + p.B() = 0x4F; + + uint8 bits[3]; + memset(bits, 0, sizeof(bits)); + p.ToBits(bits, sizeof(bits)); + + EXPECT_EQ(bits[0], 0x4F); + EXPECT_EQ(bits[1], 0x56); + EXPECT_EQ(bits[2], 0x2); + + memset(bits, 0, sizeof(bits)); + p.ToBits(bits, 3, 2); + EXPECT_EQ(bits[0], 0x3C); + EXPECT_EQ(bits[1], 0x59); + EXPECT_EQ(bits[2], 0x09); +} + TEST(Pixel, ChangeChannelBitDepth) { uint8 val = 0x43; uint8 depth = 7;