diff --git a/crnlib/crn_arealist.cpp b/crnlib/crn_arealist.cpp index 9d566f6..a68780d 100644 --- a/crnlib/crn_arealist.cpp +++ b/crnlib/crn_arealist.cpp @@ -3,7 +3,6 @@ // Ported from the PowerView DOS image viewer, a product I wrote back in 1993. Not currently used in the open source release of crnlib. #include "crn_core.h" #include "crn_arealist.h" -#include #define RECT_DEBUG @@ -20,7 +19,7 @@ namespace crnlib #ifdef _MSC_VER _vsnprintf_s(buf, sizeof(buf), pMsg, args); #else - _vsnprintf(buf, sizeof(buf), pMsg, args); + vsnprintf(buf, sizeof(buf), pMsg, args); #endif va_end(args); diff --git a/crnlib/crn_assert.cpp b/crnlib/crn_assert.cpp index 9af01ed..5900a4e 100644 --- a/crnlib/crn_assert.cpp +++ b/crnlib/crn_assert.cpp @@ -1,8 +1,9 @@ // File: crn_assert.cpp // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" +#if CRNLIB_USE_WIN32_API #include "crn_winhdr.h" -#include +#endif static bool g_fail_exceptions; static bool g_exit_on_failure = true; @@ -16,15 +17,11 @@ void crnlib_assert(const char* pExp, const char* pFile, unsigned line) { char buf[512]; -#if defined(WIN32) && defined(_MSC_VER) sprintf_s(buf, sizeof(buf), "%s(%u): Assertion failed: \"%s\"\n", pFile, line, pExp); -#else - sprintf(buf, "%s(%u): Assertion failed: \"%s\"\n", pFile, line, pExp); -#endif crnlib_output_debug_string(buf); - printf(buf); + fputs(buf, stderr); if (crnlib_is_debugger_present()) crnlib_debug_break(); @@ -34,22 +31,21 @@ void crnlib_fail(const char* pExp, const char* pFile, unsigned line) { char buf[512]; -#if defined(WIN32) && defined(_MSC_VER) sprintf_s(buf, sizeof(buf), "%s(%u): Failure: \"%s\"\n", pFile, line, pExp); -#else - sprintf(buf, "%s(%u): Failure: \"%s\"\n", pFile, line, pExp); -#endif crnlib_output_debug_string(buf); - printf(buf); + fputs(buf, stderr); if (crnlib_is_debugger_present()) crnlib_debug_break(); +#if CRNLIB_USE_WIN32_API if (g_fail_exceptions) RaiseException(CRNLIB_FAIL_EXCEPTION_CODE, 0, 0, NULL); - else if (g_exit_on_failure) + else +#endif + if (g_exit_on_failure) exit(EXIT_FAILURE); } @@ -58,11 +54,7 @@ void trace(const char* pFmt, va_list args) if (crnlib_is_debugger_present()) { char buf[512]; -#if defined(WIN32) && defined(_MSC_VER) vsprintf_s(buf, sizeof(buf), pFmt, args); -#else - vsprintf(buf, pFmt, args); -#endif crnlib_output_debug_string(buf); } diff --git a/crnlib/crn_cfile_stream.h b/crnlib/crn_cfile_stream.h index 2bd23a8..cd62c94 100644 --- a/crnlib/crn_cfile_stream.h +++ b/crnlib/crn_cfile_stream.h @@ -2,7 +2,6 @@ // See Copyright Notice and license at the end of inc/crnlib.h #pragma once #include "crn_data_stream.h" -#include namespace crnlib { @@ -13,13 +12,13 @@ namespace crnlib { } - cfile_stream(FILE* pFile, const wchar_t* pFilename, uint attribs, bool has_ownership) : + cfile_stream(FILE* pFile, const char* pFilename, uint attribs, bool has_ownership) : data_stream(), m_pFile(NULL), m_size(0), m_ofs(0), m_has_ownership(false) { open(pFile, pFilename, attribs, has_ownership); } - cfile_stream(const wchar_t* pFilename, uint attribs = cDataStreamReadable | cDataStreamSeekable, bool open_existing = false) : + cfile_stream(const char* pFilename, uint attribs = cDataStreamReadable | cDataStreamSeekable, bool open_existing = false) : data_stream(), m_pFile(NULL), m_size(0), m_ofs(0), m_has_ownership(false) { open(pFilename, attribs, open_existing); @@ -55,7 +54,7 @@ namespace crnlib return false; } - bool open(FILE* pFile, const wchar_t* pFilename, uint attribs, bool has_ownership) + bool open(FILE* pFile, const char* pFilename, uint attribs, bool has_ownership) { CRNLIB_ASSERT(pFile); CRNLIB_ASSERT(pFilename); @@ -67,17 +66,17 @@ namespace crnlib m_has_ownership = has_ownership; m_attribs = static_cast(attribs); - m_ofs = _ftelli64(m_pFile); - _fseeki64(m_pFile, 0, SEEK_END); - m_size = _ftelli64(m_pFile); - _fseeki64(m_pFile, m_ofs, SEEK_SET); + m_ofs = crn_ftell(m_pFile); + crn_fseek(m_pFile, 0, SEEK_END); + m_size = crn_ftell(m_pFile); + crn_fseek(m_pFile, m_ofs, SEEK_SET); m_opened = true; return true; } - bool open(const wchar_t* pFilename, uint attribs = cDataStreamReadable | cDataStreamSeekable, bool open_existing = false) + bool open(const char* pFilename, uint attribs = cDataStreamReadable | cDataStreamSeekable, bool open_existing = false) { CRNLIB_ASSERT(pFilename); @@ -85,13 +84,13 @@ namespace crnlib m_attribs = static_cast(attribs); - const wchar_t* pMode; + const char* pMode; if ((is_readable()) && (is_writable())) - pMode = open_existing ? L"r+b" : L"w+b"; + pMode = open_existing ? "r+b" : "w+b"; else if (is_writable()) - pMode = open_existing ? L"ab" : L"wb"; + pMode = open_existing ? "ab" : "wb"; else if (is_readable()) - pMode = L"rb"; + pMode = "rb"; else { set_error(); @@ -99,11 +98,7 @@ namespace crnlib } FILE* pFile = NULL; -#ifdef _MSC_VER - _wfopen_s(&pFile, pFilename, pMode); -#else - pFile = _wfopen(pFilename, pMode); -#endif + crn_fopen(&pFile, pFilename, pMode); m_has_ownership = true; if (!pFile) @@ -209,7 +204,7 @@ namespace crnlib if (static_cast(new_ofs) != m_ofs) { - if (_fseeki64(m_pFile, new_ofs, SEEK_SET) != 0) + if (crn_fseek(m_pFile, new_ofs, SEEK_SET) != 0) { set_error(); return false; @@ -221,7 +216,7 @@ namespace crnlib return true; } - static bool read_file_into_array(const wchar_t* pFilename, vector& buf) + static bool read_file_into_array(const char* pFilename, vector& buf) { cfile_stream in_stream(pFilename); if (!in_stream.is_opened()) @@ -229,7 +224,7 @@ namespace crnlib return in_stream.read_array(buf); } - static bool write_array_to_file(const wchar_t* pFilename, const vector& buf) + static bool write_array_to_file(const char* pFilename, const vector& buf) { cfile_stream out_stream(pFilename, cDataStreamWritable|cDataStreamSeekable); if (!out_stream.is_opened()) diff --git a/crnlib/crn_clusterizer.h b/crnlib/crn_clusterizer.h index f647116..2333e45 100644 --- a/crnlib/crn_clusterizer.h +++ b/crnlib/crn_clusterizer.h @@ -140,7 +140,7 @@ namespace crnlib inline uint get_num_training_vecs() const { return m_training_vecs.size(); } const VectorType& get_training_vec(uint index) const { return m_training_vecs[index].first; } - const uint get_training_vec_weight(uint index) const { return m_training_vecs[index].second; } + uint get_training_vec_weight(uint index) const { return m_training_vecs[index].second; } typedef crnlib::vector< std::pair > training_vec_array; @@ -170,7 +170,7 @@ namespace crnlib return m_codebook; } - const uint find_best_codebook_entry(const VectorType& v) const + uint find_best_codebook_entry(const VectorType& v) const { uint cur_node_index = 0; @@ -218,7 +218,7 @@ namespace crnlib } } - const uint find_best_codebook_entry_fs(const VectorType& v) const + uint find_best_codebook_entry_fs(const VectorType& v) const { float best_dist = math::cNearlyInfinite; uint best_index = 0; @@ -362,7 +362,7 @@ namespace crnlib void compute_split_estimate(VectorType& left_child_res, VectorType& right_child_res, const vq_node& parent_node) { - VectorType furthest; + VectorType furthest(0); double furthest_dist = -1.0f; for (uint i = 0; i < parent_node.m_vectors.size(); i++) @@ -377,7 +377,7 @@ namespace crnlib } } - VectorType opposite; + VectorType opposite(0); double opposite_dist = -1.0f; for (uint i = 0; i < parent_node.m_vectors.size(); i++) diff --git a/crnlib/crn_color.h b/crnlib/crn_color.h index 448236e..625ada7 100644 --- a/crnlib/crn_color.h +++ b/crnlib/crn_color.h @@ -11,8 +11,8 @@ namespace crnlib { cSigned = false, cFloat = false, - cMin = UINT8_MIN, - cMax = UINT8_MAX + cMin = cUINT8_MIN, + cMax = cUINT8_MAX }; }; @@ -22,8 +22,8 @@ namespace crnlib { cSigned = true, cFloat = false, - cMin = INT16_MIN, - cMax = INT16_MAX + cMin = cINT16_MIN, + cMax = cINT16_MAX }; }; @@ -33,8 +33,8 @@ namespace crnlib { cSigned = false, cFloat = false, - cMin = UINT16_MIN, - cMax = UINT16_MAX + cMin = cUINT16_MIN, + cMax = cUINT16_MAX }; }; @@ -44,8 +44,8 @@ namespace crnlib { cSigned = true, cFloat = false, - cMin = INT32_MIN, - cMax = INT32_MAX + cMin = cINT32_MIN, + cMax = cINT32_MAX }; }; @@ -55,8 +55,8 @@ namespace crnlib { cSigned = false, cFloat = false, - cMin = UINT32_MIN, - cMax = UINT32_MAX + cMin = cUINT32_MIN, + cMax = cUINT32_MAX }; }; @@ -66,8 +66,8 @@ namespace crnlib { cSigned = false, cFloat = true, - cMin = INT32_MIN, - cMax = INT32_MAX + cMin = cINT32_MIN, + cMax = cINT32_MAX }; }; @@ -77,8 +77,8 @@ namespace crnlib { cSigned = false, cFloat = true, - cMin = INT32_MIN, - cMax = INT32_MAX + cMin = cINT32_MIN, + cMax = cINT32_MAX }; }; diff --git a/crnlib/crn_command_line_params.cpp b/crnlib/crn_command_line_params.cpp index 06df53b..bd48738 100644 --- a/crnlib/crn_command_line_params.cpp +++ b/crnlib/crn_command_line_params.cpp @@ -5,41 +5,67 @@ #include "crn_console.h" #include "crn_cfile_stream.h" +#ifdef WIN32 + #define CRNLIB_CMD_LINE_ALLOW_SLASH_PARAMS 1 +#endif + +#if CRNLIB_USE_WIN32_API +#include "crn_winhdr.h" +#endif namespace crnlib { + void get_command_line(dynamic_string& cmd_line, int argc, char *argv[]) + { + argc, argv; +#if CRNLIB_USE_WIN32_API + cmd_line.set(GetCommandLineA()); +#else + cmd_line.clear(); + for (int i = 0; i < argc; i++) + { + dynamic_string tmp(argv[i]); + if ((tmp.front() != '"') && (tmp.front() != '-') && (tmp.front() != '@')) + tmp = "\"" + tmp + "\""; + if (cmd_line.get_len()) + cmd_line += " "; + cmd_line += tmp; + } +#endif + } + command_line_params::command_line_params() { } - + void command_line_params::clear() { m_params.clear(); - + m_param_map.clear(); } - - bool command_line_params::split_params(const wchar_t* p, dynamic_wstring_array& params) + + bool command_line_params::split_params(const char* p, dynamic_string_array& params) { bool within_param = false; bool within_quote = false; - + uint ofs = 0; - dynamic_wstring str; - + dynamic_string str; + while (p[ofs]) { - const wchar_t c = p[ofs]; - + const char c = p[ofs]; + if (within_param) { if (within_quote) { - if (c == L'"') + if (c == '"') within_quote = false; - + str.append_char(c); } - else if ((c == L' ') || (c == L'\t')) + else if ((c == ' ') || (c == '\t')) { if (!str.is_empty()) { @@ -50,141 +76,144 @@ namespace crnlib } else { - if (c == L'"') + if (c == '"') within_quote = true; - + str.append_char(c); } } - else if ((c != L' ') && (c != L'\t')) + else if ((c != ' ') && (c != '\t')) { within_param = true; - - if (c == L'"') + + if (c == '"') within_quote = true; - + str.append_char(c); } - + ofs++; } - + if (within_quote) { - console::error(L"Unmatched quote in command line \"%s\"", p); + console::error("Unmatched quote in command line \"%s\"", p); return false; } - + if (!str.is_empty()) params.push_back(str); - + return true; } - - bool command_line_params::load_string_file(const wchar_t* pFilename, dynamic_wstring_array& strings) + + bool command_line_params::load_string_file(const char* pFilename, dynamic_string_array& strings) { cfile_stream in_stream; if (!in_stream.open(pFilename, cDataStreamReadable | cDataStreamSeekable)) { - console::error(L"Unable to open file \"%s\" for reading!", pFilename); + console::error("Unable to open file \"%s\" for reading!", pFilename); return false; } - + dynamic_string ansi_str; - + for ( ; ; ) { if (!in_stream.read_line(ansi_str)) break; - + ansi_str.trim(); if (ansi_str.is_empty()) continue; - - strings.push_back(dynamic_wstring(ansi_str.get_ptr())); + + strings.push_back(dynamic_string(ansi_str.get_ptr())); } - + return true; } - - bool command_line_params::parse(const dynamic_wstring_array& params, uint n, const param_desc* pParam_desc) + + bool command_line_params::parse(const dynamic_string_array& params, uint n, const param_desc* pParam_desc) { CRNLIB_ASSERT(n && pParam_desc); - + m_params = params; - + uint arg_index = 0; while (arg_index < params.size()) { const uint cur_arg_index = arg_index; - const dynamic_wstring& src_param = params[arg_index++]; - + const dynamic_string& src_param = params[arg_index++]; + if (src_param.is_empty()) continue; - - if ((src_param[0] == L'/') || (src_param[0] == L'-')) +#if CRNLIB_CMD_LINE_ALLOW_SLASH_PARAMS + if ((src_param[0] == '/') || (src_param[0] == '-')) +#else + if (src_param[0] == '-') +#endif { if (src_param.get_len() < 2) { - console::error(L"Invalid command line parameter: \"%s\"", src_param.get_ptr()); + console::error("Invalid command line parameter: \"%s\"", src_param.get_ptr()); return false; } - - dynamic_wstring key_str(src_param); - + + dynamic_string key_str(src_param); + key_str.right(1); - + int modifier = 0; - wchar_t c = key_str[key_str.get_len() - 1]; - if (c == L'+') + char c = key_str[key_str.get_len() - 1]; + if (c == '+') modifier = 1; - else if (c == L'-') + else if (c == '-') modifier = -1; - + if (modifier) key_str.left(key_str.get_len() - 1); - + uint param_index; for (param_index = 0; param_index < n; param_index++) if (key_str == pParam_desc[param_index].m_pName) break; - + if (param_index == n) { - console::error(L"Unrecognized command line parameter: \"%s\"", src_param.get_ptr()); - return false; + console::error("Unrecognized command line parameter: \"%s\"", src_param.get_ptr()); + return false; } - + const param_desc& desc = pParam_desc[param_index]; - + const uint cMaxValues = 16; - dynamic_wstring val_str[cMaxValues]; + dynamic_string val_str[cMaxValues]; uint num_val_strs = 0; - if (desc.m_num_values) - { + if (desc.m_num_values) + { CRNLIB_ASSERT(desc.m_num_values <= cMaxValues); - + if ((arg_index + desc.m_num_values) > params.size()) { - console::error(L"Expected %u value(s) after command line parameter: \"%s\"", desc.m_num_values, src_param.get_ptr()); - return false; + console::error("Expected %u value(s) after command line parameter: \"%s\"", desc.m_num_values, src_param.get_ptr()); + return false; } - + for (uint v = 0; v < desc.m_num_values; v++) val_str[num_val_strs++] = params[arg_index++]; - } - - dynamic_wstring_array strings; - - if ((desc.m_support_listing_file) && (val_str[0].get_len() >= 2) && (val_str[0][0] == L'@')) + } + + dynamic_string_array strings; + + if ((desc.m_support_listing_file) && (val_str[0].get_len() >= 2) && (val_str[0][0] == '@')) { - dynamic_wstring filename(val_str[0]); + dynamic_string filename(val_str[0]); filename.right(1); filename.unquote(); - + if (!load_string_file(filename.get_ptr(), strings)) { - console::error(L"Failed loading listing file \"%s\"!", filename.get_ptr()); + console::error("Failed loading listing file \"%s\"!", filename.get_ptr()); return false; } } @@ -196,7 +225,7 @@ namespace crnlib strings.push_back(val_str[v]); } } - + param_value pv; pv.m_values.swap(strings); pv.m_index = cur_arg_index; @@ -209,18 +238,18 @@ namespace crnlib pv.m_values.push_back(src_param); pv.m_values.back().unquote(); pv.m_index = cur_arg_index; - m_param_map.insert(std::make_pair(g_empty_dynamic_wstring, pv)); + m_param_map.insert(std::make_pair(g_empty_dynamic_string, pv)); } } return true; } - - bool command_line_params::parse(const wchar_t* pCmd_line, uint n, const param_desc* pParam_desc, bool skip_first_param) + + bool command_line_params::parse(const char* pCmd_line, uint n, const param_desc* pParam_desc, bool skip_first_param) { CRNLIB_ASSERT(n && pParam_desc); - - dynamic_wstring_array p; + + dynamic_string_array p; if (!split_params(pCmd_line, p)) return 0; @@ -232,110 +261,114 @@ namespace crnlib return parse(p, n, pParam_desc); } - + bool command_line_params::is_param(uint index) const { CRNLIB_ASSERT(index < m_params.size()); if (index >= m_params.size()) return false; - const dynamic_wstring& w = m_params[index]; + const dynamic_string& w = m_params[index]; if (w.is_empty()) return false; - return (w.get_len() >= 2) && ((w[0] == L'-') || (w[0] == L'/')); +#if CRNLIB_CMD_LINE_ALLOW_SLASH_PARAMS + return (w.get_len() >= 2) && ((w[0] == '-') || (w[0] == '/')); +#else + return (w.get_len() >= 2) && (w[0] == '-'); +#endif } - - uint command_line_params::find(uint num_keys, const wchar_t** ppKeys, crnlib::vector* pIterators, crnlib::vector* pUnmatched_indices) const + + uint command_line_params::find(uint num_keys, const char** ppKeys, crnlib::vector* pIterators, crnlib::vector* pUnmatched_indices) const { CRNLIB_ASSERT(ppKeys); - + if (pUnmatched_indices) { pUnmatched_indices->resize(m_params.size()); for (uint i = 0; i < m_params.size(); i++) (*pUnmatched_indices)[i] = i; } - + uint n = 0; for (uint i = 0; i < num_keys; i++) { - const wchar_t* pKey = ppKeys[i]; + const char* pKey = ppKeys[i]; param_map_const_iterator begin, end; find(pKey, begin, end); - + while (begin != end) { - if (pIterators) + if (pIterators) pIterators->push_back(begin); - + if (pUnmatched_indices) { int k = pUnmatched_indices->find(begin->second.m_index); if (k >= 0) pUnmatched_indices->erase_unordered(k); } - + n++; begin++; } } - + return n; } - void command_line_params::find(const wchar_t* pKey, param_map_const_iterator& begin, param_map_const_iterator& end) const + void command_line_params::find(const char* pKey, param_map_const_iterator& begin, param_map_const_iterator& end) const { - dynamic_wstring key(pKey); + dynamic_string key(pKey); begin = m_param_map.lower_bound(key); end = m_param_map.upper_bound(key); } - uint command_line_params::get_count(const wchar_t* pKey) const + uint command_line_params::get_count(const char* pKey) const { param_map_const_iterator begin, end; find(pKey, begin, end); uint n = 0; - + while (begin != end) { n++; begin++; } - + return n; } - - command_line_params::param_map_const_iterator command_line_params::get_param(const wchar_t* pKey, uint index) const + + command_line_params::param_map_const_iterator command_line_params::get_param(const char* pKey, uint index) const { param_map_const_iterator begin, end; find(pKey, begin, end); - + if (begin == end) return m_param_map.end(); uint n = 0; - + while ((begin != end) && (n != index)) { n++; begin++; } - + if (begin == end) return m_param_map.end(); return begin; } - bool command_line_params::has_value(const wchar_t* pKey, uint index) const + bool command_line_params::has_value(const char* pKey, uint index) const { return get_num_values(pKey, index) != 0; } - - uint command_line_params::get_num_values(const wchar_t* pKey, uint index) const + + uint command_line_params::get_num_values(const char* pKey, uint index) const { param_map_const_iterator it = get_param(pKey, index); @@ -344,76 +377,76 @@ namespace crnlib return it->second.m_values.size(); } - - bool command_line_params::get_value_as_bool(const wchar_t* pKey, uint index, bool def) const + + bool command_line_params::get_value_as_bool(const char* pKey, uint index, bool def) const { param_map_const_iterator it = get_param(pKey, index); if (it == end()) return def; - + if (it->second.m_modifier) return it->second.m_modifier > 0; else return true; } - - int command_line_params::get_value_as_int(const wchar_t* pKey, uint index, int def, int l, int h, uint value_index) const + + int command_line_params::get_value_as_int(const char* pKey, uint index, int def, int l, int h, uint value_index) const { param_map_const_iterator it = get_param(pKey, index); if ((it == end()) || (value_index >= it->second.m_values.size())) return def; int val; - const wchar_t* p = it->second.m_values[value_index].get_ptr(); + const char* p = it->second.m_values[value_index].get_ptr(); if (!string_to_int(p, val)) { - crnlib::console::warning(L"Invalid value specified for parameter \"%s\", using default value of %i", pKey, def); + crnlib::console::warning("Invalid value specified for parameter \"%s\", using default value of %i", pKey, def); return def; } if (val < l) { - crnlib::console::warning(L"Value %i for parameter \"%s\" is out of range, clamping to %i", val, pKey, l); + crnlib::console::warning("Value %i for parameter \"%s\" is out of range, clamping to %i", val, pKey, l); val = l; } else if (val > h) { - crnlib::console::warning(L"Value %i for parameter \"%s\" is out of range, clamping to %i", val, pKey, h); + crnlib::console::warning("Value %i for parameter \"%s\" is out of range, clamping to %i", val, pKey, h); val = h; } - + return val; } - - float command_line_params::get_value_as_float(const wchar_t* pKey, uint index, float def, float l, float h, uint value_index) const + + float command_line_params::get_value_as_float(const char* pKey, uint index, float def, float l, float h, uint value_index) const { param_map_const_iterator it = get_param(pKey, index); if ((it == end()) || (value_index >= it->second.m_values.size())) return def; float val; - const wchar_t* p = it->second.m_values[value_index].get_ptr(); + const char* p = it->second.m_values[value_index].get_ptr(); if (!string_to_float(p, val)) { - crnlib::console::warning(L"Invalid value specified for float parameter \"%s\", using default value of %f", pKey, def); + crnlib::console::warning("Invalid value specified for float parameter \"%s\", using default value of %f", pKey, def); return def; } if (val < l) { - crnlib::console::warning(L"Value %f for parameter \"%s\" is out of range, clamping to %f", val, pKey, l); + crnlib::console::warning("Value %f for parameter \"%s\" is out of range, clamping to %f", val, pKey, l); val = l; } else if (val > h) { - crnlib::console::warning(L"Value %f for parameter \"%s\" is out of range, clamping to %f", val, pKey, h); + crnlib::console::warning("Value %f for parameter \"%s\" is out of range, clamping to %f", val, pKey, h); val = h; } return val; } - - bool command_line_params::get_value_as_string(const wchar_t* pKey, uint index, dynamic_wstring& value, uint value_index) const + + bool command_line_params::get_value_as_string(const char* pKey, uint index, dynamic_string& value, uint value_index) const { param_map_const_iterator it = get_param(pKey, index); if ((it == end()) || (value_index >= it->second.m_values.size())) @@ -425,13 +458,13 @@ namespace crnlib value = it->second.m_values[value_index]; return true; } - - const dynamic_wstring& command_line_params::get_value_as_string_or_empty(const wchar_t* pKey, uint index, uint value_index) const + + const dynamic_string& command_line_params::get_value_as_string_or_empty(const char* pKey, uint index, uint value_index) const { param_map_const_iterator it = get_param(pKey, index); if ((it == end()) || (value_index >= it->second.m_values.size())) - return g_empty_dynamic_wstring; - + return g_empty_dynamic_string; + return it->second.m_values[value_index]; } diff --git a/crnlib/crn_command_line_params.h b/crnlib/crn_command_line_params.h index 32f1592..42d3355 100644 --- a/crnlib/crn_command_line_params.h +++ b/crnlib/crn_command_line_params.h @@ -6,77 +6,79 @@ namespace crnlib { + void get_command_line(dynamic_string& cmd_line, int argc, char *argv[]); + class command_line_params { public: struct param_value { - param_value() : m_index(0), m_modifier(0) { } - - dynamic_wstring_array m_values; + inline param_value() : m_index(0), m_modifier(0) { } + + dynamic_string_array m_values; uint m_index; int8 m_modifier; }; - - typedef std::multimap param_map; + + typedef std::multimap param_map; typedef param_map::const_iterator param_map_const_iterator; typedef param_map::iterator param_map_iterator; - + command_line_params(); - + void clear(); - - static bool split_params(const wchar_t* p, dynamic_wstring_array& params); - + + static bool split_params(const char* p, dynamic_string_array& params); + struct param_desc { - const wchar_t* m_pName; + const char* m_pName; uint m_num_values; bool m_support_listing_file; }; - - bool parse(const dynamic_wstring_array& params, uint n, const param_desc* pParam_desc); - bool parse(const wchar_t* pCmd_line, uint n, const param_desc* pParam_desc, bool skip_first_param = true); - - const dynamic_wstring_array& get_array() const { return m_params; } - + + bool parse(const dynamic_string_array& params, uint n, const param_desc* pParam_desc); + bool parse(const char* pCmd_line, uint n, const param_desc* pParam_desc, bool skip_first_param = true); + + const dynamic_string_array& get_array() const { return m_params; } + bool is_param(uint index) const; - + const param_map& get_map() const { return m_param_map; } - + uint get_num_params() const { return static_cast(m_param_map.size()); } - + param_map_const_iterator begin() const { return m_param_map.begin(); } param_map_const_iterator end() const { return m_param_map.end(); } - - uint find(uint num_keys, const wchar_t** ppKeys, crnlib::vector* pIterators, crnlib::vector* pUnmatched_indices) const; - - void find(const wchar_t* pKey, param_map_const_iterator& begin, param_map_const_iterator& end) const; - - uint get_count(const wchar_t* pKey) const; - + + uint find(uint num_keys, const char** ppKeys, crnlib::vector* pIterators, crnlib::vector* pUnmatched_indices) const; + + void find(const char* pKey, param_map_const_iterator& begin, param_map_const_iterator& end) const; + + uint get_count(const char* pKey) const; + // Returns end() if param cannot be found, or index is out of range. - param_map_const_iterator get_param(const wchar_t* pKey, uint index) const; - - bool has_key(const wchar_t* pKey) const { return get_param(pKey, 0) != end(); } - - bool has_value(const wchar_t* pKey, uint index) const; - uint get_num_values(const wchar_t* pKey, uint index) const; - - bool get_value_as_bool(const wchar_t* pKey, uint index = 0, bool def = false) const; - - int get_value_as_int(const wchar_t* pKey, uint index, int def, int l = INT_MIN, int h = INT_MAX, uint value_index = 0) const; - float get_value_as_float(const wchar_t* pKey, uint index, float def = 0.0f, float l = -math::cNearlyInfinite, float h = math::cNearlyInfinite, uint value_index = 0) const; - - bool get_value_as_string(const wchar_t* pKey, uint index, dynamic_wstring& value, uint value_index = 0) const; - const dynamic_wstring& get_value_as_string_or_empty(const wchar_t* pKey, uint index = 0, uint value_index = 0) const; - + param_map_const_iterator get_param(const char* pKey, uint index) const; + + bool has_key(const char* pKey) const { return get_param(pKey, 0) != end(); } + + bool has_value(const char* pKey, uint index) const; + uint get_num_values(const char* pKey, uint index) const; + + bool get_value_as_bool(const char* pKey, uint index = 0, bool def = false) const; + + int get_value_as_int(const char* pKey, uint index, int def, int l = INT_MIN, int h = INT_MAX, uint value_index = 0) const; + float get_value_as_float(const char* pKey, uint index, float def = 0.0f, float l = -math::cNearlyInfinite, float h = math::cNearlyInfinite, uint value_index = 0) const; + + bool get_value_as_string(const char* pKey, uint index, dynamic_string& value, uint value_index = 0) const; + const dynamic_string& get_value_as_string_or_empty(const char* pKey, uint index = 0, uint value_index = 0) const; + private: - dynamic_wstring_array m_params; - - param_map m_param_map; - - static bool load_string_file(const wchar_t* pFilename, dynamic_wstring_array& strings); + dynamic_string_array m_params; + + param_map m_param_map; + + static bool load_string_file(const char* pFilename, dynamic_string_array& strings); }; } // namespace crnlib diff --git a/crnlib/crn_comp.cpp b/crnlib/crn_comp.cpp index 0d78ef2..3e2070a 100644 --- a/crnlib/crn_comp.cpp +++ b/crnlib/crn_comp.cpp @@ -12,21 +12,21 @@ namespace crnlib { static const uint cEncodingMapNumChunksPerCode = 3; - + crn_comp::crn_comp() : m_pParams(NULL) { } - + crn_comp::~crn_comp() { } - + float crn_comp::color_endpoint_similarity_func(uint index_a, uint index_b, void* pContext) { dxt_hc& hvq = *static_cast(pContext); - uint endpoint_a = hvq.get_color_endpoint(index_a); + uint endpoint_a = hvq.get_color_endpoint(index_a); uint endpoint_b = hvq.get_color_endpoint(index_b); color_quad_u8 a[2]; @@ -42,15 +42,15 @@ namespace crnlib float weight = 1.0f - math::clamp(total_error * 1.0f/8000.0f, 0.0f, 1.0f); return weight; } - + float crn_comp::alpha_endpoint_similarity_func(uint index_a, uint index_b, void* pContext) { dxt_hc& hvq = *static_cast(pContext); - uint endpoint_a = hvq.get_alpha_endpoint(index_a); + uint endpoint_a = hvq.get_alpha_endpoint(index_a); int endpoint_a_lo = dxt5_block::unpack_endpoint(endpoint_a, 0); int endpoint_a_hi = dxt5_block::unpack_endpoint(endpoint_a, 1); - + uint endpoint_b = hvq.get_alpha_endpoint(index_b); int endpoint_b_lo = dxt5_block::unpack_endpoint(endpoint_b, 0); int endpoint_b_hi = dxt5_block::unpack_endpoint(endpoint_b, 1); @@ -89,7 +89,7 @@ namespace crnlib uint n = 0; for ( ; ; ) { - chosen_flags[cur_index] = true; + chosen_flags[cur_index] = true; remapping[cur_index] = n; n++; @@ -122,7 +122,7 @@ namespace crnlib cur_index = lowest_error_index; } } - + void crn_comp::sort_alpha_endpoint_codebook(crnlib::vector& remapping, const crnlib::vector& endpoints) { remapping.resize(endpoints.size()); @@ -134,7 +134,7 @@ namespace crnlib { uint a = dxt5_block::unpack_endpoint(endpoints[i], 0); uint b = dxt5_block::unpack_endpoint(endpoints[i], 1); - + uint total = a + b; if (total < lowest_energy) @@ -151,7 +151,7 @@ namespace crnlib uint n = 0; for ( ; ; ) { - chosen_flags[cur_index] = true; + chosen_flags[cur_index] = true; remapping[cur_index] = n; n++; @@ -160,7 +160,7 @@ namespace crnlib uint lowest_error = UINT_MAX; uint lowest_error_index = 0; - + const int a = dxt5_block::unpack_endpoint(endpoints[cur_index], 0); const int b = dxt5_block::unpack_endpoint(endpoints[cur_index], 1); @@ -168,7 +168,7 @@ namespace crnlib { if (chosen_flags[i]) continue; - + const int c = dxt5_block::unpack_endpoint(endpoints[i], 0); const int d = dxt5_block::unpack_endpoint(endpoints[i], 1); @@ -185,19 +185,19 @@ namespace crnlib } } - // The indices are only used for statistical purposes. + // The indices are only used for statistical purposes. bool crn_comp::pack_color_endpoints( - crnlib::vector& data, - const crnlib::vector& remapping, - const crnlib::vector& endpoint_indices, + crnlib::vector& data, + const crnlib::vector& remapping, + const crnlib::vector& endpoint_indices, uint trial_index) { trial_index; - + #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"pack_color_endpoints: %u", trial_index); -#endif + console::debug("pack_color_endpoints: %u", trial_index); +#endif crnlib::vector remapped_endpoints(m_hvq.get_color_endpoint_codebook_size()); @@ -213,7 +213,7 @@ namespace crnlib #if CRNLIB_CREATE_DEBUG_IMAGES image_u8 endpoint_image(2, m_hvq.get_color_endpoint_codebook_size()); image_u8 endpoint_residual_image(2, m_hvq.get_color_endpoint_codebook_size()); -#endif +#endif crnlib::vector residual_syms; residual_syms.reserve(m_hvq.get_color_endpoint_codebook_size()*2*3); @@ -232,14 +232,14 @@ namespace crnlib cur[0] = dxt1_block::unpack_color((uint16)(endpoint & 0xFFFF), false); cur[1] = dxt1_block::unpack_color((uint16)((endpoint >> 16) & 0xFFFF), false); -#if CRNLIB_CREATE_DEBUG_IMAGES +#if CRNLIB_CREATE_DEBUG_IMAGES endpoint_image(0, endpoint_index) = dxt1_block::unpack_color((uint16)(endpoint & 0xFFFF), true); endpoint_image(1, endpoint_index) = dxt1_block::unpack_color((uint16)((endpoint >> 16) & 0xFFFF), true); -#endif +#endif for (uint j = 0; j < 2; j++) { - for (uint k = 0; k < 3; k++) + for (uint k = 0; k < 3; k++) { int delta = cur[j][k] - prev[j][k]; total_residuals += delta*delta; @@ -251,19 +251,19 @@ namespace crnlib residual_syms.push_back(sym); -#if CRNLIB_CREATE_DEBUG_IMAGES +#if CRNLIB_CREATE_DEBUG_IMAGES endpoint_residual_image(j, endpoint_index)[k] = static_cast(sym); -#endif +#endif } - } + } prev[0] = cur[0]; prev[1] = cur[1]; } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total endpoint residuals: %i", total_residuals); + console::debug("Total endpoint residuals: %i", total_residuals); #endif if (endpoint_indices.size() > 1) @@ -278,23 +278,23 @@ namespace crnlib total_delta += delta * delta; } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total endpoint index delta: %I64i", total_delta); -#endif + console::debug("Total endpoint index delta: " CRNLIB_INT64_FORMAT_SPECIFIER, total_delta); +#endif } -#if CRNLIB_CREATE_DEBUG_IMAGES - image_utils::save_to_file(dynamic_wstring(cVarArg, L"color_endpoint_residuals_%u.tga", trial_index).get_ptr(), endpoint_residual_image); - image_utils::save_to_file(dynamic_wstring(cVarArg, L"color_endpoints_%u.tga", trial_index).get_ptr(), endpoint_image); -#endif +#if CRNLIB_CREATE_DEBUG_IMAGES + image_utils::save_to_file(dynamic_string(cVarArg, "color_endpoint_residuals_%u.tga", trial_index).get_ptr(), endpoint_residual_image); + image_utils::save_to_file(dynamic_string(cVarArg, "color_endpoints_%u.tga", trial_index).get_ptr(), endpoint_image); +#endif static_huffman_data_model residual_dm[2]; symbol_codec codec; codec.start_encoding(1024*1024); - // Transmit residuals + // Transmit residuals for (uint i = 0; i < 2; i++) { if (!residual_dm[i].init(true, hist[i], 15)) @@ -304,11 +304,11 @@ namespace crnlib return false; } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Wrote %u bits for color endpoint residual Huffman tables", codec.encode_get_total_bits_written()); -#endif - + console::debug("Wrote %u bits for color endpoint residual Huffman tables", codec.encode_get_total_bits_written()); +#endif + uint start_bits = codec.encode_get_total_bits_written(); start_bits; @@ -319,40 +319,40 @@ namespace crnlib codec.encode(sym, residual_dm[table]); } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Wrote %u bits for color endpoint residuals", codec.encode_get_total_bits_written() - start_bits); -#endif - + console::debug("Wrote %u bits for color endpoint residuals", codec.encode_get_total_bits_written() - start_bits); +#endif + codec.stop_encoding(false); data.swap(codec.get_encoding_buf()); -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) { - console::debug(L"Wrote a total of %u bits for color endpoint codebook", codec.encode_get_total_bits_written()); + console::debug("Wrote a total of %u bits for color endpoint codebook", codec.encode_get_total_bits_written()); - console::debug(L"Wrote %f bits per each color endpoint", data.size() * 8.0f / m_hvq.get_color_endpoint_codebook_size()); - } -#endif + console::debug("Wrote %f bits per each color endpoint", data.size() * 8.0f / m_hvq.get_color_endpoint_codebook_size()); + } +#endif return true; } - // The indices are only used for statistical purposes. + // The indices are only used for statistical purposes. bool crn_comp::pack_alpha_endpoints( - crnlib::vector& data, - const crnlib::vector& remapping, - const crnlib::vector& endpoint_indices, + crnlib::vector& data, + const crnlib::vector& remapping, + const crnlib::vector& endpoint_indices, uint trial_index) { trial_index; - -#if CRNLIB_ENABLE_DEBUG_MESSAGES - if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"pack_alpha_endpoints: %u", trial_index); -#endif + +#if CRNLIB_ENABLE_DEBUG_MESSAGES + if (m_pParams->m_flags & cCRNCompFlagDebugging) + console::debug("pack_alpha_endpoints: %u", trial_index); +#endif crnlib::vector remapped_endpoints(m_hvq.get_alpha_endpoint_codebook_size()); @@ -365,7 +365,7 @@ namespace crnlib #if CRNLIB_CREATE_DEBUG_IMAGES image_u8 endpoint_image(2, m_hvq.get_alpha_endpoint_codebook_size()); image_u8 endpoint_residual_image(2, m_hvq.get_alpha_endpoint_codebook_size()); -#endif +#endif crnlib::vector residual_syms; residual_syms.reserve(m_hvq.get_alpha_endpoint_codebook_size()*2*3); @@ -382,11 +382,11 @@ namespace crnlib uint cur[2]; cur[0] = dxt5_block::unpack_endpoint(endpoint, 0); cur[1] = dxt5_block::unpack_endpoint(endpoint, 1); - -#if CRNLIB_CREATE_DEBUG_IMAGES + +#if CRNLIB_CREATE_DEBUG_IMAGES endpoint_image(0, endpoint_index) = cur[0]; endpoint_image(1, endpoint_index) = cur[1]; -#endif +#endif for (uint j = 0; j < 2; j++) { @@ -394,24 +394,24 @@ namespace crnlib total_residuals += delta*delta; int sym = delta & 255; - + hist.inc_freq(sym); residual_syms.push_back(sym); -#if CRNLIB_CREATE_DEBUG_IMAGES +#if CRNLIB_CREATE_DEBUG_IMAGES endpoint_residual_image(j, endpoint_index) = static_cast(sym); -#endif - } +#endif + } prev[0] = cur[0]; prev[1] = cur[1]; } - -#if CRNLIB_ENABLE_DEBUG_MESSAGES + +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total endpoint residuals: %i", total_residuals); -#endif + console::debug("Total endpoint residuals: %i", total_residuals); +#endif if (endpoint_indices.size() > 1) { @@ -425,34 +425,34 @@ namespace crnlib total_delta += delta * delta; } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total endpoint index delta: %I64i", total_delta); -#endif + console::debug("Total endpoint index delta: " CRNLIB_INT64_FORMAT_SPECIFIER, total_delta); +#endif } -#if CRNLIB_CREATE_DEBUG_IMAGES - image_utils::save_to_file(dynamic_wstring(cVarArg, L"alpha_endpoint_residuals_%u.tga", trial_index).get_ptr(), endpoint_residual_image); - image_utils::save_to_file(dynamic_wstring(cVarArg, L"alpha_endpoints_%u.tga", trial_index).get_ptr(), endpoint_image); -#endif +#if CRNLIB_CREATE_DEBUG_IMAGES + image_utils::save_to_file(dynamic_string(cVarArg, "alpha_endpoint_residuals_%u.tga", trial_index).get_ptr(), endpoint_residual_image); + image_utils::save_to_file(dynamic_string(cVarArg, "alpha_endpoints_%u.tga", trial_index).get_ptr(), endpoint_image); +#endif static_huffman_data_model residual_dm; symbol_codec codec; codec.start_encoding(1024*1024); - // Transmit residuals + // Transmit residuals if (!residual_dm.init(true, hist, 15)) return false; if (!codec.encode_transmit_static_huffman_data_model(residual_dm, false)) return false; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Wrote %u bits for alpha endpoint residual Huffman tables", codec.encode_get_total_bits_written()); -#endif - + console::debug("Wrote %u bits for alpha endpoint residual Huffman tables", codec.encode_get_total_bits_written()); +#endif + uint start_bits = codec.encode_get_total_bits_written(); start_bits; @@ -462,23 +462,23 @@ namespace crnlib codec.encode(sym, residual_dm); } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Wrote %u bits for alpha endpoint residuals", codec.encode_get_total_bits_written() - start_bits); -#endif - + console::debug("Wrote %u bits for alpha endpoint residuals", codec.encode_get_total_bits_written() - start_bits); +#endif + codec.stop_encoding(false); data.swap(codec.get_encoding_buf()); -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) { - console::debug(L"Wrote a total of %u bits for alpha endpoint codebook", codec.encode_get_total_bits_written()); + console::debug("Wrote a total of %u bits for alpha endpoint codebook", codec.encode_get_total_bits_written()); - console::debug(L"Wrote %f bits per each alpha endpoint", data.size() * 8.0f / m_hvq.get_alpha_endpoint_codebook_size()); - } -#endif + console::debug("Wrote %f bits per each alpha endpoint", data.size() * 8.0f / m_hvq.get_alpha_endpoint_codebook_size()); + } +#endif return true; } @@ -503,7 +503,7 @@ namespace crnlib float weight = 1.0f - math::clamp(total * 1.0f/20.0f, 0.0f, 1.0f); return weight; } - + float crn_comp::alpha_selector_similarity_func(uint index_a, uint index_b, void* pContext) { const crnlib::vector& selectors = *static_cast< const crnlib::vector* >(pContext); @@ -556,7 +556,7 @@ namespace crnlib uint n = 0; for ( ; ; ) { - chosen_flags[cur_index] = true; + chosen_flags[cur_index] = true; remapping[cur_index] = n; n++; @@ -596,28 +596,28 @@ namespace crnlib bool crn_comp::pack_selectors( crnlib::vector& packed_data, const crnlib::vector& selector_indices, - const crnlib::vector& selectors, + const crnlib::vector& selectors, const crnlib::vector& remapping, uint max_selector_value, const uint8* pTo_linear, uint trial_index) { trial_index; - -#if CRNLIB_ENABLE_DEBUG_MESSAGES + +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"pack_selectors: %u", trial_index); -#endif + console::debug("pack_selectors: %u", trial_index); +#endif crnlib::vector remapped_selectors(selectors.size()); for (uint i = 0; i < selectors.size(); i++) remapped_selectors[remapping[i]] = selectors[i]; -#if CRNLIB_CREATE_DEBUG_IMAGES +#if CRNLIB_CREATE_DEBUG_IMAGES image_u8 residual_image(16, selectors.size());; image_u8 selector_image(16, selectors.size());; -#endif +#endif crnlib::vector residual_syms; residual_syms.reserve(selectors.size() * 8); @@ -656,16 +656,16 @@ namespace crnlib #if CRNLIB_CREATE_DEBUG_IMAGES selector_image(i, selector_index) = (pTo_linear[crnlib_assert_range_incl(s.get_by_index(i), max_selector_value)] * 255) / max_selector_value; residual_image(i, selector_index) = sym; -#endif +#endif } prev_selectors = s; } - -#if CRNLIB_ENABLE_DEBUG_MESSAGES + +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total selector endpoint residuals: %u", total_residuals); -#endif + console::debug("Total selector endpoint residuals: %u", total_residuals); +#endif if (selector_indices.size() > 1) { @@ -679,34 +679,34 @@ namespace crnlib total_delta += delta * delta; } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total selector index delta: %I64i", total_delta); -#endif - } + console::debug("Total selector index delta: " CRNLIB_INT64_FORMAT_SPECIFIER, total_delta); +#endif + } -#if CRNLIB_CREATE_DEBUG_IMAGES - image_utils::save_to_file(dynamic_wstring(cVarArg, L"selectors_%u_%u.tga", trial_index, max_selector_value).get_ptr(), selector_image); - image_utils::save_to_file(dynamic_wstring(cVarArg, L"selector_residuals_%u_%u.tga", trial_index, max_selector_value).get_ptr(), residual_image); -#endif +#if CRNLIB_CREATE_DEBUG_IMAGES + image_utils::save_to_file(dynamic_string(cVarArg, "selectors_%u_%u.tga", trial_index, max_selector_value).get_ptr(), selector_image); + image_utils::save_to_file(dynamic_string(cVarArg, "selector_residuals_%u_%u.tga", trial_index, max_selector_value).get_ptr(), residual_image); +#endif static_huffman_data_model residual_dm; symbol_codec codec; codec.start_encoding(1024*1024); - // Transmit residuals + // Transmit residuals if (!residual_dm.init(true, hist, 15)) return false; if (!codec.encode_transmit_static_huffman_data_model(residual_dm, false)) return false; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Wrote %u bits for selector residual Huffman tables", codec.encode_get_total_bits_written()); -#endif - + console::debug("Wrote %u bits for selector residual Huffman tables", codec.encode_get_total_bits_written()); +#endif + uint start_bits = codec.encode_get_total_bits_written(); start_bits; @@ -716,34 +716,34 @@ namespace crnlib codec.encode(sym, residual_dm); } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Wrote %u bits for selector residuals", codec.encode_get_total_bits_written() - start_bits); -#endif + console::debug("Wrote %u bits for selector residuals", codec.encode_get_total_bits_written() - start_bits); +#endif codec.stop_encoding(false); packed_data.swap(codec.get_encoding_buf()); - -#if CRNLIB_ENABLE_DEBUG_MESSAGES + +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) { - console::debug(L"Wrote a total of %u bits for selector codebook", codec.encode_get_total_bits_written()); + console::debug("Wrote a total of %u bits for selector codebook", codec.encode_get_total_bits_written()); - console::debug(L"Wrote %f bits per each selector codebook entry", packed_data.size() * 8.0f / selectors.size()); - } -#endif + console::debug("Wrote %f bits per each selector codebook entry", packed_data.size() * 8.0f / selectors.size()); + } +#endif return true; } - + bool crn_comp::pack_chunks( uint first_chunk, uint num_chunks, bool clear_histograms, symbol_codec* pCodec, - const crnlib::vector* pColor_endpoint_remap, + const crnlib::vector* pColor_endpoint_remap, const crnlib::vector* pColor_selector_remap, - const crnlib::vector* pAlpha_endpoint_remap, + const crnlib::vector* pAlpha_endpoint_remap, const crnlib::vector* pAlpha_selector_remap) { if (!pCodec) @@ -751,7 +751,7 @@ namespace crnlib m_chunk_encoding_hist.resize(1 << (3 * cEncodingMapNumChunksPerCode)); if (clear_histograms) m_chunk_encoding_hist.set_all(0); - + if (pColor_endpoint_remap) { CRNLIB_ASSERT(pColor_endpoint_remap->size() == m_hvq.get_color_endpoint_codebook_size()); @@ -767,7 +767,7 @@ namespace crnlib if (clear_histograms) m_selector_index_hist[0].set_all(0); } - + if (pAlpha_endpoint_remap) { CRNLIB_ASSERT(pAlpha_endpoint_remap->size() == m_hvq.get_alpha_endpoint_codebook_size()); @@ -775,7 +775,7 @@ namespace crnlib if (clear_histograms) m_endpoint_index_hist[1].set_all(0); } - + if (pAlpha_selector_remap) { CRNLIB_ASSERT(pAlpha_selector_remap->size() == m_hvq.get_alpha_selector_codebook_size()); @@ -783,16 +783,16 @@ namespace crnlib if (clear_histograms) m_selector_index_hist[1].set_all(0); } - } - + } + uint prev_endpoint_index[cNumComps]; utils::zero_object(prev_endpoint_index); - + uint prev_selector_index[cNumComps]; utils::zero_object(prev_selector_index); - + uint num_encodings_left = 0; - + for (uint chunk_index = first_chunk; chunk_index < (first_chunk + num_chunks); chunk_index++) { if (!num_encodings_left) @@ -801,17 +801,17 @@ namespace crnlib for (uint i = 0; i < cEncodingMapNumChunksPerCode; i++) if ((chunk_index + i) < (first_chunk + num_chunks)) index |= (m_hvq.get_chunk_encoding(chunk_index + i).m_encoding_index << (i * 3)); - + if (pCodec) pCodec->encode(index, m_chunk_encoding_dm); else m_chunk_encoding_hist.inc_freq(index); - + num_encodings_left = cEncodingMapNumChunksPerCode; } num_encodings_left--; - const dxt_hc::chunk_encoding& encoding = m_hvq.get_chunk_encoding(chunk_index); + const dxt_hc::chunk_encoding& encoding = m_hvq.get_chunk_encoding(chunk_index); const chunk_detail& details = m_chunk_details[chunk_index]; const uint comp_order[3] = { cAlpha0, cAlpha1, cColor }; @@ -820,7 +820,7 @@ namespace crnlib const uint comp_index = comp_order[c]; if (!m_has_comp[comp_index]) continue; - + // endpoints if (comp_index == cColor) { @@ -870,8 +870,8 @@ namespace crnlib } } } - } // c - + } // c + // selectors for (uint y = 0; y < 2; y++) { @@ -882,8 +882,8 @@ namespace crnlib const uint comp_index = comp_order[c]; if (!m_has_comp[comp_index]) continue; - - if (comp_index == cColor) + + if (comp_index == cColor) { if (pColor_selector_remap) { @@ -902,7 +902,7 @@ namespace crnlib pCodec->encode(sym, m_selector_index_dm[cColor]); prev_selector_index[cColor] = cur_selector_index; - } + } } else if (pAlpha_selector_remap) { @@ -922,34 +922,34 @@ namespace crnlib prev_selector_index[comp_index] = cur_selector_index; } - + } // c - + } // x } // y - + } // chunk_index - + return true; } - + bool crn_comp::pack_chunks_simulation( uint first_chunk, uint num_chunks, uint& total_bits, - const crnlib::vector* pColor_endpoint_remap, + const crnlib::vector* pColor_endpoint_remap, const crnlib::vector* pColor_selector_remap, - const crnlib::vector* pAlpha_endpoint_remap, + const crnlib::vector* pAlpha_endpoint_remap, const crnlib::vector* pAlpha_selector_remap) - { + { if (!pack_chunks(first_chunk, num_chunks, true, NULL, pColor_endpoint_remap, pColor_selector_remap, pAlpha_endpoint_remap, pAlpha_selector_remap)) return false; symbol_codec codec; codec.start_encoding(2*1024*1024); codec.encode_enable_simulation(true); - + m_chunk_encoding_dm.init(true, m_chunk_encoding_hist, 16); - + for (uint i = 0; i < 2; i++) { if (m_endpoint_index_hist[i].size()) @@ -957,26 +957,26 @@ namespace crnlib m_endpoint_index_dm[i].init(true, m_endpoint_index_hist[i], 16); codec.encode_transmit_static_huffman_data_model(m_endpoint_index_dm[i], false); - } + } if (m_selector_index_hist[i].size()) { m_selector_index_dm[i].init(true, m_selector_index_hist[i], 16); codec.encode_transmit_static_huffman_data_model(m_selector_index_dm[i], false); - } + } } - + if (!pack_chunks(first_chunk, num_chunks, false, &codec, pColor_endpoint_remap, pColor_selector_remap, pAlpha_endpoint_remap, pAlpha_selector_remap)) return false; - + codec.stop_encoding(false); - + total_bits = codec.encode_get_total_bits_written(); - + return true; - } - + } + void crn_comp::append_vec(crnlib::vector& a, const void* p, uint size) { if (size) @@ -985,7 +985,7 @@ namespace crnlib a.resize(ofs + size); memcpy(&a[ofs], p, size); - } + } } void crn_comp::append_vec(crnlib::vector& a, const crnlib::vector& b) @@ -996,10 +996,10 @@ namespace crnlib a.resize(ofs + b.size()); memcpy(&a[ofs], &b[0], b.size()); - } - } + } + } -#if 0 +#if 0 bool crn_comp::init_chunk_encoding_dm() { symbol_histogram hist(1 << (3 * cEncodingMapNumChunksPerCode)); @@ -1021,11 +1021,11 @@ namespace crnlib if (!m_chunk_encoding_dm.init(true, hist, 16)) return false; - + return true; } -#endif - +#endif + bool crn_comp::alias_images() { for (uint face_index = 0; face_index < m_pParams->m_faces; face_index++) @@ -1034,14 +1034,14 @@ namespace crnlib { const uint width = math::maximum(1U, m_pParams->m_width >> level_index); const uint height = math::maximum(1U, m_pParams->m_height >> level_index); - + if (!m_pParams->m_pImages[face_index][level_index]) return false; - + m_images[face_index][level_index].alias((color_quad_u8*)m_pParams->m_pImages[face_index][level_index], width, height); } } - + image_utils::conversion_type conv_type = image_utils::get_image_conversion_type_from_crn_format((crn_format)m_pParams->m_format); if (conv_type != image_utils::cConversion_Invalid) { @@ -1050,19 +1050,19 @@ namespace crnlib for (uint level_index = 0; level_index < m_pParams->m_levels; level_index++) { image_u8 cooked_image(m_images[face_index][level_index]); - + image_utils::convert_image(cooked_image, conv_type); - + m_images[face_index][level_index].swap(cooked_image); } } } - + m_mip_groups.clear(); m_mip_groups.resize(m_pParams->m_levels); - + utils::zero_object(m_levels); - + uint mip_group = 0; uint chunk_index = 0; uint mip_group_chunk_index = 0; @@ -1073,12 +1073,12 @@ namespace crnlib const uint chunk_width = math::align_up_value(width, cChunkPixelWidth) / cChunkPixelWidth; const uint chunk_height = math::align_up_value(height, cChunkPixelHeight) / cChunkPixelHeight; const uint num_chunks = m_pParams->m_faces * chunk_width * chunk_height; - + m_mip_groups[mip_group].m_first_chunk = chunk_index; mip_group_chunk_index = 0; - + m_mip_groups[mip_group].m_num_chunks += num_chunks; - + m_levels[level_index].m_width = width; m_levels[level_index].m_height = height; m_levels[level_index].m_chunk_width = chunk_width; @@ -1087,17 +1087,17 @@ namespace crnlib m_levels[level_index].m_num_chunks = num_chunks; m_levels[level_index].m_group_index = mip_group; m_levels[level_index].m_group_first_chunk = 0; - + chunk_index += num_chunks; - + mip_group++; } - + m_total_chunks = chunk_index; - + return true; - } - + } + void crn_comp::append_chunks(const image_u8& img, uint num_chunks_x, uint num_chunks_y, dxt_hc::pixel_chunk_vec& chunks, float weight) { for (uint y = 0; y < num_chunks_y; y++) @@ -1108,7 +1108,7 @@ namespace crnlib if (y & 1) { x_start = num_chunks_x - 1; - x_end = -1; + x_end = -1; x_dir = -1; } @@ -1131,16 +1131,16 @@ namespace crnlib chunk(cx, cy) = img(px, py); } - } + } } } } - + void crn_comp::create_chunks() { m_chunks.reserve(m_total_chunks); m_chunks.resize(0); - + for (uint level = 0; level < m_pParams->m_levels; level++) { for (uint face = 0; face < m_pParams->m_faces; face++) @@ -1149,49 +1149,49 @@ namespace crnlib { CRNLIB_ASSERT(m_levels[level].m_first_chunk == m_chunks.size()); } - + float mip_weight = math::minimum(12.0f, powf( 1.3f, static_cast(level) ) ); //float mip_weight = 1.0f; - + append_chunks(m_images[face][level], m_levels[level].m_chunk_width, m_levels[level].m_chunk_height, m_chunks, mip_weight); - } + } } - + CRNLIB_ASSERT(m_chunks.size() == m_total_chunks); } - + void crn_comp::clear() { m_pParams = NULL; - + for (uint f = 0; f < cCRNMaxFaces; f++) for (uint l = 0; l < cCRNMaxLevels; l++) m_images[f][l].clear(); - + utils::zero_object(m_levels); - + m_mip_groups.clear(); - + utils::zero_object(m_has_comp); - + m_chunk_details.clear(); - + for (uint i = 0; i < cNumComps; i++) { m_endpoint_indices[i].clear(); m_selector_indices[i].clear(); } - - m_total_chunks = 0; - + + m_total_chunks = 0; + m_chunks.clear(); - + utils::zero_object(m_crn_header); - + m_comp_data.clear(); - + m_hvq.clear(); - + m_chunk_encoding_hist.clear(); m_chunk_encoding_dm.clear(); for (uint i = 0; i < 2; i++) @@ -1201,25 +1201,25 @@ namespace crnlib m_selector_index_hist[i].clear(); m_selector_index_dm[i].clear(); } - + for (uint i = 0; i < cCRNMaxLevels; i++) m_packed_chunks[i].clear(); - + m_packed_data_models.clear(); m_packed_color_endpoints.clear(); - m_packed_color_selectors.clear(); + m_packed_color_selectors.clear(); m_packed_alpha_endpoints.clear(); m_packed_alpha_selectors.clear(); } - + bool crn_comp::quantize_chunks() { dxt_hc::params params; - + params.m_adaptive_tile_alpha_psnr_derating = m_pParams->m_crn_adaptive_tile_alpha_psnr_derating; params.m_adaptive_tile_color_psnr_derating = m_pParams->m_crn_adaptive_tile_color_psnr_derating; - + if (m_pParams->m_flags & cCRNCompFlagManualPaletteSizes) { params.m_color_endpoint_codebook_size = math::clamp(m_pParams->m_crn_color_endpoint_palette_size, cCRNMinPaletteSize, cCRNMaxPaletteSize); @@ -1244,7 +1244,7 @@ namespace crnlib } else if (m_pParams->m_format == cCRNFmtDXT5) color_quality_power_mul = .75f; - + float color_endpoint_quality = powf(quality, 1.8f * color_quality_power_mul); float color_selector_quality = powf(quality, 1.65f * color_quality_power_mul); params.m_color_endpoint_codebook_size = math::clamp(math::float_to_uint(.5f + math::lerp(math::maximum(64, cCRNMinPaletteSize), (float)max_codebook_entries, color_endpoint_quality)), cCRNMinPaletteSize, cCRNMaxPaletteSize); @@ -1258,63 +1258,63 @@ namespace crnlib if (m_pParams->m_flags & cCRNCompFlagDebugging) { - console::debug(L"Color endpoints: %u", params.m_color_endpoint_codebook_size); - console::debug(L"Color selectors: %u", params.m_color_selector_codebook_size); - console::debug(L"Alpha endpoints: %u", params.m_alpha_endpoint_codebook_size); - console::debug(L"Alpha selectors: %u", params.m_alpha_selector_codebook_size); + console::debug("Color endpoints: %u", params.m_color_endpoint_codebook_size); + console::debug("Color selectors: %u", params.m_color_selector_codebook_size); + console::debug("Alpha endpoints: %u", params.m_alpha_endpoint_codebook_size); + console::debug("Alpha selectors: %u", params.m_alpha_selector_codebook_size); } - + params.m_hierarchical = (m_pParams->m_flags & cCRNCompFlagHierarchical) != 0; params.m_perceptual = (m_pParams->m_flags & cCRNCompFlagPerceptual) != 0; - + params.m_pProgress_func = m_pParams->m_pProgress_func; params.m_pProgress_func_data = m_pParams->m_pProgress_func_data; - + switch (m_pParams->m_format) { - case cCRNFmtDXT1: + case cCRNFmtDXT1: { - params.m_format = cDXT1; + params.m_format = cDXT1; m_has_comp[cColor] = true; break; } - case cCRNFmtDXT3: + case cCRNFmtDXT3: { m_has_comp[cAlpha0] = true; return false; } - case cCRNFmtDXT5: + case cCRNFmtDXT5: { - params.m_format = cDXT5; + params.m_format = cDXT5; params.m_alpha_component_indices[0] = m_pParams->m_alpha_component; m_has_comp[cColor] = true; m_has_comp[cAlpha0] = true; break; } - case cCRNFmtDXT5_CCxY: + case cCRNFmtDXT5_CCxY: { - params.m_format = cDXT5; + params.m_format = cDXT5; params.m_alpha_component_indices[0] = 3; m_has_comp[cColor] = true; m_has_comp[cAlpha0] = true; params.m_perceptual = false; - + //params.m_adaptive_tile_color_alpha_weighting_ratio = 1.0f; params.m_adaptive_tile_color_alpha_weighting_ratio = 1.5f; break; } - case cCRNFmtDXT5_xGBR: - case cCRNFmtDXT5_AGBR: - case cCRNFmtDXT5_xGxR: + case cCRNFmtDXT5_xGBR: + case cCRNFmtDXT5_AGBR: + case cCRNFmtDXT5_xGxR: { - params.m_format = cDXT5; + params.m_format = cDXT5; params.m_alpha_component_indices[0] = 3; m_has_comp[cColor] = true; m_has_comp[cAlpha0] = true; params.m_perceptual = false; - break; + break; } - case cCRNFmtDXN_XY: + case cCRNFmtDXN_XY: { params.m_format = cDXN_XY; params.m_alpha_component_indices[0] = 0; @@ -1324,7 +1324,7 @@ namespace crnlib params.m_perceptual = false; break; } - case cCRNFmtDXN_YX: + case cCRNFmtDXN_YX: { params.m_format = cDXN_YX; params.m_alpha_component_indices[0] = 1; @@ -1334,28 +1334,28 @@ namespace crnlib params.m_perceptual = false; break; } - case cCRNFmtDXT5A: + case cCRNFmtDXT5A: { - params.m_format = cDXT5A; + params.m_format = cDXT5A; params.m_alpha_component_indices[0] = m_pParams->m_alpha_component; m_has_comp[cAlpha0] = true; params.m_perceptual = false; break; } - default: + default: { return false; } } params.m_debugging = (m_pParams->m_flags & cCRNCompFlagDebugging) != 0; - + params.m_num_levels = m_pParams->m_levels; for (uint i = 0; i < m_pParams->m_levels; i++) { - params.m_levels[i].m_first_chunk = m_levels[i].m_first_chunk; - params.m_levels[i].m_num_chunks = m_levels[i].m_num_chunks; + params.m_levels[i].m_first_chunk = m_levels[i].m_first_chunk; + params.m_levels[i].m_num_chunks = m_levels[i].m_num_chunks; } - + if (!m_hvq.compress(params, m_total_chunks, &m_chunks[0], m_task_pool)) return false; @@ -1363,30 +1363,30 @@ namespace crnlib if (params.m_debugging) { const dxt_hc::pixel_chunk_vec& pixel_chunks = m_hvq.get_compressed_chunk_pixels_final(); - + image_u8 img; dxt_hc::create_debug_image_from_chunks((m_pParams->m_width+7)>>3, (m_pParams->m_height+7)>>3, pixel_chunks, &m_hvq.get_chunk_encoding_vec(), img, true, -1); - image_utils::save_to_file(L"quantized_chunks.tga", img); + image_utils::save_to_file("quantized_chunks.tga", img); } -#endif - +#endif + return true; } - + void crn_comp::create_chunk_indices() { m_chunk_details.resize(m_total_chunks); - + for (uint i = 0; i < cNumComps; i++) { m_endpoint_indices[i].clear(); m_selector_indices[i].clear(); - } - + } + for (uint chunk_index = 0; chunk_index < m_total_chunks; chunk_index++) { const dxt_hc::chunk_encoding& chunk_encoding = m_hvq.get_chunk_encoding(chunk_index); - + for (uint i = 0; i < cNumComps; i++) { if (m_has_comp[i]) @@ -1396,34 +1396,34 @@ namespace crnlib break; } } - - for (uint i = 0; i < cNumComps; i++) + + for (uint i = 0; i < cNumComps; i++) { if (!m_has_comp[i]) continue; - + for (uint tile_index = 0; tile_index < chunk_encoding.m_num_tiles; tile_index++) m_endpoint_indices[i].push_back(chunk_encoding.m_endpoint_indices[i][tile_index]); - + for (uint y = 0; y < cChunkBlockHeight; y++) for (uint x = 0; x < cChunkBlockWidth; x++) m_selector_indices[i].push_back(chunk_encoding.m_selector_indices[i][y][x]); } } } - + struct optimize_color_endpoint_codebook_params { crnlib::vector* m_pTrial_color_endpoint_remap; uint m_iter_index; - uint m_max_iter_index; + uint m_max_iter_index; }; - + void crn_comp::optimize_color_endpoint_codebook_task(uint64 data, void* pData_ptr) - { + { data; optimize_color_endpoint_codebook_params* pParams = reinterpret_cast(pData_ptr); - + if (pParams->m_iter_index == pParams->m_max_iter_index) { sort_color_endpoint_codebook(*pParams->m_pTrial_color_endpoint_remap, m_hvq.get_color_endpoint_vec()); @@ -1431,20 +1431,20 @@ namespace crnlib else { float f = pParams->m_iter_index / static_cast(pParams->m_max_iter_index - 1); - + create_zeng_reorder_table( - m_hvq.get_color_endpoint_codebook_size(), - m_endpoint_indices[cColor].size(), - &m_endpoint_indices[cColor][0], - *pParams->m_pTrial_color_endpoint_remap, - pParams->m_iter_index ? color_endpoint_similarity_func : NULL, - &m_hvq, + m_hvq.get_color_endpoint_codebook_size(), + m_endpoint_indices[cColor].size(), + &m_endpoint_indices[cColor][0], + *pParams->m_pTrial_color_endpoint_remap, + pParams->m_iter_index ? color_endpoint_similarity_func : NULL, + &m_hvq, f); - } - + } + crnlib_delete(pParams); } - + bool crn_comp::optimize_color_endpoint_codebook(crnlib::vector& remapping) { if (m_pParams->m_flags & cCRNCompFlagQuick) @@ -1455,38 +1455,38 @@ namespace crnlib if (!pack_color_endpoints(m_packed_color_endpoints, remapping, m_endpoint_indices[cColor], 0)) return false; - + return true; } - + const uint cMaxEndpointRemapIters = 3; - + uint best_bits = UINT_MAX; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"----- Begin optimization of color endpoint codebook"); -#endif + console::debug("----- Begin optimization of color endpoint codebook"); +#endif crnlib::vector trial_color_endpoint_remaps[cMaxEndpointRemapIters + 1]; - + for (uint i = 0; i <= cMaxEndpointRemapIters; i++) { optimize_color_endpoint_codebook_params* pParams = crnlib_new(); pParams->m_iter_index = i; pParams->m_max_iter_index = cMaxEndpointRemapIters; pParams->m_pTrial_color_endpoint_remap = &trial_color_endpoint_remaps[i]; - + m_task_pool.queue_object_task(this, &crn_comp::optimize_color_endpoint_codebook_task, 0, pParams); } - + m_task_pool.join(); - + for (uint i = 0; i <= cMaxEndpointRemapIters; i++) { if (!update_progress(20, i, cMaxEndpointRemapIters+1)) return false; - + crnlib::vector& trial_color_endpoint_remap = trial_color_endpoint_remaps[i]; crnlib::vector packed_data; @@ -1497,46 +1497,46 @@ namespace crnlib if (!pack_chunks_simulation(0, m_total_chunks, total_packed_chunk_bits, &trial_color_endpoint_remap, NULL, NULL, NULL)) return false; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Pack chunks simulation: %u bits", total_packed_chunk_bits); -#endif + console::debug("Pack chunks simulation: %u bits", total_packed_chunk_bits); +#endif - uint total_bits = packed_data.size() * 8 + total_packed_chunk_bits; + uint total_bits = packed_data.size() * 8 + total_packed_chunk_bits; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total bits: %u", total_bits); -#endif + console::debug("Total bits: %u", total_bits); +#endif if (total_bits < best_bits) - { + { m_packed_color_endpoints.swap(packed_data); remapping.swap(trial_color_endpoint_remap); best_bits = total_bits; } - } - -#if CRNLIB_ENABLE_DEBUG_MESSAGES + } + +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"End optimization of color endpoint codebook"); -#endif - + console::debug("End optimization of color endpoint codebook"); +#endif + return true; } - + struct optimize_color_selector_codebook_params { crnlib::vector* m_pTrial_color_selector_remap; uint m_iter_index; - uint m_max_iter_index; + uint m_max_iter_index; }; - + void crn_comp::optimize_color_selector_codebook_task(uint64 data, void* pData_ptr) { data; optimize_color_selector_codebook_params* pParams = reinterpret_cast(pData_ptr); - + if (pParams->m_iter_index == pParams->m_max_iter_index) { sort_selector_codebook(*pParams->m_pTrial_color_selector_remap, m_hvq.get_color_selectors_vec(), g_dxt1_to_linear); @@ -1545,18 +1545,18 @@ namespace crnlib { float f = pParams->m_iter_index / static_cast(pParams->m_max_iter_index - 1); create_zeng_reorder_table( - m_hvq.get_color_selector_codebook_size(), - m_selector_indices[cColor].size(), - &m_selector_indices[cColor][0], - *pParams->m_pTrial_color_selector_remap, - pParams->m_iter_index ? color_selector_similarity_func : NULL, + m_hvq.get_color_selector_codebook_size(), + m_selector_indices[cColor].size(), + &m_selector_indices[cColor][0], + *pParams->m_pTrial_color_selector_remap, + pParams->m_iter_index ? color_selector_similarity_func : NULL, (void*)&m_hvq.get_color_selectors_vec(), f); - } - + } + crnlib_delete(pParams); } - + bool crn_comp::optimize_color_selector_codebook(crnlib::vector& remapping) { if (m_pParams->m_flags & cCRNCompFlagQuick) @@ -1564,32 +1564,32 @@ namespace crnlib remapping.resize(m_hvq.get_color_selectors_vec().size()); for (uint i = 0; i < m_hvq.get_color_selectors_vec().size(); i++) remapping[i] = i; - + if (!pack_selectors( m_packed_color_selectors, m_selector_indices[cColor], - m_hvq.get_color_selectors_vec(), + m_hvq.get_color_selectors_vec(), remapping, 3, g_dxt1_to_linear, 0)) - { - return false; + { + return false; } - + return true; } - + const uint cMaxSelectorRemapIters = 3; - + uint best_bits = UINT_MAX; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"----- Begin optimization of color selector codebook"); + console::debug("----- Begin optimization of color selector codebook"); #endif - + crnlib::vector trial_color_selector_remaps[cMaxSelectorRemapIters + 1]; - + for (uint i = 0; i <= cMaxSelectorRemapIters; i++) { optimize_color_selector_codebook_params* pParams = crnlib_new(); @@ -1599,72 +1599,72 @@ namespace crnlib m_task_pool.queue_object_task(this, &crn_comp::optimize_color_selector_codebook_task, 0, pParams); } - + m_task_pool.join(); - + for (uint i = 0; i <= cMaxSelectorRemapIters; i++) { if (!update_progress(21, i, cMaxSelectorRemapIters+1)) return false; - + crnlib::vector& trial_color_selector_remap = trial_color_selector_remaps[i]; - crnlib::vector packed_data; + crnlib::vector packed_data; if (!pack_selectors( packed_data, m_selector_indices[cColor], - m_hvq.get_color_selectors_vec(), + m_hvq.get_color_selectors_vec(), trial_color_selector_remap, 3, g_dxt1_to_linear, i)) - { - return false; + { + return false; } uint total_packed_chunk_bits; if (!pack_chunks_simulation(0, m_total_chunks, total_packed_chunk_bits, NULL, &trial_color_selector_remap, NULL, NULL)) return false; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Pack chunks simulation: %u bits", total_packed_chunk_bits); -#endif + console::debug("Pack chunks simulation: %u bits", total_packed_chunk_bits); +#endif - uint total_bits = packed_data.size() * 8 + total_packed_chunk_bits; + uint total_bits = packed_data.size() * 8 + total_packed_chunk_bits; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total bits: %u", total_bits); -#endif + console::debug("Total bits: %u", total_bits); +#endif if (total_bits < best_bits) - { + { m_packed_color_selectors.swap(packed_data); remapping.swap(trial_color_selector_remap); best_bits = total_bits; } - } + } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"End optimization of color selector codebook"); -#endif - + console::debug("End optimization of color selector codebook"); +#endif + return true; } - + struct optimize_alpha_endpoint_codebook_params { crnlib::vector* m_pAlpha_indices; crnlib::vector* m_pTrial_alpha_endpoint_remap; uint m_iter_index; - uint m_max_iter_index; + uint m_max_iter_index; }; void crn_comp::optimize_alpha_endpoint_codebook_task(uint64 data, void* pData_ptr) - { + { data; optimize_alpha_endpoint_codebook_params* pParams = reinterpret_cast(pData_ptr); - + if (pParams->m_iter_index == pParams->m_max_iter_index) { sort_alpha_endpoint_codebook(*pParams->m_pTrial_alpha_endpoint_remap, m_hvq.get_alpha_endpoint_vec()); @@ -1672,20 +1672,20 @@ namespace crnlib else { float f = pParams->m_iter_index / static_cast(pParams->m_max_iter_index - 1); - + create_zeng_reorder_table( - m_hvq.get_alpha_endpoint_codebook_size(), - pParams->m_pAlpha_indices->size(), - &(*pParams->m_pAlpha_indices)[0], - *pParams->m_pTrial_alpha_endpoint_remap, - pParams->m_iter_index ? alpha_endpoint_similarity_func : NULL, - &m_hvq, + m_hvq.get_alpha_endpoint_codebook_size(), + pParams->m_pAlpha_indices->size(), + &(*pParams->m_pAlpha_indices)[0], + *pParams->m_pTrial_alpha_endpoint_remap, + pParams->m_iter_index ? alpha_endpoint_similarity_func : NULL, + &m_hvq, f); - } - + } + crnlib_delete(pParams); } - + bool crn_comp::optimize_alpha_endpoint_codebook(crnlib::vector& remapping) { crnlib::vector alpha_indices; @@ -1702,18 +1702,18 @@ namespace crnlib remapping[i] = i; if (!pack_alpha_endpoints(m_packed_alpha_endpoints, remapping, alpha_indices, 0)) - return false; + return false; return true; } - + const uint cMaxEndpointRemapIters = 3; uint best_bits = UINT_MAX; - -#if CRNLIB_ENABLE_DEBUG_MESSAGES + +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"----- Begin optimization of alpha endpoint codebook"); -#endif + console::debug("----- Begin optimization of alpha endpoint codebook"); +#endif crnlib::vector trial_alpha_endpoint_remaps[cMaxEndpointRemapIters + 1]; @@ -1727,14 +1727,14 @@ namespace crnlib m_task_pool.queue_object_task(this, &crn_comp::optimize_alpha_endpoint_codebook_task, 0, pParams); } - + m_task_pool.join(); - + for (uint i = 0; i <= cMaxEndpointRemapIters; i++) { if (!update_progress(22, i, cMaxEndpointRemapIters+1)) return false; - + crnlib::vector& trial_alpha_endpoint_remap = trial_alpha_endpoint_remaps[i]; crnlib::vector packed_data; @@ -1745,47 +1745,47 @@ namespace crnlib if (!pack_chunks_simulation(0, m_total_chunks, total_packed_chunk_bits, NULL, NULL, &trial_alpha_endpoint_remap, NULL)) return false; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Pack chunks simulation: %u bits", total_packed_chunk_bits); + console::debug("Pack chunks simulation: %u bits", total_packed_chunk_bits); #endif - - uint total_bits = packed_data.size() * 8 + total_packed_chunk_bits; - -#if CRNLIB_ENABLE_DEBUG_MESSAGES + + uint total_bits = packed_data.size() * 8 + total_packed_chunk_bits; + +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total bits: %u", total_bits); -#endif + console::debug("Total bits: %u", total_bits); +#endif if (total_bits < best_bits) - { + { m_packed_alpha_endpoints.swap(packed_data); remapping.swap(trial_alpha_endpoint_remap); best_bits = total_bits; } - } - -#if CRNLIB_ENABLE_DEBUG_MESSAGES + } + +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"End optimization of alpha endpoint codebook"); -#endif - + console::debug("End optimization of alpha endpoint codebook"); +#endif + return true; } - + struct optimize_alpha_selector_codebook_params { crnlib::vector* m_pAlpha_indices; crnlib::vector* m_pTrial_alpha_selector_remap; uint m_iter_index; - uint m_max_iter_index; + uint m_max_iter_index; }; void crn_comp::optimize_alpha_selector_codebook_task(uint64 data, void* pData_ptr) - { + { data; optimize_alpha_selector_codebook_params* pParams = reinterpret_cast(pData_ptr); - + if (pParams->m_iter_index == pParams->m_max_iter_index) { sort_selector_codebook(*pParams->m_pTrial_alpha_selector_remap, m_hvq.get_alpha_selectors_vec(), g_dxt5_to_linear); @@ -1794,15 +1794,15 @@ namespace crnlib { float f = pParams->m_iter_index / static_cast(pParams->m_max_iter_index - 1); create_zeng_reorder_table( - m_hvq.get_alpha_selector_codebook_size(), - pParams->m_pAlpha_indices->size(), - &(*pParams->m_pAlpha_indices)[0], - *pParams->m_pTrial_alpha_selector_remap, - pParams->m_iter_index ? alpha_selector_similarity_func : NULL, + m_hvq.get_alpha_selector_codebook_size(), + pParams->m_pAlpha_indices->size(), + &(*pParams->m_pAlpha_indices)[0], + *pParams->m_pTrial_alpha_selector_remap, + pParams->m_iter_index ? alpha_selector_similarity_func : NULL, (void*)&m_hvq.get_alpha_selectors_vec(), f); - } - } + } + } bool crn_comp::optimize_alpha_selector_codebook(crnlib::vector& remapping) { @@ -1812,7 +1812,7 @@ namespace crnlib alpha_indices.push_back(m_selector_indices[cAlpha0][i]); for (uint i = 0; i < m_selector_indices[cAlpha1].size(); i++) alpha_indices.push_back(m_selector_indices[cAlpha1][i]); - + if (m_pParams->m_flags & cCRNCompFlagQuick) { remapping.resize(m_hvq.get_alpha_selectors_vec().size()); @@ -1822,12 +1822,12 @@ namespace crnlib if (!pack_selectors( m_packed_alpha_selectors, alpha_indices, - m_hvq.get_alpha_selectors_vec(), + m_hvq.get_alpha_selectors_vec(), remapping, 7, g_dxt5_to_linear, 0)) - { - return false; + { + return false; } return true; @@ -1837,9 +1837,9 @@ namespace crnlib uint best_bits = UINT_MAX; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"----- Begin optimization of alpha selector codebook"); + console::debug("----- Begin optimization of alpha selector codebook"); #endif crnlib::vector trial_alpha_selector_remaps[cMaxSelectorRemapIters + 1]; @@ -1856,66 +1856,66 @@ namespace crnlib } m_task_pool.join(); - + for (uint i = 0; i <= cMaxSelectorRemapIters; i++) { if (!update_progress(23, i, cMaxSelectorRemapIters+1)) return false; - + crnlib::vector& trial_alpha_selector_remap = trial_alpha_selector_remaps[i]; - - crnlib::vector packed_data; + + crnlib::vector packed_data; if (!pack_selectors( packed_data, alpha_indices, - m_hvq.get_alpha_selectors_vec(), + m_hvq.get_alpha_selectors_vec(), trial_alpha_selector_remap, 7, g_dxt5_to_linear, i)) - { - return false; + { + return false; } uint total_packed_chunk_bits; if (!pack_chunks_simulation(0, m_total_chunks, total_packed_chunk_bits, NULL, NULL, NULL, &trial_alpha_selector_remap)) return false; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Pack chunks simulation: %u bits", total_packed_chunk_bits); -#endif + console::debug("Pack chunks simulation: %u bits", total_packed_chunk_bits); +#endif - uint total_bits = packed_data.size() * 8 + total_packed_chunk_bits; + uint total_bits = packed_data.size() * 8 + total_packed_chunk_bits; -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"Total bits: %u", total_bits); -#endif + console::debug("Total bits: %u", total_bits); +#endif if (total_bits < best_bits) - { + { m_packed_alpha_selectors.swap(packed_data); - + remapping.swap(trial_alpha_selector_remap); best_bits = total_bits; } - } + } -#if CRNLIB_ENABLE_DEBUG_MESSAGES +#if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_pParams->m_flags & cCRNCompFlagDebugging) - console::debug(L"End optimization of alpha selector codebook"); -#endif - + console::debug("End optimization of alpha selector codebook"); +#endif + return true; } - + bool crn_comp::pack_data_models() { symbol_codec codec; codec.start_encoding(1024*1024); - + if (!codec.encode_transmit_static_huffman_data_model(m_chunk_encoding_dm, false)) return false; - + for (uint i = 0; i < 2; i++) { if (m_endpoint_index_dm[i].get_total_syms()) @@ -1930,18 +1930,18 @@ namespace crnlib return false; } } - + codec.stop_encoding(false); - + m_packed_data_models.swap(codec.get_encoding_buf()); - - return true; + + return true; } - + bool crn_comp::create_comp_data() { utils::zero_object(m_crn_header); - + m_crn_header.m_width = static_cast(m_pParams->m_width); m_crn_header.m_height = static_cast(m_pParams->m_height); m_crn_header.m_levels = static_cast(m_pParams->m_levels); @@ -1949,13 +1949,13 @@ namespace crnlib m_crn_header.m_format = static_cast(m_pParams->m_format); m_crn_header.m_userdata0 = m_pParams->m_userdata0; m_crn_header.m_userdata1 = m_pParams->m_userdata1; - + m_comp_data.clear(); m_comp_data.reserve(2*1024*1024); append_vec(m_comp_data, &m_crn_header, sizeof(m_crn_header)); // tack on the rest of the variable size m_level_ofs array m_comp_data.resize( m_comp_data.size() + sizeof(m_crn_header.m_level_ofs[0]) * (m_pParams->m_levels - 1) ); - + if (m_packed_color_endpoints.size()) { m_crn_header.m_color_endpoints.m_num = static_cast(m_hvq.get_color_endpoint_codebook_size()); @@ -1963,7 +1963,7 @@ namespace crnlib m_crn_header.m_color_endpoints.m_ofs = m_comp_data.size(); append_vec(m_comp_data, m_packed_color_endpoints); } - + if (m_packed_color_selectors.size()) { m_crn_header.m_color_selectors.m_num = static_cast(m_hvq.get_color_selector_codebook_size()); @@ -1971,7 +1971,7 @@ namespace crnlib m_crn_header.m_color_selectors.m_ofs = m_comp_data.size(); append_vec(m_comp_data, m_packed_color_selectors); } - + if (m_packed_alpha_endpoints.size()) { m_crn_header.m_alpha_endpoints.m_num = static_cast(m_hvq.get_alpha_endpoint_codebook_size()); @@ -1987,67 +1987,67 @@ namespace crnlib m_crn_header.m_alpha_selectors.m_ofs = m_comp_data.size(); append_vec(m_comp_data, m_packed_alpha_selectors); } - + m_crn_header.m_tables_ofs = m_comp_data.size(); m_crn_header.m_tables_size = m_packed_data_models.size(); append_vec(m_comp_data, m_packed_data_models); - + uint level_ofs[cCRNMaxLevels]; for (uint i = 0; i < m_mip_groups.size(); i++) { level_ofs[i] = m_comp_data.size(); append_vec(m_comp_data, m_packed_chunks[i]); } - + crnd::crn_header& dst_header = *(crnd::crn_header*)&m_comp_data[0]; // don't change the m_comp_data vector - or dst_header will be invalidated! - + memcpy(&dst_header, &m_crn_header, sizeof(dst_header)); - + for (uint i = 0; i < m_mip_groups.size(); i++) dst_header.m_level_ofs[i] = level_ofs[i]; - + const uint actual_header_size = sizeof(crnd::crn_header) + sizeof(dst_header.m_level_ofs[0]) * (m_mip_groups.size() - 1); - + dst_header.m_sig = crnd::crn_header::cCRNSigValue; - + dst_header.m_data_size = m_comp_data.size(); dst_header.m_data_crc16 = crc16(&m_comp_data[actual_header_size], m_comp_data.size() - actual_header_size); - + dst_header.m_header_size = actual_header_size; dst_header.m_header_crc16 = crc16(&dst_header.m_data_size, actual_header_size - (uint)((uint8*)&dst_header.m_data_size - (uint8*)&dst_header)); - + return true; } - + bool crn_comp::update_progress(uint phase_index, uint subphase_index, uint subphase_total) { if (!m_pParams->m_pProgress_func) return true; #if CRNLIB_ENABLE_DEBUG_MESSAGES - if (m_pParams->m_flags & cCRNCompFlagDebugging) + if (m_pParams->m_flags & cCRNCompFlagDebugging) return true; -#endif +#endif return (*m_pParams->m_pProgress_func)(phase_index, cTotalCompressionPhases, subphase_index, subphase_total, m_pParams->m_pProgress_func_data) != 0; } - + bool crn_comp::compress_internal() { if (!alias_images()) return false; - + create_chunks(); - + if (!quantize_chunks()) return false; - + create_chunk_indices(); - + crnlib::vector endpoint_remap[2]; crnlib::vector selector_remap[2]; - + if (m_has_comp[cColor]) { if (!optimize_color_endpoint_codebook(endpoint_remap[0])) @@ -2055,7 +2055,7 @@ namespace crnlib if (!optimize_color_selector_codebook(selector_remap[0])) return false; } - + if (m_has_comp[cAlpha0]) { if (!optimize_alpha_endpoint_codebook(endpoint_remap[1])) @@ -2063,67 +2063,67 @@ namespace crnlib if (!optimize_alpha_selector_codebook(selector_remap[1])) return false; } - + m_chunk_encoding_hist.clear(); for (uint i = 0; i < 2; i++) { m_endpoint_index_hist[i].clear(); m_endpoint_index_dm[i].clear(); - m_selector_index_hist[i].clear(); + m_selector_index_hist[i].clear(); m_selector_index_dm[i].clear(); } - + for (uint pass = 0; pass < 2; pass++) { for (uint mip_group = 0; mip_group < m_mip_groups.size(); mip_group++) { symbol_codec codec; codec.start_encoding(2*1024*1024); - + if (!pack_chunks( m_mip_groups[mip_group].m_first_chunk, m_mip_groups[mip_group].m_num_chunks, !pass && !mip_group, pass ? &codec : NULL, - m_has_comp[cColor] ? &endpoint_remap[0] : NULL, m_has_comp[cColor] ? &selector_remap[0] : NULL, + m_has_comp[cColor] ? &endpoint_remap[0] : NULL, m_has_comp[cColor] ? &selector_remap[0] : NULL, m_has_comp[cAlpha0] ? &endpoint_remap[1] : NULL, m_has_comp[cAlpha0] ? &selector_remap[1] : NULL)) { return false; } - + codec.stop_encoding(false); - + if (pass) m_packed_chunks[mip_group].swap(codec.get_encoding_buf()); } - + if (!pass) { m_chunk_encoding_dm.init(true, m_chunk_encoding_hist, 16); - + for (uint i = 0; i < 2; i++) { if (m_endpoint_index_hist[i].size()) m_endpoint_index_dm[i].init(true, m_endpoint_index_hist[i], 16); - + if (m_selector_index_hist[i].size()) m_selector_index_dm[i].init(true, m_selector_index_hist[i], 16); - } - } + } + } } - + if (!pack_data_models()) return false; if (!create_comp_data()) return false; - + if (!update_progress(24, 1, 1)) return false; - if (m_pParams->m_flags & cCRNCompFlagDebugging) + if (m_pParams->m_flags & cCRNCompFlagDebugging) { - crnlib_print_mem_stats(); + crnlib_print_mem_stats(); } - + return true; } @@ -2132,13 +2132,13 @@ namespace crnlib params; return true; } - + bool crn_comp::compress_pass(const crn_comp_params& params, float *pEffective_bitrate) { clear(); - + if (pEffective_bitrate) *pEffective_bitrate = 0.0f; - + m_pParams = ¶ms; if ((math::minimum(m_pParams->m_width, m_pParams->m_height) < 1) || (math::maximum(m_pParams->m_width, m_pParams->m_height) > cCRNMaxLevelResolution)) @@ -2150,7 +2150,7 @@ namespace crnlib bool status = compress_internal(); m_task_pool.deinit(); - + if ((status) && (pEffective_bitrate)) { uint total_pixels = 0; @@ -2158,7 +2158,7 @@ namespace crnlib for (uint f = 0; f < m_pParams->m_faces; f++) for (uint l = 0; l < m_pParams->m_levels; l++) total_pixels += m_images[f][l].get_total_pixels(); - + *pEffective_bitrate = (m_comp_data.size() * 8.0f) / total_pixels; } diff --git a/crnlib/crn_comp.h b/crnlib/crn_comp.h index 4f80e2e..5823494 100644 --- a/crnlib/crn_comp.h +++ b/crnlib/crn_comp.h @@ -18,30 +18,30 @@ namespace crnlib class crn_comp : public itexture_comp { CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(crn_comp); - + public: crn_comp(); virtual ~crn_comp(); - - virtual const wchar_t *get_ext() const { return L"CRN"; } - + + virtual const char *get_ext() const { return "CRN"; } + virtual bool compress_init(const crn_comp_params& params); virtual bool compress_pass(const crn_comp_params& params, float *pEffective_bitrate); virtual void compress_deinit(); - + virtual const crnlib::vector& get_comp_data() const { return m_comp_data; } virtual crnlib::vector& get_comp_data() { return m_comp_data; } - + uint get_comp_data_size() const { return m_comp_data.size(); } const uint8* get_comp_data_ptr() const { return m_comp_data.size() ? &m_comp_data[0] : NULL; } - + private: task_pool m_task_pool; const crn_comp_params* m_pParams; - + image_u8 m_images[cCRNMaxFaces][cCRNMaxLevels]; - - struct + + struct level_tag { uint m_width, m_height; uint m_chunk_width, m_chunk_height; @@ -50,130 +50,130 @@ namespace crnlib uint m_first_chunk; uint m_group_first_chunk; } m_levels[cCRNMaxLevels]; - + struct mip_group { mip_group() : m_first_chunk(0), m_num_chunks(0) { } - + uint m_first_chunk; uint m_num_chunks; }; crnlib::vector m_mip_groups; - - enum comp + + enum comp { cColor, cAlpha0, cAlpha1, cNumComps }; - + bool m_has_comp[cNumComps]; - + struct chunk_detail { chunk_detail() { utils::zero_object(*this); } - + uint m_first_endpoint_index; uint m_first_selector_index; }; typedef crnlib::vector chunk_detail_vec; chunk_detail_vec m_chunk_details; - + crnlib::vector m_endpoint_indices[cNumComps]; crnlib::vector m_selector_indices[cNumComps]; - + uint m_total_chunks; dxt_hc::pixel_chunk_vec m_chunks; - + crnd::crn_header m_crn_header; crnlib::vector m_comp_data; - + dxt_hc m_hvq; - - symbol_histogram m_chunk_encoding_hist; + + symbol_histogram m_chunk_encoding_hist; static_huffman_data_model m_chunk_encoding_dm; - + symbol_histogram m_endpoint_index_hist[2]; static_huffman_data_model m_endpoint_index_dm[2]; // color, alpha - - symbol_histogram m_selector_index_hist[2]; + + symbol_histogram m_selector_index_hist[2]; static_huffman_data_model m_selector_index_dm[2]; // color, alpha - + crnlib::vector m_packed_chunks[cCRNMaxLevels]; crnlib::vector m_packed_data_models; crnlib::vector m_packed_color_endpoints; - crnlib::vector m_packed_color_selectors; + crnlib::vector m_packed_color_selectors; crnlib::vector m_packed_alpha_endpoints; - crnlib::vector m_packed_alpha_selectors; - + crnlib::vector m_packed_alpha_selectors; + void clear(); - + void append_chunks(const image_u8& img, uint num_chunks_x, uint num_chunks_y, dxt_hc::pixel_chunk_vec& chunks, float weight); - + static float color_endpoint_similarity_func(uint index_a, uint index_b, void* pContext); static float alpha_endpoint_similarity_func(uint index_a, uint index_b, void* pContext); void sort_color_endpoint_codebook(crnlib::vector& remapping, const crnlib::vector& endpoints); void sort_alpha_endpoint_codebook(crnlib::vector& remapping, const crnlib::vector& endpoints); - + bool pack_color_endpoints(crnlib::vector& data, const crnlib::vector& remapping, const crnlib::vector& endpoint_indices, uint trial_index); bool pack_alpha_endpoints(crnlib::vector& data, const crnlib::vector& remapping, const crnlib::vector& endpoint_indices, uint trial_index); - + static float color_selector_similarity_func(uint index_a, uint index_b, void* pContext); static float alpha_selector_similarity_func(uint index_a, uint index_b, void* pContext); void sort_selector_codebook(crnlib::vector& remapping, const crnlib::vector& selectors, const uint8* pTo_linear); - + bool pack_selectors( crnlib::vector& packed_data, const crnlib::vector& selector_indices, - const crnlib::vector& selectors, + const crnlib::vector& selectors, const crnlib::vector& remapping, uint max_selector_value, const uint8* pTo_linear, uint trial_index); - + bool alias_images(); void create_chunks(); bool quantize_chunks(); void create_chunk_indices(); - + bool pack_chunks( uint first_chunk, uint num_chunks, bool clear_histograms, symbol_codec* pCodec, - const crnlib::vector* pColor_endpoint_remap, + const crnlib::vector* pColor_endpoint_remap, const crnlib::vector* pColor_selector_remap, - const crnlib::vector* pAlpha_endpoint_remap, + const crnlib::vector* pAlpha_endpoint_remap, const crnlib::vector* pAlpha_selector_remap); - + bool pack_chunks_simulation( uint first_chunk, uint num_chunks, uint& total_bits, - const crnlib::vector* pColor_endpoint_remap, + const crnlib::vector* pColor_endpoint_remap, const crnlib::vector* pColor_selector_remap, - const crnlib::vector* pAlpha_endpoint_remap, + const crnlib::vector* pAlpha_endpoint_remap, const crnlib::vector* pAlpha_selector_remap); - + void optimize_color_endpoint_codebook_task(uint64 data, void* pData_ptr); bool optimize_color_endpoint_codebook(crnlib::vector& remapping); - + void optimize_color_selector_codebook_task(uint64 data, void* pData_ptr); bool optimize_color_selector_codebook(crnlib::vector& remapping); - + void optimize_alpha_endpoint_codebook_task(uint64 data, void* pData_ptr); bool optimize_alpha_endpoint_codebook(crnlib::vector& remapping); - + void optimize_alpha_selector_codebook_task(uint64 data, void* pData_ptr); bool optimize_alpha_selector_codebook(crnlib::vector& remapping); - + bool create_comp_data(); - + bool pack_data_models(); - + bool update_progress(uint phase_index, uint subphase_index, uint subphase_total); - + bool compress_internal(); - + static void append_vec(crnlib::vector& a, const void* p, uint size); static void append_vec(crnlib::vector& a, const crnlib::vector& b); }; diff --git a/crnlib/crn_console.cpp b/crnlib/crn_console.cpp index 08eee84..8d13622 100644 --- a/crnlib/crn_console.cpp +++ b/crnlib/crn_console.cpp @@ -3,6 +3,7 @@ #include "crn_core.h" #include "crn_console.h" #include "crn_data_stream.h" +#include "crn_threading.h" namespace crnlib { @@ -48,7 +49,7 @@ namespace crnlib m_crlf = true; } - void console::vprintf(eConsoleMessageType type, const wchar_t* p, va_list args) + void console::vprintf(eConsoleMessageType type, const char* p, va_list args) { init(); @@ -56,12 +57,8 @@ namespace crnlib m_num_messages[type]++; - wchar_t buf[cConsoleBufSize]; -#ifdef _MSC_VER - vswprintf_s(buf, cConsoleBufSize, p, args); -#else - vswprintf(buf, p, args); -#endif + char buf[cConsoleBufSize]; + vsprintf_s(buf, cConsoleBufSize, p, args); bool handled = false; @@ -72,48 +69,38 @@ namespace crnlib handled = true; } - const wchar_t* pPrefix = NULL; + const char* pPrefix = NULL; if (m_prefixes) { switch (type) { - case cDebugConsoleMessage: pPrefix = L"Debug: "; break; - case cWarningConsoleMessage: pPrefix = L"Warning: "; break; - case cErrorConsoleMessage: pPrefix = L"Error: "; break; + case cDebugConsoleMessage: pPrefix = "Debug: "; break; + case cWarningConsoleMessage: pPrefix = "Warning: "; break; + case cErrorConsoleMessage: pPrefix = "Error: "; break; default: break; } } if ((!m_output_disabled) && (!handled)) { -#ifdef _XBOX if (pPrefix) - OutputDebugStringW(pPrefix); - OutputDebugStringW(buf); - if (m_crlf) - OutputDebugStringW(L"\n"); -#else - if (pPrefix) - ::wprintf(pPrefix); - ::wprintf(m_crlf ? L"%s\n" : L"%s", buf); -#endif + ::printf("%s", pPrefix); + ::printf(m_crlf ? "%s\n" : "%s", buf); } if ((type != cProgressConsoleMessage) && (m_pLog_stream)) { // Yes this is bad. - dynamic_wstring utf16_buf(buf); + dynamic_string tmp_buf(buf); - dynamic_string ansi_buf; - utf16_buf.as_ansi(ansi_buf); - ansi_buf.translate_lf_to_crlf(); + tmp_buf.translate_lf_to_crlf(); - m_pLog_stream->printf(m_crlf ? "%s\r\n" : "%s", ansi_buf.get_ptr()); + m_pLog_stream->printf(m_crlf ? "%s\r\n" : "%s", tmp_buf.get_ptr()); m_pLog_stream->flush(); } } - void console::printf(eConsoleMessageType type, const wchar_t* p, ...) + void console::printf(eConsoleMessageType type, const char* p, ...) { va_list args; va_start(args, p); @@ -121,7 +108,7 @@ namespace crnlib va_end(args); } - void console::printf(const wchar_t* p, ...) + void console::printf(const char* p, ...) { va_list args; va_start(args, p); @@ -172,7 +159,7 @@ namespace crnlib } } - void console::progress(const wchar_t* p, ...) + void console::progress(const char* p, ...) { va_list args; va_start(args, p); @@ -180,7 +167,7 @@ namespace crnlib va_end(args); } - void console::info(const wchar_t* p, ...) + void console::info(const char* p, ...) { va_list args; va_start(args, p); @@ -188,7 +175,7 @@ namespace crnlib va_end(args); } - void console::message(const wchar_t* p, ...) + void console::message(const char* p, ...) { va_list args; va_start(args, p); @@ -196,7 +183,7 @@ namespace crnlib va_end(args); } - void console::cons(const wchar_t* p, ...) + void console::cons(const char* p, ...) { va_list args; va_start(args, p); @@ -204,7 +191,7 @@ namespace crnlib va_end(args); } - void console::debug(const wchar_t* p, ...) + void console::debug(const char* p, ...) { va_list args; va_start(args, p); @@ -212,7 +199,7 @@ namespace crnlib va_end(args); } - void console::warning(const wchar_t* p, ...) + void console::warning(const char* p, ...) { va_list args; va_start(args, p); @@ -220,7 +207,7 @@ namespace crnlib va_end(args); } - void console::error(const wchar_t* p, ...) + void console::error(const char* p, ...) { va_list args; va_start(args, p); diff --git a/crnlib/crn_console.h b/crnlib/crn_console.h index 3a44bd3..1039680 100644 --- a/crnlib/crn_console.h +++ b/crnlib/crn_console.h @@ -3,92 +3,123 @@ #pragma once #include "crn_dynamic_string.h" +#ifdef WIN32 +#include +#include +#endif namespace crnlib { class dynamic_string; class data_stream; class mutex; - + enum eConsoleMessageType { cDebugConsoleMessage, // debugging messages cProgressConsoleMessage, // progress messages - cInfoConsoleMessage, // ordinary messages + cInfoConsoleMessage, // ordinary messages cConsoleConsoleMessage, // user console output cMessageConsoleMessage, // high importance messages cWarningConsoleMessage, // warnings cErrorConsoleMessage, // errors - + cCMTTotal }; - - typedef bool (*console_output_func)(eConsoleMessageType type, const wchar_t* pMsg, void* pData); - - class console + + typedef bool (*console_output_func)(eConsoleMessageType type, const char* pMsg, void* pData); + + class console { public: static void init(); static void deinit(); static bool is_initialized() { return m_pMutex != NULL; } - + static void set_default_category(eConsoleMessageType category); static eConsoleMessageType get_default_category(); static void add_console_output_func(console_output_func pFunc, void* pData); static void remove_console_output_func(console_output_func pFunc); - - static void printf(const wchar_t* p, ...); - - static void vprintf(eConsoleMessageType type, const wchar_t* p, va_list args); - static void printf(eConsoleMessageType type, const wchar_t* p, ...); - - static void cons(const wchar_t* p, ...); - static void debug(const wchar_t* p, ...); - static void progress(const wchar_t* p, ...); - static void info(const wchar_t* p, ...); - static void message(const wchar_t* p, ...); - static void warning(const wchar_t* p, ...); - static void error(const wchar_t* p, ...); + + static void printf(const char* p, ...); + + static void vprintf(eConsoleMessageType type, const char* p, va_list args); + static void printf(eConsoleMessageType type, const char* p, ...); + + static void cons(const char* p, ...); + static void debug(const char* p, ...); + static void progress(const char* p, ...); + static void info(const char* p, ...); + static void message(const char* p, ...); + static void warning(const char* p, ...); + static void error(const char* p, ...); // FIXME: All console state is currently global! static void disable_prefixes(); static void enable_prefixes(); static bool get_prefixes() { return m_prefixes; } - + static void disable_crlf(); static void enable_crlf(); static bool get_crlf() { return m_crlf; } - + static void disable_output() { m_output_disabled = true; } static void enable_output() { m_output_disabled = false; } static bool get_output_disabled() { return m_output_disabled; } - + static void set_log_stream(data_stream* pStream) { m_pLog_stream = pStream; } static data_stream* get_log_stream() { return m_pLog_stream; } - + static uint get_num_messages(eConsoleMessageType type) { return m_num_messages[type]; } - - private: + + private: static eConsoleMessageType m_default_category; - - struct console_func + + struct console_func { console_func(console_output_func func = NULL, void* pData = NULL) : m_func(func), m_pData(pData) { } - + console_output_func m_func; void* m_pData; }; static crnlib::vector m_output_funcs; - + static bool m_crlf, m_prefixes, m_output_disabled; - + static data_stream* m_pLog_stream; - + static mutex* m_pMutex; - + static uint m_num_messages[cCMTTotal]; }; +#if defined(WIN32) + inline int crn_getch() + { + return _getch(); + } +#elif defined(__GNUC__) + #include + #include + inline int crn_getch() + { + struct termios oldt, newt; + int ch; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + ch = getchar(); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return ch; + } +#else + inline int crn_getch() + { + printf("crn_getch: Unimplemented"); + return 0; + } +#endif } // namespace crnlib diff --git a/crnlib/crn_core.cpp b/crnlib/crn_core.cpp index d0b18da..d2d9a1d 100644 --- a/crnlib/crn_core.cpp +++ b/crnlib/crn_core.cpp @@ -1,7 +1,14 @@ // File: crn_core.cpp // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" -#include "crn_winhdr.h" -char *g_copyright_str = "Copyright (c) 2010-2012 Rich Geldreich and Tenacious Software LLC"; -char *g_sig_str = "C8cfRlaorj0wLtnMSxrBJxTC85rho2L9hUZKHcBL"; +#if CRNLIB_USE_WIN32_API +#include "crn_winhdr.h" +#endif + +namespace crnlib +{ + const char *g_copyright_str = "Copyright (c) 2010-2012 Rich Geldreich and Tenacious Software LLC"; + const char *g_sig_str = "C8cfRlaorj0wLtnMSxrBJxTC85rho2L9hUZKHcBL"; + +} // namespace crnlib diff --git a/crnlib/crn_core.h b/crnlib/crn_core.h index f92c919..91a23b9 100644 --- a/crnlib/crn_core.h +++ b/crnlib/crn_core.h @@ -6,38 +6,34 @@ #pragma warning (disable: 4201) // nonstandard extension used : nameless struct/union #pragma warning (disable: 4127) // conditional expression is constant #pragma warning (disable: 4793) // function compiled as native + #pragma warning (disable: 4324) // structure was padded due to __declspec(align()) #endif -#if defined(WIN32) - -#if 0 +#if defined(WIN32) && !defined(CRNLIB_ANSI_CPLUSPLUS) + // MSVC or MinGW, x86 or x64, Win32 API's for threading and Win32 Interlocked API's or GCC built-ins for atomic ops. #ifdef NDEBUG // Ensure checked iterators are disabled. #define _SECURE_SCL 0 #define _HAS_ITERATOR_DEBUGGING 0 #endif - #ifndef _DLL // If we're using the DLL form of the run-time libs, we're also going to be enabling exceptions because we'll be building CLR apps. - // Otherwise, we disable exceptions for a small (up to 5%) speed boost. + // Otherwise, we disable exceptions for a small speed boost. #define _HAS_EXCEPTIONS 0 #endif -#endif - - //#define _CRT_SECURE_NO_WARNINGS #define NOMINMAX - #define CRNLIB_PLATFORM_PC 1 - - #ifdef _WIN64 - #define CRNLIB_PLATFORM_PC_X64 1 - #else - #define CRNLIB_PLATFORM_PC_X86 1 - #endif - #define CRNLIB_USE_WIN32_API 1 - #ifdef _WIN64 + #if defined(__MINGW32__) || defined(__MINGW64__) + #define CRNLIB_USE_GCC_ATOMIC_BUILTINS 1 + #else + #define CRNLIB_USE_WIN32_ATOMIC_FUNCTIONS 1 + #endif + + #define CRNLIB_PLATFORM_PC 1 + + #if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) #define CRNLIB_PLATFORM_PC_X64 1 #define CRNLIB_64BIT_POINTERS 1 #define CRNLIB_CPU_HAS_64BIT_REGISTERS 1 @@ -48,15 +44,99 @@ #define CRNLIB_CPU_HAS_64BIT_REGISTERS 0 #define CRNLIB_LITTLE_ENDIAN_CPU 1 #endif + + #define CRNLIB_USE_UNALIGNED_INT_LOADS 1 + #define CRNLIB_RESTRICT __restrict + #define CRNLIB_FORCE_INLINE __forceinline + + #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) + #define CRNLIB_USE_MSVC_INTRINSICS 1 + #endif + + #define CRNLIB_INT64_FORMAT_SPECIFIER "%I64i" + #define CRNLIB_UINT64_FORMAT_SPECIFIER "%I64u" + + #define CRNLIB_STDCALL __stdcall + #define CRNLIB_MEMORY_IMPORT_BARRIER + #define CRNLIB_MEMORY_EXPORT_BARRIER +#elif defined(__GNUC__) && !defined(CRNLIB_ANSI_CPLUSPLUS) + // GCC x86 or x64, pthreads for threading and GCC built-ins for atomic ops. + #define CRNLIB_PLATFORM_PC 1 + + #if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) + #define CRNLIB_PLATFORM_PC_X64 1 + #define CRNLIB_64BIT_POINTERS 1 + #define CRNLIB_CPU_HAS_64BIT_REGISTERS 1 + #else + #define CRNLIB_PLATFORM_PC_X86 1 + #define CRNLIB_64BIT_POINTERS 0 + #define CRNLIB_CPU_HAS_64BIT_REGISTERS 0 + #endif + + #define CRNLIB_USE_UNALIGNED_INT_LOADS 1 + + #define CRNLIB_LITTLE_ENDIAN_CPU 1 + + #define CRNLIB_USE_PTHREADS_API 1 + #define CRNLIB_USE_GCC_ATOMIC_BUILTINS 1 + + #define CRNLIB_RESTRICT + + #define CRNLIB_FORCE_INLINE inline __attribute__((__always_inline__,__gnu_inline__)) + + #define CRNLIB_INT64_FORMAT_SPECIFIER "%lli" + #define CRNLIB_UINT64_FORMAT_SPECIFIER "%llu" + + #define CRNLIB_STDCALL + #define CRNLIB_MEMORY_IMPORT_BARRIER + #define CRNLIB_MEMORY_EXPORT_BARRIER +#else + // Vanilla ANSI-C/C++ + // No threading support, unaligned loads are NOT okay. + #if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) + #define CRNLIB_64BIT_POINTERS 1 + #define CRNLIB_CPU_HAS_64BIT_REGISTERS 1 + #else + #define CRNLIB_64BIT_POINTERS 0 + #define CRNLIB_CPU_HAS_64BIT_REGISTERS 0 + #endif + + #define CRNLIB_USE_UNALIGNED_INT_LOADS 0 + + #if __BIG_ENDIAN__ + #define CRNLIB_BIG_ENDIAN_CPU 1 + #else + #define CRNLIB_LITTLE_ENDIAN_CPU 1 + #endif + + #define CRNLIB_USE_GCC_ATOMIC_BUILTINS 0 + #define CRNLIB_USE_WIN32_ATOMIC_FUNCTIONS 0 + + #define CRNLIB_RESTRICT + #define CRNLIB_FORCE_INLINE inline + + #define CRNLIB_INT64_FORMAT_SPECIFIER "%I64i" + #define CRNLIB_UINT64_FORMAT_SPECIFIER "%I64u" + + #define CRNLIB_STDCALL + #define CRNLIB_MEMORY_IMPORT_BARRIER + #define CRNLIB_MEMORY_EXPORT_BARRIER #endif +#define CRNLIB_SLOW_STRING_LEN_CHECKS 1 + #include +#include #include #include #include #include #include #include +#include +#include +#include +#include #ifdef min #undef min @@ -78,16 +158,15 @@ #ifndef NDEBUG #define NDEBUG #endif + + #ifdef DEBUG + #error DEBUG cannot be defined in CRNLIB_BUILD_RELEASE + #endif #endif -#include "crn_platform.h" - -#if defined(WIN32) - #include "crn_mutex.h" -#endif - -#include "crn_assert.h" #include "crn_types.h" +#include "crn_assert.h" +#include "crn_platform.h" #include "crn_helpers.h" #include "crn_traits.h" #include "crn_mem.h" @@ -95,9 +174,5 @@ #include "crn_utils.h" #include "crn_hash.h" #include "crn_vector.h" -#include "crn_win32_timer.h" -#include "crn_win32_threading.h" +#include "crn_timer.h" #include "crn_dynamic_string.h" -#include "crn_dynamic_wstring.h" - - diff --git a/crnlib/crn_data_stream.cpp b/crnlib/crn_data_stream.cpp index 036cb26..538085e 100644 --- a/crnlib/crn_data_stream.cpp +++ b/crnlib/crn_data_stream.cpp @@ -2,7 +2,6 @@ // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" #include "crn_data_stream.h" -#include namespace crnlib { @@ -12,7 +11,7 @@ namespace crnlib { } - data_stream::data_stream(const wchar_t* pName, uint attribs) : + data_stream::data_stream(const char* pName, uint attribs) : m_name(pName), m_attribs(static_cast(attribs)), m_opened(false), m_error(false), m_got_cr(false) @@ -85,28 +84,11 @@ namespace crnlib va_list args; va_start(args, p); - char buf[4096]; -#ifdef _MSC_VER - int l = vsprintf_s(buf, sizeof(buf), p, args); -#else - int l = vsprintf(buf, p, args); -#endif - va_end(args); - if (l < 0) - return false; - return write(buf, l) == static_cast(l); - } - - bool data_stream::printf(const wchar_t* p, ...) - { - va_list args; - - va_start(args, p); - dynamic_wstring buf; + dynamic_string buf; buf.format_args(p, args); va_end(args); - return write(buf.get_ptr(), buf.get_len() * sizeof(wchar_t)) == buf.get_len() * sizeof(wchar_t); + return write(buf.get_ptr(), buf.get_len() * sizeof(char)) == buf.get_len() * sizeof(char); } bool data_stream::write_line(const dynamic_string& str) @@ -117,14 +99,6 @@ namespace crnlib return true; } - bool data_stream::write_line(const dynamic_wstring& str) - { - if (!str.is_empty()) - return write(str.get_ptr(), str.get_len() * sizeof(wchar_t)) == str.get_len() * sizeof(wchar_t); - - return true; - } - bool data_stream::read_array(vector& buf) { if (buf.size() < get_remaining()) diff --git a/crnlib/crn_data_stream.h b/crnlib/crn_data_stream.h index aa8c96d..aa6d756 100644 --- a/crnlib/crn_data_stream.h +++ b/crnlib/crn_data_stream.h @@ -10,82 +10,80 @@ namespace crnlib cDataStreamWritable = 2, cDataStreamSeekable = 4 }; - - const int64 DATA_STREAM_SIZE_UNKNOWN = INT64_MAX; - const int64 DATA_STREAM_SIZE_INFINITE = UINT64_MAX; - + + const int64 DATA_STREAM_SIZE_UNKNOWN = cINT64_MAX; + const int64 DATA_STREAM_SIZE_INFINITE = cUINT64_MAX; + class data_stream { data_stream(const data_stream&); data_stream& operator= (const data_stream&); - + public: data_stream(); - data_stream(const wchar_t* pName, uint attribs); - + data_stream(const char* pName, uint attribs); + virtual ~data_stream() { } - + virtual data_stream *get_parent() { return NULL; } - + virtual bool close() { m_opened = false; m_error = false; m_got_cr = false; return true; } - typedef uint16 attribs_t; + typedef uint16 attribs_t; inline attribs_t get_attribs() const { return m_attribs; } - + inline bool is_opened() const { return m_opened; } - + inline bool is_readable() const { return utils::is_bit_set(m_attribs, cDataStreamReadable); } inline bool is_writable() const { return utils::is_bit_set(m_attribs, cDataStreamWritable); } inline bool is_seekable() const { return utils::is_bit_set(m_attribs, cDataStreamSeekable); } - + inline bool get_error() const { return m_error; } - - inline const dynamic_wstring& get_name() const { return m_name; } - inline void set_name(const wchar_t* pName) { m_name.set(pName); } - + + inline const dynamic_string& get_name() const { return m_name; } + inline void set_name(const char* pName) { m_name.set(pName); } + virtual uint read(void* pBuf, uint len) = 0; virtual uint64 skip(uint64 len); - + virtual uint write(const void* pBuf, uint len) = 0; virtual bool flush() = 0; - + virtual bool is_size_known() const { return true; } - + // Returns DATA_STREAM_SIZE_UNKNOWN if size hasn't been determined yet, or DATA_STREAM_SIZE_INFINITE for infinite streams. virtual uint64 get_size() = 0; virtual uint64 get_remaining() = 0; - + virtual uint64 get_ofs() = 0; virtual bool seek(int64 ofs, bool relative) = 0; - + virtual const void* get_ptr() const { return NULL; } - + inline int read_byte() { uint8 c; if (read(&c, 1) != 1) return -1; return c; } inline bool write_byte(uint8 c) { return write(&c, 1) == 1; } - + bool read_line(dynamic_string& str); bool printf(const char* p, ...); - bool printf(const wchar_t* p, ...); bool write_line(const dynamic_string& str); - bool write_line(const dynamic_wstring& str); bool write_bom() { uint16 bom = 0xFEFF; return write(&bom, sizeof(bom)) == sizeof(bom); } - + bool read_array(vector& buf); bool write_array(const vector& buf); - + protected: - dynamic_wstring m_name; - + dynamic_string m_name; + attribs_t m_attribs; bool m_opened : 1; bool m_error : 1; bool m_got_cr : 1; - + inline void set_error() { m_error = true; } inline void clear_error() { m_error = false; } - + inline void post_seek() { m_got_cr = false; } }; - + } // namespace crnlib diff --git a/crnlib/crn_dds_comp.h b/crnlib/crn_dds_comp.h index dc67145..9a8993c 100644 --- a/crnlib/crn_dds_comp.h +++ b/crnlib/crn_dds_comp.h @@ -15,7 +15,7 @@ namespace crnlib dds_comp(); virtual ~dds_comp(); - virtual const wchar_t *get_ext() const { return L"DDS"; } + virtual const char *get_ext() const { return "DDS"; } virtual bool compress_init(const crn_comp_params& params); virtual bool compress_pass(const crn_comp_params& params, float *pEffective_bitrate); @@ -23,7 +23,7 @@ namespace crnlib virtual const crnlib::vector& get_comp_data() const { return m_comp_data; } virtual crnlib::vector& get_comp_data() { return m_comp_data; } - + private: dds_texture m_src_tex; dds_texture m_packed_tex; @@ -31,7 +31,7 @@ namespace crnlib crnlib::vector m_comp_data; const crn_comp_params* m_pParams; - + pixel_format m_pixel_fmt; dxt_image::pack_params m_pack_params; @@ -39,7 +39,7 @@ namespace crnlib qdxt1_params m_q1_params; qdxt5_params m_q5_params; dds_texture::qdxt_state *m_pQDXT_state; - + void clear(); bool create_dds_tex(dds_texture &dds_tex); bool convert_to_dxt(const crn_comp_params& params); diff --git a/crnlib/crn_dds_texture.cpp b/crnlib/crn_dds_texture.cpp index 1e7a7e5..f8e43c2 100644 --- a/crnlib/crn_dds_texture.cpp +++ b/crnlib/crn_dds_texture.cpp @@ -216,7 +216,7 @@ namespace crnlib if (m_pImage->is_grayscale()) m_format = m_pImage->has_alpha() ? PIXEL_FMT_A8L8 : PIXEL_FMT_L8; - else + else m_format = m_pImage->has_alpha() ? PIXEL_FMT_A8R8G8B8 : PIXEL_FMT_R8G8B8; return true; @@ -380,7 +380,7 @@ namespace crnlib return *this; } - bool dds_texture::write_dds(const wchar_t* pFilename) const + bool dds_texture::write_dds(const char* pFilename) const { cfile_stream out_stream(pFilename, cDataStreamWritable | cDataStreamSeekable); if (!out_stream.is_opened()) @@ -390,7 +390,7 @@ namespace crnlib return write_dds(out_serializer); } - bool dds_texture::read_dds(const wchar_t* pFilename) + bool dds_texture::read_dds(const char* pFilename) { cfile_stream in_stream(pFilename); if (!in_stream.is_opened()) @@ -417,7 +417,7 @@ namespace crnlib clear(); - set_last_error(L"Not a DDS file"); + set_last_error("Not a DDS file"); uint8 hdr[4]; if (!serializer.read(hdr, sizeof(hdr))) @@ -460,7 +460,7 @@ namespace crnlib const uint all_faces_mask = DDSCAPS2_CUBEMAP_POSITIVEX|DDSCAPS2_CUBEMAP_NEGATIVEX|DDSCAPS2_CUBEMAP_POSITIVEY|DDSCAPS2_CUBEMAP_NEGATIVEY|DDSCAPS2_CUBEMAP_POSITIVEZ|DDSCAPS2_CUBEMAP_NEGATIVEZ; if ((desc.ddsCaps.dwCaps2 & all_faces_mask) != all_faces_mask) { - set_last_error(L"Incomplete cubemaps unsupported"); + set_last_error("Incomplete cubemaps unsupported"); return false; } @@ -468,7 +468,7 @@ namespace crnlib } else if (desc.ddsCaps.dwCaps2 & DDSCAPS2_VOLUME) { - set_last_error(L"Volume textures unsupported"); + set_last_error("Volume textures unsupported"); return false; } } @@ -479,7 +479,7 @@ namespace crnlib // nvdxt just hangs // dxtex.exe just makes all-white textures // So screw it. - set_last_error(L"Palettized textures unsupported"); + set_last_error("Palettized textures unsupported"); return false; } @@ -555,7 +555,7 @@ namespace crnlib } default: { - dynamic_wstring err_msg(cVarArg, L"Unsupported DDS FOURCC format: 0x%08X", desc.ddpfPixelFormat.dwFourCC); + dynamic_string err_msg(cVarArg, "Unsupported DDS FOURCC format: 0x%08X", desc.ddpfPixelFormat.dwFourCC); set_last_error(err_msg.get_ptr()); return false; } @@ -563,7 +563,7 @@ namespace crnlib } else if ((desc.ddpfPixelFormat.dwRGBBitCount < 8) || (desc.ddpfPixelFormat.dwRGBBitCount > 32) || (desc.ddpfPixelFormat.dwRGBBitCount & 7)) { - set_last_error(L"Unsupported bit count"); + set_last_error("Unsupported bit count"); return false; } else if (desc.ddpfPixelFormat.dwFlags & DDPF_RGB) @@ -597,7 +597,7 @@ namespace crnlib } else { - set_last_error(L"Unsupported format"); + set_last_error("Unsupported format"); return false; } @@ -609,7 +609,7 @@ namespace crnlib //bits_per_pixel = ((m_format == PIXEL_FMT_DXT1) || (m_format == PIXEL_FMT_DXT5A)) ? 4 : 8; bits_per_pixel = pixel_format_helpers::get_bpp(m_format); - set_last_error(L"Load failed"); + set_last_error("Load failed"); uint default_pitch; if (desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC) @@ -620,19 +620,19 @@ namespace crnlib uint pitch = desc.lPitch; if (!pitch) pitch = default_pitch; -#if 0 +#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."); + console::warning("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"); + set_last_error("Invalid pitch"); return false; } @@ -869,11 +869,11 @@ namespace crnlib { if (!m_width) { - set_last_error(L"Nothing to write"); + set_last_error("Nothing to write"); return false; } - set_last_error(L"Write_dds() failed"); + set_last_error("Write_dds() failed"); if (!serializer.write("DDS ", sizeof(uint32))) return false; @@ -1017,7 +1017,7 @@ namespace crnlib desc.lPitch = (desc.dwWidth * bits_per_pixel) >> 3; desc.dwFlags |= DDSD_LINEARSIZE; } - + if (!c_crnlib_little_endian_platform) utils::endian_switch_dwords(reinterpret_cast(&desc), sizeof(desc) / sizeof(uint32)); @@ -1257,7 +1257,7 @@ namespace crnlib CRNLIB_ASSERT(check()); } - void dds_texture::init(uint width, uint height, uint levels, uint faces, pixel_format fmt, const wchar_t* pName) + void dds_texture::init(uint width, uint height, uint levels, uint faces, pixel_format fmt, const char* pName) { clear(); @@ -2029,7 +2029,7 @@ namespace crnlib { dxt1_blocks.resize(state.m_pixel_blocks.size()); float pow_mul = 1.0f; - + if (state.m_fmt == PIXEL_FMT_DXT5_CCxY) { // use a "deeper" codebook size curves when compressing chroma into DXT1, because it's not as important @@ -2099,7 +2099,7 @@ namespace crnlib return true; } - bool dds_texture::load_from_file(const wchar_t* pFilename, texture_file_types::format file_format) + bool dds_texture::load_from_file(const char* pFilename, texture_file_types::format file_format) { clear(); @@ -2108,11 +2108,11 @@ namespace crnlib if (file_format == texture_file_types::cFormatInvalid) { - set_last_error(L"Unrecognized image format extension"); + set_last_error("Unrecognized image format extension"); return false; } - set_last_error(L"Image file load failed"); + set_last_error("Image file load failed"); bool success = false; switch (file_format) @@ -2143,7 +2143,7 @@ namespace crnlib return success; } - bool dds_texture::load_regular(const wchar_t* pFilename, texture_file_types::format file_format) + bool dds_texture::load_regular(const char* pFilename, texture_file_types::format file_format) { file_format; @@ -2153,7 +2153,7 @@ namespace crnlib { crnlib_delete(pImg); - set_last_error(L"Failed loading image file"); + set_last_error("Failed loading image file"); return false; } @@ -2166,12 +2166,12 @@ namespace crnlib return true; } - bool dds_texture::load_dds(const wchar_t* pFilename) + bool dds_texture::load_dds(const char* pFilename) { cfile_stream in_stream; if (!in_stream.open(pFilename)) { - set_last_error(L"Failed opening file"); + set_last_error("Failed opening file"); return false; } @@ -2188,11 +2188,11 @@ namespace crnlib return true; } - bool dds_texture::load_crn_from_memory(const wchar_t* pFilename, const void *pData, uint data_size) + bool dds_texture::load_crn_from_memory(const char* pFilename, const void *pData, uint data_size) { clear(); - set_last_error(L"Image file load failed"); + set_last_error("Image file load failed"); if ((!pData) || (data_size < 1)) return false; @@ -2200,14 +2200,14 @@ namespace crnlib tex_info.m_struct_size = sizeof(crnd::crn_texture_info); if (!crnd_get_texture_info(pData, data_size, &tex_info)) { - set_last_error(L"crnd_get_texture_info() failed"); + set_last_error("crnd_get_texture_info() failed"); return false; } const pixel_format dds_fmt = (pixel_format)crnd::crnd_crn_format_to_fourcc(tex_info.m_format); if (dds_fmt == PIXEL_FMT_INVALID) { - set_last_error(L"Unsupported DXT format"); + set_last_error("Unsupported DXT format"); return false; } @@ -2229,7 +2229,7 @@ namespace crnlib // Create temp buffer big enough to hold the largest mip level, and all faces if it's a cubemap. dxt_data.resize(tex_info.m_bytes_per_block * tex_num_blocks_x * tex_num_blocks_y * tex_info.m_faces); - set_last_error(L"CRN unpack failed"); + set_last_error("CRN unpack failed"); timer t; double total_time = 0.0f; @@ -2305,7 +2305,7 @@ namespace crnlib #if 0 if (total_pixels) { - console::info(L"load_crn: Total pixels: %u, ms: %3.3fms, megapixels/sec: %3.3f", + console::info("load_crn: Total pixels: %u, ms: %3.3fms, megapixels/sec: %3.3f", total_pixels, total_time * 1000.0f, total_pixels / total_time); } #endif @@ -2321,19 +2321,19 @@ namespace crnlib return true; } - bool dds_texture::load_crn(const wchar_t* pFilename) + bool dds_texture::load_crn(const char* pFilename) { cfile_stream in_stream; if (!in_stream.open(pFilename)) { - set_last_error(L"Failed opening CRN file"); + set_last_error("Failed opening CRN file"); return false; } crnlib::vector crn_data; if (!in_stream.read_array(crn_data)) { - set_last_error(L"Failed reading CRN file"); + set_last_error("Failed reading CRN file"); return false; } @@ -2343,7 +2343,7 @@ namespace crnlib } bool dds_texture::write_to_file( - const wchar_t* pFilename, + const char* pFilename, texture_file_types::format file_format, crn_comp_params* pCRN_comp_params, uint32 *pActual_quality_level, float *pActual_bitrate) @@ -2353,7 +2353,7 @@ namespace crnlib if (!is_valid()) { - set_last_error(L"Unable to save empty texture"); + set_last_error("Unable to save empty texture"); return false; } @@ -2386,26 +2386,26 @@ namespace crnlib return success; } - bool dds_texture::save_regular(const wchar_t* pFilename) + bool dds_texture::save_regular(const char* pFilename) { image_u8 tmp; image_u8* pLevel_image = get_level_image(0, 0, tmp); if (!image_utils::save_to_file(pFilename, *pLevel_image, 0)) { - set_last_error(L"File write failed"); + set_last_error("File write failed"); return false; } return true; } - bool dds_texture::save_dds(const wchar_t* pFilename) + bool dds_texture::save_dds(const char* pFilename) { cfile_stream out_stream; if (!out_stream.open(pFilename, cDataStreamWritable | cDataStreamSeekable)) { - set_last_error(L"Unable to open file"); + set_last_error("Unable to open file"); return false; } @@ -2413,7 +2413,7 @@ namespace crnlib if (!write_dds(serializer)) { - set_last_error(L"File write failed"); + set_last_error("File write failed"); return false; } @@ -2422,34 +2422,34 @@ namespace crnlib void dds_texture::print_crn_comp_params(const crn_comp_params& p) { - console::debug(L"CRN compression params:"); - console::debug(L" File Type: %s", crn_get_file_type_ext(p.m_file_type)); - console::debug(L" Quality level: %u", p.m_quality_level); - console::debug(L" Target Bitrate: %f", p.m_target_bitrate); - console::debug(L" Faces: %u", p.m_faces); - console::debug(L" Width: %u", p.m_width); - console::debug(L" Height: %u", p.m_height); - console::debug(L" Levels: %u", p.m_levels); - console::debug(L" Pixel Format: %s", crn_get_format_string(p.m_format)); - console::debug(L"Use manual CRN palette sizes: %u", p.get_flag(cCRNCompFlagManualPaletteSizes)); - console::debug(L"Color endpoints: %u", p.m_crn_color_endpoint_palette_size); - console::debug(L"Color selectors: %u", p.m_crn_color_selector_palette_size); - console::debug(L"Alpha endpoints: %u", p.m_crn_alpha_endpoint_palette_size); - console::debug(L"Alpha selectors: %u", p.m_crn_alpha_selector_palette_size); - console::debug(L"Flags:"); - console::debug(L" Perceptual: %u", p.get_flag(cCRNCompFlagPerceptual)); - console::debug(L" Hierarchical: %u", p.get_flag(cCRNCompFlagHierarchical)); - console::debug(L" UseBothBlockTypes: %u", p.get_flag(cCRNCompFlagUseBothBlockTypes)); - console::debug(L" UseTransparentIndicesForBlack: %u", p.get_flag(cCRNCompFlagUseTransparentIndicesForBlack)); - console::debug(L" DisableEndpointCaching: %u", p.get_flag(cCRNCompFlagDisableEndpointCaching)); - console::debug(L"GrayscaleSampling: %u", p.get_flag(cCRNCompFlagGrayscaleSampling)); - console::debug(L" UseDXT1ATransparency: %u", p.get_flag(cCRNCompFlagDXT1AForTransparency)); - console::debug(L"AdaptiveTileColorPSNRDerating: %2.2fdB", p.m_crn_adaptive_tile_color_psnr_derating); - console::debug(L"AdaptiveTileAlphaPSNRDerating: %2.2fdB", p.m_crn_adaptive_tile_alpha_psnr_derating); - console::debug(L"NumHelperThreads: %u", p.m_num_helper_threads); + console::debug("CRN compression params:"); + console::debug(" File Type: %s", crn_get_file_type_ext(p.m_file_type)); + console::debug(" Quality level: %u", p.m_quality_level); + console::debug(" Target Bitrate: %f", p.m_target_bitrate); + console::debug(" Faces: %u", p.m_faces); + console::debug(" Width: %u", p.m_width); + console::debug(" Height: %u", p.m_height); + console::debug(" Levels: %u", p.m_levels); + console::debug(" Pixel Format: %s", crn_get_format_string(p.m_format)); + console::debug("Use manual CRN palette sizes: %u", p.get_flag(cCRNCompFlagManualPaletteSizes)); + console::debug("Color endpoints: %u", p.m_crn_color_endpoint_palette_size); + console::debug("Color selectors: %u", p.m_crn_color_selector_palette_size); + console::debug("Alpha endpoints: %u", p.m_crn_alpha_endpoint_palette_size); + console::debug("Alpha selectors: %u", p.m_crn_alpha_selector_palette_size); + console::debug("Flags:"); + console::debug(" Perceptual: %u", p.get_flag(cCRNCompFlagPerceptual)); + console::debug(" Hierarchical: %u", p.get_flag(cCRNCompFlagHierarchical)); + console::debug(" UseBothBlockTypes: %u", p.get_flag(cCRNCompFlagUseBothBlockTypes)); + console::debug(" UseTransparentIndicesForBlack: %u", p.get_flag(cCRNCompFlagUseTransparentIndicesForBlack)); + console::debug(" DisableEndpointCaching: %u", p.get_flag(cCRNCompFlagDisableEndpointCaching)); + console::debug("GrayscaleSampling: %u", p.get_flag(cCRNCompFlagGrayscaleSampling)); + console::debug(" UseDXT1ATransparency: %u", p.get_flag(cCRNCompFlagDXT1AForTransparency)); + console::debug("AdaptiveTileColorPSNRDerating: %2.2fdB", p.m_crn_adaptive_tile_color_psnr_derating); + console::debug("AdaptiveTileAlphaPSNRDerating: %2.2fdB", p.m_crn_adaptive_tile_alpha_psnr_derating); + console::debug("NumHelperThreads: %u", p.m_num_helper_threads); } - bool dds_texture::save_comp_texture(const wchar_t* pFilename, const crn_comp_params &orig_comp_params, uint32 *pActual_quality_level, float *pActual_bitrate) + bool dds_texture::save_comp_texture(const char* pFilename, const crn_comp_params &orig_comp_params, uint32 *pActual_quality_level, float *pActual_bitrate) { crn_comp_params comp_params(orig_comp_params); @@ -2458,7 +2458,7 @@ namespace crnlib if (math::maximum(get_height(), get_width()) > cCRNMaxLevelResolution) { - set_last_error(L"Texture resolution is too big!"); + set_last_error("Texture resolution is too big!"); return false; } @@ -2487,32 +2487,32 @@ namespace crnlib crnlib::vector comp_data; if (!create_compressed_texture(comp_params, comp_data, pActual_quality_level, pActual_bitrate)) { - set_last_error(L"CRN compression failed"); + set_last_error("CRN compression failed"); return false; } double total_time = t.get_elapsed_secs(); if (comp_params.get_flag(cCRNCompFlagDebugging)) { - console::debug(L"\nTotal compression time: %3.3fs", total_time); + console::debug("\nTotal compression time: %3.3fs", total_time); } cfile_stream out_stream; if (!out_stream.open(pFilename, cDataStreamWritable | cDataStreamSeekable)) { - set_last_error(L"Failed opening file"); + set_last_error("Failed opening file"); return false; } if (out_stream.write(comp_data.get_ptr(), comp_data.size()) != comp_data.size()) { - set_last_error(L"Failed writing to file"); + set_last_error("Failed writing to file"); return false; } if (!out_stream.close()) { - set_last_error(L"Failed writing to file"); + set_last_error("Failed writing to file"); return false; } diff --git a/crnlib/crn_dds_texture.h b/crnlib/crn_dds_texture.h index ebe0187..f372b63 100644 --- a/crnlib/crn_dds_texture.h +++ b/crnlib/crn_dds_texture.h @@ -15,7 +15,7 @@ namespace crnlib { extern const vec2I g_vertical_cross_image_offsets[6]; - + class mip_level { friend class dds_texture; @@ -23,29 +23,29 @@ namespace crnlib public: mip_level(); ~mip_level(); - + mip_level(const mip_level& other); mip_level& operator= (const mip_level& rhs); - + // Assumes ownership. void assign(image_u8* p, pixel_format fmt = PIXEL_FMT_INVALID); void assign(dxt_image* p, pixel_format fmt = PIXEL_FMT_INVALID); - + void clear(); - + inline uint get_width() const { return m_width; } inline uint get_height() const { return m_height; } inline uint get_total_pixels() const { return m_width * m_height; } inline image_u8* get_image() const { return m_pImage; } inline dxt_image* get_dxt_image() const { return m_pDXTImage; } - + image_u8* get_unpacked_image(image_u8& tmp, bool uncook) const; - + inline bool is_packed() const { return m_pDXTImage != NULL; } - + inline bool is_valid() const { return (m_pImage != NULL) || (m_pDXTImage != NULL); } - + inline pixel_format_helpers::component_flags get_comp_flags() const { return m_comp_flags; } inline void set_comp_flags(pixel_format_helpers::component_flags comp_flags) { m_comp_flags = comp_flags; } @@ -53,35 +53,35 @@ namespace crnlib inline void set_format(pixel_format fmt) { m_format = fmt; } bool convert(pixel_format fmt, bool cook, const dxt_image::pack_params& p); - + bool pack_to_dxt(const image_u8& img, pixel_format fmt, bool cook, const dxt_image::pack_params& p); - bool pack_to_dxt(pixel_format fmt, bool cook, const dxt_image::pack_params& p); - + bool pack_to_dxt(pixel_format fmt, bool cook, const dxt_image::pack_params& p); + bool unpack_from_dxt(bool uncook = true); - + bool set_alpha_to_luma(); bool convert(image_utils::conversion_type conv_type); - + private: uint m_width; uint m_height; - + pixel_format_helpers::component_flags m_comp_flags; pixel_format m_format; - + image_u8* m_pImage; dxt_image* m_pDXTImage; - + void cook_image(image_u8& img) const; void uncook_image(image_u8& img) const; }; - + // A face is an array of mip_level ptr's. typedef crnlib::vector mip_ptr_vec; - + // And an array of one, six, or N faces make up a texture. typedef crnlib::vector face_vec; - + class dds_texture { public: @@ -93,8 +93,8 @@ namespace crnlib dds_texture& operator= (const dds_texture& rhs); void clear(); - - void init(uint width, uint height, uint levels, uint faces, pixel_format fmt, const wchar_t* pName); + + void init(uint width, uint height, uint levels, uint faces, pixel_format fmt, const char* pName); // Assumes ownership. void assign(face_vec& faces); @@ -109,10 +109,10 @@ namespace crnlib inline bool is_valid() const { return m_faces.size() > 0; } - const dynamic_wstring& get_name() const { return m_name; } - void set_name(const dynamic_wstring& name) { m_name = name; } + const dynamic_string& get_name() const { return m_name; } + void set_name(const dynamic_string& name) { m_name = name; } - const dynamic_wstring& get_source_filename() const { return get_name(); } + const dynamic_string& get_source_filename() const { return get_name(); } texture_file_types::format get_source_file_type() const { return m_source_file_type; } inline uint get_width() const { return m_width; } @@ -133,34 +133,34 @@ namespace crnlib inline const mip_level* get_level(uint face, uint mip) const { return m_faces[face][mip]; } inline mip_level* get_level(uint face, uint mip) { return m_faces[face][mip]; } - + bool has_alpha() const; bool is_normal_map() const; bool is_vertical_cross() const; - bool is_packed() const; + bool is_packed() const; texture_type determine_texture_type() const; - const dynamic_wstring& get_last_error() const { return m_last_error; } + const dynamic_string& get_last_error() const { return m_last_error; } void clear_last_error() { m_last_error.clear(); } // Loading/saving - bool read_dds(const wchar_t* pFilename); + bool read_dds(const char* pFilename); bool read_dds(data_stream_serializer& serializer); - bool write_dds(const wchar_t* pFilename) const; + bool write_dds(const char* pFilename) const; bool write_dds(data_stream_serializer& serializer) const; - - bool load_crn_from_memory(const wchar_t* pFilename, const void *pData, uint data_size); + + bool load_crn_from_memory(const char* pFilename, const void *pData, uint data_size); // If file_format is texture_file_types::cFormatInvalid, the format will be determined from the filename's extension. - bool load_from_file(const wchar_t* pFilename, texture_file_types::format file_format); + bool load_from_file(const char* pFilename, texture_file_types::format file_format); bool write_to_file( - const wchar_t* pFilename, - texture_file_types::format file_format, + const char* pFilename, + texture_file_types::format file_format, crn_comp_params* pCRN_comp_params, uint32 *pActual_quality_level, float *pActual_bitrate); - + // Conversion bool convert(pixel_format fmt, bool cook, const dxt_image::pack_params& p); bool convert(pixel_format fmt, const dxt_image::pack_params& p); @@ -168,16 +168,16 @@ namespace crnlib bool convert(image_utils::conversion_type conv_type); bool unpack_from_dxt(bool uncook = true); - - bool set_alpha_to_luma(); - + + bool set_alpha_to_luma(); + void discard_mipmaps(); - + void discard_mips(); - + struct resample_params { - resample_params() : + resample_params() : m_pFilter("kaiser"), m_wrapping(false), m_srgb(false), @@ -186,8 +186,8 @@ namespace crnlib m_gamma(1.75f), // or 2.2f m_multithreaded(true) { - } - + } + const char* m_pFilter; bool m_wrapping; bool m_srgb; @@ -196,45 +196,45 @@ namespace crnlib float m_gamma; bool m_multithreaded; }; - + bool resize(uint new_width, uint new_height, const resample_params& params); - + struct generate_mipmap_params : public resample_params { - generate_mipmap_params() : + generate_mipmap_params() : resample_params(), m_min_mip_size(1), m_max_mips(0) { - } - + } + uint m_min_mip_size; uint m_max_mips; // actually the max # of total levels }; - + bool generate_mipmaps(const generate_mipmap_params& params, bool force); - + bool crop(uint x, uint y, uint width, uint height); - + bool vertical_cross_to_cubemap(); - + // Low-level clustered DXT (QDXT) compression struct qdxt_state { qdxt_state(task_pool& tp) : m_fmt(PIXEL_FMT_INVALID), m_qdxt1(tp), m_qdxt5a(tp), m_qdxt5b(tp) { } - + pixel_format m_fmt; qdxt1 m_qdxt1; qdxt5 m_qdxt5a; qdxt5 m_qdxt5b; crnlib::vector m_pixel_blocks; - + qdxt1_params m_qdxt1_params; qdxt5_params m_qdxt5_params[2]; bool m_has_blocks[3]; - + void clear() { m_fmt = PIXEL_FMT_INVALID; @@ -250,43 +250,43 @@ namespace crnlib }; bool qdxt_pack_init(qdxt_state& state, dds_texture& dst_tex, const qdxt1_params& dxt1_params, const qdxt5_params& dxt5_params, pixel_format fmt, bool cook); bool qdxt_pack(qdxt_state& state, dds_texture& dst_tex, const qdxt1_params& dxt1_params, const qdxt5_params& dxt5_params); - + void swap(dds_texture& img); - + bool check() const; - + private: - dynamic_wstring m_name; - + dynamic_string m_name; + uint m_width; uint m_height; - + pixel_format_helpers::component_flags m_comp_flags; pixel_format m_format; - + face_vec m_faces; texture_file_types::format m_source_file_type; - - mutable dynamic_wstring m_last_error; - + + mutable dynamic_string m_last_error; + inline void clear_last_error() const { m_last_error.clear(); } - inline void set_last_error(const wchar_t* p) const { m_last_error = p; } - + inline void set_last_error(const char* p) const { m_last_error = p; } + void free_all_mips(); bool read_dds_internal(data_stream_serializer& serializer); - bool load_regular(const wchar_t* pFilename, texture_file_types::format file_format); - bool load_dds(const wchar_t* pFilename); - bool load_crn(const wchar_t* pFilename); + bool load_regular(const char* pFilename, texture_file_types::format file_format); + bool load_dds(const char* pFilename); + bool load_crn(const char* pFilename); void print_crn_comp_params(const crn_comp_params& p); - bool save_regular(const wchar_t* pFilename); - bool save_dds(const wchar_t* pFilename); - bool save_comp_texture(const wchar_t* pFilename, const crn_comp_params &comp_params, uint32 *pActual_quality_level, float *pActual_bitrate); + bool save_regular(const char* pFilename); + bool save_dds(const char* pFilename); + bool save_comp_texture(const char* pFilename, const crn_comp_params &comp_params, uint32 *pActual_quality_level, float *pActual_bitrate); }; - + inline void swap(dds_texture& a, dds_texture& b) { - a.swap(b); - } - + a.swap(b); + } + } // namespace crnlib diff --git a/crnlib/crn_dxt.cpp b/crnlib/crn_dxt.cpp index 5a4e3a5..1cc37d4 100644 --- a/crnlib/crn_dxt.cpp +++ b/crnlib/crn_dxt.cpp @@ -11,43 +11,46 @@ namespace crnlib { const uint8 g_dxt5_from_linear[cDXT5SelectorValues] = { 0U, 2U, 3U, 4U, 5U, 6U, 7U, 1U }; const uint8 g_dxt5_to_linear[cDXT5SelectorValues] = { 0U, 7U, 1U, 2U, 3U, 4U, 5U, 6U }; - + const uint8 g_dxt5_alpha6_to_linear[cDXT5SelectorValues] = { 0U, 5U, 1U, 2U, 3U, 4U, 0U, 0U }; const uint8 g_dxt1_from_linear[cDXT1SelectorValues] = { 0U, 2U, 3U, 1U }; const uint8 g_dxt1_to_linear[cDXT1SelectorValues] = { 0U, 3U, 1U, 2U }; - + const uint8 g_six_alpha_invert_table[cDXT5SelectorValues] = { 1, 0, 5, 4, 3, 2, 6, 7 }; const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues] = { 1, 0, 7, 6, 5, 4, 3, 2 }; - const wchar_t* get_dxt_format_string(dxt_format fmt) + const char* get_dxt_format_string(dxt_format fmt) { switch (fmt) { - case cDXT1: return L"DXT1"; - case cDXT1A: return L"DXT1A"; - case cDXT3: return L"DXT3"; - case cDXT5: return L"DXT5"; - case cDXT5A: return L"DXT5A"; - case cDXN_XY: return L"DXN_XY"; - case cDXN_YX: return L"DXN_YX"; + case cDXT1: return "DXT1"; + case cDXT1A: return "DXT1A"; + case cDXT3: return "DXT3"; + case cDXT5: return "DXT5"; + case cDXT5A: return "DXT5A"; + case cDXN_XY: return "DXN_XY"; + case cDXN_YX: return "DXN_YX"; default: break; } CRNLIB_ASSERT(false); - return L"?"; + return "?"; } - const wchar_t* get_dxt_compressor_name(crn_dxt_compressor_type c) + const char* get_dxt_compressor_name(crn_dxt_compressor_type c) { switch (c) { - case cCRNDXTCompressorCRN: return L"CRN"; - case cCRNDXTCompressorCRNF: return L"CRNF"; - case cCRNDXTCompressorRYG: return L"RYG"; + case cCRNDXTCompressorCRN: return "CRN"; + case cCRNDXTCompressorCRNF: return "CRNF"; + case cCRNDXTCompressorRYG: return "RYG"; +#if CRNLIB_SUPPORT_ATI_COMPRESS + case cCRNDXTCompressorATI: return "ATI"; +#endif default: break; } CRNLIB_ASSERT(false); - return L"?"; + return "?"; } uint get_dxt_format_bits_per_pixel(dxt_format fmt) diff --git a/crnlib/crn_dxt.h b/crnlib/crn_dxt.h index 5a1244c..18d2c19 100644 --- a/crnlib/crn_dxt.h +++ b/crnlib/crn_dxt.h @@ -1,6 +1,6 @@ // File: crn_dxt.h // See Copyright Notice and license at the end of inc/crnlib.h -#pragma once +#pragma once #include "../inc/crnlib.h" #include "crn_color.h" #include "crn_vec.h" @@ -25,7 +25,7 @@ namespace crnlib cDXT1SelectorBits = 2U, cDXT1SelectorValues = 1U << cDXT1SelectorBits, cDXT1SelectorMask = cDXT1SelectorValues - 1U, - + cDXTBlockShift = 2U, cDXTBlockSize = 1U << cDXTBlockShift }; @@ -33,28 +33,28 @@ namespace crnlib enum dxt_format { cDXTInvalid = -1, - + // cDXT1/1A must appear first! - cDXT1, - cDXT1A, - - cDXT3, - cDXT5, + cDXT1, + cDXT1A, + + cDXT3, + cDXT5, cDXT5A, - + cDXN_XY, // inverted relative to standard ATI2, 360's DXN cDXN_YX // standard ATI2 }; - + const float cDXT1MaxLinearValue = 3.0f; const float cDXT1InvMaxLinearValue = 1.0f/3.0f; - + const float cDXT5MaxLinearValue = 7.0f; const float cDXT5InvMaxLinearValue = 1.0f/7.0f; - + // Converts DXT1 raw color selector index to a linear value. extern const uint8 g_dxt1_to_linear[cDXT1SelectorValues]; - + // Converts DXT5 raw alpha selector index to a linear value. extern const uint8 g_dxt5_to_linear[cDXT5SelectorValues]; @@ -63,33 +63,33 @@ namespace crnlib // Converts DXT5 linear alpha selector index to a raw value (inverse of g_dxt5_to_linear). extern const uint8 g_dxt5_from_linear[cDXT5SelectorValues]; - + extern const uint8 g_dxt5_alpha6_to_linear[cDXT5SelectorValues]; - + extern const uint8 g_six_alpha_invert_table[cDXT5SelectorValues]; extern const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues]; - - const wchar_t* get_dxt_format_string(dxt_format fmt); + + const char* get_dxt_format_string(dxt_format fmt); uint get_dxt_format_bits_per_pixel(dxt_format fmt); bool get_dxt_format_has_alpha(dxt_format fmt); - - const wchar_t* get_dxt_quality_string(crn_dxt_quality q); - - const wchar_t* get_dxt_compressor_name(crn_dxt_compressor_type c); - + + const char* get_dxt_quality_string(crn_dxt_quality q); + + const char* get_dxt_compressor_name(crn_dxt_compressor_type c); + struct dxt1_block { uint8 m_low_color[2]; uint8 m_high_color[2]; - + enum { cNumSelectorBytes = 4 }; uint8 m_selectors[cNumSelectorBytes]; - + inline void clear() { utils::zero_this(this); } - + // These methods assume the in-memory rep is in LE byte order. inline uint get_low_color() const { @@ -100,73 +100,73 @@ namespace crnlib { return m_high_color[0] | (m_high_color[1] << 8U); } - - inline void set_low_color(uint16 c) + + inline void set_low_color(uint16 c) { m_low_color[0] = static_cast(c & 0xFF); m_low_color[1] = static_cast((c >> 8) & 0xFF); } - + inline void set_high_color(uint16 c) { m_high_color[0] = static_cast(c & 0xFF); m_high_color[1] = static_cast((c >> 8) & 0xFF); } - + inline bool is_constant_color_block() const { return get_low_color() == get_high_color(); } inline bool is_alpha_block() const { return get_low_color() <= get_high_color(); } inline bool is_non_alpha_block() const { return !is_alpha_block(); } - + inline uint get_selector(uint x, uint y) const { CRNLIB_ASSERT((x < 4U) && (y < 4U)); return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask; } - + inline void set_selector(uint x, uint y, uint val) { CRNLIB_ASSERT((x < 4U) && (y < 4U) && (val < 4U)); - + m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits))); m_selectors[y] |= (val << (x * cDXT1SelectorBits)); } - + static uint16 pack_color(const color_quad_u8& color, bool scaled, uint bias = 127U); static uint16 pack_color(uint r, uint g, uint b, bool scaled, uint bias = 127U); - + static color_quad_u8 unpack_color(uint16 packed_color, bool scaled, uint alpha = 255U); static void unpack_color(uint& r, uint& g, uint& b, uint16 packed_color, bool scaled); - + static uint get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1); static uint get_block_colors3_round(color_quad_u8* pDst, uint16 color0, uint16 color1); - + static uint get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1); static uint get_block_colors4_round(color_quad_u8* pDst, uint16 color0, uint16 color1); - + // pDst must point to an array at least cDXT1SelectorValues long. static uint get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1); - + static uint get_block_colors_round(color_quad_u8* pDst, uint16 color0, uint16 color1); - + static color_quad_u8 unpack_endpoint(uint32 endpoints, uint index, bool scaled, uint alpha = 255U); static uint pack_endpoints(uint lo, uint hi); - + static void get_block_colors_NV5x(color_quad_u8* pDst, uint16 packed_col0, uint16 packed_col1, bool color4); }; - + CRNLIB_DEFINE_BITWISE_COPYABLE(dxt1_block); - + struct dxt3_block { enum { cNumAlphaBytes = 8 }; uint8 m_alpha[cNumAlphaBytes]; - + void set_alpha(uint x, uint y, uint value, bool scaled); uint get_alpha(uint x, uint y, bool scaled) const; }; - + CRNLIB_DEFINE_BITWISE_COPYABLE(dxt3_block); - + struct dxt5_block { uint8 m_endpoints[2]; @@ -189,23 +189,23 @@ namespace crnlib return m_endpoints[1]; } - inline void set_low_alpha(uint i) + inline void set_low_alpha(uint i) { - CRNLIB_ASSERT(i <= UINT8_MAX); + CRNLIB_ASSERT(i <= cUINT8_MAX); m_endpoints[0] = static_cast(i); } - inline void set_high_alpha(uint i) + inline void set_high_alpha(uint i) { - CRNLIB_ASSERT(i <= UINT8_MAX); + CRNLIB_ASSERT(i <= cUINT8_MAX); m_endpoints[1] = static_cast(i); } - + inline bool is_alpha6_block() const { return get_low_alpha() <= get_high_alpha(); } - + uint get_endpoints_as_word() const { return m_endpoints[0] | (m_endpoints[1] << 8); } uint get_selectors_as_word(uint index) { CRNLIB_ASSERT(index < 3); return m_selectors[index * 2] | (m_selectors[index * 2 + 1] << 8); } - + inline uint get_selector(uint x, uint y) const { CRNLIB_ASSERT((x < 4U) && (y < 4U)); @@ -244,7 +244,7 @@ namespace crnlib if (byte_index < (cNumSelectorBytes - 1)) m_selectors[byte_index + 1] = static_cast(v >> 8); } - + enum { cMaxSelectorValues = 8 }; // Results written to alpha channel. @@ -260,19 +260,19 @@ namespace crnlib static uint unpack_endpoint(uint packed, uint index); static uint pack_endpoints(uint lo, uint hi); }; - + CRNLIB_DEFINE_BITWISE_COPYABLE(dxt5_block); - + struct dxt_pixel_block { color_quad_u8 m_pixels[cDXTBlockSize][cDXTBlockSize]; // [y][x] inline void clear() { - utils::zero_object(*this); + utils::zero_object(*this); } - }; - + }; + CRNLIB_DEFINE_BITWISE_COPYABLE(dxt_pixel_block); } // namespace crnlib diff --git a/crnlib/crn_dxt1.cpp b/crnlib/crn_dxt1.cpp index 0a0453e..9a94f79 100644 --- a/crnlib/crn_dxt1.cpp +++ b/crnlib/crn_dxt1.cpp @@ -13,8 +13,8 @@ namespace crnlib m_pParams(NULL), m_pResults(NULL), m_pSolutions(NULL), - m_has_color_weighting(false), m_perceptual(false), + m_has_color_weighting(false), m_all_pixels_grayscale(false) { m_low_coords.reserve(512); @@ -26,7 +26,7 @@ namespace crnlib m_norm_unique_colors.reserve(512); m_norm_unique_colors_weighted.reserve(512); - + m_lo_cells.reserve(128); m_hi_cells.reserve(128); } @@ -41,10 +41,10 @@ namespace crnlib m_unique_color_hash_map.clear(); else m_unique_color_hash_map.reset(); - + if (m_solutions_tried.get_table_size() > 8192) m_solutions_tried.clear(); - + m_unique_colors.resize(0); m_has_transparent_pixels = false; @@ -57,7 +57,7 @@ namespace crnlib m_mean_norm_color_weighted.clear(); m_principle_axis.clear(); - + m_total_evals = 0; m_all_pixels_grayscale = false; m_has_color_weighting = false; @@ -107,7 +107,7 @@ namespace crnlib high_color = (ryg_dxt::OMatch5_3[ave_r][1]<<11) | (ryg_dxt::OMatch6_3[ave_g][1]<<5) | ryg_dxt::OMatch5_3[ave_b][1]; improved |= evaluate_solution(dxt1_solution_coordinates((uint16)low_color, (uint16)high_color), true, &m_best_solution); } - + if (m_pParams->m_quality == cCRNDXTQualityUber) { for (uint i = 0; i < m_unique_colors.size(); i++) @@ -121,7 +121,7 @@ namespace crnlib uint low_color = (ryg_dxt::OMatch5[r][0]<<11) | (ryg_dxt::OMatch6[g][0]<<5) | ryg_dxt::OMatch5[b][0]; uint high_color = (ryg_dxt::OMatch5[r][1]<<11) | (ryg_dxt::OMatch6[g][1]<<5) | ryg_dxt::OMatch5[b][1]; improved |= evaluate_solution(dxt1_solution_coordinates((uint16)low_color, (uint16)high_color), true, &m_best_solution); - + if ((m_pParams->m_use_alpha_blocks) && (m_best_solution.m_error)) { low_color = (ryg_dxt::OMatch5_3[r][0]<<11) | (ryg_dxt::OMatch6_3[g][0]<<5) | ryg_dxt::OMatch5_3[b][0]; @@ -130,7 +130,7 @@ namespace crnlib } } } - + return improved; } @@ -142,18 +142,18 @@ namespace crnlib //uint packed_color = dxt1_block::pack_color(r, g, b, true); //evaluate_solution(dxt1_solution_coordinates((uint16)packed_color, (uint16)packed_color), false, &m_best_solution); - + uint low_color = (ryg_dxt::OMatch5[r][0]<<11) | (ryg_dxt::OMatch6[g][0]<<5) | ryg_dxt::OMatch5[b][0]; uint high_color = (ryg_dxt::OMatch5[r][1]<<11) | (ryg_dxt::OMatch6[g][1]<<5) | ryg_dxt::OMatch5[b][1]; evaluate_solution(dxt1_solution_coordinates((uint16)low_color, (uint16)high_color), false, &m_best_solution); - + if ((m_pParams->m_use_alpha_blocks) && (m_best_solution.m_error)) { low_color = (ryg_dxt::OMatch5_3[r][0]<<11) | (ryg_dxt::OMatch6_3[g][0]<<5) | ryg_dxt::OMatch5_3[b][0]; high_color = (ryg_dxt::OMatch5_3[r][1]<<11) | (ryg_dxt::OMatch6_3[g][1]<<5) | ryg_dxt::OMatch5_3[b][1]; evaluate_solution(dxt1_solution_coordinates((uint16)low_color, (uint16)high_color), true, &m_best_solution); } - + return_solution(*m_pResults, m_best_solution); return true; @@ -221,35 +221,35 @@ namespace crnlib axis[0] += (x * v); axis[1] += (y * v); axis[2] += (z * v); - } + } } axis.normalize(&def); #else double cov[6] = { 0, 0, 0, 0, 0, 0 }; - + //vec3F lo(math::cNearlyInfinite); //vec3F hi(-math::cNearlyInfinite); for(uint i = 0; i < norm_colors.size(); i++) { const vec3F& v = norm_colors[i]; - + //if (v[0] < lo[0]) lo[0] = v[0]; //if (v[1] < lo[1]) lo[1] = v[1]; //if (v[2] < lo[2]) lo[2] = v[2]; //if (v[0] > hi[0]) hi[0] = v[0]; //if (v[1] > hi[1]) hi[1] = v[1]; //if (v[2] > hi[2]) hi[2] = v[2]; - + float r = v[0]; float g = v[1]; float b = v[2]; - + if (m_unique_colors[i].m_weight > 1) { const double weight = m_unique_colors[i].m_weight; - + cov[0] += r*r*weight; cov[1] += r*g*weight; cov[2] += r*b*weight; @@ -265,7 +265,7 @@ namespace crnlib cov[3] += g*g; cov[4] += g*b; cov[5] += b*b; - } + } } double vfr, vfg, vfb; @@ -277,7 +277,7 @@ namespace crnlib vfb = .7f; const uint cNumIters = 8; - + for (uint iter = 0; iter < cNumIters; iter++) { double r = vfr*cov[0] + vfg*cov[1] + vfb*cov[2]; @@ -292,19 +292,19 @@ namespace crnlib g *= m; b *= m; } - + double delta = math::square(vfr-r) + math::square(vfg-g) + math::square(vfb-b); - + vfr = r; vfg = g; vfb = b; - + if ((iter > 2) && (delta < 1e-8)) break; } - + double len = vfr*vfr + vfg*vfg + vfb*vfb; - + if (len < 1e-10) { axis = def; @@ -315,12 +315,12 @@ namespace crnlib vfr *= len; vfg *= len; vfb *= len; - + axis.set(static_cast(vfr), static_cast(vfg), static_cast(vfb)); - } -#endif + } +#endif } - + static const uint8 g_invTableNull[4] = { 0, 1, 2, 3 }; static const uint8 g_invTableAlpha[4] = { 1, 0, 2, 3 }; static const uint8 g_invTableColor[4] = { 1, 0, 3, 2 }; @@ -328,10 +328,10 @@ namespace crnlib void dxt1_endpoint_optimizer::return_solution(results& res, const potential_solution& solution) { bool invert_selectors; - + if (solution.m_alpha_block) invert_selectors = (solution.m_coords.m_low_color > solution.m_coords.m_high_color); - else + else { CRNLIB_ASSERT(solution.m_coords.m_low_color != solution.m_coords.m_high_color); @@ -352,18 +352,18 @@ namespace crnlib const uint8* pInvert_table = g_invTableNull; if (invert_selectors) pInvert_table = solution.m_alpha_block ? g_invTableAlpha : g_invTableColor; - + const uint alpha_thresh = m_pParams->m_pixels_have_alpha ? (m_pParams->m_dxt1a_alpha_threshold << 24U) : 0; - + const uint32* pSrc_pixels = reinterpret_cast(m_pParams->m_pPixels); uint8* pDst_selectors = res.m_pSelectors; - + if ((m_unique_colors.size() == 1) && (!m_pParams->m_pixels_have_alpha)) { uint32 c = utils::read_le32(pSrc_pixels); - + CRNLIB_ASSERT(c >= alpha_thresh); - + c |= 0xFF000000U; unique_color_hash_map::const_iterator it(m_unique_color_hash_map.find(c)); @@ -378,10 +378,10 @@ namespace crnlib else { uint8* pDst_selectors_end = pDst_selectors + m_pParams->m_num_pixels; - + uint8 prev_selector = 0; uint32 prev_color = 0; - + do { uint32 c = utils::read_le32(pSrc_pixels); @@ -392,28 +392,28 @@ namespace crnlib if (c >= alpha_thresh) { c |= 0xFF000000U; - + if (c == prev_color) selector = prev_selector; else { unique_color_hash_map::const_iterator it(m_unique_color_hash_map.find(c)); - + CRNLIB_ASSERT(it != m_unique_color_hash_map.end()); - + uint unique_color_index = it->second; - + selector = pInvert_table[solution.m_selectors[unique_color_index]]; - + prev_color = c; prev_selector = selector; - } + } } *pDst_selectors++ = selector; - - } while (pDst_selectors != pDst_selectors_end); - } + + } while (pDst_selectors != pDst_selectors_end); + } res.m_alpha_block = solution.m_alpha_block; res.m_error = solution.m_error; @@ -425,7 +425,7 @@ namespace crnlib return vec3F(c.r * 1.0f/31.0f, c.g * 1.0f/63.0f, c.b * 1.0f/31.0f); } - + inline vec3F dxt1_endpoint_optimizer::unpack_to_vec3F_raw(uint16 packed_color) { color_quad_u8 c(dxt1_block::unpack_color(packed_color, false)); @@ -437,7 +437,7 @@ namespace crnlib { if ((m_best_solution.m_alpha_block) || (!m_best_solution.m_error)) return; - + //color_quad_u8 orig_l(dxt1_block::unpack_color(m_best_solution.m_coords.m_low_color, false)); //color_quad_u8 orig_h(dxt1_block::unpack_color(m_best_solution.m_coords.m_high_color, false)); //uint orig_error = m_best_solution.m_error; @@ -548,18 +548,18 @@ namespace crnlib h[comp_index] = static_cast(p); bool better = evaluate_solution( - dxt1_solution_coordinates(dxt1_block::pack_color(l, false), dxt1_block::pack_color(h, false)), + dxt1_solution_coordinates(dxt1_block::pack_color(l, false), dxt1_block::pack_color(h, false)), true, &m_best_solution); better; if (better) { #if 0 - printf("comp: %u, orig: %u %u, new: %u %u, orig_error: %u, new_error: %u\n", comp_index, + printf("comp: %u, orig: %u %u, new: %u %u, orig_error: %u, new_error: %u\n", comp_index, orig_l[comp_index], orig_h[comp_index], l[comp_index], h[comp_index], - orig_error, m_best_solution.m_error); -#endif + orig_error, m_best_solution.m_error); +#endif if (!m_best_solution.m_error) return; @@ -576,13 +576,13 @@ namespace crnlib } // if (trial_error < error_to_beat) } // for (uint p = 0; p <= m; p++) - } + } } // for (uint o = 0; o <= m; o++) } // comp_index } - + static const struct adjacent_coords { int8 x, y, z; @@ -595,7 +595,7 @@ namespace crnlib {1, 0, -1}, {-1, 1, -1}, {0, 1, -1}, - + {1, 1, -1}, {-1, -1, 0}, {0, -1, 0}, @@ -604,7 +604,7 @@ namespace crnlib {1, 0, 0}, {-1, 1, 0}, {0, 1, 0}, - + {1, 1, 0}, {-1, -1, 1}, {0, -1, 1}, @@ -613,15 +613,15 @@ namespace crnlib {0, 0, 1}, {1, 0, 1}, {-1, 1, 1}, - + {0, 1, 1}, {1, 1, 1} }; - + bool dxt1_endpoint_optimizer::refine_solution(int refinement_level) { CRNLIB_ASSERT(m_best_solution.m_valid); - + static const int w1Tab[4] = { 3,0,2,1 }; static const int prods_0[4] = { 0x00,0x00,0x02,0x02 }; @@ -640,7 +640,7 @@ namespace crnlib { const color_quad_u8& c = m_unique_colors[i].m_color; const double weight = m_unique_colors[i].m_weight; - + double r = c.r*weight; double g = c.g*weight; double b = c.b*weight; @@ -675,7 +675,7 @@ namespace crnlib double fg = frb * (63.0f / 31.0f); bool improved = false; - + if (refinement_level == 0) { uint max16; @@ -687,7 +687,7 @@ namespace crnlib min16 = math::clamp(static_cast((At2_r*xx - At1_r*xy)*frb+0.5f),0,31) << 11; min16 |= math::clamp(static_cast((At2_g*xx - At1_g*xy)*fg +0.5f),0,63) << 5; min16 |= math::clamp(static_cast((At2_b*xx - At1_b*xy)*frb+0.5f),0,31) << 0; - + dxt1_solution_coordinates nc((uint16)min16, (uint16)max16); nc.canonicalize(); improved |= evaluate_solution(nc, true, &m_best_solution, false); @@ -701,8 +701,8 @@ namespace crnlib e[1][0] = (uint8)math::clamp(static_cast((At2_r*xx - At1_r*xy)*frb+0.5f),0,31); e[1][1] = (uint8)math::clamp(static_cast((At2_g*xx - At1_g*xy)*fg +0.5f),0,63); - e[1][2] = (uint8)math::clamp(static_cast((At2_b*xx - At1_b*xy)*frb+0.5f),0,31); - + e[1][2] = (uint8)math::clamp(static_cast((At2_b*xx - At1_b*xy)*frb+0.5f),0,31); + for (uint i = 0; i < 2; i++) { for (int rr = -1; rr <= 1; rr++) @@ -712,28 +712,28 @@ namespace crnlib for (int br = -1; br <= 1; br++) { dxt1_solution_coordinates nc; - + color_quad_u8 c[2]; c[0] = e[0]; c[1] = e[1]; - + c[i][0] = (uint8)math::clamp(c[i][0] + rr, 0, 31); c[i][1] = (uint8)math::clamp(c[i][1] + gr, 0, 63); c[i][2] = (uint8)math::clamp(c[i][2] + br, 0, 31); - + nc.m_low_color = dxt1_block::pack_color(c[0], false); nc.m_high_color = dxt1_block::pack_color(c[1], false); - + nc.canonicalize(); - + if ((nc.m_low_color != m_best_solution.m_coords.m_low_color) || (nc.m_high_color != m_best_solution.m_coords.m_high_color)) { improved |= evaluate_solution(nc, true, &m_best_solution, false); - } + } } } } - } + } } else { @@ -744,8 +744,8 @@ namespace crnlib e[1][0] = (uint8)math::clamp(static_cast((At2_r*xx - At1_r*xy)*frb+0.5f),0,31); e[1][1] = (uint8)math::clamp(static_cast((At2_g*xx - At1_g*xy)*fg +0.5f),0,63); - e[1][2] = (uint8)math::clamp(static_cast((At2_b*xx - At1_b*xy)*frb+0.5f),0,31); - + e[1][2] = (uint8)math::clamp(static_cast((At2_b*xx - At1_b*xy)*frb+0.5f),0,31); + for (int orr = -1; orr <= 1; orr++) { for (int ogr = -1; ogr <= 1; ogr++) @@ -753,15 +753,15 @@ namespace crnlib for (int obr = -1; obr <= 1; obr++) { dxt1_solution_coordinates nc; - + color_quad_u8 c[2]; c[0] = e[0]; c[1] = e[1]; - + c[0][0] = (uint8)math::clamp(c[0][0] + orr, 0, 31); c[0][1] = (uint8)math::clamp(c[0][1] + ogr, 0, 63); c[0][2] = (uint8)math::clamp(c[0][2] + obr, 0, 31); - + for (int rr = -1; rr <= 1; rr++) { for (int gr = -1; gr <= 1; gr++) @@ -771,7 +771,7 @@ namespace crnlib c[1][0] = (uint8)math::clamp(c[1][0] + rr, 0, 31); c[1][1] = (uint8)math::clamp(c[1][1] + gr, 0, 63); c[1][2] = (uint8)math::clamp(c[1][2] + br, 0, 31); - + nc.m_low_color = dxt1_block::pack_color(c[0], false); nc.m_high_color = dxt1_block::pack_color(c[1], false); nc.canonicalize(); @@ -781,15 +781,15 @@ namespace crnlib } } } - } - } - } - + } + } + } + return improved; - } - + } + //----------------------------------------------------------------------------------------------------------------------------------------- - + static int16 g_fast_probe_table[] = { 0, @@ -797,8 +797,8 @@ namespace crnlib 2, 3 }; - const uint cFastProbeTableSize = sizeof(g_fast_probe_table) / sizeof(g_fast_probe_table[0]); - + const uint cFastProbeTableSize = sizeof(g_fast_probe_table) / sizeof(g_fast_probe_table[0]); + static int16 g_normal_probe_table[] = { 0, @@ -807,7 +807,7 @@ namespace crnlib 5, 7 }; - const uint cNormalProbeTableSize = sizeof(g_normal_probe_table) / sizeof(g_normal_probe_table[0]); + const uint cNormalProbeTableSize = sizeof(g_normal_probe_table) / sizeof(g_normal_probe_table[0]); static int16 g_better_probe_table[] = { @@ -815,17 +815,17 @@ namespace crnlib 1, 2, 3, - + 5, 9, 15, 19, - + 27, 43 }; - const uint cBetterProbeTableSize = sizeof(g_better_probe_table) / sizeof(g_better_probe_table[0]); - + const uint cBetterProbeTableSize = sizeof(g_better_probe_table) / sizeof(g_better_probe_table[0]); + static int16 g_uber_probe_table[] = { 0, @@ -844,21 +844,21 @@ namespace crnlib 59, 91 }; - - const uint cUberProbeTableSize = sizeof(g_uber_probe_table) / sizeof(g_uber_probe_table[0]); - + + const uint cUberProbeTableSize = sizeof(g_uber_probe_table) / sizeof(g_uber_probe_table[0]); + bool dxt1_endpoint_optimizer::optimize_endpoints(vec3F& low_color, vec3F& high_color) { vec3F orig_low_color(low_color); vec3F orig_high_color(high_color); - + m_trial_solution.clear(); - + uint num_passes; int16* pProbe_table = g_uber_probe_table; uint probe_range; float dist_per_trial = .015625f; - + switch (m_pParams->m_quality) { case cCRNDXTQualitySuperFast: @@ -895,7 +895,7 @@ namespace crnlib if (m_pParams->m_endpoint_caching) { - const uint num_prev_results = math::minimum(cMaxPrevResults, m_num_prev_results); + const uint num_prev_results = math::minimum(cMaxPrevResults, m_num_prev_results); for (uint i = 0; i < num_prev_results; i++) { const dxt1_solution_coordinates& coords = m_prev_results[i]; @@ -904,7 +904,7 @@ namespace crnlib if (!solution_res.second) continue; - evaluate_solution(coords, true, &m_best_solution); + evaluate_solution(coords, true, &m_best_solution); } if (!m_best_solution.m_error) @@ -918,22 +918,22 @@ namespace crnlib { //evaluate_solution(dxt1_solution_coordinates(low_color, high_color), true, &m_best_solution); //refine_solution(); - + try_median4(orig_low_color, orig_high_color); } uint probe_low[cUberProbeTableSize * 2 + 1]; uint probe_high[cUberProbeTableSize * 2 + 1]; - + vec3F scaled_principle_axis[2]; - + scaled_principle_axis[1] = m_principle_axis * dist_per_trial; scaled_principle_axis[1][0] *= 31.0f; scaled_principle_axis[1][1] *= 63.0f; scaled_principle_axis[1][2] *= 31.0f; - + scaled_principle_axis[0] = -scaled_principle_axis[1]; - + //vec3F initial_ofs(scaled_principle_axis * (float)-probe_range); //initial_ofs[0] += .5f; //initial_ofs[1] += .5f; @@ -958,7 +958,7 @@ namespace crnlib const uint64 prev_best_error = m_best_solution.m_error; if (!prev_best_error) break; - + int prev_packed_color[2] = { -1, -1 }; uint num_low_trials = 0; vec3F initial_probe_low_color(low_color + vec3F(.5f)); @@ -966,11 +966,11 @@ namespace crnlib { const int ls = i ? 0 : 1; int x = pProbe_table[i]; - + for (int s = ls; s < 2; s++) { vec3F probe_low_color(initial_probe_low_color + scaled_principle_axis[s] * (float)x); - + int r = math::clamp((int)floor(probe_low_color[0]), 0, 31); int g = math::clamp((int)floor(probe_low_color[1]), 0, 63); int b = math::clamp((int)floor(probe_low_color[2]), 0, 31); @@ -981,23 +981,23 @@ namespace crnlib probe_low[num_low_trials++] = packed_color; prev_packed_color[s] = packed_color; } - } + } } - + prev_packed_color[0] = -1; prev_packed_color[1] = -1; - + uint num_high_trials = 0; vec3F initial_probe_high_color(high_color + vec3F(.5f)); for (uint i = 0; i < probe_range; i++) { const int ls = i ? 0 : 1; int x = pProbe_table[i]; - + for (int s = ls; s < 2; s++) { vec3F probe_high_color(initial_probe_high_color + scaled_principle_axis[s] * (float)x); - + int r = math::clamp((int)floor(probe_high_color[0]), 0, 31); int g = math::clamp((int)floor(probe_high_color[1]), 0, 63); int b = math::clamp((int)floor(probe_high_color[2]), 0, 31); @@ -1008,7 +1008,7 @@ namespace crnlib probe_high[num_high_trials++] = packed_color; prev_packed_color[s] = packed_color; } - } + } } for (uint i = 0; i < num_low_trials; i++) @@ -1031,7 +1031,7 @@ namespace crnlib color_quad_u8 lc(dxt1_block::unpack_color(m_best_solution.m_coords.m_low_color, false)); for (int i = 0; i < 26; i++) - { + { int r = lc.r + g_adjacency[i].x; if ((r < 0) || (r > 31)) continue; @@ -1073,12 +1073,12 @@ namespace crnlib evaluate_solution(coords, true, &m_best_solution); } } - } + } color_quad_u8 hc(dxt1_block::unpack_color(m_best_solution.m_coords.m_high_color, false)); for (int i = 0; i < 26; i++) - { + { int r = hc.r + g_adjacency[i].x; if ((r < 0) || (r > 31)) continue; @@ -1120,7 +1120,7 @@ namespace crnlib evaluate_solution(coords, true, &m_best_solution); } } - } + } } if ((!m_best_solution.m_error) || ((pass) && (m_best_solution.m_error == prev_best_error))) @@ -1128,7 +1128,7 @@ namespace crnlib if (m_pParams->m_quality >= cCRNDXTQualityUber) refine_solution(1); - } + } if (m_pParams->m_quality >= cCRNDXTQualityNormal) { @@ -1144,10 +1144,10 @@ namespace crnlib if (m_pParams->m_quality == cCRNDXTQualityUber) { - if (m_best_solution.m_error) + if (m_best_solution.m_error) try_combinatorial_encoding(); - } - } + } + } return_solution(*m_pResults, m_best_solution); @@ -1157,9 +1157,9 @@ namespace crnlib m_num_prev_results++; } - return true; + return true; } - + static inline int mul_8bit(int a, int b) { int t = a * b + 128; @@ -1170,7 +1170,7 @@ namespace crnlib { uint num_passes = 1; vec3F perceptual_weights(1.0f); - + if (m_perceptual) { float ave_redness = 0; @@ -1185,24 +1185,24 @@ namespace crnlib int l = mul_8bit(c.r + c.g + c.b, 0x55); // /3 ave_l += l; l = math::maximum(1, l); - + float scale = weight / static_cast(l); ave_redness += scale * c.r; ave_blueness += scale * c.b; - } - + } + ave_redness /= m_total_unique_color_weight; ave_blueness /= m_total_unique_color_weight; ave_l /= m_total_unique_color_weight; - + ave_l = math::minimum(1.0f, ave_l * 16.0f / 255.0f); //float r = ave_l * powf(math::saturate(ave_redness / 3.0f), 5.0f); //float b = ave_l * powf(math::saturate(ave_blueness / 3.0f), 5.0f); - + float p = ave_l * powf(math::saturate(math::maximum(ave_redness, ave_blueness) * 1.0f/3.0f), 2.75f); - + if (p >= 1.0f) num_passes = 1; else @@ -1211,14 +1211,14 @@ namespace crnlib perceptual_weights = vec3F::lerp(vec3F(.212f, .72f, .072f), perceptual_weights, p); } } - + for (uint pass_index = 0; pass_index < num_passes; pass_index++) { compute_vectors(perceptual_weights); - + compute_pca(m_principle_axis, m_norm_unique_colors_weighted, vec3F(.2837149f, 0.9540631f, 0.096277453f)); -#if 0 +#if 0 matrix44F m(matrix44F::make_scale_matrix(perceptual_weights[0], perceptual_weights[1], perceptual_weights[2])); matrix44F im(m.get_inverse()); im.transpose_in_place(); @@ -1227,8 +1227,8 @@ namespace crnlib m_principle_axis[0] /= perceptual_weights[0]; m_principle_axis[1] /= perceptual_weights[1]; m_principle_axis[2] /= perceptual_weights[2]; -#endif - m_principle_axis.normalize_in_place(); +#endif + m_principle_axis.normalize_in_place(); if (num_passes > 1) { @@ -1238,7 +1238,7 @@ namespace crnlib perceptual_weights.set(.212f, .6f, .212f); else break; - } + } } float l = 1e+9; @@ -1253,7 +1253,7 @@ namespace crnlib vec3F low_color(m_mean_norm_color + l * m_principle_axis); vec3F high_color(m_mean_norm_color + h * m_principle_axis); - + if (!low_color.is_within_bounds(0.0f, 1.0f)) { vec3F coord; @@ -1262,8 +1262,8 @@ namespace crnlib intersection::result res = intersection::ray_aabb(coord, t, ray3F(low_color, m_principle_axis), bounds); if (res == intersection::cSuccess) low_color = coord; - } - + } + if (!high_color.is_within_bounds(0.0f, 1.0f)) { vec3F coord; @@ -1272,7 +1272,7 @@ namespace crnlib intersection::result res = intersection::ray_aabb(coord, t, ray3F(high_color, -m_principle_axis), bounds); if (res == intersection::cSuccess) high_color = coord; - } + } if (!optimize_endpoints(low_color, high_color)) return false; @@ -1285,11 +1285,11 @@ namespace crnlib // TODO return true; } - + bool dxt1_endpoint_optimizer::try_median4(const vec3F& low_color, const vec3F& high_color) { vec3F means[4]; - + if (m_unique_colors.size() <= 4) { for (uint i = 0; i < 4; i++) @@ -1301,19 +1301,19 @@ namespace crnlib means[3] = high_color - m_mean_norm_color; means[1] = vec3F::lerp(means[0], means[3], 1.0f/3.0f); means[2] = vec3F::lerp(means[0], means[3], 2.0f/3.0f); - + fast_random rm; const uint cMaxIters = 8; uint reassign_rover = 0; float prev_total_dist = math::cNearlyInfinite; - for (uint iter = 0; iter < cMaxIters; iter++) + for (uint iter = 0; iter < cMaxIters; iter++) { vec3F new_means[4]; float new_weights[4]; utils::zero_object(new_means); utils::zero_object(new_weights); - + float total_dist = 0; for (uint i = 0; i < m_unique_colors.size(); i++) @@ -1322,7 +1322,7 @@ namespace crnlib float best_dist = means[0].squared_distance(v); int best_index = 0; - + for (uint j = 1; j < 4; j++) { float dist = means[j].squared_distance(v); @@ -1332,7 +1332,7 @@ namespace crnlib best_index = j; } } - + total_dist += best_dist; new_means[best_index] += v * (float)m_unique_colors[i].m_weight; @@ -1356,12 +1356,12 @@ namespace crnlib else empty_cell = true; } - + if (!empty_cell) { if (fabs(total_dist - prev_total_dist) < .00001f) break; - + prev_total_dist = total_dist; } else @@ -1379,13 +1379,13 @@ namespace crnlib means[j] = means[ri]; means[j] += vec3F::make_random(rm, -.00196f, .00196f); } - } - } + } + } } - } + } bool improved = false; - + for (uint i = 0; i < 3; i++) { for (uint j = i + 1; j < 4; j++) @@ -1407,15 +1407,15 @@ namespace crnlib return improved; } - + bool dxt1_endpoint_optimizer::evaluate_solution( - const dxt1_solution_coordinates& coords, + const dxt1_solution_coordinates& coords, bool early_out, potential_solution* pBest_solution, bool alternate_rounding) { m_total_evals++; - + if ((!m_pSolutions) || (alternate_rounding)) { if (m_pParams->m_quality >= cCRNDXTQualityBetter) @@ -1423,26 +1423,26 @@ namespace crnlib else return evaluate_solution_fast(m_trial_solution, coords, early_out, pBest_solution, alternate_rounding); } - + evaluate_solution_uber(m_trial_solution, coords, false, NULL, alternate_rounding); - + CRNLIB_ASSERT(m_trial_solution.m_valid); - + m_pSolutions->resize(m_pSolutions->size() + 1); solution& new_solution = m_pSolutions->back(); new_solution.m_selectors.resize(m_pParams->m_num_pixels); new_solution.m_results.m_pSelectors = &new_solution.m_selectors[0]; - + return_solution(new_solution.m_results, m_trial_solution); - + if ((pBest_solution) && (m_trial_solution.m_error < m_best_solution.m_error)) { *pBest_solution = m_trial_solution; return true; } - + return false; - } + } inline uint dxt1_endpoint_optimizer::color_distance(bool perceptual, const color_quad_u8& e1, const color_quad_u8& e2, bool alpha) { @@ -1481,7 +1481,7 @@ namespace crnlib { int da = (int)e1[3] - (int)e2[3]; da = (da * da) * (m_pParams->m_color_weights[0] + m_pParams->m_color_weights[1] + m_pParams->m_color_weights[2]); - return dr + dg + db + da; + return dr + dg + db + da; } else { @@ -1495,20 +1495,20 @@ namespace crnlib } bool dxt1_endpoint_optimizer::evaluate_solution_uber( - potential_solution& solution, - const dxt1_solution_coordinates& coords, + potential_solution& solution, + const dxt1_solution_coordinates& coords, bool early_out, potential_solution* pBest_solution, bool alternate_rounding) { solution.m_coords = coords; solution.m_selectors.resize(m_unique_colors.size()); - + if ((pBest_solution) && (early_out)) solution.m_error = pBest_solution->m_error; else - solution.m_error = UINT64_MAX; - + solution.m_error = cUINT64_MAX; + solution.m_alpha_block = false; solution.m_valid = false; @@ -1523,19 +1523,19 @@ namespace crnlib m_trial_selectors.resize(m_unique_colors.size()); color_quad_u8 colors[cDXT1SelectorValues]; - + colors[0] = dxt1_block::unpack_color(coords.m_low_color, true); colors[1] = dxt1_block::unpack_color(coords.m_high_color, true); - + for (uint block_type = first_block_type; block_type <= last_block_type; block_type++) { uint64 trial_error = 0; - + if (!block_type) { colors[2].set_noclamp_rgba( (colors[0].r * 2 + colors[1].r + alternate_rounding) / 3, (colors[0].g * 2 + colors[1].g + alternate_rounding) / 3, (colors[0].b * 2 + colors[1].b + alternate_rounding) / 3, 0); colors[3].set_noclamp_rgba( (colors[1].r * 2 + colors[0].r + alternate_rounding) / 3, (colors[1].g * 2 + colors[0].g + alternate_rounding) / 3, (colors[1].b * 2 + colors[0].b + alternate_rounding) / 3, 0); - + if (m_perceptual) { for (int unique_color_index = (int)m_unique_colors.size() - 1; unique_color_index >= 0; unique_color_index--) @@ -1566,31 +1566,31 @@ namespace crnlib for (int unique_color_index = (int)m_unique_colors.size() - 1; unique_color_index >= 0; unique_color_index--) { const color_quad_u8& c = m_unique_colors[unique_color_index].m_color; - + uint best_error = color_distance(false, c, colors[0], false); uint best_color_index = 0; - + uint err = color_distance(false, c, colors[1], false); if (err < best_error) { best_error = err; best_color_index = 1; } - + err = color_distance(false, c, colors[2], false); if (err < best_error) { best_error = err; best_color_index = 2; } - + err = color_distance(false, c, colors[3], false); if (err < best_error) { best_error = err; best_color_index = 3; } - + trial_error += best_error * m_unique_colors[unique_color_index].m_weight; if (trial_error >= solution.m_error) break; m_trial_selectors[unique_color_index] = static_cast(best_color_index); } - } + } } else { colors[2].set_noclamp_rgba( (colors[0].r + colors[1].r + alternate_rounding) >> 1, (colors[0].g + colors[1].g + alternate_rounding) >> 1, (colors[0].b + colors[1].b + alternate_rounding) >> 1, 255U); - + if (m_perceptual) { for (int unique_color_index = (int)m_unique_colors.size() - 1; unique_color_index >= 0; unique_color_index--) @@ -1618,7 +1618,7 @@ namespace crnlib for (int unique_color_index = (int)m_unique_colors.size() - 1; unique_color_index >= 0; unique_color_index--) { const color_quad_u8& c = m_unique_colors[unique_color_index].m_color; - + uint best_error = color_distance(false, c, colors[0], false); uint best_color_index = 0; @@ -1634,9 +1634,9 @@ namespace crnlib m_trial_selectors[unique_color_index] = static_cast(best_color_index); } - } + } } - + if (trial_error < solution.m_error) { solution.m_error = trial_error; @@ -1670,12 +1670,12 @@ namespace crnlib return true; } - return false; + return false; } - + bool dxt1_endpoint_optimizer::evaluate_solution_fast( - potential_solution& solution, - const dxt1_solution_coordinates& coords, + potential_solution& solution, + const dxt1_solution_coordinates& coords, bool early_out, potential_solution* pBest_solution, bool alternate_rounding) @@ -1686,7 +1686,7 @@ namespace crnlib if ((pBest_solution) && (early_out)) solution.m_error = pBest_solution->m_error; else - solution.m_error = UINT64_MAX; + solution.m_error = cUINT64_MAX; solution.m_alpha_block = false; solution.m_valid = false; @@ -1698,9 +1698,9 @@ namespace crnlib first_block_type = 1; else if (!m_pParams->m_use_alpha_blocks) last_block_type = 0; - + m_trial_selectors.resize(m_unique_colors.size()); - + color_quad_u8 colors[cDXT1SelectorValues]; colors[0] = dxt1_block::unpack_color(coords.m_low_color, true); colors[1] = dxt1_block::unpack_color(coords.m_high_color, true); @@ -1717,11 +1717,11 @@ namespace crnlib int stops[4]; stops[0] = colors[0].r*vr + colors[0].g*vg + colors[0].b*vb; stops[1] = colors[1].r*vr + colors[1].g*vg + colors[1].b*vb; - + int dirr = vr * 2; int dirg = vg * 2; int dirb = vb * 2; - + for (uint block_type = first_block_type; block_type <= last_block_type; block_type++) { uint64 trial_error = 0; @@ -1730,10 +1730,10 @@ namespace crnlib { colors[2].set_noclamp_rgba( (colors[0].r * 2 + colors[1].r + alternate_rounding) / 3, (colors[0].g * 2 + colors[1].g + alternate_rounding) / 3, (colors[0].b * 2 + colors[1].b + alternate_rounding) / 3, 255U); colors[3].set_noclamp_rgba( (colors[1].r * 2 + colors[0].r + alternate_rounding) / 3, (colors[1].g * 2 + colors[0].g + alternate_rounding) / 3, (colors[1].b * 2 + colors[0].b + alternate_rounding) / 3, 255U); - + stops[2] = colors[2].r*vr + colors[2].g*vg + colors[2].b*vb; stops[3] = colors[3].r*vr + colors[3].g*vg + colors[3].b*vb; - + // 0 2 3 1 int c0Point = stops[1] + stops[3]; int halfPoint = stops[3] + stops[2]; @@ -1750,9 +1750,9 @@ namespace crnlib best_color_index = (dot < c3Point) ? 0 : 2; else best_color_index = (dot < c0Point) ? 3 : 1; - + uint best_error = color_distance(m_perceptual, c, colors[best_color_index], false); - + trial_error += best_error * m_unique_colors[unique_color_index].m_weight; if (trial_error >= solution.m_error) break; @@ -1765,11 +1765,11 @@ namespace crnlib colors[2].set_noclamp_rgba( (colors[0].r + colors[1].r + alternate_rounding) >> 1, (colors[0].g + colors[1].g + alternate_rounding) >> 1, (colors[0].b + colors[1].b + alternate_rounding) >> 1, 255U); stops[2] = colors[2].r*vr + colors[2].g*vg + colors[2].b*vb; - + // 0 2 1 int c02Point = stops[0] + stops[2]; int c21Point = stops[2] + stops[1]; - + for (int unique_color_index = (int)m_unique_colors.size() - 1; unique_color_index >= 0; unique_color_index--) { const color_quad_u8& c = m_unique_colors[unique_color_index].m_color; @@ -1783,7 +1783,7 @@ namespace crnlib best_color_index = 2; else best_color_index = 1; - + uint best_error = color_distance(m_perceptual, c, colors[best_color_index], false); trial_error += best_error * m_unique_colors[unique_color_index].m_weight; @@ -1827,19 +1827,19 @@ namespace crnlib return true; } - return false; + return false; } - + unique_color dxt1_endpoint_optimizer::lerp_color(const color_quad_u8& a, const color_quad_u8& b, float f, int rounding) { color_quad_u8 res; - + float r = rounding ? 1.0f : 0.0f; res[0] = static_cast(math::clamp(math::float_to_int(r + math::lerp(a[0], b[0], f)), 0, 255)); res[1] = static_cast(math::clamp(math::float_to_int(r + math::lerp(a[1], b[1], f)), 0, 255)); res[2] = static_cast(math::clamp(math::float_to_int(r + math::lerp(a[2], b[2], f)), 0, 255)); res[3] = 255; - + return unique_color(res, 1); } @@ -1847,9 +1847,9 @@ namespace crnlib { if ((m_unique_colors.size() < 2) || (m_unique_colors.size() > 4)) return; - + m_temp_unique_colors = m_unique_colors; - + if (m_temp_unique_colors.size() == 2) { // a b c d @@ -1860,17 +1860,17 @@ namespace crnlib for (uint q = 0; q < 2; q++) { const uint r = q ^ 1; - + // a b m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, 2.0f, k)); m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, 3.0f, k)); - + // a c m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, .5f, k)); m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, 1.5f, k)); - + // a d - + // b c m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, -1.0f, k)); m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, 2.0f, k)); @@ -1878,41 +1878,41 @@ namespace crnlib // b d m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, -.5f, k)); m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, .5f, k)); - + // c d m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, -2.0f, k)); m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[q].m_color, m_temp_unique_colors[r].m_color, -1.0f, k)); - } - } + } + } } else if (m_temp_unique_colors.size() == 3) { // a b c d // 0.0 1/3 2/3 1.0 - + for (uint i = 0; i <= 2; i++) { for (uint j = 0; j <= 2; j++) { - if (i == j) + if (i == j) continue; - - // a b c + + // a b c m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[i].m_color, m_temp_unique_colors[j].m_color, 1.5f)); - + // a b d m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[i].m_color, m_temp_unique_colors[j].m_color, 2.0f/3.0f)); - + // a c d m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[i].m_color, m_temp_unique_colors[j].m_color, 1.0f/3.0f)); - + // b c d m_temp_unique_colors.push_back(lerp_color(m_temp_unique_colors[i].m_color, m_temp_unique_colors[j].m_color, -.5f)); - } - } + } + } } - m_unique_packed_colors.resize(0); + m_unique_packed_colors.resize(0); for (uint i = 0; i < m_temp_unique_colors.size(); i++) { @@ -1927,7 +1927,7 @@ namespace crnlib if (m_unique_packed_colors.size() < 2) return; - + for (uint alt_rounding = 0; alt_rounding < 2; alt_rounding++) { for (uint i = 0; i < m_unique_packed_colors.size() - 1; i++) @@ -1935,66 +1935,66 @@ namespace crnlib for (uint j = i + 1; j < m_unique_packed_colors.size(); j++) { evaluate_solution( - dxt1_solution_coordinates(m_unique_packed_colors[i], m_unique_packed_colors[j]), - true, - (alt_rounding == 0) ? &m_best_solution : NULL, + dxt1_solution_coordinates(m_unique_packed_colors[i], m_unique_packed_colors[j]), + true, + (alt_rounding == 0) ? &m_best_solution : NULL, (alt_rounding != 0)); - + if (m_trial_solution.m_error == 0) { if (alt_rounding) m_best_solution = m_trial_solution; - + return; } } } } - + return; } - + bool dxt1_endpoint_optimizer::try_alpha_as_black_optimization() { const params* pOrig_params = m_pParams; pOrig_params; results* pOrig_results = m_pResults; - + uint num_dark_colors = 0; - + for (uint i = 0; i < m_unique_colors.size(); i++) if ( (m_unique_colors[i].m_color[0] <= 4) && (m_unique_colors[i].m_color[1] <= 4) && (m_unique_colors[i].m_color[2] <= 4) ) num_dark_colors++; - + if ( (!num_dark_colors) || (num_dark_colors == m_unique_colors.size()) ) return true; - - params trial_params(*m_pParams); + + params trial_params(*m_pParams); crnlib::vector trial_colors; trial_colors.insert(0, m_pParams->m_pPixels, m_pParams->m_num_pixels); - + trial_params.m_pPixels = trial_colors.get_ptr(); trial_params.m_pixels_have_alpha = true; - + for (uint i = 0; i < trial_colors.size(); i++) if ( (trial_colors[i][0] <= 4) && (trial_colors[i][1] <= 4) && (trial_colors[i][2] <= 4) ) trial_colors[i][3] = 0; results trial_results; - + crnlib::vector trial_selectors(m_pParams->m_num_pixels); trial_results.m_pSelectors = trial_selectors.get_ptr(); - + if (!compute_internal(trial_params, trial_results, NULL)) - return false; - + return false; + CRNLIB_ASSERT(trial_results.m_alpha_block); - + color_quad_u8 c[4]; dxt1_block::get_block_colors3(c, trial_results.m_low_color, trial_results.m_high_color); - + uint64 trial_error = 0; - + for (uint i = 0; i < trial_colors.size(); i++) { if (trial_colors[i][3] == 0) @@ -2005,23 +2005,23 @@ namespace crnlib { CRNLIB_ASSERT(trial_selectors[i] != 3); } - + trial_error += color_distance(m_perceptual, trial_colors[i], c[trial_selectors[i]], false); } - + if (trial_error < pOrig_results->m_error) { pOrig_results->m_error = trial_error; - + pOrig_results->m_low_color = trial_results.m_low_color; pOrig_results->m_high_color = trial_results.m_high_color; - + if (pOrig_results->m_pSelectors) memcpy(pOrig_results->m_pSelectors, trial_results.m_pSelectors, m_pParams->m_num_pixels); - + pOrig_results->m_alpha_block = true; } - + return true; } @@ -2039,26 +2039,26 @@ namespace crnlib find_unique_colors(); m_best_solution.clear(); - + if (m_unique_colors.empty()) return handle_all_transparent_block(); else if ((m_unique_colors.size() == 1) && (!m_has_transparent_pixels)) return handle_solid_block(); - else + else { if (!handle_multicolor_block()) return false; - + if ((m_all_pixels_grayscale) && (m_best_solution.m_error)) { if (!handle_grayscale_block()) return false; } } - + return true; } - + bool dxt1_endpoint_optimizer::compute(const params& p, results& r, solution_vec* pSolutions) { if (!p.m_pPixels) @@ -2067,37 +2067,37 @@ namespace crnlib bool status = compute_internal(p, r, pSolutions); if (!status) return false; - + if ( (m_pParams->m_use_alpha_blocks) && (m_pParams->m_use_transparent_indices_for_black) && (!m_pParams->m_pixels_have_alpha) && (!pSolutions) ) { if (!try_alpha_as_black_optimization()) return false; - } - + } + return true; } - + void dxt1_endpoint_optimizer::find_unique_colors() { m_has_transparent_pixels = false; uint num_opaque_pixels = 0; - + const uint alpha_thresh = m_pParams->m_pixels_have_alpha ? (m_pParams->m_dxt1a_alpha_threshold << 24U) : 0; const uint32* pSrc_pixels = reinterpret_cast(m_pParams->m_pPixels); const uint32* pSrc_pixels_end = pSrc_pixels + m_pParams->m_num_pixels; - + m_unique_colors.resize(m_pParams->m_num_pixels); uint num_unique_colors = 0; - + m_all_pixels_grayscale = true; - + do { uint32 c = utils::read_le32(pSrc_pixels); pSrc_pixels++; - + if (c < alpha_thresh) { m_has_transparent_pixels = true; @@ -2114,9 +2114,9 @@ namespace crnlib } c |= 0xFF000000U; - + unique_color_hash_map::insert_result ins_result(m_unique_color_hash_map.insert(c, num_unique_colors)); - + if (ins_result.second) { utils::write_le32(&m_unique_colors[num_unique_colors].m_color.m_u32, c); @@ -2125,13 +2125,13 @@ namespace crnlib } else m_unique_colors[ins_result.first->second].m_weight++; - + num_opaque_pixels++; - + } while (pSrc_pixels != pSrc_pixels_end); - + m_unique_colors.resize(num_unique_colors); - + m_total_unique_color_weight = num_opaque_pixels; } diff --git a/crnlib/crn_dxt1.h b/crnlib/crn_dxt1.h index 7ff7388..9a747ca 100644 --- a/crnlib/crn_dxt1.h +++ b/crnlib/crn_dxt1.h @@ -258,7 +258,7 @@ namespace crnlib struct potential_solution { - potential_solution() : m_coords(), m_error(UINT64_MAX), m_alpha_block(false), m_valid(false) + potential_solution() : m_coords(), m_error(cUINT64_MAX), m_alpha_block(false), m_valid(false) { } @@ -272,7 +272,7 @@ namespace crnlib { m_coords.clear(); m_selectors.resize(0); - m_error = UINT64_MAX; + m_error = cUINT64_MAX; m_alpha_block = false; m_valid = false; } diff --git a/crnlib/crn_dxt5a.cpp b/crnlib/crn_dxt5a.cpp index f2fe2ee..9901a66 100644 --- a/crnlib/crn_dxt5a.cpp +++ b/crnlib/crn_dxt5a.cpp @@ -62,7 +62,7 @@ namespace crnlib m_trial_selectors.resize(m_unique_values.size()); m_best_selectors.resize(m_unique_values.size()); - r.m_error = UINT64_MAX; + r.m_error = cUINT64_MAX; for (uint i = 0; i < m_unique_values.size() - 1; i++) { diff --git a/crnlib/crn_dxt_endpoint_refiner.cpp b/crnlib/crn_dxt_endpoint_refiner.cpp index a7a312e..a78b7df 100644 --- a/crnlib/crn_dxt_endpoint_refiner.cpp +++ b/crnlib/crn_dxt_endpoint_refiner.cpp @@ -20,7 +20,7 @@ namespace crnlib m_pParams = &p; m_pResults = &r; - r.m_error = UINT64_MAX; + r.m_error = cUINT64_MAX; r.m_low_color = 0; r.m_high_color = 0; diff --git a/crnlib/crn_dxt_endpoint_refiner.h b/crnlib/crn_dxt_endpoint_refiner.h index 3a97e13..131f904 100644 --- a/crnlib/crn_dxt_endpoint_refiner.h +++ b/crnlib/crn_dxt_endpoint_refiner.h @@ -19,7 +19,7 @@ namespace crnlib m_num_pixels(0), m_pSelectors(NULL), m_alpha_comp_index(0), - m_error_to_beat(UINT64_MAX), + m_error_to_beat(cUINT64_MAX), m_dxt1_selectors(true), m_perceptual(true), m_highest_quality(true) diff --git a/crnlib/crn_dxt_fast.cpp b/crnlib/crn_dxt_fast.cpp index fffdcb9..e698a73 100644 --- a/crnlib/crn_dxt_fast.cpp +++ b/crnlib/crn_dxt_fast.cpp @@ -507,7 +507,7 @@ namespace crnlib static void refine_endpoints2(uint n, const color_quad_u8* pBlock, uint& low16, uint& high16, uint8* pSelectors, float axis[3]) { - uint64 orig_error = determine_error(n, pBlock, low16, high16, UINT64_MAX); + uint64 orig_error = determine_error(n, pBlock, low16, high16, cUINT64_MAX); if (!orig_error) return; @@ -623,7 +623,7 @@ namespace crnlib { improved = true; - uint64 cur_error = determine_error(n, pBlock, low16, high16, UINT64_MAX); + uint64 cur_error = determine_error(n, pBlock, low16, high16, cUINT64_MAX); if (!cur_error) return; } diff --git a/crnlib/crn_dxt_hc.cpp b/crnlib/crn_dxt_hc.cpp index 1d92f97..33b309f 100644 --- a/crnlib/crn_dxt_hc.cpp +++ b/crnlib/crn_dxt_hc.cpp @@ -33,7 +33,7 @@ namespace crnlib m_has_color_blocks(false), m_has_alpha0_blocks(false), m_has_alpha1_blocks(false), - m_main_thread_id(get_current_thread_id()), + m_main_thread_id(crn_get_current_thread_id()), m_canceled(false), m_pTask_pool(NULL), m_prev_phase_index(-1), @@ -104,7 +104,7 @@ namespace crnlib bool dxt_hc::compress(const params& p, uint num_chunks, const pixel_chunk* pChunks, task_pool& task_pool) { m_pTask_pool = &task_pool; - m_main_thread_id = get_current_thread_id(); + m_main_thread_id = crn_get_current_thread_id(); bool result = compress_internal(p, num_chunks, pChunks); @@ -335,7 +335,7 @@ namespace crnlib if (m_canceled) return; - if ((get_current_thread_id() == m_main_thread_id) && ((chunk_index & 511) == 0)) + if ((crn_get_current_thread_id() == m_main_thread_id) && ((chunk_index & 511) == 0)) { if (!update_progress(0, chunk_index, m_num_chunks)) return; @@ -550,9 +550,9 @@ namespace crnlib } } - interlocked_increment32(&m_encoding_hist[best_encoding]); + atomic_increment32(&m_encoding_hist[best_encoding]); - interlocked_exchange_add32(&m_total_tiles, g_chunk_encodings[best_encoding].m_num_tiles); + atomic_exchange_add32(&m_total_tiles, g_chunk_encodings[best_encoding].m_num_tiles); for (uint q = 0; q < cNumCompressedChunkVecs; q++) { @@ -664,15 +664,15 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) { - console::info(L"Total Pixels: %u, Chunks: %u, Blocks: %u, Adapted Tiles: %u", m_num_chunks * cChunkPixelWidth * cChunkPixelHeight, m_num_chunks, m_num_chunks * cChunkBlockWidth * cChunkBlockHeight, m_total_tiles); + console::info("Total Pixels: %u, Chunks: %u, Blocks: %u, Adapted Tiles: %u", m_num_chunks * cChunkPixelWidth * cChunkPixelHeight, m_num_chunks, m_num_chunks * cChunkBlockWidth * cChunkBlockHeight, m_total_tiles); - console::info(L"Chunk encoding type symbol_histogram: "); + console::info("Chunk encoding type symbol_histogram: "); for (uint e = 0; e < cNumChunkEncodings; e++) - console::info(L"%u ", m_encoding_hist[e]); + console::info("%u ", m_encoding_hist[e]); - console::info(L"Blocks per chunk encoding type: "); + console::info("Blocks per chunk encoding type: "); for (uint e = 0; e < cNumChunkEncodings; e++) - console::info(L"%u ", m_encoding_hist[e] * cChunkBlockWidth * cChunkBlockHeight); + console::info("%u ", m_encoding_hist[e] * cChunkBlockWidth * cChunkBlockHeight); } #endif @@ -689,7 +689,7 @@ namespace crnlib if (m_canceled) return; - if ((get_current_thread_id() == m_main_thread_id) && ((chunk_index & 63) == 0)) + if ((crn_get_current_thread_id() == m_main_thread_id) && ((chunk_index & 63) == 0)) { if (!update_progress(2, chunk_index, m_num_chunks)) return; @@ -719,7 +719,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Generating color training vectors"); + console::info("Generating color training vectors"); #endif const float r_scale = .5f; @@ -804,7 +804,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Begin color cluster analysis"); + console::info("Begin color cluster analysis"); timer t; t.start(); #endif @@ -816,7 +816,7 @@ namespace crnlib if (m_params.m_debugging) { double total_time = t.get_elapsed_secs(); - console::info(L"Codebook gen time: %3.3fs, Total color clusters: %u", total_time, vq.get_codebook_size()); + console::info("Codebook gen time: %3.3fs, Total color clusters: %u", total_time, vq.get_codebook_size()); } #endif @@ -824,7 +824,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Begin color cluster assignment"); + console::info("Begin color cluster assignment"); #endif assign_color_endpoint_clusters_state state(vq, training_vecs); @@ -850,7 +850,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Completed color cluster assignment"); + console::info("Completed color cluster assignment"); #endif return true; @@ -868,7 +868,7 @@ namespace crnlib if (m_canceled) return; - if ((get_current_thread_id() == m_main_thread_id) && ((chunk_index & 63) == 0)) + if ((crn_get_current_thread_id() == m_main_thread_id) && ((chunk_index & 63) == 0)) { if (!update_progress(7, m_num_chunks * a + chunk_index, m_num_chunks * m_num_alpha_blocks)) return; @@ -899,7 +899,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Generating alpha training vectors"); + console::info("Generating alpha training vectors"); #endif determine_alpha_endpoint_clusters_state state; @@ -966,7 +966,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Begin alpha cluster analysis"); + console::info("Begin alpha cluster analysis"); timer t; t.start(); #endif @@ -978,7 +978,7 @@ namespace crnlib if (m_params.m_debugging) { double total_time = t.get_elapsed_secs(); - console::info(L"Codebook gen time: %3.3fs, Total alpha clusters: %u", total_time, state.m_vq.get_codebook_size()); + console::info("Codebook gen time: %3.3fs, Total alpha clusters: %u", total_time, state.m_vq.get_codebook_size()); } #endif @@ -986,7 +986,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Begin alpha cluster assignment"); + console::info("Begin alpha cluster assignment"); #endif for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++) @@ -1013,7 +1013,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Completed alpha cluster assignment"); + console::info("Completed alpha cluster assignment"); #endif return true; @@ -1040,7 +1040,7 @@ namespace crnlib if (m_canceled) return; - if ((get_current_thread_id() == m_main_thread_id) && ((cluster_index & 63) == 0)) + if ((crn_get_current_thread_id() == m_main_thread_id) && ((cluster_index & 63) == 0)) { if (!update_progress(3, cluster_index, m_color_clusters.size())) return; @@ -1151,7 +1151,7 @@ namespace crnlib if (m_params.m_debugging) { if (total_empty_clusters) - console::warning(L"Total empty color clusters: %u", total_empty_clusters); + console::warning("Total empty color clusters: %u", total_empty_clusters); } #endif } @@ -1163,7 +1163,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Computing optimal color cluster endpoints"); + console::info("Computing optimal color cluster endpoints"); #endif for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++) @@ -1192,7 +1192,7 @@ namespace crnlib if (m_canceled) return; - if ((get_current_thread_id() == m_main_thread_id) && ((cluster_index & 63) == 0)) + if ((crn_get_current_thread_id() == m_main_thread_id) && ((cluster_index & 63) == 0)) { if (!update_progress(8, cluster_index, m_alpha_clusters.size())) return; @@ -1311,7 +1311,7 @@ namespace crnlib if (m_params.m_debugging) { if (total_empty_clusters) - console::warning(L"Total empty alpha clusters: %u", total_empty_clusters); + console::warning("Total empty alpha clusters: %u", total_empty_clusters); } #endif } @@ -1323,7 +1323,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Computing optimal alpha cluster endpoints"); + console::info("Computing optimal alpha cluster endpoints"); #endif for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++) @@ -1461,7 +1461,7 @@ namespace crnlib if (m_canceled) return; - if ((get_current_thread_id() == m_main_thread_id) && ((chunk_index & 127) == 0)) + if ((crn_get_current_thread_id() == m_main_thread_id) && ((chunk_index & 127) == 0)) { if (!update_progress(12 + comp_chunk_index, chunk_index, m_num_chunks)) return; @@ -1632,7 +1632,7 @@ namespace crnlib { #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Computing selector training vectors"); + console::info("Computing selector training vectors"); #endif const uint cColorDistToWeight = 2000; @@ -1775,7 +1775,7 @@ namespace crnlib if (m_params.m_debugging) { double total_time = t.get_elapsed_secs(); - console::info(L"Codebook gen time: %3.3fs, Selector codebook size: %u", total_time, selector_vq.get_codebook_size()); + console::info("Codebook gen time: %3.3fs, Selector codebook size: %u", total_time, selector_vq.get_codebook_size()); } #endif @@ -1827,7 +1827,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Refining quantized color selectors"); + console::info("Refining quantized color selectors"); #endif uint total_refined_selectors = 0; @@ -1917,7 +1917,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Total refined pixels: %u, selectors: %u out of %u", total_refined_pixels, total_refined_selectors, total_selectors); + console::info("Total refined pixels: %u, selectors: %u out of %u", total_refined_pixels, total_refined_selectors, total_selectors); #endif return true; @@ -1930,7 +1930,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Refining quantized alpha selectors"); + console::info("Refining quantized alpha selectors"); #endif uint total_refined_selectors = 0; @@ -2021,7 +2021,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Total refined pixels: %u, selectors: %u out of %u", total_refined_pixels, total_refined_selectors, total_selectors); + console::info("Total refined pixels: %u, selectors: %u out of %u", total_refined_pixels, total_refined_selectors, total_selectors); #endif return true; @@ -2037,7 +2037,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Refining quantized color endpoints"); + console::info("Refining quantized color endpoints"); #endif for (uint cluster_index = 0; cluster_index < m_color_clusters.size(); cluster_index++) @@ -2138,7 +2138,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Total refined pixels: %u, endpoints: %u out of %u", total_refined_pixels, total_refined_tiles, m_color_clusters.size()); + console::info("Total refined pixels: %u, endpoints: %u out of %u", total_refined_pixels, total_refined_tiles, m_color_clusters.size()); #endif return true; @@ -2153,7 +2153,7 @@ namespace crnlib uint total_refined_pixels = 0; #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Refining quantized alpha endpoints"); + console::info("Refining quantized alpha endpoints"); #endif for (uint cluster_index = 0; cluster_index < m_alpha_clusters.size(); cluster_index++) @@ -2257,7 +2257,7 @@ namespace crnlib #if CRNLIB_ENABLE_DEBUG_MESSAGES if (m_params.m_debugging) - console::info(L"Total refined pixels: %u, endpoints: %u out of %u", total_refined_pixels, total_refined_tiles, m_alpha_clusters.size()); + console::info("Total refined pixels: %u, endpoints: %u out of %u", total_refined_pixels, total_refined_tiles, m_alpha_clusters.size()); #endif return true; @@ -2515,7 +2515,7 @@ namespace crnlib bool dxt_hc::update_progress(uint phase_index, uint subphase_index, uint subphase_total) { - CRNLIB_ASSERT(get_current_thread_id() == m_main_thread_id); + CRNLIB_ASSERT(crn_get_current_thread_id() == m_main_thread_id); if (!m_params.m_pProgress_func) return true; diff --git a/crnlib/crn_dxt_hc.h b/crnlib/crn_dxt_hc.h index 0d0bb26..a421a4b 100644 --- a/crnlib/crn_dxt_hc.h +++ b/crnlib/crn_dxt_hc.h @@ -9,8 +9,7 @@ #include "crn_image.h" #include "crn_dxt_hc_common.h" #include "crn_tree_clusterizer.h" -#include "crn_task_pool.h" -#include "crn_spinlock.h" +#include "crn_threading.h" #define CRN_NO_FUNCTION_DEFINITIONS #include "../inc/crnlib.h" @@ -163,8 +162,8 @@ namespace crnlib uint8 m_selectors[cBlockPixelHeight][cBlockPixelWidth]; - uint8 get_by_index(uint i) const { CRNLIB_ASSERT(i < (cBlockPixelWidth * cBlockPixelHeight)); return *(&m_selectors[0][0] + i); } - void set_by_index(uint i, uint v) { CRNLIB_ASSERT(i < (cBlockPixelWidth * cBlockPixelHeight)); *(&m_selectors[0][0] + i) = static_cast(v); } + uint8 get_by_index(uint i) const { CRNLIB_ASSERT(i < (cBlockPixelWidth * cBlockPixelHeight)); const uint8* p = (const uint8*)m_selectors; return *(p + i); } + void set_by_index(uint i, uint v) { CRNLIB_ASSERT(i < (cBlockPixelWidth * cBlockPixelHeight)); uint8* p = (uint8*)m_selectors; *(p + i) = static_cast(v); } }; typedef crnlib::vector selectors_vec; @@ -272,9 +271,9 @@ namespace crnlib }; compressed_chunk_vec m_compressed_chunks[cNumCompressedChunkVecs]; - int32 m_encoding_hist[cNumChunkEncodings]; + volatile atomic32_t m_encoding_hist[cNumChunkEncodings]; - int32 m_total_tiles; + atomic32_t m_total_tiles; void compress_dxt1_block( dxt1_endpoint_optimizer::results& results, @@ -350,7 +349,7 @@ namespace crnlib pixel_chunk_vec m_dbg_chunk_pixels_final; - uint32 m_main_thread_id; + crn_thread_id_t m_main_thread_id; bool m_canceled; task_pool* m_pTask_pool; diff --git a/crnlib/crn_dxt_image.cpp b/crnlib/crn_dxt_image.cpp index d3f395d..7e3e225 100644 --- a/crnlib/crn_dxt_image.cpp +++ b/crnlib/crn_dxt_image.cpp @@ -7,8 +7,8 @@ #endif #include "crn_ryg_dxt.hpp" #include "crn_dxt_fast.h" -#include "crn_task_pool.h" #include "crn_console.h" +#include "crn_threading.h" #if CRNLIB_SUPPORT_ATI_COMPRESS #ifdef _DLL @@ -216,8 +216,8 @@ namespace crnlib dxt_format m_fmt; const image_u8* m_pImg; const dxt_image::pack_params* m_pParams; - uint32 m_main_thread; - int32 m_canceled; + crn_thread_id_t m_main_thread; + atomic32_t m_canceled; }; void dxt_image::init_task(uint64 data, void* pData_ptr) @@ -227,7 +227,7 @@ namespace crnlib const image_u8& img = *pInit_params->m_pImg; const pack_params& p = *pInit_params->m_pParams; - const bool is_main_thread = (get_current_thread_id() == pInit_params->m_main_thread); + const bool is_main_thread = (crn_get_current_thread_id() == pInit_params->m_main_thread); uint block_index = 0; @@ -252,7 +252,7 @@ namespace crnlib prev_progress_percentage = progress_percentage; if (!(p.m_pProgress_callback)(progress_percentage, p.m_pProgress_callback_user_data_ptr)) { - interlocked_exchange32(&pInit_params->m_canceled, CRNLIB_TRUE); + atomic_exchange32(&pInit_params->m_canceled, CRNLIB_TRUE); return; } } @@ -351,7 +351,7 @@ namespace crnlib if (fmt == cDXT1A) { - options.bDXT1UseAlpha = TRUE; + options.bDXT1UseAlpha = true; options.nAlphaThreshold = (ATI_TC_BYTE)p.m_dxt1a_alpha_threshold; } options.bDisableMultiThreading = (p.m_num_helper_threads == 0); @@ -370,7 +370,7 @@ namespace crnlib if (p.m_perceptual) { - options.bUseChannelWeighting = TRUE; + options.bUseChannelWeighting = true; options.fWeightingRed = .212671f; options.fWeightingGreen = .715160f; options.fWeightingBlue = .072169f; @@ -405,7 +405,7 @@ namespace crnlib init_params.m_fmt = fmt; init_params.m_pImg = &img; init_params.m_pParams = &p; - init_params.m_main_thread = get_current_thread_id(); + init_params.m_main_thread = crn_get_current_thread_id(); init_params.m_canceled = false; for (uint i = 0; i <= p.m_num_helper_threads; i++) @@ -1135,7 +1135,7 @@ namespace crnlib int dxt_image::get_block_endpoints(uint block_x, uint block_y, uint element_index, color_quad_u8& low_endpoint, color_quad_u8& high_endpoint, bool scaled) const { - uint l, h; + uint l = 0, h = 0; get_block_endpoints(block_x, block_y, element_index, l, h); switch (m_element_type[element_index]) diff --git a/crnlib/crn_dxt_image.h b/crnlib/crn_dxt_image.h index 9c68dc9..6be139b 100644 --- a/crnlib/crn_dxt_image.h +++ b/crnlib/crn_dxt_image.h @@ -61,8 +61,8 @@ namespace crnlib uint get_le_word(uint index) const { CRNLIB_ASSERT(index < 4); return m_bytes[index*2] | (m_bytes[index * 2 + 1] << 8); } uint get_be_word(uint index) const { CRNLIB_ASSERT(index < 4); return m_bytes[index*2 + 1] | (m_bytes[index * 2] << 8); } - void set_le_word(uint index, uint val) { CRNLIB_ASSERT((index < 4) && (val <= UINT16_MAX)); m_bytes[index*2] = static_cast(val & 0xFF); m_bytes[index * 2 + 1] = static_cast((val >> 8) & 0xFF); } - void set_be_word(uint index, uint val) { CRNLIB_ASSERT((index < 4) && (val <= UINT16_MAX)); m_bytes[index*2+1] = static_cast(val & 0xFF); m_bytes[index * 2] = static_cast((val >> 8) & 0xFF); } + void set_le_word(uint index, uint val) { CRNLIB_ASSERT((index < 4) && (val <= cUINT16_MAX)); m_bytes[index*2] = static_cast(val & 0xFF); m_bytes[index * 2 + 1] = static_cast((val >> 8) & 0xFF); } + void set_be_word(uint index, uint val) { CRNLIB_ASSERT((index < 4) && (val <= cUINT16_MAX)); m_bytes[index*2+1] = static_cast(val & 0xFF); m_bytes[index * 2] = static_cast((val >> 8) & 0xFF); } void clear() { diff --git a/crnlib/crn_dynamic_stream.h b/crnlib/crn_dynamic_stream.h index b5a1076..f134b21 100644 --- a/crnlib/crn_dynamic_stream.h +++ b/crnlib/crn_dynamic_stream.h @@ -8,32 +8,32 @@ namespace crnlib class dynamic_stream : public data_stream { public: - dynamic_stream(uint initial_size, const wchar_t* pName = L"dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) : + dynamic_stream(uint initial_size, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) : data_stream(pName, attribs), m_ofs(0) { open(initial_size, pName, attribs); } - - dynamic_stream(const void* pBuf, uint size, const wchar_t* pName = L"dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) : + + dynamic_stream(const void* pBuf, uint size, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) : data_stream(pName, attribs), m_ofs(0) { open(pBuf, size, pName, attribs); } - - dynamic_stream() : + + dynamic_stream() : data_stream(), m_ofs(0) { open(); } - + virtual ~dynamic_stream() { } - - bool open(uint initial_size = 0, const wchar_t* pName = L"dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) + + bool open(uint initial_size = 0, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) { close(); @@ -41,24 +41,24 @@ namespace crnlib m_buf.clear(); m_buf.resize(initial_size); m_ofs = 0; - m_name.set(pName ? pName : L"dynamic_stream"); + m_name.set(pName ? pName : "dynamic_stream"); m_attribs = static_cast(attribs); return true; } - - bool reopen(const wchar_t* pName, uint attribs) + + bool reopen(const char* pName, uint attribs) { if (!m_opened) { return open(0, pName, attribs); } - - m_name.set(pName ? pName : L"dynamic_stream"); + + m_name.set(pName ? pName : "dynamic_stream"); m_attribs = static_cast(attribs); return true; } - - bool open(const void* pBuf, uint size, const wchar_t* pName = L"dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) + + bool open(const void* pBuf, uint size, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) { if (!m_opened) { @@ -70,14 +70,14 @@ namespace crnlib memcpy(&m_buf[0], pBuf, size); } m_ofs = 0; - m_name.set(pName ? pName : L"dynamic_stream"); + m_name.set(pName ? pName : "dynamic_stream"); m_attribs = static_cast(attribs); return true; } - + return false; } - + virtual bool close() { if (m_opened) @@ -87,10 +87,10 @@ namespace crnlib m_ofs = 0; return true; } - + return false; } - + const crnlib::vector& get_buf() const { return m_buf; } crnlib::vector& get_buf() { return m_buf; } @@ -101,102 +101,102 @@ namespace crnlib m_buf.reserve(size); } } - + virtual const void* get_ptr() const { return m_buf.empty() ? NULL : &m_buf[0]; } - + virtual uint read(void* pBuf, uint len) { CRNLIB_ASSERT(pBuf && (len <= 0x7FFFFFFF)); - + if ((!m_opened) || (!is_readable()) || (!len)) return 0; - + CRNLIB_ASSERT(m_ofs <= m_buf.size()); - + uint bytes_left = m_buf.size() - m_ofs; - + len = math::minimum(len, bytes_left); - + if (len) memcpy(pBuf, &m_buf[m_ofs], len); - + m_ofs += len; - + return len; } - + virtual uint write(const void* pBuf, uint len) { CRNLIB_ASSERT(pBuf && (len <= 0x7FFFFFFF)); - + if ((!m_opened) || (!is_writable()) || (!len)) return 0; - + CRNLIB_ASSERT(m_ofs <= m_buf.size()); - + uint new_ofs = m_ofs + len; if (new_ofs > m_buf.size()) m_buf.resize(new_ofs); - + memcpy(&m_buf[m_ofs], pBuf, len); m_ofs = new_ofs; return len; } - + virtual bool flush() { if (!m_opened) return false; - + return true; } - virtual uint64 get_size() - { + virtual uint64 get_size() + { if (!m_opened) return 0; - - return m_buf.size(); + + return m_buf.size(); } - + virtual uint64 get_remaining() { if (!m_opened) return 0; - + CRNLIB_ASSERT(m_ofs <= m_buf.size()); - + return m_buf.size() - m_ofs; } - virtual uint64 get_ofs() + virtual uint64 get_ofs() { if (!m_opened) return 0; - + return m_ofs; } - - virtual bool seek(int64 ofs, bool relative) + + virtual bool seek(int64 ofs, bool relative) { if ((!m_opened) || (!is_seekable())) return false; - + int64 new_ofs = relative ? (m_ofs + ofs) : ofs; - + if (new_ofs < 0) return false; else if (new_ofs > m_buf.size()) return false; - + m_ofs = static_cast(new_ofs); - + post_seek(); - + return true; } - + private: crnlib::vector m_buf; uint m_ofs; diff --git a/crnlib/crn_dynamic_string.cpp b/crnlib/crn_dynamic_string.cpp index 464ef98..e3e76bd 100644 --- a/crnlib/crn_dynamic_string.cpp +++ b/crnlib/crn_dynamic_string.cpp @@ -1,10 +1,7 @@ // File: crn_dynamic_string.cpp // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" -#include "crn_dynamic_string.h" -#include "crn_dynamic_wstring.h" -#include "crn_winhdr.h" -#include +#include "crn_strutils.h" namespace crnlib { @@ -43,51 +40,6 @@ namespace crnlib set(other); } - dynamic_string::dynamic_string(const wchar_t* pStr) : - m_buf_size(0), m_len(0), m_pStr(NULL) - { - set(pStr); - } - - dynamic_string& dynamic_string::set(const wchar_t *pStr) - { - uint len = static_cast(wcslen(pStr)); - if (!len) - { - clear(); - return *this; - } - - const uint num_needed = WideCharToMultiByte(CP_ACP, 0, pStr, len, NULL, 0, NULL, NULL); - if (num_needed <= 0) - { - clear(); - return *this; - } - - if (!ensure_buf(num_needed, false)) - { - clear(); - return *this; - } - - const uint num_written = WideCharToMultiByte(CP_ACP, 0, pStr, len, get_ptr_raw(), num_needed, NULL, NULL); - CRNLIB_ASSERT(num_written == num_needed); - - get_ptr_raw()[num_written] = 0; - m_len = static_cast(num_written); - - check(); - - return *this; - } - - dynamic_wstring& dynamic_string::as_utf16(dynamic_wstring &buf) - { - buf.set(get_ptr()); - return buf; - } - void dynamic_string::clear() { check(); @@ -133,7 +85,7 @@ namespace crnlib { CRNLIB_ASSERT(p); - const int result = (case_sensitive ? strcmp : _stricmp)(get_ptr_priv(), p); + const int result = (case_sensitive ? strcmp : crn_stricmp)(get_ptr_priv(), p); if (result < 0) return -1; @@ -153,9 +105,9 @@ namespace crnlib CRNLIB_ASSERT(p); const uint len = math::minimum(max_len, static_cast(strlen(p))); - CRNLIB_ASSERT(len < UINT16_MAX); + CRNLIB_ASSERT(len < cUINT16_MAX); - if ((!len) || (len >= UINT16_MAX)) + if ((!len) || (len >= cUINT16_MAX)) clear(); else if ((m_pStr) && (p >= m_pStr) && (p < (m_pStr + m_buf_size))) { @@ -206,8 +158,11 @@ namespace crnlib bool dynamic_string::set_len(uint new_len, char fill_char) { - if ((new_len >= UINT16_MAX) || (!fill_char)) + if ((new_len >= cUINT16_MAX) || (!fill_char)) + { + CRNLIB_ASSERT(0); return false; + } uint cur_len = m_len; @@ -226,22 +181,41 @@ namespace crnlib return true; } + dynamic_string& dynamic_string::set_from_raw_buf_and_assume_ownership(char *pBuf, uint buf_size_in_chars, uint len_in_chars) + { + CRNLIB_ASSERT(buf_size_in_chars <= cUINT16_MAX); + CRNLIB_ASSERT(math::is_power_of_2(buf_size_in_chars) || (buf_size_in_chars == cUINT16_MAX)); + CRNLIB_ASSERT((len_in_chars + 1) <= buf_size_in_chars); + + clear(); + + m_pStr = pBuf; + m_buf_size = static_cast(buf_size_in_chars); + m_len = static_cast(len_in_chars); + + check(); + + return *this; + } + dynamic_string& dynamic_string::set_from_buf(const void* pBuf, uint buf_size) { CRNLIB_ASSERT(pBuf); - if (buf_size >= UINT16_MAX) + if (buf_size >= cUINT16_MAX) { clear(); return *this; } +#ifdef CRNLIB_BUILD_DEBUG if ((buf_size) && (memchr(pBuf, 0, buf_size) != NULL)) { CRNLIB_ASSERT(0); clear(); return *this; } +#endif if (ensure_buf(buf_size, false)) { @@ -569,9 +543,12 @@ namespace crnlib else { CRNLIB_ASSERT(m_buf_size); - CRNLIB_ASSERT((m_buf_size == UINT16_MAX) || math::is_power_of_2((uint32)m_buf_size)); + CRNLIB_ASSERT((m_buf_size == cUINT16_MAX) || math::is_power_of_2((uint32)m_buf_size)); CRNLIB_ASSERT(m_len < m_buf_size); + CRNLIB_ASSERT(!m_pStr[m_len]); +#if CRNLIB_SLOW_STRING_LEN_CHECKS CRNLIB_ASSERT(strlen(m_pStr) == m_len); +#endif } } #endif @@ -580,9 +557,9 @@ namespace crnlib { uint buf_size_needed = len + 1; - CRNLIB_ASSERT(buf_size_needed <= UINT16_MAX); + CRNLIB_ASSERT(buf_size_needed <= cUINT16_MAX); - if (buf_size_needed <= UINT16_MAX) + if (buf_size_needed <= cUINT16_MAX) { if (buf_size_needed > m_buf_size) expand_buf(buf_size_needed, preserve_contents); @@ -593,7 +570,7 @@ namespace crnlib bool dynamic_string::expand_buf(uint new_buf_size, bool preserve_contents) { - new_buf_size = math::minimum(UINT16_MAX, math::next_pow2(math::maximum(m_buf_size, new_buf_size))); + new_buf_size = math::minimum(cUINT16_MAX, math::next_pow2(math::maximum(m_buf_size, new_buf_size))); if (new_buf_size != m_buf_size) { @@ -625,8 +602,9 @@ namespace crnlib { uint buf_left = buf_size; - if (m_len > UINT16_MAX) - return -1; + //if (m_len > cUINT16_MAX) + // return -1; + CRNLIB_ASSUME(sizeof(m_len) == sizeof(uint16)); if (!utils::write_val((uint16)m_len, pBuf, buf_left, little_endian)) return -1; @@ -687,9 +665,4 @@ namespace crnlib swap(tmp); } - dynamic_string& dynamic_string::operator= (const dynamic_wstring& rhs) - { - return set(rhs.get_ptr()); - } - } // namespace crnlib diff --git a/crnlib/crn_dynamic_string.h b/crnlib/crn_dynamic_string.h index f0d6f36..e5eeac3 100644 --- a/crnlib/crn_dynamic_string.h +++ b/crnlib/crn_dynamic_string.h @@ -4,12 +4,9 @@ namespace crnlib { - class dynamic_wstring; - + enum { cMaxDynamicStringLen = cUINT16_MAX - 1 }; class dynamic_string { - friend class dynamic_wstring; - public: inline dynamic_string() : m_buf_size(0), m_len(0), m_pStr(NULL) { } dynamic_string(eVarArg dummy, const char* p, ...); @@ -19,25 +16,26 @@ namespace crnlib inline ~dynamic_string() { if (m_pStr) crnlib_delete_array(m_pStr); } - explicit dynamic_string(const wchar_t* pStr); - dynamic_string& set(const wchar_t *pStr); - dynamic_wstring& as_utf16(dynamic_wstring &buf); - // Truncates the string to 0 chars and frees the buffer. void clear(); void optimize(); // Truncates the string to 0 chars, but does not free the buffer. void empty(); + inline const char *assume_ownership() { const char *p = m_pStr; m_pStr = NULL; m_len = 0; m_buf_size = 0; return p; } inline uint get_len() const { return m_len; } inline bool is_empty() const { return !m_len; } inline const char* get_ptr() const { return m_pStr ? m_pStr : ""; } + inline const char* c_str() const { return get_ptr(); } inline const char* get_ptr_raw() const { return m_pStr; } inline char* get_ptr_raw() { return m_pStr; } + inline char front() const { return m_len ? m_pStr[0] : '\0'; } + inline char back() const { return m_len ? m_pStr[m_len - 1] : '\0'; } + inline char operator[] (uint i) const { CRNLIB_ASSERT(i <= m_len); return get_ptr()[i]; } inline operator size_t() const { return fast_hash(get_ptr(), m_len) ^ fast_hash(&m_len, sizeof(m_len)); } @@ -74,7 +72,6 @@ namespace crnlib dynamic_string& set_from_buf(const void* pBuf, uint buf_size); dynamic_string& operator= (const dynamic_string& rhs) { return set(rhs); } - dynamic_string& operator= (const dynamic_wstring& rhs); dynamic_string& operator= (const char* p) { return set(p); } dynamic_string& set_char(uint index, char c); @@ -130,6 +127,9 @@ namespace crnlib void translate_lf_to_crlf(); + static inline char *create_raw_buffer(uint& buf_size_in_chars); + static inline void free_raw_buffer(char *p) { crnlib_delete_array(p); } + dynamic_string& set_from_raw_buf_and_assume_ownership(char *pBuf, uint buf_size_in_chars, uint len_in_chars); private: uint16 m_buf_size; uint16 m_len; @@ -160,4 +160,14 @@ namespace crnlib a.swap(b); } + inline char *dynamic_string::create_raw_buffer(uint& buf_size_in_chars) + { + if (buf_size_in_chars > cUINT16_MAX) + { + CRNLIB_ASSERT(0); + return NULL; + } + buf_size_in_chars = math::minimum(cUINT16_MAX, math::next_pow2(buf_size_in_chars)); + return crnlib_new_array(buf_size_in_chars); + } } // namespace crnlib diff --git a/crnlib/crn_helpers.h b/crnlib/crn_helpers.h index 8a63176..a9e3322 100644 --- a/crnlib/crn_helpers.h +++ b/crnlib/crn_helpers.h @@ -30,7 +30,7 @@ namespace crnlib } template - void construct_array(T* p, uint n) + inline void construct_array(T* p, uint n) { T* q = p + n; for ( ; p != q; ++p) @@ -38,7 +38,7 @@ namespace crnlib } template - void construct_array(T* p, uint n, const U& init) + inline void construct_array(T* p, uint n, const U& init) { T* q = p + n; for ( ; p != q; ++p) diff --git a/crnlib/crn_huffman_codes.cpp b/crnlib/crn_huffman_codes.cpp index 2ebdc16..83f30aa 100644 --- a/crnlib/crn_huffman_codes.cpp +++ b/crnlib/crn_huffman_codes.cpp @@ -228,7 +228,7 @@ namespace crnlib sym_freq& sf = state.syms0[num_used_syms]; sf.m_left = (uint16)i; - sf.m_right = UINT16_MAX; + sf.m_right = cUINT16_MAX; sf.m_freq = freq; num_used_syms++; } @@ -263,8 +263,8 @@ namespace crnlib #else // Dummy node sym_freq& sf = state.syms0[num_used_syms]; - sf.m_left = UINT16_MAX; - sf.m_right = UINT16_MAX; + sf.m_left = cUINT16_MAX; + sf.m_right = cUINT16_MAX; sf.m_freq = UINT_MAX; uint next_internal_node = num_used_syms + 1; diff --git a/crnlib/crn_image_utils.cpp b/crnlib/crn_image_utils.cpp index 60e05a7..603f8c5 100644 --- a/crnlib/crn_image_utils.cpp +++ b/crnlib/crn_image_utils.cpp @@ -6,6 +6,8 @@ #include "crn_resampler.h" #include "crn_threaded_resampler.h" #include "crn_strutils.h" +#include "crn_file_utils.h" +#include "crn_threading.h" #define STBI_HEADER_FILE_ONLY #include "crn_stb_image.cpp" @@ -18,10 +20,10 @@ namespace crnlib namespace image_utils { - bool load_from_file_stb(const wchar_t* pFilename, image_u8& img) + bool load_from_file_stb(const char* pFilename, image_u8& img) { int x = 0, y = 0, n = 0; - unsigned char* pData = stbi_load_w(pFilename, &x, &y, &n, 4); + unsigned char* pData = stbi_load(pFilename, &x, &y, &n, 4); if (!pData) return false; @@ -66,20 +68,20 @@ namespace crnlib return true; } - bool save_to_file_stb(const wchar_t* pFilename, const image_u8& img, uint save_flags, int comp_index) + bool save_to_file_stb(const char* pFilename, const image_u8& img, uint save_flags, int comp_index) { if (!img.get_width()) return false; bool bSaveBMP = false; - dynamic_wstring ext(pFilename); - if (get_extension(ext)) + dynamic_string ext(pFilename); + if (file_utils::get_extension(ext)) { - if (ext == L"bmp") + if (ext == "bmp") bSaveBMP = true; - else if (ext != L"tga") + else if (ext != "tga") { - console::error(L"crnlib::image_utils::save_to_file_stb: Can only write .BMP or .TGA files!\n"); + console::error("crnlib::image_utils::save_to_file_stb: Can only write .BMP or .TGA files!\n"); return false; } } @@ -114,7 +116,7 @@ namespace crnlib } } - return (bSaveBMP ? stbi_write_bmp_w : stbi_write_tga_w)(pFilename, img.get_width(), img.get_height(), 1, &temp[0]) == CRNLIB_TRUE; + return (bSaveBMP ? stbi_write_bmp : stbi_write_tga)(pFilename, img.get_width(), img.get_height(), 1, &temp[0]) == CRNLIB_TRUE; } else if ((!img.is_component_valid(3)) || (save_flags & cSaveIgnoreAlpha)) { @@ -138,27 +140,27 @@ namespace crnlib } } - return (bSaveBMP ? stbi_write_bmp_w : stbi_write_tga_w)(pFilename, img.get_width(), img.get_height(), 3, &temp[0]) == CRNLIB_TRUE; + return (bSaveBMP ? stbi_write_bmp : stbi_write_tga)(pFilename, img.get_width(), img.get_height(), 3, &temp[0]) == CRNLIB_TRUE; } else { - return (bSaveBMP ? stbi_write_bmp_w : stbi_write_tga_w)(pFilename, img.get_width(), img.get_height(), 4, img.get_ptr()) == CRNLIB_TRUE; + return (bSaveBMP ? stbi_write_bmp : stbi_write_tga)(pFilename, img.get_width(), img.get_height(), 4, img.get_ptr()) == CRNLIB_TRUE; } } - bool load_from_file(image_u8& dest, const wchar_t* pFilename, int flags) + bool load_from_file(image_u8& dest, const char* pFilename, int flags) { flags; return image_utils::load_from_file_stb(pFilename, dest); } - bool save_to_grayscale_file(const wchar_t* pFilename, const image_u8& src, int component, int flags) + bool save_to_grayscale_file(const char* pFilename, const image_u8& src, int component, int flags) { flags; return image_utils::save_to_file_stb(pFilename, src, image_utils::cSaveGrayscale, component); } - bool save_to_file(const wchar_t* pFilename, const image_u8& src, int flags, bool ignore_alpha) + bool save_to_file(const char* pFilename, const image_u8& src, int flags, bool ignore_alpha) { if (src.is_grayscale()) return save_to_grayscale_file(pFilename, src, cSaveLuma, flags); @@ -220,7 +222,7 @@ namespace crnlib } } - bool is_normal_map(const image_u8& img, const wchar_t* pFilename) + bool is_normal_map(const image_u8& img, const char* pFilename) { float score = 0.0f; @@ -259,13 +261,13 @@ namespace crnlib if (pFilename) { - dynamic_wstring str(pFilename); + dynamic_string str(pFilename); str.tolower(); - if (str.contains(L"normal") || str.contains(L"local") || str.contains(L"nmap")) + if (str.contains("normal") || str.contains("local") || str.contains("nmap")) score += 1.0f; - if (str.contains(L"diffuse") || str.contains(L"spec") || str.contains(L"gloss")) + if (str.contains("diffuse") || str.contains("spec") || str.contains("gloss")) score -= 1.0f; } @@ -712,32 +714,34 @@ namespace crnlib if (!total_blocks) return 0.0f; - //save_to_file_stb(L"ssim.tga", yimg, cSaveGrayscale); + //save_to_file_stb("ssim.tga", yimg, cSaveGrayscale); return total_ssim / total_blocks; } void print_ssim(const image_u8& src_img, const image_u8& dst_img) { - double y_ssim = compute_ssim(src_img, dst_img, -1); - console::printf(L"Luma MSSIM: %f, Scaled: %f", y_ssim, (y_ssim - .8f) / .2f); + src_img; + dst_img; + //double y_ssim = compute_ssim(src_img, dst_img, -1); + //console::printf("Luma MSSIM: %f, Scaled: %f", y_ssim, (y_ssim - .8f) / .2f); //double r_ssim = compute_ssim(src_img, dst_img, 0); - //console::printf(L" R MSSIM: %f", r_ssim); + //console::printf(" R MSSIM: %f", r_ssim); //double g_ssim = compute_ssim(src_img, dst_img, 1); - //console::printf(L" G MSSIM: %f", g_ssim); + //console::printf(" G MSSIM: %f", g_ssim); //double b_ssim = compute_ssim(src_img, dst_img, 2); - //console::printf(L" B MSSIM: %f", b_ssim); + //console::printf(" B MSSIM: %f", b_ssim); } - void error_metrics::print(const wchar_t* pName) const + void error_metrics::print(const char* pName) const { if (mPeakSNR >= cInfinitePSNR) - console::printf(L"%s Error: Max: %3u, Mean: %3.3f, RMS: %3.3f, PSNR: Infinite", pName, mMax, mMean, mRootMeanSquared); + console::printf("%s Error: Max: %3u, Mean: %3.3f, MSE: %3.3f, RMS: %3.3f, PSNR: Infinite", pName, mMax, mMean, mMeanSquared, mRootMeanSquared); else - console::printf(L"%s Error: Max: %3u, Mean: %3.3f, RMS: %3.3f, PSNR: %3.3f", pName, mMax, mMean, mRootMeanSquared, mPeakSNR); + console::printf("%s Error: Max: %3u, Mean: %3.3f, MSE: %3.3f, RMS: %3.3f, PSNR: %3.3f", pName, mMax, mMean, mMeanSquared, mRootMeanSquared, mPeakSNR); } bool error_metrics::compute(const image_u8& a, const image_u8& b, uint first_channel, uint num_channels, bool average_component_error) @@ -808,35 +812,35 @@ namespace crnlib void print_image_metrics(const image_u8& src_img, const image_u8& dst_img) { if ( (!src_img.get_width()) || (!dst_img.get_height()) || (src_img.get_width() != dst_img.get_width()) || (src_img.get_height() != dst_img.get_height()) ) - console::printf(L"print_image_metrics: Image resolutions don't match exactly (%ux%u) vs. (%ux%u)", src_img.get_width(), src_img.get_height(), dst_img.get_width(), dst_img.get_height()); + console::printf("print_image_metrics: Image resolutions don't match exactly (%ux%u) vs. (%ux%u)", src_img.get_width(), src_img.get_height(), dst_img.get_width(), dst_img.get_height()); image_utils::error_metrics error_metrics; if (src_img.has_rgb() || dst_img.has_rgb()) { error_metrics.compute(src_img, dst_img, 0, 3, false); - error_metrics.print(L"RGB Total "); + error_metrics.print("RGB Total "); error_metrics.compute(src_img, dst_img, 0, 3, true); - error_metrics.print(L"RGB Average"); + error_metrics.print("RGB Average"); error_metrics.compute(src_img, dst_img, 0, 0); - error_metrics.print(L"Luma "); + error_metrics.print("Luma "); error_metrics.compute(src_img, dst_img, 0, 1); - error_metrics.print(L"Red "); + error_metrics.print("Red "); error_metrics.compute(src_img, dst_img, 1, 1); - error_metrics.print(L"Green "); + error_metrics.print("Green "); error_metrics.compute(src_img, dst_img, 2, 1); - error_metrics.print(L"Blue "); + error_metrics.print("Blue "); } if (src_img.has_alpha() || dst_img.has_alpha()) { error_metrics.compute(src_img, dst_img, 3, 1); - error_metrics.print(L"Alpha "); + error_metrics.print("Alpha "); } } diff --git a/crnlib/crn_image_utils.h b/crnlib/crn_image_utils.h index ac50f08..08ecc60 100644 --- a/crnlib/crn_image_utils.h +++ b/crnlib/crn_image_utils.h @@ -6,12 +6,12 @@ namespace crnlib { enum pixel_format; - + namespace image_utils { - bool load_from_file_stb(const wchar_t* pFilename, image_u8& img); - - enum + bool load_from_file_stb(const char* pFilename, image_u8& img); + + enum { cSaveIgnoreAlpha = 1, cSaveGrayscale = 2 @@ -19,18 +19,18 @@ namespace crnlib const int cSaveLuma = -1; - bool save_to_file_stb(const wchar_t* pFilename, const image_u8& img, uint save_flags = 0, int comp_index = cSaveLuma); - - bool load_from_file(image_u8& dest, const wchar_t* pFilename, int flags = 0); + bool save_to_file_stb(const char* pFilename, const image_u8& img, uint save_flags = 0, int comp_index = cSaveLuma); - bool save_to_grayscale_file(const wchar_t* pFilename, const image_u8& src, int component, int flags = 0); + bool load_from_file(image_u8& dest, const char* pFilename, int flags = 0); + + bool save_to_grayscale_file(const char* pFilename, const image_u8& src, int component, int flags = 0); + + bool save_to_file(const char* pFilename, const image_u8& src, int flags = 0, bool ignore_alpha = false); - bool save_to_file(const wchar_t* pFilename, const image_u8& src, int flags = 0, bool ignore_alpha = false); - bool has_alpha(const image_u8& img); - bool is_normal_map(const image_u8& img, const wchar_t* pFilename = NULL); + bool is_normal_map(const image_u8& img, const char* pFilename = NULL); void renorm_normal_map(image_u8& img); - + struct resample_params { resample_params() : @@ -46,7 +46,7 @@ namespace crnlib m_multithreaded(true) { } - + uint m_dst_width; uint m_dst_height; const char* m_pFilter; @@ -58,40 +58,40 @@ namespace crnlib float m_source_gamma; bool m_multithreaded; }; - + bool resample_single_thread(const image_u8& src, image_u8& dst, const resample_params& params); bool resample_multithreaded(const image_u8& src, image_u8& dst, const resample_params& params); bool resample(const image_u8& src, image_u8& dst, const resample_params& params); - + bool compute_delta(image_u8& dest, image_u8& a, image_u8& b, uint scale = 2); - + class error_metrics { public: error_metrics() { utils::zero_this(this); } - - void print(const wchar_t* pName) const; - + + void print(const char* pName) const; + // If num_channels==0, luma error is computed. // If pHist != NULL, it must point to a 256 entry array. bool compute(const image_u8& a, const image_u8& b, uint first_channel, uint num_channels, bool average_component_error = true); - + uint mMax; double mMean; double mMeanSquared; double mRootMeanSquared; double mPeakSNR; - + inline bool operator== (const error_metrics& other) const { return mPeakSNR == other.mPeakSNR; } - + inline bool operator< (const error_metrics& other) const { return mPeakSNR < other.mPeakSNR; } - + inline bool operator> (const error_metrics& other) const { return mPeakSNR > other.mPeakSNR; @@ -99,43 +99,43 @@ namespace crnlib }; void print_image_metrics(const image_u8& src_img, const image_u8& dst_img); - + double compute_block_ssim(uint n, const uint8* pX, const uint8* pY); double compute_ssim(const image_u8& a, const image_u8& b, int channel_index); void print_ssim(const image_u8& src_img, const image_u8& dst_img); - + enum conversion_type { cConversion_Invalid = -1, - + cConversion_To_CCxY, cConversion_From_CCxY, - + cConversion_To_xGxR, cConversion_From_xGxR, - + cConversion_To_xGBR, cConversion_From_xGBR, - + cConversion_To_AGBR, cConversion_From_AGBR, - + cConversion_XY_to_XYZ, - + cConversion_Y_To_A, cConversion_A_To_RGBA, cConversion_Y_To_RGB, - + cConversionTotal }; - + void convert_image(image_u8& img, conversion_type conv_type); - + image_utils::conversion_type get_conversion_type(bool cooking, pixel_format fmt); image_utils::conversion_type get_image_conversion_type_from_crn_format(crn_format fmt); - + double compute_std_dev(uint n, const color_quad_u8* pPixels, uint first_channel, uint num_channels); } } diff --git a/crnlib/crn_lzma_codec.cpp b/crnlib/crn_lzma_codec.cpp index 3114879..a88d33f 100644 --- a/crnlib/crn_lzma_codec.cpp +++ b/crnlib/crn_lzma_codec.cpp @@ -4,17 +4,18 @@ #include "crn_lzma_codec.h" #include "crn_strutils.h" #include "crn_checksum.h" -#include "lzma_lzmalib.h" +#include "lzma_LzmaLib.h" +#include "crn_threading.h" namespace crnlib { - lzma_codec::lzma_codec() : + lzma_codec::lzma_codec() : m_pCompress(LzmaCompress), m_pUncompress(LzmaUncompress) { CRNLIB_ASSUME(cLZMAPropsSize == LZMA_PROPS_SIZE); } - + lzma_codec::~lzma_codec() { } @@ -23,29 +24,29 @@ namespace crnlib { if (n > 1024U*1024U*1024U) return false; - + uint max_comp_size = n + math::maximum(128, n >> 8); buf.resize(sizeof(header) + max_comp_size); - + header* pHDR = reinterpret_cast(&buf[0]); uint8* pComp_data = &buf[sizeof(header)]; - + utils::zero_object(*pHDR); - + pHDR->m_uncomp_size = n; pHDR->m_adler32 = adler32(p, n); - + if (n) { size_t destLen = 0; size_t outPropsSize = 0; int status = SZ_ERROR_INPUT_EOF; - + for (uint trial = 0; trial < 3; trial++) { destLen = max_comp_size; outPropsSize = cLZMAPropsSize; - + status = (*m_pCompress)(pComp_data, &destLen, reinterpret_cast(p), n, pHDR->m_lzma_props, &outPropsSize, -1, /* 0 <= level <= 9, default = 5 */ @@ -54,83 +55,87 @@ namespace crnlib -1, /* 0 <= lp <= 4, default = 0 */ -1, /* 0 <= pb <= 4, default = 2 */ -1, /* 5 <= fb <= 273, default = 32 */ +#ifdef WIN32 (g_number_of_processors > 1) ? 2 : 1 +#else + 1 +#endif ); if (status != SZ_ERROR_OUTPUT_EOF) break; - + max_comp_size += ((n+1)/2); buf.resize(sizeof(header) + max_comp_size); pHDR = reinterpret_cast(&buf[0]); pComp_data = &buf[sizeof(header)]; } - - if (status != SZ_OK) + + if (status != SZ_OK) { buf.clear(); return false; } - + pHDR->m_comp_size = static_cast(destLen); - + buf.resize(CRNLIB_SIZEOF_U32(header) + static_cast(destLen)); - } - + } + pHDR->m_sig = header::cSig; pHDR->m_checksum = static_cast(adler32((uint8*)pHDR + header::cChecksumSkipBytes, sizeof(header) - header::cChecksumSkipBytes)); - + return true; } bool lzma_codec::unpack(const void* p, uint n, crnlib::vector& buf) { buf.resize(0); - + if (n < sizeof(header)) return false; - + const header& hdr = *static_cast(p); if (hdr.m_sig != header::cSig) return false; - + if (static_cast(adler32((const uint8*)&hdr + header::cChecksumSkipBytes, sizeof(hdr) - header::cChecksumSkipBytes)) != hdr.m_checksum) return false; - + if (!hdr.m_uncomp_size) return true; - + if (!hdr.m_comp_size) return false; - + if (hdr.m_uncomp_size > 1024U*1024U*1024U) return false; - - if (!buf.try_resize(hdr.m_uncomp_size)) + + if (!buf.try_resize(hdr.m_uncomp_size)) return false; - + const uint8* pComp_data = static_cast(p) + sizeof(header); size_t srcLen = n - sizeof(header); if (srcLen < hdr.m_comp_size) return false; - + size_t destLen = hdr.m_uncomp_size; - + int status = (*m_pUncompress)(&buf[0], &destLen, pComp_data, &srcLen, - hdr.m_lzma_props, cLZMAPropsSize); - + hdr.m_lzma_props, cLZMAPropsSize); + if ((status != SZ_OK) || (destLen != hdr.m_uncomp_size)) { buf.clear(); - return false; + return false; } - + if (adler32(&buf[0], buf.size()) != hdr.m_adler32) { buf.clear(); return false; } - + return true; } diff --git a/crnlib/crn_lzma_codec.h b/crnlib/crn_lzma_codec.h index 79ac996..97bdcd1 100644 --- a/crnlib/crn_lzma_codec.h +++ b/crnlib/crn_lzma_codec.h @@ -12,14 +12,14 @@ namespace crnlib ~lzma_codec(); // Always available, because we're statically linking in lzmalib now vs. dynamically loading the DLL. - const bool is_initialized() const { return true; } + bool is_initialized() const { return true; } bool pack(const void* p, uint n, crnlib::vector& buf); bool unpack(const void* p, uint n, crnlib::vector& buf); private: - typedef int (__stdcall *LzmaCompressFuncPtr)(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + typedef int (CRNLIB_STDCALL *LzmaCompressFuncPtr)(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* default = (1 << 24) */ @@ -30,7 +30,7 @@ namespace crnlib int numThreads /* 1 or 2, default = 2 */ ); - typedef int (__stdcall *LzmaUncompressFuncPtr)(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, + typedef int (CRNLIB_STDCALL *LzmaUncompressFuncPtr)(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, const unsigned char *props, size_t propsSize); LzmaCompressFuncPtr m_pCompress; diff --git a/crnlib/crn_math.h b/crnlib/crn_math.h index 6da79a5..7d0e4c6 100644 --- a/crnlib/crn_math.h +++ b/crnlib/crn_math.h @@ -216,6 +216,14 @@ namespace crnlib void compute_lower_pow2_dim(int& width, int& height); void compute_upper_pow2_dim(int& width, int& height); + inline bool equal_tol(float a, float b, float t) + { + return fabs(a - b) < ((maximum(fabs(a), fabs(b)) + 1.0f) * t); + } + inline bool equal_tol(double a, double b, double t) + { + return fabs(a - b) < ((maximum(fabs(a), fabs(b)) + 1.0f) * t); + } } } // namespace crnlib diff --git a/crnlib/crn_mem.cpp b/crnlib/crn_mem.cpp index 02e73fe..b388ea2 100644 --- a/crnlib/crn_mem.cpp +++ b/crnlib/crn_mem.cpp @@ -1,15 +1,16 @@ // File: crn_mem.cpp // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" -#include "crn_spinlock.h" #include "crn_console.h" #include "../inc/crnlib.h" #include +#if CRNLIB_USE_WIN32_API #include "crn_winhdr.h" +#endif #define CRNLIB_MEM_STATS 0 -#ifndef CRNLIB_USE_WIN32_API +#if !CRNLIB_USE_WIN32_API #define _msize malloc_usable_size #endif @@ -59,7 +60,7 @@ namespace crnlib return new_total_allocated; } #endif // CRNLIB_MEM_STATS - + static void* crnlib_default_realloc(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data) { pUser_data; @@ -88,7 +89,6 @@ namespace crnlib #ifdef WIN32 p_new = ::_expand(p, size); #else - p_new = NULL; #endif @@ -121,15 +121,96 @@ namespace crnlib return p ? _msize(p) : 0; } +#if 0 + static __declspec(thread) void *g_pBuf; + static __declspec(thread) size_t g_buf_size; + static __declspec(thread) size_t g_buf_ofs; + + static size_t crnlib_nofree_msize(void* p, void* pUser_data) + { + pUser_data; + return p ? ((const size_t*)p)[-1] : 0; + } + + static void* crnlib_nofree_realloc(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data) + { + pUser_data; + + void* p_new; + + if (!p) + { + size = math::align_up_value(size, CRNLIB_MIN_ALLOC_ALIGNMENT); + size_t actual_size = sizeof(size_t)*2 + size; + size_t num_remaining = g_buf_size - g_buf_ofs; + if (num_remaining < actual_size) + { + g_buf_size = CRNLIB_MAX(actual_size, 32*1024*1024); + g_buf_ofs = 0; + g_pBuf = malloc(g_buf_size); + if (!g_pBuf) + return NULL; + } + + p_new = (uint8*)g_pBuf + g_buf_ofs; + ((size_t*)p_new)[1] = size; + p_new = (size_t*)p_new + 2; + g_buf_ofs += actual_size; + + if (pActual_size) + *pActual_size = size; + + CRNLIB_ASSERT(crnlib_nofree_msize(p_new, NULL) == size); + } + else if (!size) + { + if (pActual_size) + *pActual_size = 0; + p_new = NULL; + } + else + { + size_t cur_size = crnlib_nofree_msize(p, NULL); + p_new = p; + + if (!movable) + return NULL; + + if (size > cur_size) + { + p_new = crnlib_nofree_realloc(NULL, size, NULL, true, NULL); + if (!p_new) + return NULL; + + memcpy(p_new, p, cur_size); + + cur_size = size; + } + + if (pActual_size) + *pActual_size = cur_size; + } + + return p_new; + } + + static crn_realloc_func g_pRealloc = crnlib_nofree_realloc; + static crn_msize_func g_pMSize = crnlib_nofree_msize; +#else static crn_realloc_func g_pRealloc = crnlib_default_realloc; static crn_msize_func g_pMSize = crnlib_default_msize; +#endif static void* g_pUser_data; - + void crnlib_mem_error(const char* p_msg) { crnlib_assert(p_msg, __FILE__, __LINE__); } - + void* crnlib_malloc(size_t size) + { + return crnlib_malloc(size, NULL); + } + void* crnlib_malloc(size_t size, size_t* pActual_size) { size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U); @@ -182,7 +263,7 @@ namespace crnlib size_t cur_size = p ? (*g_pMSize)(p, g_pUser_data) : 0; CRNLIB_ASSERT(!p || (cur_size >= sizeof(uint32))); #endif - if ((size) && (size < sizeof(uint32))) + if ((size) && (size < sizeof(uint32))) size = sizeof(uint32); size_t actual_size = size; @@ -253,19 +334,19 @@ namespace crnlib return (*g_pMSize)(p, g_pUser_data); } - + void crnlib_print_mem_stats() { #if CRNLIB_MEM_STATS if (console::is_initialized()) { - console::debug(L"crnlib_print_mem_stats:"); - console::debug(L"Current blocks: %u, allocated: %I64u, max ever allocated: %I64i", g_total_blocks, (int64)g_total_allocated, (int64)g_max_allocated); + console::debug("crnlib_print_mem_stats:"); + console::debug("Current blocks: %u, allocated: " CRNLIB_INT64_FORMAT_SPECIFIER ", max ever allocated: " CRNLIB_INT64_FORMAT_SPECIFIER, g_total_blocks, (int64)g_total_allocated, (int64)g_max_allocated); } else { printf("crnlib_print_mem_stats:\n"); - printf("Current blocks: %u, allocated: %I64u, max ever allocated: %I64i\n", g_total_blocks, (int64)g_total_allocated, (int64)g_max_allocated); + printf("Current blocks: %u, allocated: " CRNLIB_INT64_FORMAT_SPECIFIER ", max ever allocated: " CRNLIB_INT64_FORMAT_SPECIFIER "\n", g_total_blocks, (int64)g_total_allocated, (int64)g_max_allocated); } #endif } diff --git a/crnlib/crn_mem.h b/crnlib/crn_mem.h index aea30f3..767192f 100644 --- a/crnlib/crn_mem.h +++ b/crnlib/crn_mem.h @@ -14,7 +14,8 @@ namespace crnlib const uint32 CRNLIB_MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U; #endif - void* crnlib_malloc(size_t size, size_t* pActual_size = NULL); + void* crnlib_malloc(size_t size); + void* crnlib_malloc(size_t size, size_t* pActual_size); void* crnlib_realloc(void* p, size_t size, size_t* pActual_size = NULL, bool movable = true); void* crnlib_calloc(size_t count, size_t size, size_t* pActual_size = NULL); void crnlib_free(void* p); @@ -183,3 +184,26 @@ namespace crnlib } } // namespace crnlib +#define CRNLIB_DEFINE_NEW_DELETE \ + void* operator new (size_t size) \ + { \ + void* p = crnlib::crnlib_malloc(size); \ + if (!p) \ + crnlib_fail("new: Out of memory!", __FILE__, __LINE__); \ + return p; \ + } \ + void* operator new[] (size_t size) \ + { \ + void* p = crnlib::crnlib_malloc(size); \ + if (!p) \ + crnlib_fail("new[]: Out of memory!", __FILE__, __LINE__); \ + return p; \ + } \ + void operator delete (void* p_block) \ + { \ + crnlib::crnlib_free(p_block); \ + } \ + void operator delete[] (void* p_block) \ + { \ + crnlib::crnlib_free(p_block); \ + } diff --git a/crnlib/crn_pixel_format.cpp b/crnlib/crn_pixel_format.cpp index 9191e20..88bda7f 100644 --- a/crnlib/crn_pixel_format.cpp +++ b/crnlib/crn_pixel_format.cpp @@ -41,36 +41,7 @@ namespace crnlib return g_all_pixel_formats[index]; } - const wchar_t* get_pixel_format_string(pixel_format fmt) - { - switch (fmt) - { - case PIXEL_FMT_INVALID: return L"INVALID"; - case PIXEL_FMT_DXT1: return L"DXT1"; - case PIXEL_FMT_DXT1A: return L"DXT1A"; - case PIXEL_FMT_DXT2: return L"DXT2"; - case PIXEL_FMT_DXT3: return L"DXT3"; - case PIXEL_FMT_DXT4: return L"DXT4"; - case PIXEL_FMT_DXT5: return L"DXT5"; - case PIXEL_FMT_3DC: return L"3DC"; - case PIXEL_FMT_DXN: return L"DXN"; - case PIXEL_FMT_DXT5A: return L"DXT5A"; - case PIXEL_FMT_DXT5_CCxY: return L"DXT5_CCxY"; - case PIXEL_FMT_DXT5_xGxR: return L"DXT5_xGxR"; - case PIXEL_FMT_DXT5_xGBR: return L"DXT5_xGBR"; - case PIXEL_FMT_DXT5_AGBR: return L"DXT5_AGBR"; - case PIXEL_FMT_R8G8B8: return L"R8G8B8"; - case PIXEL_FMT_A8R8G8B8: return L"A8R8G8B8"; - case PIXEL_FMT_A8: return L"A8"; - case PIXEL_FMT_L8: return L"L8"; - case PIXEL_FMT_A8L8: return L"A8L8"; - default: break; - } - CRNLIB_ASSERT(false); - return L"?"; - } - - const char* get_pixel_format_stringa(pixel_format fmt) + const char* get_pixel_format_string(pixel_format fmt) { switch (fmt) { @@ -99,27 +70,7 @@ namespace crnlib return "?"; } - const wchar_t* get_crn_format_string(crn_format fmt) - { - switch (fmt) - { - case cCRNFmtDXT1: return L"DXT1"; - case cCRNFmtDXT3: return L"DXT3"; - case cCRNFmtDXT5: return L"DXT5"; - case cCRNFmtDXT5_CCxY: return L"DXT5_CCxY"; - case cCRNFmtDXT5_xGBR: return L"DXT5_xGBR"; - case cCRNFmtDXT5_AGBR: return L"DXT5_AGBR"; - case cCRNFmtDXT5_xGxR: return L"DXT5_xGxR"; - case cCRNFmtDXN_XY: return L"DXN_XY"; - case cCRNFmtDXN_YX: return L"DXN_YX"; - case cCRNFmtDXT5A: return L"DXT5A"; - default: break; - } - CRNLIB_ASSERT(false); - return L"?"; - } - - const char* get_crn_format_stringa(crn_format fmt) + const char* get_crn_format_string(crn_format fmt) { switch (fmt) { diff --git a/crnlib/crn_pixel_format.h b/crnlib/crn_pixel_format.h index e7e0ae6..527c9b2 100644 --- a/crnlib/crn_pixel_format.h +++ b/crnlib/crn_pixel_format.h @@ -12,11 +12,9 @@ namespace crnlib uint get_num_formats(); pixel_format get_pixel_format_by_index(uint index); - const wchar_t* get_pixel_format_string(pixel_format fmt); - const char* get_pixel_format_stringa(pixel_format fmt); + const char* get_pixel_format_string(pixel_format fmt); - const wchar_t* get_crn_format_string(crn_format fmt); - const char* get_crn_format_stringa(crn_format fmt); + const char* get_crn_format_string(crn_format fmt); inline bool is_grayscale(pixel_format fmt) { diff --git a/crnlib/crn_platform.cpp b/crnlib/crn_platform.cpp index bc72041..4ffe271 100644 --- a/crnlib/crn_platform.cpp +++ b/crnlib/crn_platform.cpp @@ -1,6 +1,73 @@ // File: crn_platform.cpp // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" + +#if CRNLIB_USE_WIN32_API +#include "crn_winhdr.h" +#endif +#ifndef _MSC_VER +int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...) +{ + if (!sizeOfBuffer) + return 0; + + va_list args; + va_start(args, format); + int c = vsnprintf(buffer, sizeOfBuffer, format, args); + va_end(args); + + buffer[sizeOfBuffer - 1] = '\0'; + + if (c < 0) + return sizeOfBuffer - 1; + + return CRNLIB_MIN(c, (int)sizeOfBuffer - 1); +} + +int vsprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, va_list args) +{ + if (!sizeOfBuffer) + return 0; + + int c = vsnprintf(buffer, sizeOfBuffer, format, args); + + buffer[sizeOfBuffer - 1] = '\0'; + + if (c < 0) + return sizeOfBuffer - 1; + + return CRNLIB_MIN(c, (int)sizeOfBuffer - 1); +} + +char* strlwr(char* p) +{ + char *q = p; + while (*q) + { + char c = *q; + *q++ = tolower(c); + } + return p; +} + +char* strupr(char *p) +{ + char *q = p; + while (*q) + { + char c = *q; + *q++ = toupper(c); + } + return p; +} +#endif // __GNUC__ + +void crnlib_debug_break(void) +{ + CRNLIB_BREAKPOINT +} + +#if CRNLIB_USE_WIN32_API #include "crn_winhdr.h" bool crnlib_is_debugger_present(void) @@ -8,12 +75,18 @@ bool crnlib_is_debugger_present(void) return IsDebuggerPresent() != 0; } -void crnlib_debug_break(void) -{ - DebugBreak(); -} - void crnlib_output_debug_string(const char* p) { OutputDebugStringA(p); } +#else +bool crnlib_is_debugger_present(void) +{ + return false; +} + +void crnlib_output_debug_string(const char* p) +{ + puts(p); +} +#endif // CRNLIB_USE_WIN32_API diff --git a/crnlib/crn_platform.h b/crnlib/crn_platform.h index 8af9018..5e4b312 100644 --- a/crnlib/crn_platform.h +++ b/crnlib/crn_platform.h @@ -2,44 +2,6 @@ // See Copyright Notice and license at the end of inc/crnlib.h #pragma once -#ifdef CRNLIB_PLATFORM_PC - const bool c_crnlib_little_endian_platform = true; -#else - const bool c_crnlib_little_endian_platform = false; -#endif - -const bool c_crnlib_big_endian_platform = !c_crnlib_little_endian_platform; - -inline bool crnlib_is_little_endian() { return c_crnlib_little_endian_platform; } -inline bool crnlib_is_big_endian() { return c_crnlib_big_endian_platform; } - -inline bool crnlib_is_pc() -{ -#ifdef CRNLIB_PLATFORM_PC - return true; -#else - return false; -#endif -} - -inline bool crnlib_is_x86() -{ -#ifdef CRNLIB_PLATFORM_PC_X86 - return true; -#else - return false; -#endif -} - -inline bool crnlib_is_x64() -{ -#ifdef CRNLIB_PLATFORM_PC_X64 - return true; -#else - return false; -#endif -} - bool crnlib_is_debugger_present(void); void crnlib_debug_break(void); void crnlib_output_debug_string(const char* p); @@ -47,3 +9,85 @@ void crnlib_output_debug_string(const char* p); // actually in crnlib_assert.cpp void crnlib_assert(const char* pExp, const char* pFile, unsigned line); void crnlib_fail(const char* pExp, const char* pFile, unsigned line); + +#if CRNLIB_LITTLE_ENDIAN_CPU + const bool c_crnlib_little_endian_platform = true; +#else + const bool c_crnlib_little_endian_platform = false; +#endif + +const bool c_crnlib_big_endian_platform = !c_crnlib_little_endian_platform; + +#ifdef __GNUC__ + #define crn_fopen(pDstFile, f, m) *(pDstFile) = fopen64(f, m) + #define crn_fseek fseeko64 + #define crn_ftell ftello64 +#elif defined( _MSC_VER ) + #define crn_fopen(pDstFile, f, m) fopen_s(pDstFile, f, m) + #define crn_fseek _fseeki64 + #define crn_ftell _ftelli64 +#else + #define crn_fopen(pDstFile, f, m) *(pDstFile) = fopen(f, m) + #define crn_fseek(s, o, w) fseek(s, static_cast(o), w) + #define crn_ftell ftell +#endif + +#if CRNLIB_USE_WIN32_API + #define CRNLIB_BREAKPOINT DebugBreak(); + #define CRNLIB_BUILTIN_EXPECT(c, v) c +#elif defined(__GNUC__) + #define CRNLIB_BREAKPOINT asm("int $3"); + #define CRNLIB_BUILTIN_EXPECT(c, v) __builtin_expect(c, v) +#else + #define CRNLIB_BREAKPOINT + #define CRNLIB_BUILTIN_EXPECT(c, v) c +#endif + +#if defined(__GNUC__) + #define CRNLIB_ALIGNED(x) __attribute__((aligned(x))) +#elif defined(_MSC_VER) + #define CRNLIB_ALIGNED(x) __declspec(align(x)) +#else + #define CRNLIB_ALIGNED(x) +#endif + +#define CRNLIB_GET_ALIGNMENT(v) ((!sizeof(v)) ? 1 : (__alignof(v) ? __alignof(v) : sizeof(uint32))) + +#ifndef _MSC_VER + int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...); + int vsprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, va_list args); + char* strlwr(char* p); + char* strupr(char *p); + #define _stricmp strcasecmp + #define _strnicmp strncasecmp +#endif + +inline bool crnlib_is_little_endian() { return c_crnlib_little_endian_platform; } +inline bool crnlib_is_big_endian() { return c_crnlib_big_endian_platform; } + +inline bool crnlib_is_pc() +{ +#ifdef CRNLIB_PLATFORM_PC + return true; +#else + return false; +#endif +} + +inline bool crnlib_is_x86() +{ +#ifdef CRNLIB_PLATFORM_PC_X86 + return true; +#else + return false; +#endif +} + +inline bool crnlib_is_x64() +{ +#ifdef CRNLIB_PLATFORM_PC_X64 + return true; +#else + return false; +#endif +} diff --git a/crnlib/crn_prefix_coding.cpp b/crnlib/crn_prefix_coding.cpp index 6585ab1..e608ffc 100644 --- a/crnlib/crn_prefix_coding.cpp +++ b/crnlib/crn_prefix_coding.cpp @@ -156,7 +156,7 @@ namespace crnlib uint c = pCodesizes[i]; if (c) { - CRNLIB_ASSERT(next_code[c] <= UINT16_MAX); + CRNLIB_ASSERT(next_code[c] <= cUINT16_MAX); pCodes[i] = static_cast(next_code[c]++); CRNLIB_ASSERT(math::total_bits(pCodes[i]) <= pCodesizes[i]); @@ -300,7 +300,7 @@ namespace crnlib CRNLIB_ASSERT(t < (1U << table_bits)); - CRNLIB_ASSERT(pTables->m_lookup[t] == UINT32_MAX); + CRNLIB_ASSERT(pTables->m_lookup[t] == cUINT32_MAX); pTables->m_lookup[t] = sym_index | (codesize << 16U); } diff --git a/crnlib/crn_qdxt1.cpp b/crnlib/crn_qdxt1.cpp index 9ef780a..e092d88 100644 --- a/crnlib/crn_qdxt1.cpp +++ b/crnlib/crn_qdxt1.cpp @@ -61,7 +61,7 @@ namespace crnlib CRNLIB_ASSERT(n && pBlocks); - m_main_thread_id = get_current_thread_id(); + m_main_thread_id = crn_get_current_thread_id(); m_num_blocks = n; m_pBlocks = pBlocks; @@ -99,6 +99,11 @@ namespace crnlib if (debugging) debug_img.resize(num_chunks_x * cChunkPixelWidth, num_chunks_y * cChunkPixelHeight); + float adaptive_tile_color_psnr_derating = 1.5f; // was 2.4f + if ((level) && (adaptive_tile_color_psnr_derating > .25f)) + { + adaptive_tile_color_psnr_derating = math::maximum(.25f, adaptive_tile_color_psnr_derating / powf(3.1f, static_cast(level))); // was 3.0f + } for (uint chunk_y = 0; chunk_y < num_chunks_y; chunk_y++) { for (uint chunk_x = 0; chunk_x < num_chunks_x; chunk_x++) @@ -197,13 +202,8 @@ namespace crnlib if (mean_squared) peak_snr = math::clamp(log10(255.0f / root_mean_squared) * 20.0f, 0.0f, 500.0f); - float adaptive_tile_color_psnr_derating = 2.4f; //if (level) // adaptive_tile_color_psnr_derating = math::lerp(adaptive_tile_color_psnr_derating * .5f, .3f, math::maximum((level - 1) / float(m_params.m_num_mips - 2), 1.0f)); - if ((level) && (adaptive_tile_color_psnr_derating > .25f)) - { - adaptive_tile_color_psnr_derating = math::maximum(.25f, adaptive_tile_color_psnr_derating / powf(3.0f, static_cast(level))); - } float color_derating = math::lerp( 0.0f, adaptive_tile_color_psnr_derating, (g_chunk_encodings[e].m_num_tiles - 1) / 3.0f ); peak_snr = peak_snr - color_derating; @@ -306,7 +306,7 @@ namespace crnlib #if GENERATE_DEBUG_IMAGES if (debugging) - image_utils::save_to_file_stb(dynamic_wstring(cVarArg, L"debug_%u.tga", level).get_ptr(), debug_img, image_utils::cSaveIgnoreAlpha); + image_utils::save_to_file_stb(dynamic_string(cVarArg, "debug_%u.tga", level).get_ptr(), debug_img, image_utils::cSaveIgnoreAlpha); #endif } // level @@ -440,7 +440,7 @@ namespace crnlib if ((cluster_index & cluster_index_progress_mask) == 0) { - if (get_current_thread_id() == m_main_thread_id) + if (crn_get_current_thread_id() == m_main_thread_id) { if (!update_progress(cluster_index, m_endpoint_cluster_indices.size() - 1)) return; @@ -547,7 +547,8 @@ namespace crnlib { const uint block_index = indices[block_iter]; - const color_quad_u8* pSrc_pixels = &m_pBlocks[block_index].m_pixels[0][0]; + //const color_quad_u8* pSrc_pixels = &m_pBlocks[block_index].m_pixels[0][0]; + const color_quad_u8* pSrc_pixels = (const color_quad_u8*)m_pBlocks[block_index].m_pixels; for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++) { @@ -646,7 +647,7 @@ namespace crnlib if ((cluster_index & 255) == 0) { - if (get_current_thread_id() == m_main_thread_id) + if (crn_get_current_thread_id() == m_main_thread_id) { if (!update_progress(cluster_index, task_params.m_selector_cluster_indices.size() - 1)) return; @@ -681,7 +682,7 @@ namespace crnlib if (m_params.m_dxt1a_alpha_threshold > 0) { - const color_quad_u8* pSrc_pixels = &m_pBlocks[block_index].m_pixels[0][0]; + const color_quad_u8* pSrc_pixels = (const color_quad_u8*)m_pBlocks[block_index].m_pixels; for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++) { @@ -809,7 +810,7 @@ namespace crnlib { CRNLIB_ASSERT(m_num_blocks); - m_main_thread_id = get_current_thread_id(); + m_main_thread_id = crn_get_current_thread_id(); m_canceled = false; m_pDst_elements = pDst_elements; @@ -824,7 +825,7 @@ namespace crnlib const float quality = m_params.m_quality_level / (float)qdxt1_params::cMaxQuality; const float endpoint_quality = powf(quality, 1.8f * quality_power_mul); const float selector_quality = powf(quality, 1.65f * quality_power_mul); - + //const uint max_endpoint_clusters = math::clamp(static_cast(m_endpoint_clusterizer.get_codebook_size() * endpoint_quality), 128U, m_endpoint_clusterizer.get_codebook_size()); //const uint max_selector_clusters = math::clamp(static_cast(m_max_selector_clusters * selector_quality), 150U, m_max_selector_clusters); const uint max_endpoint_clusters = math::clamp(static_cast(m_endpoint_clusterizer.get_codebook_size() * endpoint_quality), 96U, m_endpoint_clusterizer.get_codebook_size()); diff --git a/crnlib/crn_qdxt1.h b/crnlib/crn_qdxt1.h index 8a03ed3..3051798 100644 --- a/crnlib/crn_qdxt1.h +++ b/crnlib/crn_qdxt1.h @@ -2,8 +2,6 @@ // See Copyright Notice and license at the end of inc/crnlib.h #pragma once #include "crn_dxt.h" -#include "crn_task_pool.h" -#include "crn_spinlock.h" #include "crn_hash_map.h" #include "crn_clusterizer.h" #include "crn_hash.h" @@ -17,8 +15,8 @@ namespace crnlib qdxt1_params() { clear(); - } - + } + void clear() { m_quality_level = cMaxQuality; @@ -44,27 +42,27 @@ namespace crnlib m_quality_level = quality_level; m_dxt1a_alpha_threshold = pp.m_dxt1a_alpha_threshold; } - + enum { cMaxQuality = cCRNMaxQualityLevel }; uint m_quality_level; - + uint m_dxt1a_alpha_threshold; crn_dxt_quality m_dxt_quality; bool m_perceptual; bool m_use_alpha_blocks; bool m_hierarchical; - + struct mip_desc { uint m_first_block; uint m_block_width; uint m_block_height; }; - + uint m_num_mips; enum { cMaxMips = 128 }; mip_desc m_mip_desc[cMaxMips]; - + typedef bool (*progress_callback_func)(uint percentage_completed, void* pProgress_data); progress_callback_func m_pProgress_func; void* m_pProgress_data; @@ -75,67 +73,67 @@ namespace crnlib class qdxt1 { CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(qdxt1); - + public: qdxt1(task_pool& task_pool); ~qdxt1(); - + void clear(); - + bool init(uint n, const dxt_pixel_block* pBlocks, const qdxt1_params& params); - + uint get_num_blocks() const { return m_num_blocks; } const dxt_pixel_block* get_blocks() const { return m_pBlocks; } - + bool pack(dxt1_block* pDst_elements, uint elements_per_block, const qdxt1_params& params, float quality_power_mul); private: task_pool* m_pTask_pool; - uint32 m_main_thread_id; + crn_thread_id_t m_main_thread_id; bool m_canceled; - + uint m_progress_start; uint m_progress_range; - + uint m_num_blocks; const dxt_pixel_block* m_pBlocks; - + dxt1_block* m_pDst_elements; uint m_elements_per_block; qdxt1_params m_params; - + uint m_max_selector_clusters; - + int m_prev_percentage_complete; - + typedef vec<6, float> vec6F; typedef clusterizer vec6F_clusterizer; vec6F_clusterizer m_endpoint_clusterizer; - + crnlib::vector< crnlib::vector > m_endpoint_cluster_indices; - + typedef vec<16, float> vec16F; typedef threaded_clusterizer vec16F_clusterizer; - + typedef vec16F_clusterizer::weighted_vec weighted_selector_vec; typedef vec16F_clusterizer::weighted_vec_array weighted_selector_vec_array; - + vec16F_clusterizer m_selector_clusterizer; - + crnlib::vector< crnlib::vector > m_cached_selector_cluster_indices[qdxt1_params::cMaxQuality + 1]; - + struct cluster_id { cluster_id() : m_hash(0) { - + } - + cluster_id(const crnlib::vector& indices) { set(indices); } - + void set(const crnlib::vector& indices) { m_cells.resize(indices.size()); @@ -145,29 +143,29 @@ namespace crnlib std::sort(m_cells.begin(), m_cells.end()); - m_hash = fast_hash(&m_cells[0], sizeof(m_cells[0]) * m_cells.size()); + m_hash = fast_hash(&m_cells[0], sizeof(m_cells[0]) * m_cells.size()); } - + bool operator< (const cluster_id& rhs) const { return m_cells < rhs.m_cells; } - + bool operator== (const cluster_id& rhs) const { - if (m_hash != rhs.m_hash) + if (m_hash != rhs.m_hash) return false; - + return m_cells == rhs.m_cells; } - + crnlib::vector m_cells; - + size_t m_hash; - + operator size_t() const { return m_hash; } }; - + typedef crnlib::hash_map cluster_hash; cluster_hash m_cluster_hash; spinlock m_cluster_hash_lock; @@ -178,10 +176,10 @@ namespace crnlib void pack_endpoints_task(uint64 data, void* pData_ptr); void optimize_selectors_task(uint64 data, void* pData_ptr); bool create_selector_clusters(uint max_selector_clusters, crnlib::vector< crnlib::vector >& selector_cluster_indices); - + inline dxt1_block& get_block(uint index) const { return m_pDst_elements[index * m_elements_per_block]; } }; - + CRNLIB_DEFINE_BITWISE_MOVABLE(qdxt1::cluster_id); - + } // namespace crnlib diff --git a/crnlib/crn_qdxt5.cpp b/crnlib/crn_qdxt5.cpp index b423fed..fa27c8d 100644 --- a/crnlib/crn_qdxt5.cpp +++ b/crnlib/crn_qdxt5.cpp @@ -62,7 +62,7 @@ namespace crnlib CRNLIB_ASSERT(n && pBlocks); - m_main_thread_id = get_current_thread_id(); + m_main_thread_id = crn_get_current_thread_id(); m_num_blocks = n; m_pBlocks = pBlocks; @@ -286,7 +286,7 @@ namespace crnlib #if QDXT5_DEBUGGING if (debugging) - image_utils::save_to_file_stb(dynamic_wstring(cVarArg, L"debug_%u.tga", level).get_ptr(), debug_img, image_utils::cSaveIgnoreAlpha); + image_utils::save_to_file_stb(dynamic_wstring(cVarArg, "debug_%u.tga", level).get_ptr(), debug_img, image_utils::cSaveIgnoreAlpha); #endif } // level @@ -419,7 +419,7 @@ namespace crnlib if ((cluster_index & cluster_index_progress_mask) == 0) { - if (get_current_thread_id() == m_main_thread_id) + if (crn_get_current_thread_id() == m_main_thread_id) { if (!update_progress(cluster_index, m_endpoint_cluster_indices.size() - 1)) return; @@ -444,7 +444,8 @@ namespace crnlib { const uint block_index = cluster_indices[block_iter]; - const color_quad_u8* pSrc_pixels = &m_pBlocks[block_index].m_pixels[0][0]; + //const color_quad_u8* pSrc_pixels = &m_pBlocks[block_index].m_pixels[0][0]; + const color_quad_u8* pSrc_pixels = (const color_quad_u8*)m_pBlocks[block_index].m_pixels; for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++) { @@ -521,7 +522,7 @@ namespace crnlib if ((cluster_index & 255) == 0) { - if (get_current_thread_id() == m_main_thread_id) + if (crn_get_current_thread_id() == m_main_thread_id) { if (!update_progress(cluster_index, task_params.m_selector_cluster_indices.size() - 1)) return; @@ -735,7 +736,7 @@ namespace crnlib { CRNLIB_ASSERT(m_num_blocks); - m_main_thread_id = get_current_thread_id(); + m_main_thread_id = crn_get_current_thread_id(); m_canceled = false; m_pDst_elements = pDst_elements; diff --git a/crnlib/crn_qdxt5.h b/crnlib/crn_qdxt5.h index ce3c664..355a9d8 100644 --- a/crnlib/crn_qdxt5.h +++ b/crnlib/crn_qdxt5.h @@ -1,8 +1,6 @@ // File: crn_qdxt5.h // See Copyright Notice and license at the end of inc/crnlib.h #pragma once -#include "crn_task_pool.h" -#include "crn_spinlock.h" #include "crn_hash_map.h" #include "crn_clusterizer.h" #include "crn_hash.h" @@ -17,23 +15,23 @@ namespace crnlib qdxt5_params() { clear(); - } + } void clear() { m_quality_level = cMaxQuality; m_dxt_quality = cCRNDXTQualityUber; - + m_pProgress_func = NULL; m_pProgress_data = NULL; m_num_mips = 0; m_hierarchical = true; utils::zero_object(m_mip_desc); - + m_comp_index = 3; m_progress_start = 0; m_progress_range = 100; - + m_use_both_block_types = true; } @@ -50,7 +48,7 @@ namespace crnlib uint m_quality_level; crn_dxt_quality m_dxt_quality; bool m_hierarchical; - + struct mip_desc { uint m_first_block; @@ -67,20 +65,20 @@ namespace crnlib void* m_pProgress_data; uint m_progress_start; uint m_progress_range; - + uint m_comp_index; - + bool m_use_both_block_types; }; - + class qdxt5 { CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(qdxt5); - + public: qdxt5(task_pool& task_pool); ~qdxt5(); - + void clear(); bool init(uint n, const dxt_pixel_block* pBlocks, const qdxt5_params& params); @@ -92,7 +90,7 @@ namespace crnlib private: task_pool* m_pTask_pool; - uint32 m_main_thread_id; + crn_thread_id_t m_main_thread_id; bool m_canceled; uint m_progress_start; @@ -146,7 +144,7 @@ namespace crnlib std::sort(m_cells.begin(), m_cells.end()); - m_hash = fast_hash(&m_cells[0], sizeof(m_cells[0]) * m_cells.size()); + m_hash = fast_hash(&m_cells[0], sizeof(m_cells[0]) * m_cells.size()); } bool operator< (const cluster_id& rhs) const @@ -156,7 +154,7 @@ namespace crnlib bool operator== (const cluster_id& rhs) const { - if (m_hash != rhs.m_hash) + if (m_hash != rhs.m_hash) return false; return m_cells == rhs.m_cells; diff --git a/crnlib/crn_rand.cpp b/crnlib/crn_rand.cpp index 1e14abc..c6159dd 100644 --- a/crnlib/crn_rand.cpp +++ b/crnlib/crn_rand.cpp @@ -174,6 +174,13 @@ namespace crnlib return m_kiss99.next() ^ (m_ranctx.next() + m_well512.next()); } + uint64 random::urand64() + { + uint64 result = urand32(); + result <<= 32ULL; + result |= urand32(); + return result; + } uint32 random::fast_urand32() { return m_well512.next(); @@ -317,6 +324,13 @@ namespace crnlib return SHR3 ^ CONG; } + uint64 fast_random::urand64() + { + uint64 result = urand32(); + result <<= 32ULL; + result |= urand32(); + return result; + } int fast_random::irand(int l, int h) { CRNLIB_ASSERT(l < h); diff --git a/crnlib/crn_rand.h b/crnlib/crn_rand.h index 4cf48e8..64d823d 100644 --- a/crnlib/crn_rand.h +++ b/crnlib/crn_rand.h @@ -63,6 +63,7 @@ namespace crnlib void seed(uint32 i1, uint32 i2, uint32 i3); uint32 urand32(); + uint64 urand64(); // "Fast" variant uses no multiplies. uint32 fast_urand32(); @@ -99,6 +100,7 @@ namespace crnlib void seed(uint32 i); uint32 urand32(); + uint64 urand64(); int irand(int l, int h); diff --git a/crnlib/crn_stb_image.cpp b/crnlib/crn_stb_image.cpp index 213d028..0a37228 100644 --- a/crnlib/crn_stb_image.cpp +++ b/crnlib/crn_stb_image.cpp @@ -193,17 +193,23 @@ typedef unsigned char stbi_uc; // (you must include the appropriate extension in the filename). // returns TRUE on success, FALSE if couldn't open file, error writing file extern int stbi_write_bmp (char const *filename, int x, int y, int comp, const void *data); +#ifdef _MSC_VER extern int stbi_write_bmp_w (wchar_t const *filename, int x, int y, int comp, const void *data); +#endif extern int stbi_write_tga (char const *filename, int x, int y, int comp, const void *data); +#ifdef _MSC_VER extern int stbi_write_tga_w (wchar_t const *filename, int x, int y, int comp, const void *data); #endif +#endif // PRIMARY API - works on images of any type // load image by filename, open file, or memory buffer #ifndef STBI_NO_STDIO extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); +#ifdef _MSC_VER extern stbi_uc *stbi_load_w (wchar_t const *filename, int *x, int *y, int *comp, int req_comp); +#endif extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); #endif @@ -227,7 +233,7 @@ extern void stbi_ldr_to_hdr_scale(float scale); // get a VERY brief reason for failure // NOT THREADSAFE -extern char *stbi_failure_reason (void); +extern const char *stbi_failure_reason (void); // free the loaded image -- this is just stb_free() extern void stbi_image_free (void *retval_from_stbi_load); @@ -418,14 +424,14 @@ typedef unsigned char validate_uint32[sizeof(uint32)==4]; // // this is not threadsafe -static char *failure_reason; +static const char *failure_reason; -char *stbi_failure_reason(void) +const char *stbi_failure_reason(void) { return failure_reason; } -static int e(char *str) +static int e(const char *str) { failure_reason = str; return 0; @@ -485,6 +491,7 @@ unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int re return result; } +#ifdef _MSC_VER unsigned char *stbi_load_w(wchar_t const *filename, int *x, int *y, int *comp, int req_comp) { FILE *f = _wfopen(filename, L"rb"); @@ -494,6 +501,7 @@ unsigned char *stbi_load_w(wchar_t const *filename, int *x, int *y, int *comp, i fclose(f); return result; } +#endif unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) { @@ -748,7 +756,7 @@ static void getn(stbi *s, stbi_uc *buffer, int n) { #ifndef STBI_NO_STDIO if (s->img_file) { - fread(buffer, 1, n, s->img_file); + size_t nr = fread(buffer, 1, n, s->img_file); nr; return; } #endif @@ -1615,11 +1623,13 @@ typedef uint8 *(*resample_row_func)(uint8 *out, uint8 *in0, uint8 *in1, static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) { + out, in_far, w, hs; return in_near; } static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) { + hs; // need to generate two samples vertically for every one in input int i; for (i=0; i < w; ++i) @@ -1629,6 +1639,7 @@ static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) { + hs, in_far; // need to generate two samples horizontally for every one in input int i; uint8 *input = in_near; @@ -1654,6 +1665,7 @@ static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) { + hs; // need to generate 2x2 samples for every one in input int i,t0,t1; if (w == 1) { @@ -1675,6 +1687,7 @@ static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) { + in_far; // resample with nearest-neighbor int i,j; for (i=0; i < w; ++i) @@ -2395,10 +2408,14 @@ static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, u a->out = (uint8 *) stb_malloc(x * y * out_n); if (!a->out) return e("outofmem", "Out of memory"); if (!stbi_png_partial) { - if (s->img_x == x && s->img_y == y) + if ((s->img_x == x) && (s->img_y == y)) + { if (raw_len != (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG"); + } else // interlaced: + { if (raw_len < (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG"); + } } for (j=0; j < y; ++j) { uint8 *cur = a->out + stride*j; @@ -2528,6 +2545,7 @@ static int compute_transparency(png *z, uint8 tc[3], int out_n) static int expand_palette(png *a, uint8 *palette, int len, int pal_img_n) { + len; uint32 i, pixel_count = a->s.img_x * a->s.img_y; uint8 *p, *temp_out, *orig = a->out; @@ -3164,7 +3182,7 @@ static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) unsigned char *tga_palette = NULL; int i, j; unsigned char raw_data[4]; - unsigned char trans_data[4]; + unsigned char trans_data[4] = { 0, 0, 0, 0 }; int RLE_count = 0; int RLE_repeating = 0; int read_next_pixel = 1; @@ -3402,6 +3420,7 @@ int stbi_psd_test_file(FILE *f) { stbi s; int r,n = ftell(f); + memset(&s, 0, sizeof(s)); start_file(&s, f); r = psd_test(&s); fseek(f,n,SEEK_SET); @@ -3608,7 +3627,7 @@ stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int #ifndef STBI_NO_HDR static int hdr_test(stbi *s) { - char *signature = "#?RADIANCE\n"; + const char *signature = "#?RADIANCE\n"; int i; for (i=0; signature[i]; ++i) if (get8(s) != signature[i]) @@ -3628,6 +3647,7 @@ int stbi_hdr_test_file(FILE *f) { stbi s; int r,n = ftell(f); + memset(&s, 0, sizeof(s)); start_file(&s, f); r = hdr_test(&s); fseek(f,n,SEEK_SET); @@ -3639,7 +3659,8 @@ int stbi_hdr_test_file(FILE *f) static char *hdr_gettoken(stbi *z, char *buffer) { int len=0; - char *s = buffer, c = '\0'; + //char *s = buffer; + char c = '\0'; c = get8(z); @@ -3859,18 +3880,18 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, fwrite(&d[comp-1], 1, 1, f); switch (comp) { case 1: - case 2: writef(f, "111", d[0],d[0],d[0]); + case 2: writef(f, (char*)"111", d[0],d[0],d[0]); break; case 4: if (!write_alpha) { for (k=0; k < 3; ++k) px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255; - writef(f, "111", px[1-rgb_dir],px[1],px[1+rgb_dir]); + writef(f, (char*)"111", px[1-rgb_dir],px[1],px[1+rgb_dir]); break; } /* FALLTHROUGH */ case 3: - writef(f, "111", d[1-rgb_dir],d[1],d[1+rgb_dir]); + writef(f, (char*)"111", d[1-rgb_dir],d[1],d[1+rgb_dir]); break; } if (write_alpha > 0) @@ -3894,6 +3915,7 @@ static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, in return f != NULL; } +#ifdef _MSC_VER static int outfile_w(wchar_t const *filename, int rgb_dir, int vdir, int x, int y, int comp, const void *data, int alpha, int pad, char *fmt, ...) { FILE *f = _wfopen(filename, L"wb"); @@ -3907,38 +3929,43 @@ static int outfile_w(wchar_t const *filename, int rgb_dir, int vdir, int x, int } return f != NULL; } +#endif int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) { int pad = (-x*3) & 3; return outfile(filename,-1,-1,x,y,comp,data,0,pad, - "11 4 22 4" "4 44 22 444444", + (char*)"11 4 22 4" "4 44 22 444444", 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header } +#ifdef _MSC_VER int stbi_write_bmp_w(wchar_t const *filename, int x, int y, int comp, const void *data) { int pad = (-x*3) & 3; return outfile_w(filename,-1,-1,x,y,comp,data,0,pad, - "11 4 22 4" "4 44 22 444444", + (char*)"11 4 22 4" "4 44 22 444444", 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header } +#endif int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) { int has_alpha = !(comp & 1); return outfile(filename, -1,-1, x, y, comp, data, has_alpha, 0, - "111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); + (char*)"111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); } +#ifdef _MSC_VER int stbi_write_tga_w(wchar_t const *filename, int x, int y, int comp, const void *data) { int has_alpha = !(comp & 1); return outfile_w(filename, -1,-1, x, y, comp, data, has_alpha, 0, - "111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); + (char*)"111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); } +#endif // any other image formats that do interleaved rgb data? // PNG: requires adler32,crc32 -- significant amount of code diff --git a/crnlib/crn_strutils.cpp b/crnlib/crn_strutils.cpp index 3dddbd5..3a53c28 100644 --- a/crnlib/crn_strutils.cpp +++ b/crnlib/crn_strutils.cpp @@ -2,10 +2,27 @@ // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" #include "crn_strutils.h" -#include namespace crnlib { + char* crn_strdup(const char* pStr) + { + if (!pStr) + pStr = ""; + + size_t l = strlen(pStr) + 1; + char *p = (char *)crnlib_malloc(l); + if (p) + memcpy(p, pStr, l); + + return p; + } + + int crn_stricmp(const char *p, const char *q) + { + return _stricmp(p, q); + } + char* strcpy_safe(char* pDst, uint dst_len, const char* pSrc) { CRNLIB_ASSERT(pDst && pSrc && dst_len); @@ -164,76 +181,6 @@ namespace crnlib return true; } - bool string_to_int(const wchar_t*& pBuf, int& value) - { - value = 0; - - CRNLIB_ASSERT(pBuf); - const wchar_t* p = pBuf; - - while (*p && isspace(*p)) - p++; - - uint result = 0; - bool negative = false; - - if (!iswdigit(*p)) - { - if (p[0] == '-') - { - negative = true; - p++; - } - else - return false; - } - - while (*p && iswdigit(*p)) - { - if (result & 0xE0000000U) - return false; - - const uint result8 = result << 3U; - const uint result2 = result << 1U; - - if (result2 > (0xFFFFFFFFU - result8)) - return false; - - result = result8 + result2; - - uint c = p[0] - L'0'; - if (c > (0xFFFFFFFFU - result)) - return false; - - result += c; - - p++; - } - - if (negative) - { - if (result > 0x80000000U) - { - value = 0; - return false; - } - value = -static_cast(result); - } - else - { - if (result > 0x7FFFFFFFU) - { - value = 0; - return false; - } - value = static_cast(result); - } - - pBuf = p; - - return true; - } - bool string_to_int64(const char*& pBuf, int64& value) { value = 0; @@ -348,50 +295,6 @@ namespace crnlib return true; } - bool string_to_uint(const wchar_t*& pBuf, uint& value) - { - value = 0; - - CRNLIB_ASSERT(pBuf); - const wchar_t* p = pBuf; - - while (*p && iswspace(*p)) - p++; - - uint result = 0; - - if (!iswdigit(*p)) - return false; - - while (*p && iswdigit(*p)) - { - if (result & 0xE0000000U) - return false; - - const uint result8 = result << 3U; - const uint result2 = result << 1U; - - if (result2 > (0xFFFFFFFFU - result8)) - return false; - - result = result8 + result2; - - uint c = p[0] - L'0'; - if (c > (0xFFFFFFFFU - result)) - return false; - - result += c; - - p++; - } - - value = result; - - pBuf = p; - - return true; - } - bool string_to_uint64(const char*& pBuf, uint64& value) { value = 0; @@ -467,77 +370,66 @@ namespace crnlib return false; } - bool string_to_bool(const wchar_t* p, bool& value) - { - CRNLIB_ASSERT(p); - - value = false; - - if (_wcsicmp(p, L"false") == 0) - return true; - - if (_wcsicmp(p, L"true") == 0) - { - value = true; - return true; - } - - const wchar_t* q = p; - uint v; - if (string_to_uint(q, v)) - { - if (!v) - return true; - else if (v == 1) - { - value = true; - return true; - } - } - - return false; - } - bool string_to_float(const char*& p, float& value, uint round_digit) + { + double d; + if (!string_to_double(p, d, round_digit)) + { + value = 0; + return false; + } + value = static_cast(d); + return true; + } + + bool string_to_double(const char*& p, double& value, uint round_digit) + { + return string_to_double(p, p + 128, value, round_digit); + } + + // I wrote this approx. 20 years ago in C/assembly using a limited FP emulator package, so it's a bit crude. + bool string_to_double(const char*& p, const char *pEnd, double& value, uint round_digit) { CRNLIB_ASSERT(p); + value = 0; enum { AF_BLANK = 1, AF_SIGN = 2, AF_DPOINT = 3, AF_BADCHAR = 4, AF_OVRFLOW = 5, AF_EXPONENT = 6, AF_NODIGITS = 7 }; + int status = 0; const char* buf = p; - int status = 0; + int got_sign_flag = 0, got_dp_flag = 0, got_num_flag = 0; + int got_e_flag = 0, got_e_sign_flag = 0, e_sign = 0; + uint whole_count = 0, frac_count = 0; - if (round_digit > 10) - round_digit = 10; + double whole = 0, frac = 0, scale = 1, exponent = 1; - int got_sign_flag = 0; - int got_dp_flag = 0; - int got_num_flag = 0; - - int got_e_flag = 0; - int got_e_sign_flag = 0; - int e_sign = 0; - - uint whole_count = 0; - uint frac_count = 0; - - float whole = 0; - float frac = 0; - float scale = 1; - float exponent = 1; + if (p >= pEnd) + { + status = AF_NODIGITS; + goto af_exit; + } while (*buf) { if (!isspace(*buf)) break; - - buf++; + if (++buf >= pEnd) + { + status = AF_NODIGITS; + goto af_exit; + } } + p = buf; + while (*buf) { + p = buf; + if (buf >= pEnd) + break; + int i = *buf++; switch (i) @@ -616,7 +508,7 @@ namespace crnlib whole_count++; - if (whole > 1e+30f) + if (whole > 1e+100) { status = AF_OVRFLOW; goto af_exit; @@ -646,6 +538,10 @@ namespace crnlib while (*buf) { + p = buf; + if (buf >= pEnd) + break; + int i = *buf++; if (i == '+') @@ -674,7 +570,7 @@ namespace crnlib { got_num_flag = 1; - if ((e = (e * 10) + (i - 48)) > 16) + if ((e = (e * 10) + (i - 48)) > 100) { status = AF_EXPONENT; goto af_exit; @@ -709,552 +605,9 @@ namespace crnlib whole = -whole; value = whole; - p = buf; af_exit: return (status == 0); } - bool string_to_float(const wchar_t*& p, float& value, uint round_digit) - { - CRNLIB_ASSERT(p); - value = 0; - - enum { AF_BLANK = 1, AF_SIGN = 2, AF_DPOINT = 3, AF_BADCHAR = 4, AF_OVRFLOW = 5, AF_EXPONENT = 6, AF_NODIGITS = 7 }; - - const wchar_t* buf = p; - - int status = 0; - - if (round_digit > 10) - round_digit = 10; - - int got_sign_flag = 0; - int got_dp_flag = 0; - int got_num_flag = 0; - - int got_e_flag = 0; - int got_e_sign_flag = 0; - int e_sign = 0; - - uint whole_count = 0; - uint frac_count = 0; - - float whole = 0; - float frac = 0; - float scale = 1; - float exponent = 1; - - while (*buf) - { - if (!iswspace(*buf)) - break; - - buf++; - } - - while (*buf) - { - int i = *buf++; - - switch (i) - { - case L'e': - case L'E': - { - got_e_flag = 1; - goto exit_while; - } - case L'+': - { - if ((got_num_flag) || (got_sign_flag)) - { - status = AF_SIGN; - goto af_exit; - } - - got_sign_flag = 1; - - break; - } - case L'-': - { - if ((got_num_flag) || (got_sign_flag)) - { - status = AF_SIGN; - goto af_exit; - } - - got_sign_flag = -1; - - break; - } - case L'.': - { - if (got_dp_flag) - { - status = AF_DPOINT; - goto af_exit; - } - - got_dp_flag = 1; - - break; - } - default: - { - if ((i < L'0') || (i > L'9')) - goto exit_while; - else - { - i -= L'0'; - - got_num_flag = 1; - - if (got_dp_flag) - { - if (frac_count < round_digit) - { - frac = frac * 10.0f + i; - - scale = scale * 10.0f; - } - else if (frac_count == round_digit) - { - if (i >= 5) /* check for round */ - frac = frac + 1.0f; - } - - frac_count++; - } - else - { - whole = whole * 10.0f + i; - - whole_count++; - - if (whole > 1e+30f) - { - status = AF_OVRFLOW; - goto af_exit; - } - } - } - - break; - } - } - } - - exit_while: - - if (got_e_flag) - { - if ((got_num_flag == 0) && (got_dp_flag)) - { - status = AF_EXPONENT; - goto af_exit; - } - - int e = 0; - e_sign = 1; - got_num_flag = 0; - got_e_sign_flag = 0; - - while (*buf) - { - int i = *buf++; - - if (i == L'+') - { - if ((got_num_flag) || (got_e_sign_flag)) - { - status = AF_EXPONENT; - goto af_exit; - } - - e_sign = 1; - got_e_sign_flag = 1; - } - else if (i == L'-') - { - if ((got_num_flag) || (got_e_sign_flag)) - { - status = AF_EXPONENT; - goto af_exit; - } - - e_sign = -1; - got_e_sign_flag = 1; - } - else if ((i >= L'0') && (i <= L'9')) - { - got_num_flag = 1; - - if ((e = (e * 10) + (i - 48)) > 16) - { - status = AF_EXPONENT; - goto af_exit; - } - } - else - break; - } - - for (int i = 1; i <= e; i++) /* compute 10^e */ - exponent = exponent * 10.0f; - } - - if (((whole_count + frac_count) == 0) && (got_e_flag == 0)) - { - status = AF_NODIGITS; - goto af_exit; - } - - if (frac) - whole = whole + (frac / scale); - - if (got_e_flag) - { - if (e_sign > 0) - whole = whole * exponent; - else - whole = whole / exponent; - } - - if (got_sign_flag < 0) - whole = -whole; - - value = whole; - p = buf; - - af_exit: - return (status == 0); - } - - bool split_path(const char* p, dynamic_string* pDrive, dynamic_string* pDir, dynamic_string* pFilename, dynamic_string* pExt) - { - CRNLIB_ASSERT(p); - - char drive_buf[_MAX_DRIVE]; - char dir_buf[_MAX_DIR]; - char fname_buf[_MAX_FNAME]; - char ext_buf[_MAX_EXT]; - -#ifdef _MSC_VER - errno_t error = _splitpath_s(p, - pDrive ? drive_buf : NULL, pDrive ? _MAX_DRIVE : 0, - pDir ? dir_buf : NULL, pDir ? _MAX_DIR : 0, - pFilename ? fname_buf : NULL, pFilename ? _MAX_FNAME : 0, - pExt ? ext_buf : NULL, pExt ? _MAX_EXT : 0); - if (error != 0) - return false; -#else - _splitpath(p, - pDrive ? drive_buf : NULL, - pDir ? dir_buf : NULL, - pFilename ? fname_buf : NULL, - pExt ? ext_buf : NULL); -#endif - - if (pDrive) *pDrive = drive_buf; - if (pDir) *pDir = dir_buf; - if (pFilename) *pFilename = fname_buf; - if (pExt) *pExt = ext_buf; - - return true; - } - - bool split_path(const wchar_t* p, dynamic_wstring* pDrive, dynamic_wstring* pDir, dynamic_wstring* pFilename, dynamic_wstring* pExt) - { - CRNLIB_ASSERT(p); - - wchar_t drive_buf[_MAX_DRIVE]; - wchar_t dir_buf[_MAX_DIR]; - wchar_t fname_buf[_MAX_FNAME]; - wchar_t ext_buf[_MAX_EXT]; - -#ifdef _MSC_VER - errno_t error = _wsplitpath_s(p, - pDrive ? drive_buf : NULL, pDrive ? _MAX_DRIVE : 0, - pDir ? dir_buf : NULL, pDir ? _MAX_DIR : 0, - pFilename ? fname_buf : NULL, pFilename ? _MAX_FNAME : 0, - pExt ? ext_buf : NULL, pExt ? _MAX_EXT : 0); - if (error != 0) - return false; -#else - _wsplitpath(p, - pDrive ? drive_buf : NULL, - pDir ? dir_buf : NULL, - pFilename ? fname_buf : NULL, - pExt ? ext_buf : NULL); -#endif - - if (pDrive) *pDrive = drive_buf; - if (pDir) *pDir = dir_buf; - if (pFilename) *pFilename = fname_buf; - if (pExt) *pExt = ext_buf; - - return true; - } - - bool split_path(const char* p, dynamic_string& path, dynamic_string& filename) - { - dynamic_string temp_drive, temp_path, temp_ext; - if (!split_path(p, &temp_drive, &temp_path, &filename, &temp_ext)) - return false; - - filename += temp_ext; - - combine_path(path, temp_drive.get_ptr(), temp_path.get_ptr()); - return true; - } - - bool split_path(const wchar_t* p, dynamic_wstring& path, dynamic_wstring& filename) - { - dynamic_wstring temp_drive, temp_path, temp_ext; - if (!split_path(p, &temp_drive, &temp_path, &filename, &temp_ext)) - return false; - - filename += temp_ext; - - combine_path(path, temp_drive.get_ptr(), temp_path.get_ptr()); - return true; - } - - bool get_pathname(const char* p, dynamic_string& path) - { - dynamic_string temp_drive, temp_path; - if (!split_path(p, &temp_drive, &temp_path, NULL, NULL)) - return false; - - combine_path(path, temp_drive.get_ptr(), temp_path.get_ptr()); - return true; - } - - bool get_pathname(const wchar_t* p, dynamic_wstring& path) - { - dynamic_wstring temp_drive, temp_path; - if (!split_path(p, &temp_drive, &temp_path, NULL, NULL)) - return false; - - combine_path(path, temp_drive.get_ptr(), temp_path.get_ptr()); - return true; - } - - bool get_filename(const char* p, dynamic_string& filename) - { - dynamic_string temp_ext; - if (!split_path(p, NULL, NULL, &filename, &temp_ext)) - return false; - - filename += temp_ext; - return true; - } - - bool get_filename(const wchar_t* p, dynamic_wstring& filename) - { - dynamic_wstring temp_ext; - if (!split_path(p, NULL, NULL, &filename, &temp_ext)) - return false; - - filename += temp_ext; - return true; - } - - void combine_path(dynamic_string& dst, const char* pA, const char* pB) - { - dynamic_string temp; - temp = pA; - if ((!temp.is_empty()) && (pB[0] != '\\') && (pB[0] != '/')) - { - char c = temp[temp.get_len() - 1]; - if ((c != '\\') && (c != '/')) - { - temp.append_char('\\'); - } - } - temp += pB; - dst.swap(temp); - } - - void combine_path(dynamic_wstring& dst, const wchar_t* pA, const wchar_t* pB) - { - dynamic_wstring temp; - temp = pA; - if ((!temp.is_empty()) && (pB[0] != L'\\') && (pB[0] != L'/')) - { - wchar_t c = temp[temp.get_len() - 1]; - if ((c != L'\\') && (c != L'/')) - { - temp.append_char(L'\\'); - } - } - temp += pB; - dst.swap(temp); - } - - void combine_path(dynamic_string& dst, const char* pA, const char* pB, const char* pC) - { - combine_path(dst, pA, pB); - combine_path(dst, dst.get_ptr(), pC); - } - - void combine_path(dynamic_wstring& dst, const wchar_t* pA, const wchar_t* pB, const wchar_t* pC) - { - combine_path(dst, pA, pB); - combine_path(dst, dst.get_ptr(), pC); - } - - void combine_path(dynamic_wstring& dst, const wchar_t* pA, const wchar_t* pB, const wchar_t* pC, const wchar_t *pD) - { - combine_path(dst, pA, pB); - combine_path(dst, dst.get_ptr(), pC); - combine_path(dst, dst.get_ptr(), pD); - } - - bool full_path(dynamic_string& path) - { -#ifndef _XBOX - char buf[CRNLIB_MAX_PATH]; - - char* p = _fullpath(buf, path.get_ptr(), CRNLIB_MAX_PATH); - if (!p) - return false; - - path.set(buf); -#endif - return true; - } - - bool full_path(dynamic_wstring& path) - { -#ifndef _XBOX - wchar_t buf[CRNLIB_MAX_PATH]; - - wchar_t* p = _wfullpath(buf, path.get_ptr(), CRNLIB_MAX_PATH); - if (!p) - return false; - - path.set(buf); -#endif - return true; - } - - bool get_extension(dynamic_string& filename) - { - int sep = filename.find_right('\\'); - if (sep < 0) - sep = filename.find_right('/'); - - int dot = filename.find_right('.'); - if (dot < sep) - { - filename.clear(); - return false; - } - - filename.right(dot + 1); - - return true; - } - - bool get_extension(dynamic_wstring& filename) - { - int sep = filename.find_right(L'\\'); - if (sep < 0) - sep = filename.find_right(L'/'); - - int dot = filename.find_right(L'.'); - if (dot < sep) - { - filename.clear(); - return false; - } - - filename.right(dot + 1); - - return true; - } - - bool remove_extension(dynamic_string& filename) - { - int sep = filename.find_right('\\'); - if (sep < 0) - sep = filename.find_right('/'); - - int dot = filename.find_right('.'); - if (dot < sep) - return false; - - filename.left(dot); - - return true; - } - - bool remove_extension(dynamic_wstring& filename) - { - int sep = filename.find_right(L'\\'); - if (sep < 0) - sep = filename.find_right(L'/'); - - int dot = filename.find_right(L'.'); - if (dot < sep) - return false; - - filename.left(dot); - - return true; - } - - bool create_path(const dynamic_wstring& path) - { - bool unc = false; - dynamic_wstring cur_path; - - const int l = path.get_len(); - - int n = 0; - while (n < l) - { - const wchar_t c = path.get_ptr()[n]; - - const bool sep = (c == L'/') || (c == L'\\'); - - if ((sep) || (n == (l - 1))) - { - if ((n == (l - 1)) && (!sep)) - cur_path.append_char(c); - - bool valid = false; - if ((cur_path.get_len() > 3) && (cur_path.get_ptr()[1] == L':')) - valid = true; - else if (cur_path.get_len() > 2) - { - if (unc) - valid = true; - unc = true; - } - - if (valid) - _wmkdir(cur_path.get_ptr()); - } - - cur_path.append_char(c); - - n++; - } - - return true; - } - - void trim_trailing_seperator(dynamic_wstring& path) - { - if ( (path.get_len()) && ( (path[path.get_len() - 1] == L'\\') || (path[path.get_len() - 1] == L'/') ) ) - path.truncate(path.get_len() - 1); - } - } // namespace crnlib - - - diff --git a/crnlib/crn_strutils.h b/crnlib/crn_strutils.h index b734c73..af4fbd0 100644 --- a/crnlib/crn_strutils.h +++ b/crnlib/crn_strutils.h @@ -2,58 +2,34 @@ // See Copyright Notice and license at the end of inc/crnlib.h #pragma once +#ifdef WIN32 + #define CRNLIB_PATH_SEPERATOR_CHAR '\\' +#else + #define CRNLIB_PATH_SEPERATOR_CHAR '/' +#endif + namespace crnlib { + char* crn_strdup(const char* pStr); + int crn_stricmp(const char *p, const char *q); + char* strcpy_safe(char* pDst, uint dst_len, const char* pSrc); bool int_to_string(int value, char* pDst, uint len); bool uint_to_string(uint value, char* pDst, uint len); - + bool string_to_int(const char*& pBuf, int& value); - bool string_to_int(const wchar_t*& pBuf, int& value); - + bool string_to_uint(const char*& pBuf, uint& value); - bool string_to_uint(const wchar_t*& pBuf, uint& value); - + bool string_to_int64(const char*& pBuf, int64& value); bool string_to_uint64(const char*& pBuf, uint64& value); - + bool string_to_bool(const char* p, bool& value); - bool string_to_bool(const wchar_t* p, bool& value); - - bool string_to_float(const char*& p, float& value, uint round_digit = 10U); - bool string_to_float(const wchar_t*& p, float& value, uint round_digit = 10U); - - bool split_path(const char* p, dynamic_string* pDrive, dynamic_string* pDir, dynamic_string* pFilename, dynamic_string* pExt); - bool split_path(const wchar_t* p, dynamic_wstring* pDrive, dynamic_wstring* pDir, dynamic_wstring* pFilename, dynamic_wstring* pExt); - - bool split_path(const char* p, dynamic_string& path, dynamic_string& filename); - bool split_path(const wchar_t* p, dynamic_wstring& path, dynamic_wstring& filename); - - bool get_pathname(const char* p, dynamic_string& path); - bool get_pathname(const wchar_t* p, dynamic_wstring& path); - - bool get_filename(const char* p, dynamic_string& filename); - bool get_filename(const wchar_t* p, dynamic_wstring& filename); - - void combine_path(dynamic_string& dst, const char* pA, const char* pB); - void combine_path(dynamic_wstring& dst, const wchar_t* pA, const wchar_t* pB); - - void combine_path(dynamic_string& dst, const char* pA, const char* pB, const char* pC); - void combine_path(dynamic_wstring& dst, const wchar_t* pA, const wchar_t* pB, const wchar_t* pC); - void combine_path(dynamic_wstring& dst, const wchar_t* pA, const wchar_t* pB, const wchar_t* pC, const wchar_t *pD); - - bool full_path(dynamic_string& path); - bool full_path(dynamic_wstring& path); - - bool get_extension(dynamic_string& filename); - bool get_extension(dynamic_wstring& filename); - - bool remove_extension(dynamic_string& filename); - bool remove_extension(dynamic_wstring& filename); - - bool create_path(const dynamic_wstring& path); - - void trim_trailing_seperator(dynamic_wstring& path); - + + bool string_to_float(const char*& p, float& value, uint round_digit = 512U); + + bool string_to_double(const char*& p, double& value, uint round_digit = 512U); + bool string_to_double(const char*& p, const char *pEnd, double& value, uint round_digit = 512U); + } // namespace crnlib diff --git a/crnlib/crn_symbol_codec.cpp b/crnlib/crn_symbol_codec.cpp index f52d8dc..410b3e3 100644 --- a/crnlib/crn_symbol_codec.cpp +++ b/crnlib/crn_symbol_codec.cpp @@ -361,7 +361,7 @@ namespace crnlib if (!max_freq) return false; - if (max_freq <= UINT16_MAX) + if (max_freq <= cUINT16_MAX) { for (uint i = 0; i < total_syms; i++) sym_freq16[i] = static_cast(pSym_freq[i]); @@ -381,7 +381,7 @@ namespace crnlib if (fl < 1) fl = 1; - CRNLIB_ASSERT(fl <= UINT16_MAX); + CRNLIB_ASSERT(fl <= cUINT16_MAX); sym_freq16[i] = static_cast(fl); } @@ -917,7 +917,7 @@ namespace crnlib freq++; model.m_sym_freq[sym] = static_cast(freq); - if (freq == UINT16_MAX) + if (freq == cUINT16_MAX) model.rescale(); if (--model.m_symbols_until_update == 0) @@ -1426,8 +1426,8 @@ namespace crnlib { uint32 t = pTables->m_lookup[m_bit_buf >> (cBitBufSize - pTables->m_table_bits)]; - CRNLIB_ASSERT(t != UINT32_MAX); - sym = t & UINT16_MAX; + CRNLIB_ASSERT(t != cUINT32_MAX); + sym = t & cUINT16_MAX; len = t >> 16; CRNLIB_ASSERT(model.m_code_sizes[sym] == len); @@ -1462,7 +1462,7 @@ namespace crnlib freq++; model.m_sym_freq[sym] = static_cast(freq); - if (freq == UINT16_MAX) + if (freq == cUINT16_MAX) model.rescale(); if (--model.m_symbols_until_update == 0) @@ -1614,8 +1614,8 @@ namespace crnlib { uint32 t = pTables->m_lookup[m_bit_buf >> (cBitBufSize - pTables->m_table_bits)]; - CRNLIB_ASSERT(t != UINT32_MAX); - sym = t & UINT16_MAX; + CRNLIB_ASSERT(t != cUINT32_MAX); + sym = t & cUINT16_MAX; len = t >> 16; CRNLIB_ASSERT(model.m_code_sizes[sym] == len); diff --git a/crnlib/crn_texture_comp.cpp b/crnlib/crn_texture_comp.cpp index 54254db..862096f 100644 --- a/crnlib/crn_texture_comp.cpp +++ b/crnlib/crn_texture_comp.cpp @@ -26,7 +26,7 @@ namespace crnlib { if (local_params.get_flag(cCRNCompFlagPerceptual)) { - //console::warning(L"Output pixel format is swizzled or not RGB, disabling perceptual color metrics"); + console::info("Output pixel format is swizzled or not RGB, disabling perceptual color metrics"); // Destination compressed pixel format is swizzled or not RGB at all, so be sure perceptual colorspace metrics are disabled. local_params.set_flag(cCRNCompFlagPerceptual, false); @@ -53,6 +53,18 @@ namespace crnlib ((local_params.m_file_type == cCRNFileTypeCRN) && ((local_params.m_flags & cCRNCompFlagManualPaletteSizes) != 0)) ) { + if ( (local_params.m_file_type == cCRNFileTypeCRN) || + ((local_params.m_file_type == cCRNFileTypeDDS) && (local_params.m_quality_level < cCRNMaxQualityLevel)) ) + { + console::info("Compressing using quality level %i", local_params.m_quality_level); + } + if (local_params.m_format == cCRNFmtDXT3) + { + if (local_params.m_file_type == cCRNFileTypeCRN) + console::warning("CRN format doesn't support DXT3"); + else if ((local_params.m_file_type == cCRNFileTypeDDS) && (local_params.m_quality_level < cCRNMaxQualityLevel)) + console::warning("Clustered DDS compressor doesn't support DXT3"); + } if (!pTexture_comp->compress_pass(local_params, pActual_bitrate)) { crnlib_delete(pTexture_comp); @@ -95,7 +107,7 @@ namespace crnlib { if (params.m_flags & cCRNCompFlagDebugging) { - console::debug(L"Quality level bracket: [%u, %u]", low_quality, high_quality); + console::debug("Quality level bracket: [%u, %u]", low_quality, high_quality); } int trial_quality = (low_quality + high_quality) / 2; @@ -137,7 +149,7 @@ namespace crnlib } } - console::info(L"Compressing to quality level %u", trial_quality); + console::info("Compressing to quality level %u", trial_quality); float bitrate = 0.0f; @@ -153,7 +165,7 @@ namespace crnlib highest_bitrate = math::maximum(highest_bitrate, bitrate); - console::info(L"\nTried quality level %u, bpp: %3.3f", trial_quality, bitrate); + console::info("\nTried quality level %u, bpp: %3.3f", trial_quality, bitrate); if ( (best_quality_level < 0) || ((bitrate <= local_params.m_target_bitrate) && (best_bitrate > local_params.m_target_bitrate)) || @@ -165,7 +177,7 @@ namespace crnlib best_quality_level = trial_quality; if (params.m_flags & cCRNCompFlagDebugging) { - console::debug(L"Choose new best quality level"); + console::debug("Choose new best quality level"); } if ((best_bitrate <= local_params.m_target_bitrate) && (fabs(best_bitrate - local_params.m_target_bitrate) < .005f)) @@ -188,7 +200,7 @@ namespace crnlib (highest_bitrate < local_params.m_target_bitrate) && (fabs(best_bitrate - local_params.m_target_bitrate) >= .005f)) { - console::info(L"Unable to achieve desired bitrate - disabling adaptive block sizes and retrying search."); + console::info("Unable to achieve desired bitrate - disabling adaptive block sizes and retrying search."); local_params.m_flags &= ~cCRNCompFlagHierarchical; @@ -214,7 +226,7 @@ namespace crnlib if (pActual_quality_level) *pActual_quality_level = best_quality_level; if (pActual_bitrate) *pActual_bitrate = best_bitrate; - console::printf(L"Selected quality level %u bpp: %f", best_quality_level, best_bitrate); + console::printf("Selected quality level %u bpp: %f", best_quality_level, best_bitrate); return true; } @@ -310,14 +322,14 @@ namespace crnlib { if (work_tex.get_num_faces() > 1) { - console::warning(L"Can't crop cubemap textures"); + console::warning("Can't crop cubemap textures"); } else { - console::info(L"Cropping input texture from window (%ux%u)-(%ux%u)", window_rect.get_left(), window_rect.get_top(), window_rect.get_right(), window_rect.get_bottom()); + console::info("Cropping input texture from window (%ux%u)-(%ux%u)", window_rect.get_left(), window_rect.get_top(), window_rect.get_right(), window_rect.get_bottom()); if (!work_tex.crop(window_rect.get_left(), window_rect.get_top(), window_rect.get_width(), window_rect.get_height())) - console::warning(L"Failed cropping window rect"); + console::warning("Failed cropping window rect"); } } @@ -332,13 +344,13 @@ namespace crnlib { if (work_tex.get_num_faces() > 1) { - console::warning(L"Can't crop cubemap textures"); + console::warning("Can't crop cubemap textures"); } else { new_width = math::minimum(mipmap_params.m_clamp_width, new_width); new_height = math::minimum(mipmap_params.m_clamp_height, new_height); - console::info(L"Clamping input texture to %ux%u", new_width, new_height); + console::info("Clamping input texture to %ux%u", new_width, new_height); work_tex.crop(0, 0, new_width, new_height); } } @@ -420,7 +432,7 @@ namespace crnlib if ((new_width != (int)work_tex.get_width()) || (new_height != (int)work_tex.get_height())) { - console::info(L"Resampling input texture to %ux%u", new_width, new_height); + console::info("Resampling input texture to %ux%u", new_width, new_height); const char* pFilter = crn_get_mip_filter_name(mipmap_params.m_filter); @@ -439,7 +451,7 @@ namespace crnlib if (!work_tex.resize(new_width, new_height, res_params)) { - console::error(L"Failed resizing texture!"); + console::error("Failed resizing texture!"); return false; } } @@ -461,18 +473,18 @@ namespace crnlib gen_params.m_max_mips = mipmap_params.m_max_levels; gen_params.m_min_mip_size = mipmap_params.m_min_mip_size; - console::info(L"Generating mipmaps using filter \"%S\"", pFilter); + console::info("Generating mipmaps using filter \"%s\"", pFilter); timer tm; tm.start(); if (!work_tex.generate_mipmaps(gen_params, true)) { - console::error(L"Failed generating mipmaps!"); + console::error("Failed generating mipmaps!"); return false; } double t = tm.get_elapsed_secs(); - console::info(L"Generated %u mipmap levels in %3.3fs", work_tex.get_num_levels() - 1, t); + console::info("Generated %u mipmap levels in %3.3fs", work_tex.get_num_levels() - 1, t); } return true; @@ -487,7 +499,7 @@ namespace crnlib dds_texture work_tex; if (!create_dds_tex(params, work_tex)) { - console::error(L"Failed creating DDS texture from crn_comp_params!"); + console::error("Failed creating DDS texture from crn_comp_params!"); return false; } diff --git a/crnlib/crn_texture_comp.h b/crnlib/crn_texture_comp.h index 96242f5..12692e6 100644 --- a/crnlib/crn_texture_comp.h +++ b/crnlib/crn_texture_comp.h @@ -16,7 +16,7 @@ namespace crnlib itexture_comp() { } virtual ~itexture_comp() { } - virtual const wchar_t *get_ext() const = 0; + virtual const char *get_ext() const = 0; virtual bool compress_init(const crn_comp_params& params) = 0; virtual bool compress_pass(const crn_comp_params& params, float *pEffective_bitrate) = 0; diff --git a/crnlib/crn_texture_conversion.cpp b/crnlib/crn_texture_conversion.cpp index ef976f7..b6334e9 100644 --- a/crnlib/crn_texture_conversion.cpp +++ b/crnlib/crn_texture_conversion.cpp @@ -3,7 +3,7 @@ #include "crn_core.h" #include "crn_texture_conversion.h" #include "crn_console.h" -#include "crn_win32_file_utils.h" +#include "crn_file_utils.h" #include "crn_cfile_stream.h" #include "crn_image_utils.h" #include "crn_texture_comp.h" @@ -26,8 +26,8 @@ namespace crnlib } bool convert_stats::init( - const wchar_t* pSrc_filename, - const wchar_t* pDst_filename, + const char* pSrc_filename, + const char* pDst_filename, dds_texture& src_tex, texture_file_types::format dst_file_type, bool lzma_stats) @@ -38,8 +38,8 @@ namespace crnlib m_pInput_tex = &src_tex; - win32_file_utils::get_file_size(pSrc_filename, m_input_file_size); - win32_file_utils::get_file_size(pDst_filename, m_output_file_size); + file_utils::get_file_size(pSrc_filename, m_input_file_size); + file_utils::get_file_size(pDst_filename, m_output_file_size); m_total_input_pixels = 0; for (uint i = 0; i < src_tex.get_num_levels(); i++) @@ -58,12 +58,12 @@ namespace crnlib vector dst_tex_bytes; if (!cfile_stream::read_file_into_array(pDst_filename, dst_tex_bytes)) { - console::error(L"Failed loading output file: %s", pDst_filename); + console::error("Failed loading output file: %s", pDst_filename); return false; } if (!dst_tex_bytes.size()) { - console::error(L"Output file is empty: %s", pDst_filename); + console::error("Output file is empty: %s", pDst_filename); return false; } vector cmp_tex_bytes; @@ -76,7 +76,7 @@ namespace crnlib if (!m_output_tex.load_from_file(pDst_filename, m_dst_file_type)) { - console::error(L"Failed loading output file: %s", pDst_filename); + console::error("Failed loading output file: %s", pDst_filename); return false; } @@ -91,12 +91,12 @@ namespace crnlib return true; } - bool convert_stats::print(bool psnr_metrics, bool mip_stats, bool grayscale_sampling, const wchar_t *pCSVStatsFile) const + bool convert_stats::print(bool psnr_metrics, bool mip_stats, bool grayscale_sampling, const char *pCSVStatsFile) const { if (!m_pInput_tex) return false; - console::info(L"Input texture: %ux%u, Levels: %u, Faces: %u, Format: %s", + console::info("Input texture: %ux%u, Levels: %u, Faces: %u, Format: %s", m_pInput_tex->get_width(), m_pInput_tex->get_height(), m_pInput_tex->get_num_levels(), @@ -104,29 +104,29 @@ namespace crnlib pixel_format_helpers::get_pixel_format_string(m_pInput_tex->get_format())); // Just casting the uint64's filesizes to uint32 here to work around gcc issues - it's not even possible to have files that large anyway. - console::info(L"Input pixels: %u, Input file size: %u, Input bits/pixel: %1.3f", + console::info("Input pixels: %u, Input file size: %u, Input bits/pixel: %1.3f", m_total_input_pixels, (uint32)m_input_file_size, (m_input_file_size * 8.0f) / m_total_input_pixels); - console::info(L"Output texture: %ux%u, Levels: %u, Faces: %u, Format: %s", + console::info("Output texture: %ux%u, Levels: %u, Faces: %u, Format: %s", m_output_tex.get_width(), m_output_tex.get_height(), m_output_tex.get_num_levels(), m_output_tex.get_num_faces(), pixel_format_helpers::get_pixel_format_string(m_output_tex.get_format())); - console::info(L"Output pixels: %u, Output file size: %u, Output bits/pixel: %1.3f", + console::info("Output pixels: %u, Output file size: %u, Output bits/pixel: %1.3f", m_total_output_pixels, (uint32)m_output_file_size, (m_output_file_size * 8.0f) / m_total_output_pixels); if (m_output_comp_file_size) { - console::info(L"LZMA compressed output file size: %u bytes, %1.3f bits/pixel", + console::info("LZMA compressed output file size: %u bytes, %1.3f bits/pixel", (uint32)m_output_comp_file_size, (m_output_comp_file_size * 8.0f) / m_total_output_pixels); } if (psnr_metrics) { if ( (m_pInput_tex->get_width() != m_output_tex.get_width()) || (m_pInput_tex->get_height() != m_output_tex.get_height()) || (m_pInput_tex->get_num_faces() != m_output_tex.get_num_faces()) ) { - console::warning(L"Unable to compute image statistics - input/output texture dimensions are different."); + console::warning("Unable to compute image statistics - input/output texture dimensions are different."); } else { @@ -155,7 +155,7 @@ namespace crnlib pB = &grayscale_b; } - console::info(L"Mipmap level %u statistics:", level); + console::info("Mipmap level %u statistics:", level); image_utils::print_image_metrics(*pA, *pB); if ((pA->has_rgb()) || (pB->has_rgb())) @@ -187,23 +187,22 @@ namespace crnlib image_utils::error_metrics luma_error; if (rgb_error.compute(*pA, *pB, 0, 3, false) && luma_error.compute(*pA, *pB, 0, 0, true)) { - FILE *pFile = NULL; -#ifdef _MSC_VER - _wfopen_s(&pFile, pCSVStatsFile, L"a"); -#else - pFile = _wfopen(pCSVStatsFile, L"a"); -#endif + bool bCSVStatsFileExists = file_utils::does_file_exist(pCSVStatsFile); + FILE* pFile; + crn_fopen(&pFile, pCSVStatsFile, "a"); if (!pFile) - console::warning(L"Unable to append to CSV stats file: %s\n", pCSVStatsFile); + console::warning("Unable to append to CSV stats file: %s\n", pCSVStatsFile); else { - dynamic_wstring filename; - split_path(m_src_filename.get_ptr(), NULL, NULL, &filename, NULL); - dynamic_string filenamea; + if (!bCSVStatsFileExists) + fprintf(pFile, "name,width,height,miplevels,rgb_rms,luma_rms,effective_output_size,effective_bitrate\n"); + dynamic_string filename; + file_utils::split_path(m_src_filename.get_ptr(), NULL, NULL, &filename, NULL); + uint64 effective_output_size = m_output_comp_file_size ? m_output_comp_file_size : m_output_file_size; float bitrate = (effective_output_size * 8.0f) / m_total_output_pixels; fprintf(pFile, "%s,%u,%u,%u,%f,%f,%u,%f\n", - filename.as_ansi(filenamea).get_ptr(), + filename.get_ptr(), pB->get_width(), pB->get_height(), m_output_tex.get_num_levels(), rgb_error.mRootMeanSquared, luma_error.mRootMeanSquared, (uint32)effective_output_size, bitrate); @@ -283,12 +282,12 @@ namespace crnlib return true; } - static bool convert_error(const convert_params& params, const wchar_t* pError_msg) + static bool convert_error(const convert_params& params, const char* pError_msg) { params.m_status = false; params.m_error_message = pError_msg; - _wremove(params.m_dst_filename.get_ptr()); + remove(params.m_dst_filename.get_ptr()); return false; } @@ -369,55 +368,55 @@ namespace crnlib static void print_comp_params(const crn_comp_params &comp_params) { - console::debug(L"\nTexture conversion compression parameters:"); - console::debug(L" Desired bitrate: %3.3f", comp_params.m_target_bitrate); - console::debug(L" CRN Quality: %i", comp_params.m_quality_level); - console::debug(L"CRN C endpoints/selectors: %u %u", comp_params.m_crn_color_endpoint_palette_size, comp_params.m_crn_color_selector_palette_size); - console::debug(L"CRN A endpoints/selectors: %u %u", comp_params.m_crn_alpha_endpoint_palette_size, comp_params.m_crn_alpha_selector_palette_size); - console::debug(L" DXT both block types: %u, Alpha threshold: %u", comp_params.get_flag(cCRNCompFlagUseBothBlockTypes), comp_params.m_dxt1a_alpha_threshold); - console::debug(L" DXT compression quality: %s", crn_get_dxt_quality_string(comp_params.m_dxt_quality)); - console::debug(L" Perceptual: %u, Large Blocks: %u", comp_params.get_flag(cCRNCompFlagPerceptual), comp_params.get_flag(cCRNCompFlagHierarchical)); - console::debug(L" Compressor: %s", get_dxt_compressor_name(comp_params.m_dxt_compressor_type)); - console::debug(L" Disable endpoint caching: %u", comp_params.get_flag(cCRNCompFlagDisableEndpointCaching)); - console::debug(L" Grayscale sampling: %u", comp_params.get_flag(cCRNCompFlagGrayscaleSampling)); - console::debug(L" Max helper threads: %u", comp_params.m_num_helper_threads); - console::debug(L""); + console::debug("\nTexture conversion compression parameters:"); + console::debug(" Desired bitrate: %3.3f", comp_params.m_target_bitrate); + console::debug(" CRN Quality: %i", comp_params.m_quality_level); + console::debug("CRN C endpoints/selectors: %u %u", comp_params.m_crn_color_endpoint_palette_size, comp_params.m_crn_color_selector_palette_size); + console::debug("CRN A endpoints/selectors: %u %u", comp_params.m_crn_alpha_endpoint_palette_size, comp_params.m_crn_alpha_selector_palette_size); + console::debug(" DXT both block types: %u, Alpha threshold: %u", comp_params.get_flag(cCRNCompFlagUseBothBlockTypes), comp_params.m_dxt1a_alpha_threshold); + console::debug(" DXT compression quality: %s", crn_get_dxt_quality_string(comp_params.m_dxt_quality)); + console::debug(" Perceptual: %u, Large Blocks: %u", comp_params.get_flag(cCRNCompFlagPerceptual), comp_params.get_flag(cCRNCompFlagHierarchical)); + console::debug(" Compressor: %s", get_dxt_compressor_name(comp_params.m_dxt_compressor_type)); + console::debug(" Disable endpoint caching: %u", comp_params.get_flag(cCRNCompFlagDisableEndpointCaching)); + console::debug(" Grayscale sampling: %u", comp_params.get_flag(cCRNCompFlagGrayscaleSampling)); + console::debug(" Max helper threads: %u", comp_params.m_num_helper_threads); + console::debug(""); } static void print_mipmap_params(const crn_mipmap_params &mipmap_params) { - console::debug(L"\nTexture conversion MIP-map parameters:"); - console::debug(L" Mode: %s", crn_get_mip_mode_name(mipmap_params.m_mode)); - console::debug(L" Filter: %S", crn_get_mip_filter_name(mipmap_params.m_filter)); - console::debug(L"Gamma filtering: %u, Gamma: %2.2f", mipmap_params.m_gamma_filtering, mipmap_params.m_gamma); - console::debug(L" Blurriness: %2.2f", mipmap_params.m_blurriness); - console::debug(L" Renormalize: %u", mipmap_params.m_renormalize); - console::debug(L" Tiled: %u", mipmap_params.m_tiled); - console::debug(L" Max Levels: %u", mipmap_params.m_max_levels); - console::debug(L" Min level size: %u", mipmap_params.m_min_mip_size); - console::debug(L" window: %u %u %u %u", mipmap_params.m_window_left, mipmap_params.m_window_top, mipmap_params.m_window_right, mipmap_params.m_window_bottom); - console::debug(L" scale mode: %s", crn_get_scale_mode_desc(mipmap_params.m_scale_mode)); - console::debug(L" scale: %f %f", mipmap_params.m_scale_x, mipmap_params.m_scale_y); - console::debug(L" clamp: %u %u, clamp_scale: %u", mipmap_params.m_clamp_width, mipmap_params.m_clamp_height, mipmap_params.m_clamp_scale); - console::debug(L""); + console::debug("\nTexture conversion MIP-map parameters:"); + console::debug(" Mode: %s", crn_get_mip_mode_name(mipmap_params.m_mode)); + console::debug(" Filter: %s", crn_get_mip_filter_name(mipmap_params.m_filter)); + console::debug("Gamma filtering: %u, Gamma: %2.2f", mipmap_params.m_gamma_filtering, mipmap_params.m_gamma); + console::debug(" Blurriness: %2.2f", mipmap_params.m_blurriness); + console::debug(" Renormalize: %u", mipmap_params.m_renormalize); + console::debug(" Tiled: %u", mipmap_params.m_tiled); + console::debug(" Max Levels: %u", mipmap_params.m_max_levels); + console::debug(" Min level size: %u", mipmap_params.m_min_mip_size); + console::debug(" window: %u %u %u %u", mipmap_params.m_window_left, mipmap_params.m_window_top, mipmap_params.m_window_right, mipmap_params.m_window_bottom); + console::debug(" scale mode: %s", crn_get_scale_mode_desc(mipmap_params.m_scale_mode)); + console::debug(" scale: %f %f", mipmap_params.m_scale_x, mipmap_params.m_scale_y); + console::debug(" clamp: %u %u, clamp_scale: %u", mipmap_params.m_clamp_width, mipmap_params.m_clamp_height, mipmap_params.m_clamp_scale); + console::debug(""); } void convert_params::print() { - console::debug(L"\nTexture conversion parameters:"); - console::debug(L" Resolution: %ux%u, Faces: %u, Levels: %u, Format: %s", + console::debug("\nTexture conversion parameters:"); + console::debug(" Resolution: %ux%u, Faces: %u, Levels: %u, Format: %s", m_pInput_texture->get_width(), m_pInput_texture->get_height(), m_pInput_texture->get_num_faces(), 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" use_source_format: %u", m_use_source_format); + console::debug(" texture_type: %s", get_texture_type_desc(m_texture_type)); + console::debug(" dst_filename: %s", m_dst_filename.get_ptr()); + console::debug(" dst_file_type: %s", texture_file_types::get_extension(m_dst_file_type)); + console::debug(" dst_format: %s", pixel_format_helpers::get_pixel_format_string(m_dst_format)); + console::debug(" quick: %u", m_quick); + console::debug(" use_source_format: %u", m_use_source_format); } static bool write_compressed_texture( @@ -432,19 +431,19 @@ namespace crnlib crn_format crn_fmt = pixel_format_helpers::convert_pixel_format_to_best_crn_format(dst_format); comp_params.m_format = crn_fmt; - console::message(L"Writing %s texture to file: \"%s\"", crn_get_format_string(crn_fmt), params.m_dst_filename.get_ptr()); + console::message("Writing %s texture to file: \"%s\"", crn_get_format_string(crn_fmt), params.m_dst_filename.get_ptr()); uint32 actual_quality_level; float actual_bitrate; bool status = work_tex.write_to_file(params.m_dst_filename.get_ptr(), params.m_dst_file_type, &comp_params, &actual_quality_level, &actual_bitrate); if (!status) - return convert_error(params, L"Failed writing output file!"); + return convert_error(params, "Failed writing output file!"); if (!params.m_no_stats) { if (!stats.init(params.m_pInput_texture->get_source_filename().get_ptr(), params.m_dst_filename.get_ptr(), *params.m_pIntermediate_texture, params.m_dst_file_type, params.m_lzma_stats)) { - console::warning(L"Unable to compute output statistics for file: %s", params.m_pInput_texture->get_source_filename().get_ptr()); + console::warning("Unable to compute output statistics for file: %s", params.m_pInput_texture->get_source_filename().get_ptr()); } } @@ -471,7 +470,7 @@ namespace crnlib pack_params.m_num_helper_threads = comp_params.m_num_helper_threads; pack_params.m_use_transparent_indices_for_black = comp_params.get_flag(cCRNCompFlagUseTransparentIndicesForBlack); - console::info(L"Converting texture format from %s to %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format)); + console::info("Converting texture format from %s to %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format)); timer tm; tm.start(); @@ -480,7 +479,7 @@ namespace crnlib double t = tm.get_elapsed_secs(); - console::info(L""); + console::info(""); if (!status) { @@ -491,11 +490,11 @@ namespace crnlib } else { - return convert_error(params, L"Failed converting texture to output format!"); + return convert_error(params, "Failed converting texture to output format!"); } } - console::info(L"Texture format conversion took %3.3fs", t); + console::info("Texture format conversion took %3.3fs", t); } if (params.m_write_mipmaps_to_multiple_files) @@ -504,13 +503,13 @@ namespace crnlib { for (uint l = 0; l < work_tex.get_num_levels(); l++) { - dynamic_wstring filename(params.m_dst_filename.get_ptr()); + dynamic_string filename(params.m_dst_filename.get_ptr()); - dynamic_wstring drv, dir, fn, ext; - if (!split_path(params.m_dst_filename.get_ptr(), &drv, &dir, &fn, &ext)) + dynamic_string drv, dir, fn, ext; + if (!file_utils::split_path(params.m_dst_filename.get_ptr(), &drv, &dir, &fn, &ext)) return false; - fn += dynamic_wstring(cVarArg, L"_face%u_mip%u", f, l).get_ptr(); + fn += dynamic_string(cVarArg, "_face%u_mip%u", f, l).get_ptr(); filename = drv + dir + fn + ext; mip_level *pLevel = work_tex.get_level(f, l); @@ -521,25 +520,25 @@ namespace crnlib dds_texture new_tex; new_tex.assign(face); - console::info(L"Writing texture face %u mip level %u to file %s", f, l, filename.get_ptr()); + console::info("Writing texture face %u mip level %u to file %s", f, l, filename.get_ptr()); if (!new_tex.write_to_file(filename.get_ptr(), params.m_dst_file_type, NULL, NULL, NULL)) - return convert_error(params, L"Failed writing output file!"); + return convert_error(params, "Failed writing output file!"); } } } else { - console::message(L"Writing texture to file: \"%s\"", params.m_dst_filename.get_ptr()); + console::message("Writing texture to file: \"%s\"", params.m_dst_filename.get_ptr()); if (!work_tex.write_to_file(params.m_dst_filename.get_ptr(), params.m_dst_file_type, NULL, NULL, NULL)) - return convert_error(params, L"Failed writing output file!"); + return convert_error(params, "Failed writing output file!"); if (!params.m_no_stats) { if (!stats.init(params.m_pInput_texture->get_source_filename().get_ptr(), params.m_dst_filename.get_ptr(), *params.m_pIntermediate_texture, params.m_dst_file_type, params.m_lzma_stats)) { - console::warning(L"Unable to compute output statistics for file: %s", params.m_pInput_texture->get_source_filename().get_ptr()); + console::warning("Unable to compute output statistics for file: %s", params.m_pInput_texture->get_source_filename().get_ptr()); } } } @@ -576,7 +575,7 @@ namespace crnlib { if ((work_tex.get_comp_flags() & pixel_format_helpers::cCompFlagAValid) == 0) { - console::warning(L"Output format is alpha-only, but input doesn't have alpha, so setting alpha to luminance."); + console::warning("Output format is alpha-only, but input doesn't have alpha, so setting alpha to luminance."); work_tex.convert(PIXEL_FMT_A8, crnlib::dxt_image::pack_params()); @@ -586,6 +585,15 @@ namespace crnlib } pixel_format dst_format = params.m_dst_format; + if (pixel_format_helpers::is_dxt(dst_format)) + { + if ((params.m_dst_file_type != texture_file_types::cFormatCRN) && + (params.m_dst_file_type != texture_file_types::cFormatDDS)) + { + console::warning("Output file format does not support DXT - automatically choosing pixel format."); + dst_format = PIXEL_FMT_INVALID; + } + } if (dst_format == PIXEL_FMT_INVALID) { @@ -611,15 +619,15 @@ namespace crnlib { if (perceptual) { - //console::warning(L"Output pixel format is swizzled or not RGB, disabling perceptual color metrics"); + console::message("Output pixel format is swizzled or not RGB, disabling perceptual color metrics"); perceptual = false; } } if (pixel_format_helpers::is_normal_map(dst_format)) { - //if (perceptual) - //console::warning(L"Output pixel format is intended for normal maps, disabling perceptual color metrics"); + if (perceptual) + console::message("Output pixel format is intended for normal maps, disabling perceptual color metrics"); perceptual = false; } @@ -639,7 +647,7 @@ namespace crnlib } if (!create_texture_mipmaps(work_tex, comp_params, mipmap_params, generate_mipmaps)) - return convert_error(params, L"Failed creating texture mipmaps!"); + return convert_error(params, "Failed creating texture mipmaps!"); bool formats_differ = work_tex.get_format() != dst_format; if (formats_differ) @@ -666,7 +674,7 @@ namespace crnlib status = convert_and_write_normal_texture(work_tex, params, comp_params, dst_format, progress_state, formats_differ, perceptual, stats); } - console::progress(L""); + console::progress(""); if (progress_state.m_canceled) { @@ -679,18 +687,18 @@ namespace crnlib if (status) { if (params.m_param_debugging) - console::info(L"Work texture format: %s, desired destination format: %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format)); + console::info("Work texture format: %s, desired destination format: %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format)); - console::message(L"Texture successfully written in %3.3fs", total_write_time); + console::message("Texture successfully written in %3.3fs", total_write_time); } else { - dynamic_wstring str; + dynamic_string str; if (work_tex.get_last_error().is_empty()) - str.format(L"Failed writing texture to file \"%s\"", params.m_dst_filename.get_ptr()); + str.format("Failed writing texture to file \"%s\"", params.m_dst_filename.get_ptr()); else - str.format(L"Failed writing texture to file \"%s\", Reason: %s", params.m_dst_filename.get_ptr(), work_tex.get_last_error().get_ptr()); + str.format("Failed writing texture to file \"%s\", Reason: %s", params.m_dst_filename.get_ptr(), work_tex.get_last_error().get_ptr()); return convert_error(params, str.get_ptr()); } diff --git a/crnlib/crn_texture_conversion.h b/crnlib/crn_texture_conversion.h index 9957d21..89245ad 100644 --- a/crnlib/crn_texture_conversion.h +++ b/crnlib/crn_texture_conversion.h @@ -16,18 +16,18 @@ namespace crnlib convert_stats(); bool init( - const wchar_t* pSrc_filename, - const wchar_t* pDst_filename, + const char* pSrc_filename, + const char* pDst_filename, dds_texture& src_tex, texture_file_types::format dst_file_type, bool lzma_stats); - bool print(bool psnr_metrics, bool mip_stats, bool grayscale_sampling, const wchar_t *pCSVStatsFile = NULL) const; + bool print(bool psnr_metrics, bool mip_stats, bool grayscale_sampling, const char *pCSVStatsFile = NULL) const; void clear(); - dynamic_wstring m_src_filename; - dynamic_wstring m_dst_filename; + dynamic_string m_src_filename; + dynamic_string m_dst_filename; texture_file_types::format m_dst_file_type; dds_texture* m_pInput_tex; @@ -58,10 +58,10 @@ namespace crnlib m_debugging(false), m_param_debugging(false), m_no_stats(false), + m_use_source_format(false), m_lzma_stats(false), m_status(false), - m_canceled(false), - m_use_source_format(false) + m_canceled(false) { } @@ -77,7 +77,7 @@ namespace crnlib texture_type m_texture_type; - dynamic_wstring m_dst_filename; + dynamic_string m_dst_filename; texture_file_types::format m_dst_file_type; pixel_format m_dst_format; @@ -90,7 +90,7 @@ namespace crnlib // Return parameters dds_texture* m_pIntermediate_texture; - mutable dynamic_wstring m_error_message; + mutable dynamic_string m_error_message; bool m_write_mipmaps_to_multiple_files; bool m_quick; @@ -98,7 +98,7 @@ namespace crnlib bool m_param_debugging; bool m_no_stats; bool m_use_source_format; - + bool m_lzma_stats; mutable bool m_status; mutable bool m_canceled; diff --git a/crnlib/crn_texture_file_types.cpp b/crnlib/crn_texture_file_types.cpp index 2f846da..75b933c 100644 --- a/crnlib/crn_texture_file_types.cpp +++ b/crnlib/crn_texture_file_types.cpp @@ -2,48 +2,48 @@ // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" #include "crn_texture_file_types.h" -#include "crn_strutils.h" +#include "crn_file_utils.h" namespace crnlib { - const wchar_t* texture_file_types::get_extension(format fmt) + const char* texture_file_types::get_extension(format fmt) { CRNLIB_ASSERT(fmt < cNumFileFormats); if (fmt >= cNumFileFormats) return NULL; - static const wchar_t* extensions[cNumFileFormats] = + static const char* extensions[cNumFileFormats] = { - L"tga", - L"png", - L"jpg", - L"jpeg", - L"bmp", - L"gif", - L"tif", - L"tiff", - L"ppm", - L"pgm", - L"dds", - L"psd", - L"jp2", - L"crn", - L"", - L"" + "tga", + "png", + "jpg", + "jpeg", + "bmp", + "gif", + "tif", + "tiff", + "ppm", + "pgm", + "dds", + "psd", + "jp2", + "crn", + "", + "" }; return extensions[fmt]; } - texture_file_types::format texture_file_types::determine_file_format(const wchar_t* pFilename) + texture_file_types::format texture_file_types::determine_file_format(const char* pFilename) { - dynamic_wstring ext; - if (!split_path(pFilename, NULL, NULL, NULL, &ext)) + dynamic_string ext; + if (!file_utils::split_path(pFilename, NULL, NULL, NULL, &ext)) return cFormatInvalid; if (ext.is_empty()) return cFormatInvalid; - if (ext[0] == L'.') + if (ext[0] == '.') ext.right(1); for (uint i = 0; i < cNumFileFormats; i++) @@ -81,21 +81,21 @@ namespace crnlib return true; } - const wchar_t* get_texture_type_desc(texture_type t) + const char* get_texture_type_desc(texture_type t) { switch (t) { - case cTextureTypeUnknown: return L"Unknown"; - case cTextureTypeRegularMap: return L"2D map"; - case cTextureTypeNormalMap: return L"Normal map"; - case cTextureTypeVerticalCrossCubemap: return L"Vertical Cross Cubemap"; - case cTextureTypeCubemap: return L"Cubemap"; + case cTextureTypeUnknown: return "Unknown"; + case cTextureTypeRegularMap: return "2D map"; + case cTextureTypeNormalMap: return "Normal map"; + case cTextureTypeVerticalCrossCubemap: return "Vertical Cross Cubemap"; + case cTextureTypeCubemap: return "Cubemap"; default: break; } CRNLIB_ASSERT(false); - return L"?"; + return "?"; } } // namespace crnlib diff --git a/crnlib/crn_texture_file_types.h b/crnlib/crn_texture_file_types.h index d45f478..08d4c76 100644 --- a/crnlib/crn_texture_file_types.h +++ b/crnlib/crn_texture_file_types.h @@ -27,24 +27,24 @@ namespace crnlib cFormatPSD, cFormatJP2, cFormatCRN, - + cNumRegularFileFormats, - - // Not really a file format + + // Not really a file format cFormatClipboard = cNumRegularFileFormats, cFormatDragDrop, cNumFileFormats }; - static const wchar_t* get_extension(format fmt); + static const char* get_extension(format fmt); + + static format determine_file_format(const char* pFilename); - static format determine_file_format(const wchar_t* pFilename); - static bool supports_mipmaps(format fmt); static bool supports_alpha(format fmt); - }; - + }; + enum texture_type { cTextureTypeUnknown = 0, @@ -55,8 +55,8 @@ namespace crnlib cNumTextureTypes }; - - const wchar_t* get_texture_type_desc(texture_type t); - + + const char* get_texture_type_desc(texture_type t); + } // namespace crnlib - + diff --git a/crnlib/crn_threaded_clusterizer.h b/crnlib/crn_threaded_clusterizer.h index a00f726..6d045dc 100644 --- a/crnlib/crn_threaded_clusterizer.h +++ b/crnlib/crn_threaded_clusterizer.h @@ -2,6 +2,7 @@ // See Copyright Notice and license at the end of inc/crnlib.h #pragma once #include "crn_clusterizer.h" +#include "crn_threading.h" namespace crnlib { @@ -43,7 +44,7 @@ namespace crnlib progress_callback_func pProgress_callback, void* pProgress_callback_data) { - m_main_thread_id = get_current_thread_id(); + m_main_thread_id = crn_get_current_thread_id(); m_canceled = false; m_pProgress_callback = pProgress_callback; m_pProgress_callback_data = pProgress_callback_data; @@ -136,7 +137,7 @@ namespace crnlib private: task_pool* m_pTask_pool; - uint32 m_main_thread_id; + crn_thread_id_t m_main_thread_id; struct create_clusters_task_state { @@ -328,7 +329,7 @@ namespace crnlib if (m_canceled) return; - const bool is_main_thread = (get_current_thread_id() == m_main_thread_id); + const bool is_main_thread = (crn_get_current_thread_id() == m_main_thread_id); const bool quick = false; m_clusterizers[partition_index].generate_codebook( diff --git a/crnlib/crn_threaded_resampler.cpp b/crnlib/crn_threaded_resampler.cpp index 4d2382e..e46f391 100644 --- a/crnlib/crn_threaded_resampler.cpp +++ b/crnlib/crn_threaded_resampler.cpp @@ -3,6 +3,7 @@ #include "crn_core.h" #include "crn_threaded_resampler.h" #include "crn_resample_filters.h" +#include "crn_threading.h" namespace crnlib { diff --git a/crnlib/crn_threaded_resampler.h b/crnlib/crn_threaded_resampler.h index 70ad888..e94a8b6 100644 --- a/crnlib/crn_threaded_resampler.h +++ b/crnlib/crn_threaded_resampler.h @@ -3,34 +3,34 @@ #pragma once #include "crn_resampler.h" #include "crn_vec.h" -#include "crn_task_pool.h" namespace crnlib { + class task_pool; class threaded_resampler { CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(threaded_resampler); - + public: threaded_resampler(task_pool& tp); ~threaded_resampler(); - + enum pixel_format { cPF_Y_F32, cPF_RGBX_F32, cPF_RGBA_F32, - + cPF_Total }; - + struct params { params() { clear(); } - + void clear() { utils::zero_object(*this); @@ -42,44 +42,44 @@ namespace crnlib m_filter_x_scale = 1.0f; m_filter_y_scale = 1.0f; } - + pixel_format m_fmt; - + const void* m_pSrc_pixels; uint m_src_width; uint m_src_height; uint m_src_pitch; - + void* m_pDst_pixels; uint m_dst_width; uint m_dst_height; uint m_dst_pitch; - + Resampler::Boundary_Op m_boundary_op; - + float m_sample_low; float m_sample_high; - + const char* m_Pfilter_name; float m_filter_x_scale; float m_filter_y_scale; - }; - + }; + bool resample(const params& p); - + private: task_pool* m_pTask_pool; - + const params* m_pParams; - + Resampler::Contrib_List* m_pX_contribs; Resampler::Contrib_List* m_pY_contribs; uint m_bytes_per_pixel; - + crnlib::vector m_tmp_img; - + void free_contrib_lists(); - + void resample_x_task(uint64 data, void* pData_ptr); void resample_y_task(uint64 data, void* pData_ptr); }; diff --git a/crnlib/crn_traits.h b/crnlib/crn_traits.h index 81e59de..b882750 100644 --- a/crnlib/crn_traits.h +++ b/crnlib/crn_traits.h @@ -4,6 +4,15 @@ namespace crnlib { + template struct int_traits { enum { cMin = crnlib::cINT32_MIN, cMax = crnlib::cINT32_MAX, cSigned = true }; }; + + template<> struct int_traits { enum { cMin = crnlib::cINT8_MIN, cMax = crnlib::cINT8_MAX, cSigned = true }; }; + template<> struct int_traits { enum { cMin = crnlib::cINT16_MIN, cMax = crnlib::cINT16_MAX, cSigned = true }; }; + template<> struct int_traits { enum { cMin = crnlib::cINT32_MIN, cMax = crnlib::cINT32_MAX, cSigned = true }; }; + + template<> struct int_traits { enum { cMin = 0, cMax = crnlib::cUINT8_MAX, cSigned = false }; }; + template<> struct int_traits { enum { cMin = 0, cMax = crnlib::cUINT16_MAX, cSigned = false }; }; + template<> struct int_traits { enum { cMin = 0, cMax = crnlib::cUINT32_MAX, cSigned = false }; }; template struct scalar_type { @@ -43,8 +52,13 @@ namespace crnlib CRNLIB_DEFINE_BUILT_IN_TYPE(unsigned int) CRNLIB_DEFINE_BUILT_IN_TYPE(long) CRNLIB_DEFINE_BUILT_IN_TYPE(unsigned long) +#ifdef __GNUC__ + CRNLIB_DEFINE_BUILT_IN_TYPE(long long) + CRNLIB_DEFINE_BUILT_IN_TYPE(unsigned long long) +#else CRNLIB_DEFINE_BUILT_IN_TYPE(__int64) CRNLIB_DEFINE_BUILT_IN_TYPE(unsigned __int64) +#endif CRNLIB_DEFINE_BUILT_IN_TYPE(float) CRNLIB_DEFINE_BUILT_IN_TYPE(double) CRNLIB_DEFINE_BUILT_IN_TYPE(long double) @@ -69,7 +83,7 @@ namespace crnlib #define CRNLIB_IS_SCALAR_TYPE(T) (scalar_type::cFlag) -#define CRNLIB_IS_BITWISE_COPYABLE(T) ((scalar_type::cFlag) || (bitwise_copyable::cFlag) || CRNLIB_IS_POD(T)) +#define CRNLIB_IS_BITWISE_COPYABLE(T) (CRNLIB_IS_SCALAR_TYPE(T) || CRNLIB_IS_POD(T) || (bitwise_copyable::cFlag)) #define CRNLIB_IS_BITWISE_MOVABLE(T) (CRNLIB_IS_BITWISE_COPYABLE(T) || (bitwise_movable::cFlag)) diff --git a/crnlib/crn_tree_clusterizer.h b/crnlib/crn_tree_clusterizer.h index 13119a5..f6388be 100644 --- a/crnlib/crn_tree_clusterizer.h +++ b/crnlib/crn_tree_clusterizer.h @@ -137,7 +137,7 @@ namespace crnlib return m_codebook; } - const uint find_best_codebook_entry(const VectorType& v) const + uint find_best_codebook_entry(const VectorType& v) const { uint cur_node_index = 0; @@ -161,7 +161,7 @@ namespace crnlib } } - const uint find_best_codebook_entry_fs(const VectorType& v) const + uint find_best_codebook_entry_fs(const VectorType& v) const { float best_dist = math::cNearlyInfinite; uint best_index = 0; @@ -222,7 +222,7 @@ namespace crnlib if (parent_node.m_vectors.size() == 1) return; - VectorType furthest; + VectorType furthest(0); double furthest_dist = -1.0f; for (uint i = 0; i < parent_node.m_vectors.size(); i++) @@ -272,9 +272,13 @@ namespace crnlib covar[x][y] = covar[x][y] + v[x] * w[y]; } - for (uint x = 0; x < N - 1; x++) - for (uint y = x + 1; y < N; y++) - covar[y][x] = covar[x][y]; + if (N > 1) + { + //for (uint x = 0; x < (N - 1); x++) + for (uint x = 0; x != (N - 1); x++) + for (uint y = x + 1; y < N; y++) + covar[y][x] = covar[x][y]; + } covar /= float(parent_node.m_total_weight); diff --git a/crnlib/crn_types.h b/crnlib/crn_types.h index 93cc634..20ce526 100644 --- a/crnlib/crn_types.h +++ b/crnlib/crn_types.h @@ -12,31 +12,36 @@ namespace crnlib typedef uint32 uint; typedef signed int int32; - typedef unsigned __int64 uint64; - typedef signed __int64 int64; + #ifdef __GNUC__ + typedef unsigned long long uint64; + typedef long long int64; + #else + typedef unsigned __int64 uint64; + typedef signed __int64 int64; + #endif - const uint8 UINT8_MIN = 0; - const uint8 UINT8_MAX = 0xFFU; - const uint16 UINT16_MIN = 0; - const uint16 UINT16_MAX = 0xFFFFU; - const uint32 UINT32_MIN = 0; - const uint32 UINT32_MAX = 0xFFFFFFFFU; - const uint64 UINT64_MIN = 0; - const uint64 UINT64_MAX = 0xFFFFFFFFFFFFFFFFULL; //0xFFFFFFFFFFFFFFFFui64; + const uint8 cUINT8_MIN = 0; + const uint8 cUINT8_MAX = 0xFFU; + const uint16 cUINT16_MIN = 0; + const uint16 cUINT16_MAX = 0xFFFFU; + const uint32 cUINT32_MIN = 0; + const uint32 cUINT32_MAX = 0xFFFFFFFFU; + const uint64 cUINT64_MIN = 0; + const uint64 cUINT64_MAX = 0xFFFFFFFFFFFFFFFFULL; //0xFFFFFFFFFFFFFFFFui64; - const int8 INT8_MIN = -128; - const int8 INT8_MAX = 127; - const int16 INT16_MIN = -32768; - const int16 INT16_MAX = 32767; - const int32 INT32_MIN = (-2147483647 - 1); - const int32 INT32_MAX = 2147483647; - const int64 INT64_MIN = (int64)0x8000000000000000ULL; //(-9223372036854775807i64 - 1); - const int64 INT64_MAX = (int64)0x7FFFFFFFFFFFFFFFULL; // 9223372036854775807i64; + const int8 cINT8_MIN = -128; + const int8 cINT8_MAX = 127; + const int16 cINT16_MIN = -32768; + const int16 cINT16_MAX = 32767; + const int32 cINT32_MIN = (-2147483647 - 1); + const int32 cINT32_MAX = 2147483647; + const int64 cINT64_MIN = (int64)0x8000000000000000ULL; //(-9223372036854775807i64 - 1); + const int64 cINT64_MAX = (int64)0x7FFFFFFFFFFFFFFFULL; // 9223372036854775807i64; -#ifdef CRNLIB_PLATFORM_PC_X64 - typedef unsigned __int64 uint_ptr; - typedef unsigned __int64 uint32_ptr; - typedef signed __int64 signed_size_t; +#if CRNLIB_64BIT_POINTERS + typedef uint64 uint_ptr; + typedef uint64 uint32_ptr; + typedef int64 signed_size_t; typedef uint64 ptr_bits_t; #else typedef unsigned int uint_ptr; diff --git a/crnlib/crn_utils.cpp b/crnlib/crn_utils.cpp index 4d77270..47aad7a 100644 --- a/crnlib/crn_utils.cpp +++ b/crnlib/crn_utils.cpp @@ -37,7 +37,19 @@ namespace crnlib *pDst++ = swap16(*pSrc++); } } - + + void copy_dwords(uint32* pDst, const uint32* pSrc, uint num, bool endian_switch) + { + if (!endian_switch) + memcpy(pDst, pSrc, num << 2U); + else + { + uint32* pDst_end = pDst + num; + while (pDst != pDst_end) + *pDst++ = swap32(*pSrc++); + } + } + uint compute_max_mips(uint width, uint height) { if ((width | height) == 0) diff --git a/crnlib/crn_utils.h b/crnlib/crn_utils.h index d46d448..1740dc1 100644 --- a/crnlib/crn_utils.h +++ b/crnlib/crn_utils.h @@ -8,18 +8,21 @@ #define CRNLIB_ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) #ifdef _MSC_VER -extern "C" unsigned long __cdecl _lrotl(unsigned long, int); -#pragma intrinsic(_lrotl) + // Need to explictly extern these with MSVC, but not MinGW. + extern "C" unsigned long __cdecl _lrotl(unsigned long, int); + #pragma intrinsic(_lrotl) -extern "C" unsigned long __cdecl _lrotr(unsigned long, int); -#pragma intrinsic(_lrotr) + extern "C" unsigned long __cdecl _lrotr(unsigned long, int); + #pragma intrinsic(_lrotr) #endif -//#define CRNLIB_ROTATE_LEFT(x, k) (((x) << (k)) | ((x) >> (32-(k)))) -#define CRNLIB_ROTATE_LEFT(x, k) _lrotl(x, k) - -//#define CRNLIB_ROTATE_RIGHT(x, k) (((x) >> (k)) | ((x) << (32-(k)))) -#define CRNLIB_ROTATE_RIGHT(x, k) _lrotr(x, k) +#ifdef WIN32 + #define CRNLIB_ROTATE_LEFT(x, k) _lrotl(x, k) + #define CRNLIB_ROTATE_RIGHT(x, k) _lrotr(x, k) +#else + #define CRNLIB_ROTATE_LEFT(x, k) (((x) << (k)) | ((x) >> (32-(k)))) + #define CRNLIB_ROTATE_RIGHT(x, k) (((x) >> (k)) | ((x) << (32-(k)))) +#endif template T decay_array_to_subtype(T (&a)[N]); #define CRNLIB_ARRAY_SIZE(X) (sizeof(X) / sizeof(decay_array_to_subtype(X))) @@ -39,12 +42,12 @@ namespace crnlib template inline void zero_object(T& obj) { - memset(&obj, 0, sizeof(obj)); + memset((void*)&obj, 0, sizeof(obj)); } template inline void zero_this(T* pObj) { - memset(pObj, 0, sizeof(*pObj)); + memset((void*)pObj, 0, sizeof(*pObj)); } inline bool is_bit_set(uint bits, uint mask) @@ -225,7 +228,8 @@ namespace crnlib void endian_switch_words(uint16* p, uint num); void endian_switch_dwords(uint32* p, uint num); void copy_words(uint16* pDst, const uint16* pSrc, uint num, bool endian_switch); - + void copy_dwords(uint32* pDst, const uint32* pSrc, uint num, bool endian_switch); + uint compute_max_mips(uint width, uint height); } // namespace utils diff --git a/crnlib/crn_value.cpp b/crnlib/crn_value.cpp index bc07477..7724500 100644 --- a/crnlib/crn_value.cpp +++ b/crnlib/crn_value.cpp @@ -5,17 +5,17 @@ namespace crnlib { - const wchar_t* gValueDataTypeStrings[cDTTotal + 1] = + const char* gValueDataTypeStrings[cDTTotal + 1] = { - L"invalid", - L"string", - L"bool", - L"int", - L"uint", - L"float", - L"vec3f", - L"vec3i", - + "invalid", + "string", + "bool", + "int", + "uint", + "float", + "vec3f", + "vec3i", + NULL, }; diff --git a/crnlib/crn_value.h b/crnlib/crn_value.h index b1a9679..eabff1f 100644 --- a/crnlib/crn_value.h +++ b/crnlib/crn_value.h @@ -2,7 +2,7 @@ // See Copyright Notice and license at the end of inc/crnlib.h #pragma once #include "crn_strutils.h" -#include "crn_dynamic_wstring.h" +#include "crn_dynamic_string.h" #include "crn_vec.h" namespace crnlib @@ -21,7 +21,7 @@ namespace crnlib cDTTotal }; - extern const wchar_t* gValueDataTypeStrings[cDTTotal + 1]; + extern const char* gValueDataTypeStrings[cDTTotal + 1]; class value { @@ -31,13 +31,13 @@ namespace crnlib { } - value(const wchar_t* pStr) : - m_pStr(crnlib_new(pStr)), m_type(cDTString) + value(const char* pStr) : + m_pStr(crnlib_new(pStr)), m_type(cDTString) { } - value(const dynamic_wstring& str) : - m_pStr(crnlib_new(str)), m_type(cDTString) + value(const dynamic_string& str) : + m_pStr(crnlib_new(str)), m_type(cDTString) { } @@ -125,7 +125,7 @@ namespace crnlib m_type = cDTInvalid; } - void set_string(const wchar_t* pStr) + void set_string(const char* pStr) { set_str(pStr); } @@ -170,7 +170,7 @@ namespace crnlib m_pVec3I->set(v); } - bool parse(const wchar_t* p) + bool parse(const char* p) { if ((!p) || (!p[0])) { @@ -178,12 +178,12 @@ namespace crnlib return false; } - if (_wcsicmp(p, L"false") == 0) + if (_stricmp(p, "false") == 0) { set_bool(false); return true; } - else if (_wcsicmp(p, L"true") == 0) + else if (_stricmp(p, "true") == 0) { set_bool(true); return true; @@ -191,7 +191,7 @@ namespace crnlib if (p[0] == '\"') { - dynamic_wstring str; + dynamic_string str; str = p + 1; if (!str.is_empty()) { @@ -205,21 +205,21 @@ namespace crnlib } } - if (wcschr(p, L',') != NULL) + if (strchr(p, ',') != NULL) { float fx = 0, fy = 0, fz = 0; #ifdef _MSC_VER - if (swscanf_s(p, L"%f,%f,%f", &fx, &fy, &fz) == 3) + if (sscanf_s(p, "%f,%f,%f", &fx, &fy, &fz) == 3) #else - if (swscanf(p, L"%f,%f,%f", &fx, &fy, &fz) == 3) + if (sscanf(p, "%f,%f,%f", &fx, &fy, &fz) == 3) #endif { bool as_float = true; int ix = 0, iy = 0, iz = 0; #ifdef _MSC_VER - if (swscanf_s(p, L"%i,%i,%i", &ix, &iy, &iz) == 3) + if (sscanf_s(p, "%i,%i,%i", &ix, &iy, &iz) == 3) #else - if (swscanf(p, L"%i,%i,%i", &ix, &iy, &iz) == 3) + if (sscanf(p, "%i,%i,%i", &ix, &iy, &iz) == 3) #endif { if ((ix == fx) && (iy == fy) && (iz == fz)) @@ -235,7 +235,7 @@ namespace crnlib } } - const wchar_t* q = p; + const char* q = p; bool success = string_to_uint(q, m_uint); if ((success) && (*q == 0)) { @@ -264,18 +264,18 @@ namespace crnlib return true; } - dynamic_wstring& get_as_string(dynamic_wstring& dst) const + dynamic_string& get_as_string(dynamic_string& dst) const { switch (m_type) { case cDTInvalid: dst.clear(); break; case cDTString: dst = *m_pStr; break; - case cDTBool: dst = m_bool ? L"TRUE" : L"FALSE"; break; - case cDTInt: dst.format(L"%i", m_int); break; - case cDTUInt: dst.format(L"%u", m_uint); break; - case cDTFloat: dst.format(L"%f", m_float); break; - case cDTVec3F: dst.format(L"%f,%f,%f", (*m_pVec3F)[0], (*m_pVec3F)[1], (*m_pVec3F)[2]); break; - case cDTVec3I: dst.format(L"%i,%i,%i", (*m_pVec3I)[0], (*m_pVec3I)[1], (*m_pVec3I)[2]); break; + case cDTBool: dst = m_bool ? "TRUE" : "FALSE"; break; + case cDTInt: dst.format("%i", m_int); break; + case cDTUInt: dst.format("%u", m_uint); break; + case cDTFloat: dst.format("%f", m_float); break; + case cDTVec3F: dst.format("%f,%f,%f", (*m_pVec3F)[0], (*m_pVec3F)[1], (*m_pVec3F)[2]); break; + case cDTVec3I: dst.format("%i,%i,%i", (*m_pVec3I)[0], (*m_pVec3I)[1], (*m_pVec3I)[2]); break; default: break; } @@ -293,7 +293,7 @@ namespace crnlib } case cDTString: { - const wchar_t* p = m_pStr->get_ptr(); + const char* p = m_pStr->get_ptr(); return string_to_int(p, val); } case cDTBool: val = m_bool; break; @@ -359,7 +359,7 @@ namespace crnlib } case cDTString: { - const wchar_t* p = m_pStr->get_ptr(); + const char* p = m_pStr->get_ptr(); return string_to_uint(p, val); } case cDTBool: @@ -438,7 +438,7 @@ namespace crnlib } case cDTString: { - const wchar_t* p = m_pStr->get_ptr(); + const char* p = m_pStr->get_ptr(); return string_to_bool(p, val); } case cDTBool: @@ -497,7 +497,7 @@ namespace crnlib } case cDTString: { - const wchar_t* p = m_pStr->get_ptr(); + const char* p = m_pStr->get_ptr(); return string_to_float(p, val); } case cDTBool: @@ -556,12 +556,12 @@ namespace crnlib } case cDTString: { - const wchar_t* p = m_pStr->get_ptr(); + const char* p = m_pStr->get_ptr(); float x = 0, y = 0, z = 0; #ifdef _MSC_VER - if (wscanf_s(p, L"%f,%f,%f", &x, &y, &z) == 3) + if (sscanf_s(p, "%f,%f,%f", &x, &y, &z) == 3) #else - if (wscanf(p, L"%f,%f,%f", &x, &y, &z) == 3) + if (sscanf(p, "%f,%f,%f", &x, &y, &z) == 3) #endif { val.set(x, y, z); @@ -619,12 +619,12 @@ namespace crnlib } case cDTString: { - const wchar_t* p = m_pStr->get_ptr(); + const char* p = m_pStr->get_ptr(); float x = 0, y = 0, z = 0; #ifdef _MSC_VER - if (wscanf_s(p, L"%f,%f,%f", &x, &y, &z) == 3) + if (sscanf_s(p, "%f,%f,%f", &x, &y, &z) == 3) #else - if (wscanf(p, L"%f,%f,%f", &x, &y, &z) == 3) + if (sscanf(p, "%f,%f,%f", &x, &y, &z) == 3) #endif { if ((x < INT_MIN) || (x > INT_MAX) || (y < INT_MIN) || (y > INT_MAX) || (z < INT_MIN) || (z > INT_MAX)) @@ -963,7 +963,7 @@ namespace crnlib switch (m_type) { case cDTString: - m_pStr = crnlib_new(); + m_pStr = crnlib_new(); break; case cDTVec3F: m_pVec3F = crnlib_new(); @@ -976,7 +976,7 @@ namespace crnlib } } - void set_str(const dynamic_wstring& s) + void set_str(const dynamic_string& s) { if (m_type == cDTString) m_pStr->set(s); @@ -985,11 +985,11 @@ namespace crnlib clear_dynamic(); m_type = cDTString; - m_pStr = crnlib_new(s); + m_pStr = crnlib_new(s); } } - void set_str(const wchar_t* p) + void set_str(const char* p) { if (m_type == cDTString) m_pStr->set(p); @@ -998,7 +998,7 @@ namespace crnlib clear_dynamic(); m_type = cDTString; - m_pStr = crnlib_new(p); + m_pStr = crnlib_new(p); } } @@ -1013,7 +1013,7 @@ namespace crnlib vec3F* m_pVec3F; vec3I* m_pVec3I; - dynamic_wstring* m_pStr; + dynamic_string* m_pStr; uint m_union[cUnionSize]; }; diff --git a/crnlib/crn_vector.cpp b/crnlib/crn_vector.cpp index a589fdc..8c21125 100644 --- a/crnlib/crn_vector.cpp +++ b/crnlib/crn_vector.cpp @@ -6,14 +6,13 @@ #include "crn_color.h" #include "crn_vec.h" -#include namespace crnlib { bool elemental_vector::increase_capacity(uint min_new_capacity, bool grow_hint, uint element_size, object_mover pMover, bool nofail) { CRNLIB_ASSERT(m_size <= m_capacity); -#ifdef CRNLIB_PLATFORM_PC_X64 +#ifdef CRNLIB_64BIT_POINTERS CRNLIB_ASSERT(min_new_capacity < (0x400000000ULL / element_size)); #else CRNLIB_ASSERT(min_new_capacity < (0x7FFF0000U / element_size)); diff --git a/crnlib/crn_vector.h b/crnlib/crn_vector.h index 732b0ac..9deca99 100644 --- a/crnlib/crn_vector.h +++ b/crnlib/crn_vector.h @@ -296,7 +296,10 @@ namespace crnlib const uint num_to_move = orig_size - index; if (CRNLIB_IS_BITWISE_COPYABLE(T)) + { + // This overwrites the destination object bits, but bitwise copyable means we don't need to worry about destruction. memmove(m_p + index + n, m_p + index, sizeof(T) * num_to_move); + } else { const T* pSrc = m_p + orig_size - 1; @@ -312,7 +315,10 @@ namespace crnlib T* pDst = m_p + index; if (CRNLIB_IS_BITWISE_COPYABLE(T)) + { + // This copies in the new bits, overwriting the existing objects, which is OK for copyable types that don't need destruction. memcpy(pDst, p, sizeof(T) * n); + } else { for (uint i = 0; i < n; i++) @@ -355,15 +361,29 @@ namespace crnlib const uint num_to_move = m_size - (start + n); T* pDst = m_p + start; - + const T* pSrc = m_p + start + n; - if (CRNLIB_IS_BITWISE_COPYABLE(T)) + if ((CRNLIB_IS_BITWISE_COPYABLE(T)) && (!CRNLIB_IS_BITWISE_MOVABLE(T))) + { + // Type is bitwise copyable, so there's no need to destruct the overwritten objects. + // Copy "down" the objects to preserve, filling in the empty slots. memmove(pDst, pSrc, num_to_move * sizeof(T)); + } + else if (CRNLIB_IS_BITWISE_MOVABLE(T)) + { + // Type is bitwise movable, which means we can move them around but they still may need to be destructed. + // First destroy the erased objects. + scalar_type::destruct_array(pDst, n); + + // Copy "down" the objects to preserve, filling in the empty slots. + memmove(pDst, pSrc, num_to_move * sizeof(T)); + } else { + // Type is not bitwise copyable or movable. + // Move them down one at a time by using the equals operator, and destroying anything that's left over at the end. T* pDst_end = pDst + num_to_move; - while (pDst != pDst_end) *pDst++ = *pSrc++; @@ -609,11 +629,11 @@ namespace crnlib // placement new new (static_cast(pDst)) T(*pSrc); pSrc->~T(); - pSrc++; - pDst++; + ++pSrc; + ++pDst; } } - + inline bool increase_capacity(uint min_new_capacity, bool grow_hint, bool nofail = false) { return reinterpret_cast(this)->increase_capacity( diff --git a/crnlib/crn_winhdr.h b/crnlib/crn_winhdr.h index ea60e52..65ee636 100644 --- a/crnlib/crn_winhdr.h +++ b/crnlib/crn_winhdr.h @@ -1,8 +1,12 @@ #pragma once +#ifndef WIN32 +#error Should not get here +#endif + #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x500 -#endif +#endif #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN diff --git a/crnlib/crnlib.2008.vcproj b/crnlib/crnlib.2008.vcproj index 3eb4469..5464c1a 100644 --- a/crnlib/crnlib.2008.vcproj +++ b/crnlib/crnlib.2008.vcproj @@ -586,6 +586,10 @@ RelativePath=".\crn_assert.h" > + + @@ -978,13 +982,6 @@ - - - - - - - @@ -1079,50 +1068,6 @@ > - - - - - - - - - - - - - - - - - - - - - - @@ -1166,6 +1111,14 @@ RelativePath=".\crn_packed_uint.h" > + + + + @@ -1210,6 +1163,14 @@ + + + + @@ -1223,35 +1184,26 @@ Name="threading" > + + + - - - - - - - - @@ -1475,6 +1427,26 @@ > + + + + + + + + + + diff --git a/crnlib/crnlib.cbp b/crnlib/crnlib.cbp index 602d965..cc62daf 100644 --- a/crnlib/crnlib.cbp +++ b/crnlib/crnlib.cbp @@ -14,6 +14,7 @@