SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Loading...
Searching...
No Matches
VTF.h
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cstddef>
5#include <span>
6#include <string>
7#include <tuple>
8#include <utility>
9#include <variant>
10#include <vector>
11
13#include <sourcepp/Macros.h>
14
15#include "ImageConversion.h"
16#include "SHT.h"
17
18namespace vtfpp {
19
23
24enum class CompressionMethod : int16_t {
25 // Strata Source v7.6 defines
26 DEFLATE = 8,
27 ZSTD = 93,
28
29 // Signify the image resource should be compressed with LZMA on console
30 CONSOLE_LZMA = 0x360,
31};
32
33struct Resource {
34 enum Type : uint32_t {
35 TYPE_UNKNOWN = 0, // Unknown
44 };
45 static const std::array<Type, 8>& getOrder();
46
47 enum Flags : uint8_t {
50 };
51
54 std::span<std::byte> data;
55
56 using ConvertedData = std::variant<
57 std::monostate, // Anything that would be equivalent to just returning data directly, or used as an error
58 SHT, // Particle Sheet
59 uint32_t, // CRC, TSO
60 std::tuple<uint8_t, uint8_t, uint8_t, uint8_t>, // LOD
61 std::string, // KVD
62 std::span<uint32_t> // AXC
63 >;
64 [[nodiscard]] ConvertedData convertData() const;
65
66 [[nodiscard]] SHT getDataAsParticleSheet() const {
67 return std::get<SHT>(this->convertData());
68 }
69
70 [[nodiscard]] uint32_t getDataAsCRC() const {
71 return std::get<uint32_t>(this->convertData());
72 }
73
74 [[nodiscard]] uint32_t getDataAsExtendedFlags() const {
75 return std::get<uint32_t>(this->convertData());
76 }
77
78 [[nodiscard]] std::tuple<uint8_t, uint8_t, uint8_t, uint8_t> getDataAsLODControlInfo() const {
79 return std::get<std::tuple<uint8_t, uint8_t, uint8_t, uint8_t>>(this->convertData());
80 }
81
82 [[nodiscard]] std::string getDataAsKeyValuesData() const {
83 return std::get<std::string>(this->convertData());
84 }
85
86 [[nodiscard]] int16_t getDataAsAuxCompressionLevel() const {
87 return static_cast<int16_t>(std::get<std::span<uint32_t>>(this->convertData())[1] & 0xffff);
88 }
89
91 auto method = static_cast<int16_t>((std::get<std::span<uint32_t>>(this->convertData())[1] & 0xffff0000) >> 16);
92 if (method <= 0) {
94 }
95 return static_cast<CompressionMethod>(method);
96 }
97
98 [[nodiscard]] uint32_t getDataAsAuxCompressionLength(uint8_t mip, uint8_t mipCount, uint16_t frame, uint16_t frameCount, uint16_t face, uint16_t faceCount) const {
99 return std::get<std::span<uint32_t>>(this->convertData())[((mipCount - 1 - mip) * frameCount * faceCount + frame * faceCount + face) + 2];
100 }
101};
103
104/*
105 * === EASY DIFFICULTY WRITER API ===
106 *
107 * Use a static helper function to create a VTF in one function call - VTF::create
108 *
109 * === MEDIUM DIFFICULTY WRITER API ===
110 *
111 * Constructing a VTF instance from existing VTF data will let you modify that data.
112 *
113 * This class has methods that should be called in a particular order
114 * when creating a VTF from scratch, or your output VTF may look incorrect:
115 *
116 * 0. Construct an empty VTF instance
117 * 1. Set the version (7.4 is the default) - VTF::setVersion
118 * 2. Set FLAG_SRGB (optional, read for image resizing) - VTF::setFlags
119 * 3. Set the image resize methods (optional) - VTF::setImageResizeMethods
120 * 4. Set the base image (mip 0, frame 0, face 0, slice 0) - VTF::setImage
121 * 5. Compute mips (optional) - VTF::computeMips
122 * 6. Set the output format (optional) - VTF::setFormat
123 *
124 * After these methods are called, the other writer methods in the class should work as expected.
125 */
126class VTF {
127public:
128 enum Flags : int32_t {
129 FLAG_NONE = 0,
130 FLAG_POINT_SAMPLE = 1 << 0,
131 FLAG_TRILINEAR = 1 << 1,
132 FLAG_CLAMP_S = 1 << 2,
133 FLAG_CLAMP_T = 1 << 3,
134 FLAG_ANISOTROPIC = 1 << 4,
135 FLAG_HINT_DXT5 = 1 << 5,
136 FLAG_PWL_CORRECTED = 1 << 6,
137 FLAG_NORMAL = 1 << 7,
138 FLAG_NO_MIP = 1 << 8, // Controlled by mip count
139 FLAG_NO_LOD = 1 << 9,
140 FLAG_LOAD_ALL_MIPS = 1 << 10,
141 FLAG_PROCEDURAL = 1 << 11,
142 FLAG_ONE_BIT_ALPHA = 1 << 12,
143 FLAG_MULTI_BIT_ALPHA = 1 << 13,
144 FLAG_ENVMAP = 1 << 14, // Controlled by face count
145 FLAG_RENDERTARGET = 1 << 15,
146 FLAG_DEPTH_RENDERTARGET = 1 << 16,
147 FLAG_NO_DEBUG_OVERRIDE = 1 << 17,
148 FLAG_SINGLE_COPY = 1 << 18, // Unused
149 FLAG_SRGB = 1 << 19,
150 FLAG_DEFAULT_POOL = 1 << 20,
151 FLAG_COMBINED = 1 << 21,
152 FLAG_ASYNC_DOWNLOAD = 1 << 22,
153 FLAG_NO_DEPTH_BUFFER = 1 << 23,
154 FLAG_SKIP_INITIAL_DOWNLOAD = 1 << 24,
155 FLAG_CLAMP_U = 1 << 25,
156 FLAG_VERTEX_TEXTURE = 1 << 26,
157 FLAG_XBOX_PRESWIZZLED = 1 << 26,
158 FLAG_SSBUMP = 1 << 27,
159 FLAG_XBOX_CACHEABLE = 1 << 27,
160 FLAG_LOAD_MOST_MIPS = 1 << 28,
161 FLAG_BORDER = 1 << 29,
162 FLAG_YCOCG = 1 << 30,
163 FLAG_ASYNC_SKIP_INITIAL_LOW_RES = 1 << 31,
164 };
165 static constexpr std::underlying_type_t<Flags> FLAG_MASK_AFTER_V7_3 = FLAG_LOAD_ALL_MIPS | FLAG_SRGB | FLAG_DEFAULT_POOL | FLAG_COMBINED | FLAG_ASYNC_DOWNLOAD | FLAG_SKIP_INITIAL_DOWNLOAD | FLAG_LOAD_MOST_MIPS | FLAG_YCOCG | FLAG_ASYNC_SKIP_INITIAL_LOW_RES;
166 static constexpr std::underlying_type_t<Flags> FLAG_MASK_INTERNAL = FLAG_NO_MIP | FLAG_ENVMAP;
167 static constexpr std::underlying_type_t<Flags> FLAG_MASK_SRGB = FLAG_PWL_CORRECTED | FLAG_SRGB;
168
169 enum Platform : uint32_t {
170 PLATFORM_UNKNOWN = 0x000,
171 PLATFORM_PC = 0x001,
172 PLATFORM_PS3_PORTAL2 = 0x003,
173 PLATFORM_PS3_ORANGEBOX = 0x333,
174 PLATFORM_X360 = 0x360,
175 };
176
178 uint32_t majorVersion = 7;
179 uint32_t minorVersion = 4;
180 ImageFormat outputFormat = FORMAT_DEFAULT;
181 ImageConversion::ResizeMethod widthResizeMethod = ImageConversion::ResizeMethod::POWER_OF_TWO_BIGGER;
182 ImageConversion::ResizeMethod heightResizeMethod = ImageConversion::ResizeMethod::POWER_OF_TWO_BIGGER;
183 ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::DEFAULT;
184 Flags flags = FLAG_NONE;
185 uint16_t initialFrameCount = 1;
186 uint16_t startFrame = 0;
187 bool isCubeMap = false;
188 bool hasSphereMap = false;
189 uint16_t initialSliceCount = 1;
190 bool computeTransparencyFlags = true;
191 bool computeMips = true;
192 bool computeThumbnail = true;
193 bool computeReflectivity = true;
194 Platform platform = PLATFORM_PC;
195 int16_t compressionLevel = -1;
196 CompressionMethod compressionMethod = CompressionMethod::ZSTD;
197 float bumpMapScale = 1.f;
198 };
199
201 static constexpr auto FORMAT_UNCHANGED = static_cast<ImageFormat>(-2);
202
204 static constexpr auto FORMAT_DEFAULT = static_cast<ImageFormat>(-1);
205
206 VTF();
207
208 explicit VTF(std::vector<std::byte>&& vtfData, bool parseHeaderOnly = false);
209
210 explicit VTF(std::span<const std::byte> vtfData, bool parseHeaderOnly = false);
211
212 explicit VTF(const std::string& vtfPath, bool parseHeaderOnly = false);
213
214 VTF(const VTF& other);
215
216 VTF& operator=(const VTF& other);
217
218 VTF(VTF&&) noexcept = default;
219
220 VTF& operator=(VTF&&) noexcept = default;
221
222 [[nodiscard]] explicit operator bool() const;
223
224 static bool create(std::span<const std::byte> imageData, ImageFormat format, uint16_t width, uint16_t height, const std::string& vtfPath, CreationOptions options);
225
226 static bool create(ImageFormat format, uint16_t width, uint16_t height, const std::string& vtfPath, CreationOptions options);
227
228 [[nodiscard]] static VTF create(std::span<const std::byte> imageData, ImageFormat format, uint16_t width, uint16_t height, CreationOptions options);
229
230 [[nodiscard]] static VTF create(ImageFormat format, uint16_t width, uint16_t height, CreationOptions options);
231
232 static bool create(const std::string& imagePath, const std::string& vtfPath, CreationOptions options);
233
234 [[nodiscard]] static VTF create(const std::string& imagePath, CreationOptions options);
235
236 [[nodiscard]] Platform getPlatform() const;
237
238 void setPlatform(Platform newPlatform);
239
240 [[nodiscard]] uint32_t getMajorVersion() const;
241
242 [[nodiscard]] uint32_t getMinorVersion() const;
243
244 void setVersion(uint32_t newMajorVersion, uint32_t newMinorVersion);
245
246 void setMajorVersion(uint32_t newMajorVersion);
247
248 void setMinorVersion(uint32_t newMinorVersion);
249
250 [[nodiscard]] ImageConversion::ResizeMethod getImageWidthResizeMethod() const;
251
252 [[nodiscard]] ImageConversion::ResizeMethod getImageHeightResizeMethod() const;
253
254 void setImageResizeMethods(ImageConversion::ResizeMethod imageWidthResizeMethod_, ImageConversion::ResizeMethod imageHeightResizeMethod_);
255
256 void setImageWidthResizeMethod(ImageConversion::ResizeMethod imageWidthResizeMethod_);
257
258 void setImageHeightResizeMethod(ImageConversion::ResizeMethod imageHeightResizeMethod_);
259
260 [[nodiscard]] uint16_t getWidth(uint8_t mip = 0) const;
261
262 [[nodiscard]] uint16_t getHeight(uint8_t mip = 0) const;
263
264 void setSize(uint16_t newWidth, uint16_t newHeight, ImageConversion::ResizeFilter filter);
265
266 [[nodiscard]] Flags getFlags() const;
267
268 void setFlags(Flags flags_);
269
270 void addFlags(Flags flags_);
271
272 void removeFlags(Flags flags_);
273
274 void computeTransparencyFlags();
275
276 [[nodiscard]] static ImageFormat getDefaultCompressedFormat(ImageFormat inputFormat, uint32_t majorVersion, uint32_t minorVersion);
277
278 [[nodiscard]] ImageFormat getFormat() const;
279
280 void setFormat(ImageFormat newFormat, ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::DEFAULT);
281
282 [[nodiscard]] uint8_t getMipCount() const;
283
284 bool setMipCount(uint8_t newMipCount);
285
286 bool setRecommendedMipCount();
287
288 void computeMips(ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::DEFAULT);
289
290 [[nodiscard]] uint16_t getFrameCount() const;
291
292 bool setFrameCount(uint16_t newFrameCount);
293
294 [[nodiscard]] uint8_t getFaceCount() const;
295
296 bool setFaceCount(bool isCubemap, bool hasSphereMap = false);
297
298 [[nodiscard]] uint16_t getSliceCount() const;
299
300 bool setSliceCount(uint16_t newSliceCount);
301
302 bool setFrameFaceAndSliceCount(uint16_t newFrameCount, bool isCubemap, bool hasSphereMap = false, uint16_t newSliceCount = 1);
303
304 [[nodiscard]] uint16_t getStartFrame() const;
305
306 void setStartFrame(uint16_t newStartFrame);
307
308 [[nodiscard]] sourcepp::math::Vec3f getReflectivity() const;
309
310 void setReflectivity(sourcepp::math::Vec3f newReflectivity);
311
312 void computeReflectivity();
313
314 [[nodiscard]] float getBumpMapScale() const;
315
316 void setBumpMapScale(float newBumpMapScale);
317
318 [[nodiscard]] ImageFormat getThumbnailFormat() const;
319
320 [[nodiscard]] uint8_t getThumbnailWidth() const;
321
322 [[nodiscard]] uint8_t getThumbnailHeight() const;
323
324 [[nodiscard]] const std::vector<Resource>& getResources() const;
325
326 [[nodiscard]] const Resource* getResource(Resource::Type type) const;
327
329 [[nodiscard]] std::vector<std::byte> getParticleSheetFrameDataRaw(uint16_t& spriteWidth, uint16_t& spriteHeight, uint32_t shtSequenceID, uint32_t shtFrame, uint8_t shtBounds = 0, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;
330
332 [[nodiscard]] std::vector<std::byte> getParticleSheetFrameDataAs(ImageFormat newFormat, uint16_t& spriteWidth, uint16_t& spriteHeight, uint32_t shtSequenceID, uint32_t shtFrame, uint8_t shtBounds = 0, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;
333
335 [[nodiscard]] std::vector<std::byte> getParticleSheetFrameDataAsRGBA8888(uint16_t& spriteWidth, uint16_t& spriteHeight, uint32_t shtSequenceID, uint32_t shtFrame, uint8_t shtBounds = 0, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;
336
337 void setParticleSheetResource(const SHT& value);
338
339 void removeParticleSheetResource();
340
341 void setCRCResource(uint32_t value);
342
343 void removeCRCResource();
344
345 void setLODResource(uint8_t u, uint8_t v, uint8_t u360 = 0, uint8_t v360 = 0);
346
347 void removeLODResource();
348
349 void setExtendedFlagsResource(uint32_t value);
350
351 void removeExtendedFlagsResource();
352
353 void setKeyValuesDataResource(const std::string& value);
354
355 void removeKeyValuesDataResource();
356
357 [[nodiscard]] int16_t getCompressionLevel() const;
358
359 void setCompressionLevel(int16_t newCompressionLevel);
360
361 [[nodiscard]] CompressionMethod getCompressionMethod() const;
362
363 void setCompressionMethod(CompressionMethod newCompressionMethod);
364
365 [[nodiscard]] bool hasImageData() const;
366
367 [[nodiscard]] bool imageDataIsSRGB() const;
368
369 [[nodiscard]] std::span<const std::byte> getImageDataRaw(uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;
370
371 [[nodiscard]] std::vector<std::byte> getImageDataAs(ImageFormat newFormat, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;
372
373 [[nodiscard]] std::vector<std::byte> getImageDataAsRGBA8888(uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0) const;
374
375 bool setImage(std::span<const std::byte> imageData_, ImageFormat format_, uint16_t width_, uint16_t height_, ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::DEFAULT, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0);
376
377 bool setImage(const std::string& imagePath, ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::DEFAULT, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0);
378
379 [[nodiscard]] std::vector<std::byte> saveImageToFile(uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0, ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) const;
380
381 bool saveImageToFile(const std::string& imagePath, uint8_t mip = 0, uint16_t frame = 0, uint8_t face = 0, uint16_t slice = 0, ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) const; // NOLINT(*-use-nodiscard)
382
383 [[nodiscard]] bool hasThumbnailData() const;
384
385 [[nodiscard]] std::span<const std::byte> getThumbnailDataRaw() const;
386
387 [[nodiscard]] std::vector<std::byte> getThumbnailDataAs(ImageFormat newFormat) const;
388
389 [[nodiscard]] std::vector<std::byte> getThumbnailDataAsRGBA8888() const;
390
391 void setThumbnail(std::span<const std::byte> imageData_, ImageFormat format_, uint16_t width_, uint16_t height_);
392
393 void computeThumbnail(ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::DEFAULT);
394
395 void removeThumbnail();
396
397 [[nodiscard]] std::vector<std::byte> saveThumbnailToFile(ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) const;
398
399 bool saveThumbnailToFile(const std::string& imagePath, ImageConversion::FileFormat fileFormat = ImageConversion::FileFormat::DEFAULT) const; // NOLINT(*-use-nodiscard)
400
401 [[nodiscard]] std::vector<std::byte> bake() const;
402
403 bool bake(const std::string& vtfPath) const; // NOLINT(*-use-nodiscard)
404
405protected:
406 static void createInternal(VTF& writer, CreationOptions options);
407
408 [[nodiscard]] Resource* getResourceInternal(Resource::Type type);
409
410 void setResourceInternal(Resource::Type type, std::span<const std::byte> data_);
411
412 void removeResourceInternal(Resource::Type type);
413
414 void regenerateImageData(ImageFormat newFormat, uint16_t newWidth, uint16_t newHeight, uint8_t newMipCount, uint16_t newFrameCount, uint8_t newFaceCount, uint16_t newSliceCount, ImageConversion::ResizeFilter filter = ImageConversion::ResizeFilter::DEFAULT);
415
416 bool opened = false;
417
418 std::vector<std::byte> data;
419
420 //uint32_t signature;
421 uint32_t majorVersion{};
422 uint32_t minorVersion{};
423 //uint32_t headerSize;
424
425 uint16_t width{};
426 uint16_t height{};
427 Flags flags{};
428
429 uint16_t frameCount = 1;
430 uint16_t startFrame{};
431
432 //uint8_t _padding0[4];
433 sourcepp::math::Vec3f reflectivity{};
434 //uint8_t _padding1[4];
435
436 float bumpMapScale{};
438 uint8_t mipCount = 1;
439
441 uint8_t thumbnailWidth{};
442 uint8_t thumbnailHeight{};
443
444 // 1 for v7.1 and lower
445 uint16_t sliceCount = 1;
446 //uint8_t _padding2[3];
447
448 // Technically added in v7.3, but we use it to store image and thumbnail data in v7.2 and lower anyway
449 //uint32_t resourceCount;
450 std::vector<Resource> resources;
451 //uint8_t _padding3[4];
452
453 // These aren't in the header
454 Platform platform = PLATFORM_PC;
455 int16_t compressionLevel = 0;
459};
461
462} // namespace vtfpp
#define SOURCEPP_BITFLAGS_ENUM(Enum)
Defines bitwise operators for an enum or enum class.
Definition: Macros.h:26
Definition: SHT.h:13
Platform
Definition: VTF.h:169
VTF(VTF &&) noexcept=default
std::vector< Resource > resources
Definition: VTF.h:450
consteval uint32_t makeFourCC(const char fourCC[4])
Creates a FourCC identifier from a string of 4 characters.
Definition: Binary.h:18
Definition: LZMA.h:11
constexpr uint32_t VTF_SIGNATURE
Definition: VTF.h:20
constexpr uint32_t VTFX_SIGNATURE
Definition: VTF.h:21
constexpr uint32_t VTF3_SIGNATURE
Definition: VTF.h:22
CompressionMethod
Definition: VTF.h:24
ImageFormat
Definition: ImageFormats.h:7
SHT getDataAsParticleSheet() const
Definition: VTF.h:66
std::variant< std::monostate, SHT, uint32_t, std::tuple< uint8_t, uint8_t, uint8_t, uint8_t >, std::string, std::span< uint32_t > > ConvertedData
Definition: VTF.h:63
CompressionMethod getDataAsAuxCompressionMethod() const
Definition: VTF.h:90
uint32_t getDataAsAuxCompressionLength(uint8_t mip, uint8_t mipCount, uint16_t frame, uint16_t frameCount, uint16_t face, uint16_t faceCount) const
Definition: VTF.h:98
Type type
Definition: VTF.h:52
ConvertedData convertData() const
Definition: VTF.cpp:135
std::tuple< uint8_t, uint8_t, uint8_t, uint8_t > getDataAsLODControlInfo() const
Definition: VTF.h:78
std::string getDataAsKeyValuesData() const
Definition: VTF.h:82
uint32_t getDataAsCRC() const
Definition: VTF.h:70
uint32_t getDataAsExtendedFlags() const
Definition: VTF.h:74
@ FLAG_LOCAL_DATA
Definition: VTF.h:49
@ FLAG_NONE
Definition: VTF.h:48
int16_t getDataAsAuxCompressionLevel() const
Definition: VTF.h:86
@ TYPE_KEYVALUES_DATA
Definition: VTF.h:42
@ TYPE_CRC
Definition: VTF.h:39
@ TYPE_PARTICLE_SHEET_DATA
Definition: VTF.h:38
@ TYPE_EXTENDED_FLAGS
Definition: VTF.h:41
@ TYPE_UNKNOWN
Definition: VTF.h:35
@ TYPE_IMAGE_DATA
Definition: VTF.h:37
@ TYPE_AUX_COMPRESSION
Definition: VTF.h:43
@ TYPE_LOD_CONTROL_INFO
Definition: VTF.h:40
@ TYPE_THUMBNAIL_DATA
Definition: VTF.h:36
Flags flags
Definition: VTF.h:53
static const std::array< Type, 8 > & getOrder()
Definition: VTF.cpp:116
std::span< std::byte > data
Definition: VTF.h:54