1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
27 // File: vogl_mipmapped_texture.h
30 #include "vogl_core.h"
31 #include "vogl_dxt_image.h"
33 #include "vogl_pixel_format.h"
34 #include "vogl_image.h"
35 #include "vogl_resampler.h"
36 #include "vogl_data_stream_serializer.h"
37 #include "vogl_texture_file_types.h"
38 #include "vogl_image_utils.h"
44 extern const vec2I g_vertical_cross_image_offsets[6];
46 enum orientation_flags_t
48 cOrientationFlagXFlipped = 1,
49 cOrientationFlagYFlipped = 2,
50 cDefaultOrientationFlags = 0
55 cUnpackFlagUncook = 1,
61 friend class mipmapped_texture;
67 mip_level(const mip_level &other);
68 mip_level &operator=(const mip_level &rhs);
71 void assign(image_u8 *p, pixel_format fmt = PIXEL_FMT_INVALID, orientation_flags_t orient_flags = cDefaultOrientationFlags);
72 void assign(dxt_image *p, pixel_format fmt = PIXEL_FMT_INVALID, orientation_flags_t orient_flags = cDefaultOrientationFlags);
76 inline uint get_width() const
80 inline uint get_height() const
84 inline uint get_total_pixels() const
86 return m_width * m_height;
89 orientation_flags_t get_orientation_flags() const
91 return m_orient_flags;
93 void set_orientation_flags(orientation_flags_t flags)
95 m_orient_flags = flags;
98 inline image_u8 *get_image() const
102 inline dxt_image *get_dxt_image() const
107 image_u8 *get_unpacked_image(image_u8 &tmp, uint unpack_flags) const;
109 inline bool is_packed() const
111 return m_pDXTImage != NULL;
114 inline bool is_valid() const
116 return (m_pImage != NULL) || (m_pDXTImage != NULL);
119 inline pixel_format_helpers::component_flags get_comp_flags() const
123 inline void set_comp_flags(pixel_format_helpers::component_flags comp_flags)
125 m_comp_flags = comp_flags;
128 inline pixel_format get_format() const
132 inline void set_format(pixel_format fmt)
137 bool convert(pixel_format fmt, bool cook, const dxt_image::pack_params &p);
139 bool pack_to_dxt(const image_u8 &img, pixel_format fmt, bool cook, const dxt_image::pack_params &p, orientation_flags_t orient_flags = cDefaultOrientationFlags);
140 bool pack_to_dxt(pixel_format fmt, bool cook, const dxt_image::pack_params &p);
142 bool unpack_from_dxt(bool uncook = true);
144 // Returns true if flipped on either axis.
145 bool is_flipped() const;
147 bool is_x_flipped() const;
148 bool is_y_flipped() const;
150 bool can_unflip_without_unpacking() const;
152 // Returns true if unflipped on either axis.
153 // Will try to flip packed (DXT/ETC) data in-place, if this isn't possible it'll unpack/uncook the mip level then unflip.
154 bool unflip(bool allow_unpacking_to_flip, bool uncook_during_unpack);
156 bool set_alpha_to_luma();
157 bool convert(image_utils::conversion_type conv_type);
166 pixel_format_helpers::component_flags m_comp_flags;
167 pixel_format m_format;
170 dxt_image *m_pDXTImage;
172 orientation_flags_t m_orient_flags;
174 void cook_image(image_u8 &img) const;
175 void uncook_image(image_u8 &img) const;
178 // A face is an array of mip_level ptr's.
179 typedef vogl::vector<mip_level *> mip_ptr_vec;
181 // And an array of one, six, or N faces make up a texture.
182 typedef vogl::vector<mip_ptr_vec> face_vec;
184 class mipmapped_texture
187 // Construction/destruction
189 ~mipmapped_texture();
191 mipmapped_texture(const mipmapped_texture &other);
192 mipmapped_texture &operator=(const mipmapped_texture &rhs);
196 void init(uint width, uint height, uint levels, uint faces, pixel_format fmt, const char *pName, orientation_flags_t orient_flags);
198 // Assumes ownership.
199 void assign(face_vec &faces);
200 void assign(mip_level *pLevel);
201 void assign(image_u8 *p, pixel_format fmt = PIXEL_FMT_INVALID, orientation_flags_t orient_flags = cDefaultOrientationFlags);
202 void assign(dxt_image *p, pixel_format fmt = PIXEL_FMT_INVALID, orientation_flags_t orient_flags = cDefaultOrientationFlags);
204 void set(texture_file_types::format source_file_type, const mipmapped_texture &mipmapped_texture);
207 image_u8 *get_level_image(uint face, uint level, image_u8 &img, uint unpack_flags = cUnpackFlagUncook | cUnpackFlagUnflip) const;
209 inline bool is_valid() const
211 return m_faces.size() > 0;
214 const dynamic_string &get_name() const
218 void set_name(const dynamic_string &name)
223 const dynamic_string &get_source_filename() const
227 texture_file_types::format get_source_file_type() const
229 return m_source_file_type;
232 inline uint get_width() const
236 inline uint get_height() const
240 inline uint get_total_pixels() const
242 return m_width * m_height;
244 uint get_total_pixels_in_all_faces_and_mips() const;
246 inline uint get_num_faces() const
248 return m_faces.size();
250 inline uint get_num_levels() const
252 if (m_faces.is_empty())
255 return m_faces[0].size();
258 inline pixel_format_helpers::component_flags get_comp_flags() const
262 inline pixel_format get_format() const
267 inline bool is_unpacked() const
271 return get_level(0, 0)->get_image() != NULL;
276 inline const mip_ptr_vec &get_face(uint face) const
278 return m_faces[face];
280 inline mip_ptr_vec &get_face(uint face)
282 return m_faces[face];
285 inline const mip_level *get_level(uint face, uint mip) const
287 return m_faces[face][mip];
289 inline mip_level *get_level(uint face, uint mip)
291 return m_faces[face][mip];
294 bool has_alpha() const;
295 bool is_normal_map() const;
296 bool is_vertical_cross() const;
297 bool is_packed() const;
298 texture_type determine_texture_type() const;
300 const dynamic_string &get_last_error() const
304 void clear_last_error()
306 m_last_error.clear();
310 bool read_dds(data_stream_serializer &serializer);
311 bool write_dds(data_stream_serializer &serializer) const;
313 bool read_ktx(data_stream_serializer &serializer);
314 bool read_ktx(const vogl::ktx_texture &ktx);
315 bool write_ktx(data_stream_serializer &serializer) const;
317 // If file_format is texture_file_types::cFormatInvalid, the format will be determined from the filename's extension.
318 bool read_from_file(const char *pFilename, texture_file_types::format file_format = texture_file_types::cFormatInvalid);
319 bool read_from_stream(data_stream_serializer &serializer, texture_file_types::format file_format = texture_file_types::cFormatInvalid);
322 const char *pFilename,
323 texture_file_types::format file_format = texture_file_types::cFormatInvalid,
324 vogl_comp_params *pComp_params = NULL,
325 uint32 *pActual_quality_level = NULL, float *pActual_bitrate = NULL,
326 uint32 image_write_flags = 0);
329 bool convert(pixel_format fmt, bool cook, const dxt_image::pack_params &p);
330 bool convert(pixel_format fmt, const dxt_image::pack_params &p);
331 bool convert(image_utils::conversion_type conv_type);
333 bool unpack_from_dxt(bool uncook = true);
335 bool set_alpha_to_luma();
337 void discard_mipmaps();
341 struct resample_params
344 : m_pFilter("kaiser"),
347 m_renormalize(false),
349 m_gamma(1.75f), // or 2.2f
350 m_multithreaded(true)
354 const char *m_pFilter;
358 float m_filter_scale;
360 bool m_multithreaded;
363 bool resize(uint new_width, uint new_height, const resample_params ¶ms);
365 struct generate_mipmap_params : public resample_params
367 generate_mipmap_params()
375 uint m_max_mips; // actually the max # of total levels
378 bool generate_mipmaps(const generate_mipmap_params ¶ms, bool force);
380 bool crop(uint x, uint y, uint width, uint height);
382 bool vertical_cross_to_cubemap();
384 void swap(mipmapped_texture &img);
388 void set_orientation_flags(orientation_flags_t flags);
390 // Returns true if any face/miplevel is flipped.
391 bool is_flipped() const;
392 bool is_x_flipped() const;
393 bool is_y_flipped() const;
394 bool can_unflip_without_unpacking() const;
395 bool unflip(bool allow_unpacking_to_flip, bool uncook_if_necessary_to_unpack);
397 bool flip_y(bool update_orientation_flags);
400 dynamic_string m_name;
405 pixel_format_helpers::component_flags m_comp_flags;
406 pixel_format m_format;
410 texture_file_types::format m_source_file_type;
412 mutable dynamic_string m_last_error;
414 inline void clear_last_error() const
416 m_last_error.clear();
418 inline void set_last_error(const char *p) const
423 void free_all_mips();
424 bool read_regular_image(data_stream_serializer &serializer, texture_file_types::format file_format);
425 bool write_regular_image(const char *pFilename, uint32 image_write_flags);
426 bool read_dds_internal(data_stream_serializer &serializer);
427 void change_dxt1_to_dxt1a();
428 bool flip_y_helper();
431 inline void swap(mipmapped_texture &a, mipmapped_texture &b)