0

I have a VTF file that looks like this inside VTFEdit:

Image as it appears inside VTFEdit (or as a tga/png/jpg)

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: Screenshot of resulting 64x64 PNG image

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?

noG23
  • 93
  • 2
  • 7
  • It's probably just a misunderstanding of what `decode_bc5` is delivering to you. – Mark Ransom Jun 21 '22 at 03:06
  • Are you sure that it's supposed to be BGRA/RGBA and not BGR/RGB? – Mark Ransom Jun 21 '22 at 03:07
  • @MarkRansom I'm almost positive, since in VTFEdit the format is specified as "8-bit alpha". I also asked a member of the Source Engine Discord and they told me VTFs are generally stored in BGRA mode. – noG23 Jun 21 '22 at 03:24
  • Well, it was worth a shot. Sorry I don't have enough familiarity with VTF to be more help. – Mark Ransom Jun 21 '22 at 03:29
  • I know nothing about VTF format. But a search on Google give https://developer.valvesoftware.com/wiki/Valve_Texture_Format which shows many formats. Be sure you use the correct one. – fmw42 Jun 21 '22 at 04:26
  • are you sure none of the data was ever compressed as JPEG or other lossy compression? that nobody ever did that? – Christoph Rackwitz Jun 21 '22 at 14:25
  • voting to close the question since it has *nothing* to do with any of the tagged technologies. it's purely a problem of `texture2ddecoder` and whatever programs OP used, which were not tagged. – Christoph Rackwitz Jun 21 '22 at 14:26
  • @ChristophRackwitz I did not know it was a problem with texture2ddecoder when I first posted the question, hence I tagged technologies I used that actually had tags on this site. It's obvious now that it wasn't an issue with python, opencv, etc., and I'll gladly change the tags (unless you would like to), but at the time I did not know. – noG23 Jun 21 '22 at 14:37
  • 1
    when you encounter such problems, _debug_ the situation. for each component, establish whether it's required for reproduction, or not. since you use opencv and PIL only for image reading, you could have tried another library, or to view the picture in some other way (photoshop/mspaint, a random browser, ...) that's just basic debugging, to narrow down where the problem could be, and where it can't be. – Christoph Rackwitz Jun 21 '22 at 14:42

1 Answers1

1

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:

Decompression after BC3 (header+low-res thumbnail data still included)

There are still some odd squares at the top, but deleting/ignoring the header info and low-res thumbnail data seems to fix it:

Decompression after BC3 (header+low-res thumbnail data not included

Know your decompression algorithms!!!

noG23
  • 93
  • 2
  • 7