- Fixing DDS reader so it doesn't require the source pitch/linear size field to be divisible by 4
- Fixing DDS writer so it writes a non-zero pitch/linearsize field (a few DDS readers in the wild require this field to be set) - Fixing example2.cpp and example3.cpp so they write non-zero pitch/linearsize fields. - Misc merges from the ddsexport branch - Adding -usesourceformat command line option, useful when reprocessing a lot of existing DDS files.
This commit is contained in:
+1
-1
@@ -3,5 +3,5 @@
|
||||
#include "crn_core.h"
|
||||
#include "crn_winhdr.h"
|
||||
|
||||
char *g_copyright_str = "Copyright (c) 2010-2011 Tenacious Software LLC";
|
||||
char *g_copyright_str = "Copyright (c) 2010-2012 Tenacious Software LLC";
|
||||
char *g_sig_str = "C8cfRlaorj0wLtnMSxrBJxTC85rho2L9hUZKHcBL";
|
||||
|
||||
@@ -620,7 +620,17 @@ namespace crnlib
|
||||
uint pitch = desc.lPitch;
|
||||
if (!pitch)
|
||||
pitch = default_pitch;
|
||||
else if ((pitch > default_pitch * 8) || (pitch & 3))
|
||||
#if 0
|
||||
else if (pitch & 3)
|
||||
{
|
||||
// MS's DDS docs say the pitch must be DWORD aligned - but this isn't always the case.
|
||||
// ATI Compressonator writes images with non-DWORD aligned pitches, and the DDSWithoutD3DX sample from MS doesn't compute the proper DWORD aligned pitch when reading DDS
|
||||
// files, so the docs must be wrong/outdated.
|
||||
console::warning(L"DDS file's pitch is not divisible by 4 - trying to load anyway.");
|
||||
}
|
||||
#endif
|
||||
// Check for obviously wacky source pitches (probably a corrupted/invalid file).
|
||||
else if (pitch > default_pitch * 8)
|
||||
{
|
||||
set_last_error(L"Invalid pitch");
|
||||
return false;
|
||||
@@ -946,6 +956,10 @@ namespace crnlib
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint bits_per_pixel = pixel_format_helpers::get_bpp(m_format);
|
||||
desc.lPitch = (((desc.dwWidth + 3) & ~3) * ((desc.dwHeight + 3) & ~3) * bits_per_pixel) >> 3;
|
||||
desc.dwFlags |= DDSD_LINEARSIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -998,8 +1012,12 @@ namespace crnlib
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint bits_per_pixel = desc.ddpfPixelFormat.dwRGBBitCount;
|
||||
desc.lPitch = (desc.dwWidth * bits_per_pixel) >> 3;
|
||||
desc.dwFlags |= DDSD_LINEARSIZE;
|
||||
}
|
||||
|
||||
if (!c_crnlib_little_endian_platform)
|
||||
utils::endian_switch_dwords(reinterpret_cast<uint32*>(&desc), sizeof(desc) / sizeof(uint32));
|
||||
|
||||
@@ -1272,6 +1290,7 @@ namespace crnlib
|
||||
else
|
||||
{
|
||||
image_u8* p = crnlib_new<image_u8>(mip_width, mip_height);
|
||||
p->set_comp_flags(m_comp_flags);
|
||||
m_faces[f][l]->assign(p, m_format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ namespace crnlib
|
||||
return (fmt == PIXEL_FMT_DXT1) || (fmt == PIXEL_FMT_DXT1A);
|
||||
}
|
||||
|
||||
// has_alpha() should probably be called "has_opacity()" - it indicates if the format encodes opacity
|
||||
// because some swizzled DXT5 formats do not encode opacity.
|
||||
inline bool has_alpha(pixel_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
@@ -48,6 +50,7 @@ namespace crnlib
|
||||
case PIXEL_FMT_A8R8G8B8:
|
||||
case PIXEL_FMT_A8:
|
||||
case PIXEL_FMT_A8L8:
|
||||
case PIXEL_FMT_DXT5_AGBR:
|
||||
return true;
|
||||
default: break;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,24 @@ namespace crnlib
|
||||
m_corner[0] = point;
|
||||
m_corner[1].set(point[0] + 1, point[1] + 1);
|
||||
}
|
||||
|
||||
inline bool operator== (const rect& r) const
|
||||
{
|
||||
return (m_corner[0] == r.m_corner[0]) && (m_corner[1] == r.m_corner[1]);
|
||||
}
|
||||
|
||||
inline bool operator< (const rect& r) const
|
||||
{
|
||||
for (uint i = 0; i < 2; i++)
|
||||
{
|
||||
if (m_corner[i] < r.m_corner[i])
|
||||
return true;
|
||||
else if (!(m_corner[i] == r.m_corner[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
@@ -70,10 +88,96 @@ namespace crnlib
|
||||
inline bool is_empty() const { return (m_corner[1][0] <= m_corner[0][0]) || (m_corner[1][1] <= m_corner[0][1]); }
|
||||
|
||||
inline uint get_dimension(uint axis) const { return m_corner[1][axis] - m_corner[0][axis]; }
|
||||
inline uint get_area() const { return get_dimension(0) * get_dimension(1); }
|
||||
|
||||
inline const vec2I& operator[] (uint i) const { CRNLIB_ASSERT(i < 2); return m_corner[i]; }
|
||||
inline vec2I& operator[] (uint i) { CRNLIB_ASSERT(i < 2); return m_corner[i]; }
|
||||
|
||||
inline rect& translate(int x_ofs, int y_ofs)
|
||||
{
|
||||
m_corner[0][0] += x_ofs;
|
||||
m_corner[0][1] += y_ofs;
|
||||
m_corner[1][0] += x_ofs;
|
||||
m_corner[1][1] += y_ofs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline rect& init_expand()
|
||||
{
|
||||
m_corner[0].set(INT_MAX);
|
||||
m_corner[1].set(INT_MIN);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline rect& expand(int x, int y)
|
||||
{
|
||||
m_corner[0][0] = math::minimum(m_corner[0][0], x);
|
||||
m_corner[0][1] = math::minimum(m_corner[0][1], y);
|
||||
m_corner[1][0] = math::maximum(m_corner[1][0], x + 1);
|
||||
m_corner[1][1] = math::maximum(m_corner[1][1], y + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline rect& expand(const rect& r)
|
||||
{
|
||||
m_corner[0][0] = math::minimum(m_corner[0][0], r[0][0]);
|
||||
m_corner[0][1] = math::minimum(m_corner[0][1], r[0][1]);
|
||||
m_corner[1][0] = math::maximum(m_corner[1][0], r[1][0]);
|
||||
m_corner[1][1] = math::maximum(m_corner[1][1], r[1][1]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool touches(const rect& r) const
|
||||
{
|
||||
for (uint i = 0; i < 2; i++)
|
||||
{
|
||||
if (r[1][i] <= m_corner[0][i])
|
||||
return false;
|
||||
else if (r[0][i] >= m_corner[1][i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool within(const rect& r) const
|
||||
{
|
||||
for (uint i = 0; i < 2; i++)
|
||||
{
|
||||
if (m_corner[0][i] < r[0][i])
|
||||
return false;
|
||||
else if (m_corner[1][i] > r[1][i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool intersect(const rect& r)
|
||||
{
|
||||
if (!touches(r))
|
||||
{
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < 2; i++)
|
||||
{
|
||||
m_corner[0][i] = math::maximum<int>(m_corner[0][i], r[0][i]);
|
||||
m_corner[1][i] = math::minimum<int>(m_corner[1][i], r[1][i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool contains(int x, int y) const
|
||||
{
|
||||
return (x >= m_corner[0][0]) && (x < m_corner[1][0]) &&
|
||||
(y >= m_corner[0][1]) && (y < m_corner[1][1]);
|
||||
}
|
||||
|
||||
inline bool contains(const vec2I& p) const { return contains(p[0], p[1]); }
|
||||
|
||||
private:
|
||||
vec2I m_corner[2];
|
||||
};
|
||||
|
||||
@@ -295,6 +295,9 @@ namespace crnlib
|
||||
|
||||
static pixel_format choose_pixel_format(convert_params& params, const crn_comp_params &comp_params, const dds_texture& src_tex, texture_type tex_type)
|
||||
{
|
||||
if (params.m_use_source_format)
|
||||
return src_tex.get_format();
|
||||
|
||||
const bool is_normal_map = (tex_type == cTextureTypeNormalMap);
|
||||
|
||||
if (params.m_dst_file_type == texture_file_types::cFormatCRN)
|
||||
@@ -409,11 +412,12 @@ namespace crnlib
|
||||
m_pInput_texture->get_num_levels(),
|
||||
pixel_format_helpers::get_pixel_format_string(m_pInput_texture->get_format()));
|
||||
|
||||
console::debug(L" texture_type: %s", get_texture_type_desc(m_texture_type));
|
||||
console::debug(L" dst_filename: %s", m_dst_filename.get_ptr());
|
||||
console::debug(L"dst_file_type: %s", texture_file_types::get_extension(m_dst_file_type));
|
||||
console::debug(L" dst_format: %s", pixel_format_helpers::get_pixel_format_string(m_dst_format));
|
||||
console::debug(L" quick: %u", m_quick);
|
||||
console::debug(L" texture_type: %s", get_texture_type_desc(m_texture_type));
|
||||
console::debug(L" dst_filename: %s", m_dst_filename.get_ptr());
|
||||
console::debug(L" dst_file_type: %s", texture_file_types::get_extension(m_dst_file_type));
|
||||
console::debug(L" dst_format: %s", pixel_format_helpers::get_pixel_format_string(m_dst_format));
|
||||
console::debug(L" quick: %u", m_quick);
|
||||
console::debug(L" use_source_format: %u", m_use_source_format);
|
||||
}
|
||||
|
||||
static bool write_compressed_texture(
|
||||
|
||||
@@ -60,7 +60,8 @@ namespace crnlib
|
||||
m_no_stats(false),
|
||||
m_lzma_stats(false),
|
||||
m_status(false),
|
||||
m_canceled(false)
|
||||
m_canceled(false),
|
||||
m_use_source_format(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -96,6 +97,7 @@ namespace crnlib
|
||||
bool m_debugging;
|
||||
bool m_param_debugging;
|
||||
bool m_no_stats;
|
||||
bool m_use_source_format;
|
||||
|
||||
bool m_lzma_stats;
|
||||
mutable bool m_status;
|
||||
|
||||
Reference in New Issue
Block a user