Users browsing this thread: 1 Guest(s)
What format is this image *really* in?
#1
I am working in an environment where I can't pull in any external modules/libraries, so I have to create my own image decoder for the BCn format. I am encountering a problem with BC7 in particular - or rather, something that everything is claiming is BC7, but fundamentally cannot be.

I can't attach the image itself because .dds isn't an allowed file type, but here's how it begins:
Code:
44 44 53 20 7c 00 00 00 07 10 00 00 00 02 00 00
00 02 00 00 00 00 04 00 00 00 00 00 01 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00
04 00 00 00 44 58 31 30 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
62 00 00 00 03 00 00 00 00 00 00 00 01 00 00 00
00 00 00 00 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24 30 ff 03 00 c0 ff af aa aa aa 4a 92
24 49 92 24

Each "30 ff 03 00 c0 ff af aa aa aa 4a 92 24 49 92 24" is a solid chunk of red pixels, as evidenced by opening the file in Visual Studio or XNViewMP (top left corner). In addition, the entire image is completely opaque and has no blue at all. Multiple programs including Visual Studio list the image as being BC7.

I'm using these references to understand the format:
According to all of these, this data is a "mode 2" block, and thus should be broken up like this:
Code:
00110000111111110000001100000000110000001111111110101111101010101010101010101010010010101001001000100100010010011001001000100100

mode: 001
partition: 100001
red endpoints: 11111 11000 00011 00000 00011 00000
green endpoints: 01111 11111 01011 11101 01010 10101
blue endpoints: 01010 10101 00100 10101 00100 10001
indexes: 0 01 00 0 10 01 00 11 00 10 01 00 01 00 10 0

The problem is that this is impossible. There are two pieces of proof:
  • None of the blue endpoints are zero. Every pixel in the image has a blue channel of zero. Contradiction.
  • When I use a hex editor to mess with the bits early in the "red endpoints" section, the pixels instead become partly transparent. Mode 2 has no alpha components, and in none of the BC7 modes does alpha ever come before colour. It can't even be a "red <-> alpha" swap, because the later red endpoints do affect the red, and no possible swap can result in the order "a,r,g,b".

So this image claims to be BC7, but the only way it can be is if all documentation on the format is extremely incorrect. Therefore, I ask: What is the actual format of this image, and how do I decode it?
Reply
Thanked by:
#2
Your problem is the order of the bits. The 16 bytes of a BC7 block are treated as a stream of 128 bits, but it goes from the lowest bit of each byte to the highest. So 0x30 isn't 00110000, it's the reverse, 00001100. Similarly, when you read a number from the stream, the first bit is the lowest bit of the result, etc. Btw this is the usual order for storing a bitstream as bytes.

That makes the mode 00001 = 4, so the whole block parses as

Code:
mode              00001
2 bit rotation    10       1
1 bit idxMode     0        0
5 bit R0          11111    31
5 bit R1          11111    31
5 bit G0          00000    0
5 bit G1          00000    0
5 bit B0          00000    0
5 bit B1          00000    0
6 bit A0          111111   63
6 bit A1          111111   63
31 bit index data 1101010101010101010101010101010
47 bit index data 10100100100100100100100100100100100100100100100

which does look like opaque red.

It seems like you could just copy/port an existing decoder. bc7decomp.h / bc7decomp.cpp from bc7enc has essentially no dependencies if that's the problem.
Reply
#3
(01-14-2023, 07:39 PM)scurest Wrote: Btw this is the usual order for storing a bitstream as bytes.

All the other BCn formats (well, BC1-5) seem to function properly when read with no byte reversal. I wouldn't have gotten stuck here if this made sense.

Unless the code I have working for them is secretly doing it in the background without being clear about it. That's a possibility.

(01-14-2023, 07:39 PM)scurest Wrote: It seems like you could just copy/port an existing decoder. bc7decomp.h / bc7decomp.cpp from bc7enc has essentially no dependencies if that's the problem.

I'm using Python in Blender. It's honestly easier to do it from scratch using references.

EDIT: I am getting improved results now, you have helped unblock me.
Reply
Thanked by:
#4
You probably just don't notice it when bit fields fall on nice byte boundaries, but when you read eg two bytes as a little-endian 16 bit int, the first bit in the stream (the lowest bit of the first byte) becomes the first (lowest) bit of the result, etc.

Quote:I'm using Python in Blender

I thought for sure you could just slap a DDS header in front of the BC7 blocks and have Blender load it in a few lines. But sure enough. Blender doesn't support BC7 and the issue for it is moving at the usual glacial pace....
Reply
Thanked by:


Forum Jump: