About VTFLib - NemPosted: Apr 18th, 2005 - 10:27:01 pm

VTFLib is a LGPL open source programming library, written by Neil Jedrzejewski and I. VTFLib provides a C and C++ API that, with a few simple functions, can open and save .vtf and .vmt files, providing access to all known features. The library functions independent of Steam, allowing third party applications to use the library without Steam present or runningi on the target system.

VTFLib includes two GPL example applications, VTFCmd and VTFEdit. VTFCmd is a C command line frontend for VTFLib that can create .vtf and .vmt files from various source formats. It is similar in functionality to Valve's vtex Source SDK utility, but offers a lot more control. VTFEdit is a C++ .NET graphical frontend for VTFLib with viewing and creation capabilities. Both VTFCmd and VTFEdit support several source image formats, including, but not limited to .bmp, .dds, .gif, .jpg, .png and .tga.


VTFEdit .vtf frame/face/mipmap viewing. VTFEdit .vtf information viewing.

VTFEdit file system browsing. VTFEdit .vmt viewing.

VTFEdit import options. VTFEdit batch conversion options.

VTFEdit .wad conversion options. VTFEdit .vmt creation wizard.

VTFEdit .vmt creation wizard. VTFCmd command line options.

Documentation: Features:
  • Convert .bmp, .dds, .gif, .jpg, .png and .tga files to .vtf and .vmt files with easy access to all .vtf options.
  • Convert .vtf files to .bmp, .jpg, .png and .tga files.
  • Convert entire folders to and from .vtf and .vmt files.
  • Convert .wad files to .vtf and .vmt files.
  • Explore .bsp, .gcf, .pak, .wad and .xzp packages.
  • Preview .vtf files.
  • Recent file menu.
  • 100% Free.
Download: Third Party Downloads:
Modified: Sep 14th, 2007 - 3:28:10 am[ 611187 Views ]

[ 1 2 3 4 5 6 7 8 9 ]

106. panziPosted: Mar 8th, 2014 - 4:43:36 pm
Why are there *so many* global variables? Well, why are there *any* global variables. This way this library cannot be used in a multi threading context. I'm not sure if I can use it where I planned it to use it. :/

107. NemPosted: Mar 8th, 2014 - 11:00:35 pm
ProcReader/ProcWriter and the many global variables exist because the library is designed to be used from both a C++ and C interface (you can, for example, use it in .Net with DLL imports).

VTFLib was not designed to be thread safe (there were no multicore CPUs 10 years ago). After a quick look, as long as you instantiate your own CVTFFile instances, and don't set some of the obscure settings outside of initialization, the only thing that is not thread safe is probably VTFLib::LastError. You could possibly declare it with thread local storage (not sure what the TLS restrictions are in Linux) or throw a Mutex into it.

108. panziPosted: Mar 9th, 2014 - 5:36:05 am
Ah, the only global variable that you have to use is LastError. Still, this makes this not thread safe.

Anyway it now works fine under Linux. I also fixed const correctness in some functions (where source data pointers where not const):

I also wrote a gdk pixbuf loader so that any Gtk+ application can now view VTF files (only one frame, might add animation support when there are >1 frames later):

It would be cool if this could be merged again with the official VTFLib.

109. panziPosted: Mar 9th, 2014 - 5:44:18 am
Just now saw your answer:
Ah I see. I think one can do C bindings without global variables: Cast all object pointers to incomplete struct types and wrap all methods like "vlVTFFileLoadPath(struct c_CVTFFile*, const char *)" and "vlVTFFileLoadBuffer(struct c_CVTFFile*, void*, size_t)" etc. It sure is a lot of wrapping work.

110. panziModified: Mar 9th, 2014 - 7:02:38 pm

111. panziPosted: Mar 9th, 2014 - 7:05:59 pm
Oh and about thread local storage: For non-POD types this only works with C++11 thread_local. Using that would hurt compatibility with MSVC.

112. NemPosted: Mar 10th, 2014 - 4:04:13 am
There's no justifying the design of this library. I wrote it almost 10 years ago when I was still fairly new to programming, and I don't think the Source engine was even multithreaded at the time (if I remember correctly, the Athlon 64 X2 had just came out). The design was loosely based on other popular libraries out around then. Since that time it has mostly only been updated when the VTF format has changed.

If it ever gets refactored, it might be to remove its dependency on the old deprecated NXDXT library. I doubt I'll ever get around to it though.

Thanks for reporting those bugs, I will integrate them back. yeahbaby

113. panziPosted: Mar 10th, 2014 - 10:14:30 pm
Btw. there seems to be a replacement for the NXDXT library:

Under Fedora I can install that with "sudo yum install libtxc_dxtn". :)

I tried to keep binary compatibility when compiled for Windows, but I haven't even tried to compile it for Windows. I would only cross-compile it with MinGW anyway. My Linux port theoretically supports Files > 4 GB (-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE make off_t 64bit and bring fseeko and ftello into existence, even under 32bit Linux), if the VTF format would support that. I replaced vlUInt and vlLong with vlSSize ("stream size"), vlSize and vlOffset. Under Windows it should typdef to the same as before, under Linux vlSSize = off_t (signed 64bit), vlSize = size_t (unsigned 32bit or 64bit) and vlOffset = off_t. This means under Windows vlSSize is unsigned and under Linux it is signed. Maybe that is not such a good idea. vlSSize has to be off_t (or something that is at least as big) because that is the type of the st_size field in the stat struct. If functions that return vlSSize fail they return -1 in Linux and 0 in Windows. I think THAT cannot be and I have to change it to 0 everywhere, even though 0 could be a valid value. Or maybe make it vlUInt64 under Windows and also return -1 there (which would break compatibility)? (I just now changed it to 0 everywhere and pushed to github.)

Btw. I also wrote a Qt4 QImageIO plugin based on this:

Next: A KDE plugin, because apparently some (the most important) KDE applications ignore the Qt QImageIO plugin infrastructure and use their own. GIMP also ignores the GDK PixBuf loader infrastructure. Bah.

114. panziPosted: Mar 11th, 2014 - 1:31:31 am
Ok, now I had to make a binary incompatible change to make it compile under certain configurations: I had to add virtual destructors to IReader and IWriter.

115. panziPosted: Mar 11th, 2014 - 12:15:10 pm
I don't have time to debug this right now, but is it possible that there is a mixup of the red and blue channel when converting to ARGB8888? (Qt only supports ARGB, not RGBA so I have to use this.)

116. panziPosted: Mar 11th, 2014 - 6:08:54 pm
Or not the red and blue channel but the alpha channel and some other channel. See these example screenshots of the file "materials/paint/prop_paint_orange.vtf" from Portal 2:

Image converted to RGBA (Gdk PixBuf):

Image converted to RGB (Qt):

Image converted to ARGB (Qt):

Image converted to RGBA but I told Qt it is ARGB:

117. panziPosted: Mar 11th, 2014 - 6:12:08 pm
Image converted to BGRA but I told Qt it is ARGB:

Looks pretty broken but it IS orange.

118. panziPosted: Mar 11th, 2014 - 6:59:01 pm
If I do this manually I get the correct images:


qformat = QImage::Format_ARGB32;
dstformat = IMAGE_FORMAT_RGBA8888;

const vlByte* frame = vtf.GetData(currentFrame, 0, 0, 0);

vlByte* temp = new vlByte[width*height*4];

if (!VTFLib::CVTFFile::Convert(frame, temp, width, height, srcformat, dstformat)) {
qDebug("%s", VTFLib::LastError.Get());
delete[] temp;
return false;

*image = QImage(width, height, qformat);
uchar *dest = image->bits();
for (vlUInt y = 0; y < height; ++ y) {
for (vlUInt x = 0; x < width; ++ x) {
dest[y * width * 4 + x * 4 + 0] = temp[y * width * 4 + x * 4 + 2];
dest[y * width * 4 + x * 4 + 1] = temp[y * width * 4 + x * 4 + 1];
dest[y * width * 4 + x * 4 + 2] = temp[y * width * 4 + x * 4 + 0];
dest[y * width * 4 + x * 4 + 3] = temp[y * width * 4 + x * 4 + 3];

delete[] temp;

Hmm, what does this mean? What is wrong/what is happening?

119. NemPosted: Mar 12th, 2014 - 6:26:12 am
I think you want:
dstformat = IMAGE_FORMAT_BGRA8888;

As QImage::Format_ARGB32 is:

Which is the opposite order on little endian.

120. panziPosted: Mar 12th, 2014 - 9:40:00 pm
I think you want:
dstformat = IMAGE_FORMAT_BGRA8888;

As QImage::Format_ARGB32 is:

Which is the opposite order on little endian.

I figured so already myself, but when I use this I get the last image I posted. (http://i.imgur.com/GL2GsjB.png) It's orange but looks broken.

[ 1 2 3 4 5 6 7 8 9 ]

You must be logged in to post a comment.
New users can register here.
Nem's Tools v2.0 © 2006 Ryan Gregg.
Execution time: 0.033692s; Queries: 17.
dishes served.
Powered by The Wavelength.

Valid XHTML 1.0 Transitional Valid CSS