I have a VTF file that looks like this inside VTFEdit:
I tried to convert it to a PNG in Python using the code below:
import texture2ddecoder, numpy, cv2
from PIL import Image
img_width = 64
img_height = 64
encoded_binary = open('bracketsTest.vtf','rb').read()
#decompressing dxt5 (compression used for this VTF file) to get actual pixel colors, returns BGRA bytes
decoded_binary = texture2ddecoder.decode_bc5(encoded_binary, img_width, img_height)
#creating RGBA png, converting from BGRA (no support for BRGA in PIL it seems)
dec_img = Image.frombytes("RGBA", (img_width, img_height), decoded_binary, 'raw', ("BGRA"))
dec_img.show()
dec_img.save('testpng.png')
And the resulting image came out like this:
As the resulting image does not look the same as it does in VTFEdit, obviously something went wrong. I suspected that it was an issue with the color channel going from BGRA (VTFs are BRGA by default + texture2ddecoder produces BRGA bytes when decompressing) to RGBA, so I tried the following code to convert the image from RGBA to BRGA:
# trying to convert png back to BGRA
image = cv2.imread('testpng.png')
image_bgra = cv2.cvtColor(image, cv2.COLOR_RGBA2BGRA)
cv2.imshow('image',image_bgra)
But the resulting image came out basically the same as before the conversion only with blue squares instead of red ones. What's going on here and how can I fix it? Is there a name for these odd squares?
DXT5 is actually known as Block Compression 3 (BC3). In my case, I incorrectly assumed BC5 = DXT5, so the decompression was wrong (see this wikipedia article for a better explanation). I changed the line decoded_binary = texture2ddecoder.decode_bc5(encoded_binary, img_width, img_height)
to decoded_binary = texture2ddecoder.decode_bc3(encoded_binary, img_width, img_height)
and the resulting image looked like this:
There are still some odd squares at the top, but deleting/ignoring the header info and low-res thumbnail data seems to fix it:
Know your decompression algorithms!!!