Browse Source

Add ATOMIC_PLATFORM_DESKTOP define, remove crunch sources and replace with lib squish (2.4 megs of source vs 129kb and much cleaner build), WIP conversion

Josh Engebretson 9 years ago
parent
commit
d4aae88010
100 changed files with 24 additions and 46455 deletions
  1. 2 2
      Build/CMake/Modules/AtomicDesktop.cmake
  2. 1 1
      CMakeLists.txt
  3. 18 20
      LICENSE.md
  4. 2 1
      Source/Atomic/Resource/Image.cpp
  5. 1 1
      Source/ThirdParty/CMakeLists.txt
  6. 0 26
      Source/ThirdParty/crunch/CMakeLists.txt
  7. 0 698
      Source/ThirdParty/crunch/crnlib/crn_arealist.cpp
  8. 0 74
      Source/ThirdParty/crunch/crnlib/crn_arealist.h
  9. 0 69
      Source/ThirdParty/crunch/crnlib/crn_assert.cpp
  10. 0 61
      Source/ThirdParty/crunch/crnlib/crn_assert.h
  11. 0 208
      Source/ThirdParty/crunch/crnlib/crn_atomics.h
  12. 0 196
      Source/ThirdParty/crunch/crnlib/crn_buffer_stream.h
  13. 0 241
      Source/ThirdParty/crunch/crnlib/crn_cfile_stream.h
  14. 0 63
      Source/ThirdParty/crunch/crnlib/crn_checksum.cpp
  15. 0 13
      Source/ThirdParty/crunch/crnlib/crn_checksum.h
  16. 0 764
      Source/ThirdParty/crunch/crnlib/crn_clusterizer.h
  17. 0 994
      Source/ThirdParty/crunch/crnlib/crn_color.h
  18. 0 119
      Source/ThirdParty/crunch/crnlib/crn_colorized_console.cpp
  19. 0 19
      Source/ThirdParty/crunch/crnlib/crn_colorized_console.h
  20. 0 472
      Source/ThirdParty/crunch/crnlib/crn_command_line_params.cpp
  21. 0 86
      Source/ThirdParty/crunch/crnlib/crn_command_line_params.h
  22. 0 2178
      Source/ThirdParty/crunch/crnlib/crn_comp.cpp
  23. 0 181
      Source/ThirdParty/crunch/crnlib/crn_comp.h
  24. 0 222
      Source/ThirdParty/crunch/crnlib/crn_console.cpp
  25. 0 128
      Source/ThirdParty/crunch/crnlib/crn_console.h
  26. 0 14
      Source/ThirdParty/crunch/crnlib/crn_core.cpp
  27. 0 178
      Source/ThirdParty/crunch/crnlib/crn_core.h
  28. 0 128
      Source/ThirdParty/crunch/crnlib/crn_data_stream.cpp
  29. 0 89
      Source/ThirdParty/crunch/crnlib/crn_data_stream.h
  30. 0 468
      Source/ThirdParty/crunch/crnlib/crn_data_stream_serializer.h
  31. 0 259
      Source/ThirdParty/crunch/crnlib/crn_dds_comp.cpp
  32. 0 48
      Source/ThirdParty/crunch/crnlib/crn_dds_comp.h
  33. 0 6
      Source/ThirdParty/crunch/crnlib/crn_decomp.cpp
  34. 0 386
      Source/ThirdParty/crunch/crnlib/crn_dxt.cpp
  35. 0 361
      Source/ThirdParty/crunch/crnlib/crn_dxt.h
  36. 0 2171
      Source/ThirdParty/crunch/crnlib/crn_dxt1.cpp
  37. 0 352
      Source/ThirdParty/crunch/crnlib/crn_dxt1.h
  38. 0 209
      Source/ThirdParty/crunch/crnlib/crn_dxt5a.cpp
  39. 0 66
      Source/ThirdParty/crunch/crnlib/crn_dxt5a.h
  40. 0 362
      Source/ThirdParty/crunch/crnlib/crn_dxt_endpoint_refiner.cpp
  41. 0 62
      Source/ThirdParty/crunch/crnlib/crn_dxt_endpoint_refiner.h
  42. 0 916
      Source/ThirdParty/crunch/crnlib/crn_dxt_fast.cpp
  43. 0 21
      Source/ThirdParty/crunch/crnlib/crn_dxt_fast.h
  44. 0 2544
      Source/ThirdParty/crunch/crnlib/crn_dxt_hc.cpp
  45. 0 439
      Source/ThirdParty/crunch/crnlib/crn_dxt_hc.h
  46. 0 47
      Source/ThirdParty/crunch/crnlib/crn_dxt_hc_common.cpp
  47. 0 43
      Source/ThirdParty/crunch/crnlib/crn_dxt_hc_common.h
  48. 0 1683
      Source/ThirdParty/crunch/crnlib/crn_dxt_image.cpp
  49. 0 248
      Source/ThirdParty/crunch/crnlib/crn_dxt_image.h
  50. 0 206
      Source/ThirdParty/crunch/crnlib/crn_dynamic_stream.h
  51. 0 668
      Source/ThirdParty/crunch/crnlib/crn_dynamic_string.cpp
  52. 0 173
      Source/ThirdParty/crunch/crnlib/crn_dynamic_string.h
  53. 0 1481
      Source/ThirdParty/crunch/crnlib/crn_etc.cpp
  54. 0 609
      Source/ThirdParty/crunch/crnlib/crn_etc.h
  55. 0 578
      Source/ThirdParty/crunch/crnlib/crn_file_utils.cpp
  56. 0 43
      Source/ThirdParty/crunch/crnlib/crn_file_utils.h
  57. 0 287
      Source/ThirdParty/crunch/crnlib/crn_find_files.cpp
  58. 0 60
      Source/ThirdParty/crunch/crnlib/crn_find_files.h
  59. 0 158
      Source/ThirdParty/crunch/crnlib/crn_freeimage_image_utils.h
  60. 0 68
      Source/ThirdParty/crunch/crnlib/crn_hash.cpp
  61. 0 34
      Source/ThirdParty/crunch/crnlib/crn_hash.h
  62. 0 155
      Source/ThirdParty/crunch/crnlib/crn_hash_map.cpp
  63. 0 876
      Source/ThirdParty/crunch/crnlib/crn_hash_map.h
  64. 0 64
      Source/ThirdParty/crunch/crnlib/crn_helpers.h
  65. 0 387
      Source/ThirdParty/crunch/crnlib/crn_huffman_codes.cpp
  66. 0 14
      Source/ThirdParty/crunch/crnlib/crn_huffman_codes.h
  67. 0 723
      Source/ThirdParty/crunch/crnlib/crn_image.h
  68. 0 1367
      Source/ThirdParty/crunch/crnlib/crn_image_utils.cpp
  69. 0 193
      Source/ThirdParty/crunch/crnlib/crn_image_utils.h
  70. 0 123
      Source/ThirdParty/crunch/crnlib/crn_intersect.h
  71. 0 3172
      Source/ThirdParty/crunch/crnlib/crn_jpgd.cpp
  72. 0 319
      Source/ThirdParty/crunch/crnlib/crn_jpgd.h
  73. 0 1044
      Source/ThirdParty/crunch/crnlib/crn_jpge.cpp
  74. 0 169
      Source/ThirdParty/crunch/crnlib/crn_jpge.h
  75. 0 920
      Source/ThirdParty/crunch/crnlib/crn_ktx_texture.cpp
  76. 0 244
      Source/ThirdParty/crunch/crnlib/crn_ktx_texture.h
  77. 0 142
      Source/ThirdParty/crunch/crnlib/crn_lzma_codec.cpp
  78. 0 60
      Source/ThirdParty/crunch/crnlib/crn_lzma_codec.h
  79. 0 76
      Source/ThirdParty/crunch/crnlib/crn_math.cpp
  80. 0 237
      Source/ThirdParty/crunch/crnlib/crn_math.h
  81. 0 565
      Source/ThirdParty/crunch/crnlib/crn_matrix.h
  82. 0 379
      Source/ThirdParty/crunch/crnlib/crn_mem.cpp
  83. 0 209
      Source/ThirdParty/crunch/crnlib/crn_mem.h
  84. 0 3948
      Source/ThirdParty/crunch/crnlib/crn_miniz.cpp
  85. 0 893
      Source/ThirdParty/crunch/crnlib/crn_miniz.h
  86. 0 3374
      Source/ThirdParty/crunch/crnlib/crn_mipmapped_texture.cpp
  87. 0 339
      Source/ThirdParty/crunch/crnlib/crn_mipmapped_texture.h
  88. 0 91
      Source/ThirdParty/crunch/crnlib/crn_packed_uint.h
  89. 0 280
      Source/ThirdParty/crunch/crnlib/crn_pixel_format.cpp
  90. 0 284
      Source/ThirdParty/crunch/crnlib/crn_pixel_format.h
  91. 0 92
      Source/ThirdParty/crunch/crnlib/crn_platform.cpp
  92. 0 96
      Source/ThirdParty/crunch/crnlib/crn_platform.h
  93. 0 356
      Source/ThirdParty/crunch/crnlib/crn_prefix_coding.cpp
  94. 0 116
      Source/ThirdParty/crunch/crnlib/crn_prefix_coding.h
  95. 0 910
      Source/ThirdParty/crunch/crnlib/crn_qdxt1.cpp
  96. 0 185
      Source/ThirdParty/crunch/crnlib/crn_qdxt1.h
  97. 0 827
      Source/ThirdParty/crunch/crnlib/crn_qdxt5.cpp
  98. 0 194
      Source/ThirdParty/crunch/crnlib/crn_qdxt5.h
  99. 0 345
      Source/ThirdParty/crunch/crnlib/crn_radix_sort.h
  100. 0 385
      Source/ThirdParty/crunch/crnlib/crn_rand.cpp

+ 2 - 2
Build/CMake/Modules/AtomicDesktop.cmake

@@ -3,9 +3,9 @@ include(AtomicCommon)
 
 include_directories(${CMAKE_SOURCE_DIR}/Source/ThirdParty/Poco/Foundation/include)
 
-add_definitions( -DATOMIC_NAVIGATION -DATOMIC_TBUI -DATOMIC_FILEWATCHER -DPOCO_NO_AUTOMATIC_LIBS -DPOCO_STATIC )
+add_definitions( -DATOMIC_PLATFORM_DESKTOP -DATOMIC_NAVIGATION -DATOMIC_TBUI -DATOMIC_FILEWATCHER -DPOCO_NO_AUTOMATIC_LIBS -DPOCO_STATIC )
 
-set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} LibCpuId SQLite)
+set (ATOMIC_LINK_LIBRARIES ${ATOMIC_LINK_LIBRARIES} LibCpuId SQLite libsquish)
 
 # Check whether the CEF submodule is available
 if (EXISTS ${CMAKE_SOURCE_DIR}/Submodules/CEF)

+ 1 - 1
CMakeLists.txt

@@ -25,7 +25,7 @@ endif()
 # this is here as QtCreator is having trouble picking up #include <Atomic/*> without it
 include_directories(${CMAKE_SOURCE_DIR}/Source ${CMAKE_SOURCE_DIR}/Source/AtomicEditor/Source)
 
-set (ATOMIC_LINK_LIBRARIES Atomic Box2D Duktape TurboBadger FreeType JO LZ4 PugiXml STB crunch)
+set (ATOMIC_LINK_LIBRARIES Atomic Box2D Duktape TurboBadger FreeType JO LZ4 PugiXml STB)
 
 if (NOT ATOMIC_BUILD_2D)
     add_definitions( -DATOMIC_PHYSICS -DATOMIC_3D)

+ 18 - 20
LICENSE.md

@@ -187,31 +187,29 @@ required.
 misrepresented as being the original software.
 3. This notice may not be removed or altered from any source distribution.
 
-#### crunch license
+#### libsquish license
 --------------
 
-crunch/crnlib uses the ZLIB license:
-http://opensource.org/licenses/Zlib
-
-Copyright (c) 2010-2012 Rich Geldreich and Tenacious Software LLC
-
-This software is provided 'as-is', without any express or implied
-warranty.  In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
+Copyright (c) 2006 Simon Brown                          [email protected]
 
-1. The origin of this software must not be misrepresented; you must not
-claim that you wrote the original software. If you use this software
-in a product, an acknowledgment in the product documentation would be
-appreciated but is not required.
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to	deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
 
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
 
-3. This notice may not be removed or altered from any source distribution.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #### Civetweb license
 ----------------

+ 2 - 1
Source/Atomic/Resource/Image.cpp

@@ -33,7 +33,6 @@
 #include <SDL/include/SDL_surface.h>
 #include <STB/stb_image.h>
 #include <STB/stb_image_write.h>
-#include <crunch/inc/crnlib.h>
 
 #include "../DebugNew.h"
 
@@ -1236,6 +1235,7 @@ bool Image::SaveDDS(const String& fileName) const
         // with subclasses for particular image output types. Also should have image settings in the image meta.
         // ImageReader/Writers should also support a progress callback so UI can be updated.
 
+#ifdef CRUNCH
         // Compression setup
         crn_comp_params compParams;
         compParams.m_width = width_;
@@ -1291,6 +1291,7 @@ bool Image::SaveDDS(const String& fileName) const
             crn_free_block(compressedData);
             return success;
         }
+#endif
         
         // #623 END TODO
     }

+ 1 - 1
Source/ThirdParty/CMakeLists.txt

@@ -34,7 +34,7 @@ if (NOT IOS AND NOT ANDROID AND NOT EMSCRIPTEN)
     add_subdirectory(SQLite)
     add_subdirectory(Poco)
     add_subdirectory(nativefiledialog)
-    add_subdirectory(crunch)
+    add_subdirectory(libsquish)
 endif ()
 
 if (LINUX OR APPLE AND NOT IOS)

+ 0 - 26
Source/ThirdParty/crunch/CMakeLists.txt

@@ -1,26 +0,0 @@
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-
-# Define source files
-file (GLOB CRNLIB_CPP_FILES crnlib/*.cpp)
-file (GLOB CRNLIB_H_FILES crnlib/*.h)
-file (GLOB INC_H_FILES inc/*.h)
-
-# Remove windows only files
-if (NOT OS_WINDOWS)
-
-    list(REMOVE_ITEM CRNLIB_CPP_FILES "crnlib/lzma_LzFindMt.cpp")
-    list(REMOVE_ITEM CRNLIB_CPP_FILES "crnlib/lzma_Threads.cpp")
-    list(REMOVE_ITEM CRNLIB_H_FILES "crnlib/lzma_LzFindMt.h")
-    list(REMOVE_ITEM CRNLIB_H_FILES "crnlib/lzma_Threads.h")
-
-endif ()
-
-set (SOURCE_FILES ${CRNLIB_CPP_FILES} ${CRNLIB_H_FILES} ${INC_H_FILES})
-
-# These are used to create visual studio folders.
-source_group(crnlib FILES ${CRNLIB_CPP_FILES} ${CRNLIB_H_FILES})
-source_group(inc FILES ${INC_H_FILES})
-
-
-add_library(crunch ${SOURCE_FILES})
-

+ 0 - 698
Source/ThirdParty/crunch/crnlib/crn_arealist.cpp

@@ -1,698 +0,0 @@
-// File: crn_arealist.cpp - 2D shape algebra (currently unused)
-// See Copyright Notice and license at the end of inc/crnlib.h
-// 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"
-
-#define RECT_DEBUG
-
-namespace crnlib
-{
-
-   static void area_fatal_error(const char* pFunc, const char* pMsg, ...)
-   {
-      pFunc;
-      va_list args;
-      va_start(args, pMsg);
-
-      char buf[512];
-#ifdef _MSC_VER
-      _vsnprintf_s(buf, sizeof(buf), pMsg, args);
-#else
-      vsnprintf(buf, sizeof(buf), pMsg, args);
-#endif
-
-      va_end(args);
-
-      CRNLIB_FAIL(buf);
-   }
-
-   static Area * delete_area(Area_List *Plist, Area *Parea)
-   {
-      Area *p, *q;
-
-   #ifdef RECT_DEBUG
-      if ((Parea == Plist->Phead) || (Parea == Plist->Ptail))
-         area_fatal_error("delete_area", "tried to remove head or tail");
-   #endif
-
-      p = Parea->Pprev;
-      q = Parea->Pnext;
-      p->Pnext = q;
-      q->Pprev = p;
-
-      Parea->Pnext = Plist->Pfree;
-      Parea->Pprev = NULL;
-      Plist->Pfree = Parea;
-
-      return (q);
-   }
-
-   static Area * alloc_area(Area_List *Plist)
-   {
-      Area *p = Plist->Pfree;
-
-      if (p == NULL)
-      {
-         if (Plist->next_free == Plist->total_areas)
-            area_fatal_error("alloc_area", "Out of areas!");
-
-         p = Plist->Phead + Plist->next_free;
-         Plist->next_free++;
-      }
-      else
-         Plist->Pfree = p->Pnext;
-
-      return (p);
-   }
-
-   static Area * insert_area_before(Area_List *Plist, Area *Parea,
-                                    int x1, int y1, int x2, int y2)
-   {
-      Area *p, *Pnew_area = alloc_area(Plist);
-
-      p = Parea->Pprev;
-
-      p->Pnext = Pnew_area;
-
-      Pnew_area->Pprev = p;
-      Pnew_area->Pnext = Parea;
-
-      Parea->Pprev = Pnew_area;
-
-      Pnew_area->x1 = x1;
-      Pnew_area->y1 = y1;
-      Pnew_area->x2 = x2;
-      Pnew_area->y2 = y2;
-
-      return (Pnew_area);
-   }
-
-   static Area * insert_area_after(Area_List *Plist, Area *Parea,
-                                   int x1, int y1, int x2, int y2)
-   {
-      Area *p, *Pnew_area = alloc_area(Plist);
-
-      p = Parea->Pnext;
-
-      p->Pprev = Pnew_area;
-
-      Pnew_area->Pnext = p;
-      Pnew_area->Pprev = Parea;
-
-      Parea->Pnext = Pnew_area;
-
-      Pnew_area->x1 = x1;
-      Pnew_area->y1 = y1;
-      Pnew_area->x2 = x2;
-      Pnew_area->y2 = y2;
-
-      return (Pnew_area);
-   }
-
-   void Area_List_deinit(Area_List* Pobj_base)
-   {
-      Area_List *Plist = (Area_List *)Pobj_base;
-
-      if (!Plist)
-         return;
-
-      if (Plist->Phead)
-      {
-         crnlib_free(Plist->Phead);
-         Plist->Phead = NULL;
-      }
-
-      crnlib_free(Plist);
-   }
-
-   Area_List * Area_List_init(int max_areas)
-   {
-      Area_List *Plist = (Area_List*)crnlib_calloc(1, sizeof(Area_List));
-
-      Plist->total_areas = max_areas + 2;
-
-      Plist->Phead = (Area *)crnlib_calloc(max_areas + 2, sizeof(Area));
-      Plist->Ptail = Plist->Phead + 1;
-
-      Plist->Phead->Pprev = NULL;
-      Plist->Phead->Pnext = Plist->Ptail;
-
-      Plist->Ptail->Pprev = Plist->Phead;
-      Plist->Ptail->Pnext = NULL;
-
-      Plist->Pfree = NULL;
-      Plist->next_free = 2;
-
-      return (Plist);
-   }
-
-   void Area_List_print(Area_List *Plist)
-   {
-      Area *Parea = Plist->Phead->Pnext;
-
-      while (Parea != Plist->Ptail)
-      {
-         printf("%04i %04i : %04i %04i\n", Parea->x1, Parea->y1, Parea->x2, Parea->y2);
-
-         Parea = Parea->Pnext;
-      }
-   }
-
-   Area_List * Area_List_dup_new(Area_List *Plist,
-                                 int x_ofs, int y_ofs)
-   {
-      int i;
-      Area_List *Pnew_list = (Area_List*)crnlib_calloc(1, sizeof(Area_List));
-
-      Pnew_list->total_areas = Plist->total_areas;
-
-      Pnew_list->Phead = (Area *)crnlib_malloc(sizeof(Area) * Plist->total_areas);
-      Pnew_list->Ptail = Pnew_list->Phead + 1;
-
-      Pnew_list->Pfree = (Plist->Pfree) ? ((Plist->Pfree - Plist->Phead) + Pnew_list->Phead) : NULL;
-
-      Pnew_list->next_free = Plist->next_free;
-
-      memcpy(Pnew_list->Phead, Plist->Phead, sizeof(Area) * Plist->total_areas);
-
-      for (i = 0; i < Plist->total_areas; i++)
-      {
-         Pnew_list->Phead[i].Pnext = (Plist->Phead[i].Pnext == NULL) ? NULL : (Plist->Phead[i].Pnext - Plist->Phead) + Pnew_list->Phead;
-         Pnew_list->Phead[i].Pprev = (Plist->Phead[i].Pprev == NULL) ? NULL : (Plist->Phead[i].Pprev - Plist->Phead) + Pnew_list->Phead;
-
-         Pnew_list->Phead[i].x1 += x_ofs;
-         Pnew_list->Phead[i].y1 += y_ofs;
-         Pnew_list->Phead[i].x2 += x_ofs;
-         Pnew_list->Phead[i].y2 += y_ofs;
-      }
-
-      return (Pnew_list);
-   }
-
-   uint Area_List_get_num(Area_List* Plist)
-   {
-      uint num = 0;
-
-      Area *Parea = Plist->Phead->Pnext;
-
-      while (Parea != Plist->Ptail)
-      {
-         num++;
-
-         Parea = Parea->Pnext;
-      }
-
-      return num;
-   }
-
-   void Area_List_dup(Area_List *Psrc_list, Area_List *Pdst_list,
-                      int x_ofs, int y_ofs)
-   {
-      int i;
-
-      if (Psrc_list->total_areas != Pdst_list->total_areas)
-         area_fatal_error("Area_List_dup", "Src and Dst total_areas must be equal!");
-
-      Pdst_list->Pfree = (Psrc_list->Pfree) ? ((Psrc_list->Pfree - Psrc_list->Phead) + Pdst_list->Phead) : NULL;
-
-      Pdst_list->next_free = Psrc_list->next_free;
-
-      memcpy(Pdst_list->Phead, Psrc_list->Phead, sizeof(Area) * Psrc_list->total_areas);
-
-      if ((x_ofs) || (y_ofs))
-      {
-         for (i = 0; i < Psrc_list->total_areas; i++)
-         {
-            Pdst_list->Phead[i].Pnext = (Psrc_list->Phead[i].Pnext == NULL) ? NULL : (Psrc_list->Phead[i].Pnext - Psrc_list->Phead) + Pdst_list->Phead;
-            Pdst_list->Phead[i].Pprev = (Psrc_list->Phead[i].Pprev == NULL) ? NULL : (Psrc_list->Phead[i].Pprev - Psrc_list->Phead) + Pdst_list->Phead;
-
-            Pdst_list->Phead[i].x1 += x_ofs;
-            Pdst_list->Phead[i].y1 += y_ofs;
-            Pdst_list->Phead[i].x2 += x_ofs;
-            Pdst_list->Phead[i].y2 += y_ofs;
-         }
-      }
-      else
-      {
-         for (i = 0; i < Psrc_list->total_areas; i++)
-         {
-            Pdst_list->Phead[i].Pnext = (Psrc_list->Phead[i].Pnext == NULL) ? NULL : (Psrc_list->Phead[i].Pnext - Psrc_list->Phead) + Pdst_list->Phead;
-            Pdst_list->Phead[i].Pprev = (Psrc_list->Phead[i].Pprev == NULL) ? NULL : (Psrc_list->Phead[i].Pprev - Psrc_list->Phead) + Pdst_list->Phead;
-         }
-      }
-   }
-
-   void Area_List_copy(
-                       Area_List *Psrc_list, Area_List *Pdst_list,
-                       int x_ofs, int y_ofs)
-   {
-      Area *Parea = Psrc_list->Phead->Pnext;
-
-      Area_List_clear(Pdst_list);
-
-      if ((x_ofs) || (y_ofs))
-      {
-         Area *Pprev_area = Pdst_list->Phead;
-
-         while (Parea != Psrc_list->Ptail)
-         {
-            //      Area *p, *Pnew_area;
-            Area *Pnew_area;
-
-            if (Pdst_list->next_free == Pdst_list->total_areas)
-               area_fatal_error("Area_List_copy", "Out of areas!");
-
-            Pnew_area = Pdst_list->Phead + Pdst_list->next_free;
-            Pdst_list->next_free++;
-
-            Pnew_area->Pprev = Pprev_area;
-            Pprev_area->Pnext = Pnew_area;
-
-            Pnew_area->x1 = Parea->x1 + x_ofs;
-            Pnew_area->y1 = Parea->y1 + y_ofs;
-            Pnew_area->x2 = Parea->x2 + x_ofs;
-            Pnew_area->y2 = Parea->y2 + y_ofs;
-
-            Pprev_area = Pnew_area;
-
-            Parea = Parea->Pnext;
-         }
-
-         Pprev_area->Pnext = Pdst_list->Ptail;
-      }
-      else
-      {
-   #if 0
-         while (Parea != Psrc_list->Ptail)
-         {
-            insert_area_after(Pdst_list, Pdst_list->Phead,
-               Parea->x1,
-               Parea->y1,
-               Parea->x2,
-               Parea->y2);
-
-            Parea = Parea->Pnext;
-         }
-   #endif
-
-         Area *Pprev_area = Pdst_list->Phead;
-
-         while (Parea != Psrc_list->Ptail)
-         {
-            //      Area *p, *Pnew_area;
-            Area *Pnew_area;
-
-            if (Pdst_list->next_free == Pdst_list->total_areas)
-               area_fatal_error("Area_List_copy", "Out of areas!");
-
-            Pnew_area = Pdst_list->Phead + Pdst_list->next_free;
-            Pdst_list->next_free++;
-
-            Pnew_area->Pprev = Pprev_area;
-            Pprev_area->Pnext = Pnew_area;
-
-            Pnew_area->x1 = Parea->x1;
-            Pnew_area->y1 = Parea->y1;
-            Pnew_area->x2 = Parea->x2;
-            Pnew_area->y2 = Parea->y2;
-
-            Pprev_area = Pnew_area;
-
-            Parea = Parea->Pnext;
-         }
-
-         Pprev_area->Pnext = Pdst_list->Ptail;
-      }
-   }
-
-   void Area_List_clear(Area_List *Plist)
-   {
-      Plist->Phead->Pnext = Plist->Ptail;
-      Plist->Ptail->Pprev = Plist->Phead;
-      Plist->Pfree = NULL;
-      Plist->next_free = 2;
-   }
-
-   void Area_List_set(Area_List *Plist, int x1, int y1, int x2, int y2)
-   {
-      Plist->Pfree = NULL;
-
-      Plist->Phead[2].x1 = x1;
-      Plist->Phead[2].y1 = y1;
-      Plist->Phead[2].x2 = x2;
-      Plist->Phead[2].y2 = y2;
-
-      Plist->Phead[2].Pprev = Plist->Phead;
-      Plist->Phead->Pnext = Plist->Phead + 2;
-
-      Plist->Phead[2].Pnext = Plist->Ptail;
-      Plist->Ptail->Pprev = Plist->Phead + 2;
-
-      Plist->next_free = 3;
-   }
-
-   void Area_List_remove(Area_List *Plist,
-                         int x1, int y1, int x2, int y2)
-   {
-      int l, h;
-      Area *Parea = Plist->Phead->Pnext;
-
-   #ifdef RECT_DEBUG
-      if ((x1 > x2) || (y1 > y2))
-         area_fatal_error("area_list_remove", "invalid coords: %i %i %i %i", x1, y1, x2, y2);
-   #endif
-
-      while (Parea != Plist->Ptail)
-      {
-         // Not touching
-         if ((x2 < Parea->x1) || (x1 > Parea->x2) ||
-            (y2 < Parea->y1) || (y1 > Parea->y2))
-         {
-            Parea = Parea->Pnext;
-            continue;
-         }
-
-         // Completely covers
-         if ((x1 <= Parea->x1) && (x2 >= Parea->x2) &&
-            (y1 <= Parea->y1) && (y2 >= Parea->y2))
-         {
-            if ((x1 == Parea->x1) && (x2 == Parea->x2) &&
-               (y1 == Parea->y1) && (y2 == Parea->y2))
-            {
-               delete_area(Plist, Parea);
-               return;
-            }
-
-            Parea = delete_area(Plist, Parea);
-
-            continue;
-         }
-
-         // top
-         if (y1 > Parea->y1)
-         {
-            insert_area_before(Plist, Parea,
-               Parea->x1, Parea->y1,
-               Parea->x2, y1 - 1);
-         }
-
-         // bottom
-         if (y2 < Parea->y2)
-         {
-            insert_area_before(Plist, Parea,
-               Parea->x1, y2 + 1,
-               Parea->x2, Parea->y2);
-         }
-
-         l = math::maximum(y1, Parea->y1);
-         h = math::minimum(y2, Parea->y2);
-
-         // left middle
-         if (x1 > Parea->x1)
-         {
-            insert_area_before(Plist, Parea,
-               Parea->x1, l,
-               x1 - 1, h);
-         }
-
-         // right middle
-         if (x2 < Parea->x2)
-         {
-            insert_area_before(Plist, Parea,
-               x2 + 1, l,
-               Parea->x2, h);
-         }
-
-         // early out - we know there's nothing else to remove, as areas can
-         // never overlap
-         if ((x1 >= Parea->x1) && (x2 <= Parea->x2) &&
-            (y1 >= Parea->y1) && (y2 <= Parea->y2))
-         {
-            delete_area(Plist, Parea);
-            return;
-         }
-
-         Parea = delete_area(Plist, Parea);
-      }
-   }
-
-   void Area_List_insert(Area_List *Plist,
-                         int x1, int y1, int x2, int y2,
-                         bool combine)
-   {
-      Area *Parea = Plist->Phead->Pnext;
-
-   #ifdef RECT_DEBUG
-      if ((x1 > x2) || (y1 > y2))
-         area_fatal_error("Area_List_insert", "invalid coords: %i %i %i %i", x1, y1, x2, y2);
-   #endif
-
-      while (Parea != Plist->Ptail)
-      {
-         // totally covers
-         if ((x1 <= Parea->x1) && (x2 >= Parea->x2) &&
-            (y1 <= Parea->y1) && (y2 >= Parea->y2))
-         {
-            Parea = delete_area(Plist, Parea);
-            continue;
-         }
-
-         // intersects
-         if ((x2 >= Parea->x1) && (x1 <= Parea->x2) &&
-            (y2 >= Parea->y1) && (y1 <= Parea->y2))
-         {
-            int ax1, ay1, ax2, ay2;
-
-            ax1 = Parea->x1;
-            ay1 = Parea->y1;
-            ax2 = Parea->x2;
-            ay2 = Parea->y2;
-
-            if (x1 < ax1)
-               Area_List_insert(Plist, x1, math::maximum(y1, ay1), ax1 - 1, math::minimum(y2, ay2), combine);
-
-            if (x2 > ax2)
-               Area_List_insert(Plist, ax2 + 1, math::maximum(y1, ay1), x2, math::minimum(y2, ay2), combine);
-
-            if (y1 < ay1)
-               Area_List_insert(Plist, x1, y1, x2, ay1 - 1, combine);
-
-            if (y2 > ay2)
-               Area_List_insert(Plist, x1, ay2 + 1, x2, y2, combine);
-
-            return;
-         }
-
-         if (combine)
-         {
-            if ((x1 == Parea->x1) && (x2 == Parea->x2))
-            {
-               if ((y2 == Parea->y1 - 1) || (y1 == Parea->y2 + 1))
-               {
-                  delete_area(Plist, Parea);
-                  Area_List_insert(Plist, x1, math::minimum(y1, Parea->y1), x2, math::maximum(y2, Parea->y2), CRNLIB_TRUE);
-                  return;
-               }
-            }
-            else if ((y1 == Parea->y1) && (y2 == Parea->y2))
-            {
-               if ((x2 == Parea->x1 - 1) || (x1 == Parea->x2 + 1))
-               {
-                  delete_area(Plist, Parea);
-                  Area_List_insert(Plist, math::minimum(x1, Parea->x1), y1, math::maximum(x2, Parea->x2), y2, CRNLIB_TRUE);
-                  return;
-               }
-            }
-         }
-
-         Parea = Parea->Pnext;
-      }
-
-      insert_area_before(Plist, Parea, x1, y1, x2, y2);
-   }
-
-   void Area_List_intersect_area(Area_List *Plist,
-                                 int x1, int y1, int x2, int y2)
-   {
-      Area *Parea = Plist->Phead->Pnext;
-
-      while (Parea != Plist->Ptail)
-      {
-         // doesn't cover
-         if ((x2 < Parea->x1) || (x1 > Parea->x2) ||
-            (y2 < Parea->y1) || (y1 > Parea->y2))
-         {
-            Parea = delete_area(Plist, Parea);
-            continue;
-         }
-
-         // totally covers
-         if ((x1 <= Parea->x1) && (x2 >= Parea->x2) &&
-            (y1 <= Parea->y1) && (y2 >= Parea->y2))
-         {
-            Parea = Parea->Pnext;
-            continue;
-         }
-
-         // Oct 21- should insert after, because deleted area will access the NEXT area!
-         //    insert_area_after(Plist, Parea,
-         //                      math::maximum(x1, Parea->x1),
-         //                      math::maximum(y1, Parea->y1),
-         //                      math::minimum(x2, Parea->x2),
-         //                      math::minimum(y2, Parea->y2));
-
-         insert_area_before(Plist, Parea,
-            math::maximum(x1, Parea->x1),
-            math::maximum(y1, Parea->y1),
-            math::minimum(x2, Parea->x2),
-            math::minimum(y2, Parea->y2));
-
-         Parea = delete_area(Plist, Parea);
-      }
-   }
-
-   #if 0
-   void Area_List_intersect_Area_List(
-                                      Area_List *Pouter_list,
-                                      Area_List *Pinner_list,
-                                      Area_List *Pdst_list)
-   {
-      Area *Parea1 = Pouter_list->Phead->Pnext;
-
-      while (Parea1 != Pouter_list->Ptail)
-      {
-         Area *Parea2 = Pinner_list->Phead->Pnext;
-         int x1, y1, x2, y2;
-
-         x1 = Parea1->x1; x2 = Parea1->x2;
-         y1 = Parea1->y1; y2 = Parea1->y2;
-
-         while (Parea2 != Pinner_list->Ptail)
-         {
-            if ((x1 <= Parea2->x2) && (x2 >= Parea2->x1) &&
-               (y1 <= Parea2->y2) && (y2 >= Parea2->y1))
-            {
-               insert_area_after(Pdst_list, Pdst_list->Phead,
-                  math::maximum(x1, Parea2->x1),
-                  math::maximum(y1, Parea2->y1),
-                  math::minimum(x2, Parea2->x2),
-                  math::minimum(y2, Parea2->y2));
-            }
-
-            Parea2 = Parea2->Pnext;
-         }
-
-         Parea1 = Parea1->Pnext;
-      }
-   }
-   #endif
-
-   #if 1
-   void Area_List_intersect_Area_List(Area_List *Pouter_list,
-                                      Area_List *Pinner_list,
-                                      Area_List *Pdst_list)
-   {
-      Area *Parea1 = Pouter_list->Phead->Pnext;
-
-      while (Parea1 != Pouter_list->Ptail)
-      {
-         Area *Parea2 = Pinner_list->Phead->Pnext;
-         int x1, y1, x2, y2;
-
-         x1 = Parea1->x1; x2 = Parea1->x2;
-         y1 = Parea1->y1; y2 = Parea1->y2;
-
-         while (Parea2 != Pinner_list->Ptail)
-         {
-            if ((x1 <= Parea2->x2) && (x2 >= Parea2->x1) &&
-               (y1 <= Parea2->y2) && (y2 >= Parea2->y1))
-            {
-               int nx1, ny1, nx2, ny2;
-
-               nx1 = math::maximum(x1, Parea2->x1);
-               ny1 = math::maximum(y1, Parea2->y1);
-               nx2 = math::minimum(x2, Parea2->x2);
-               ny2 = math::minimum(y2, Parea2->y2);
-
-               if (Pdst_list->Phead->Pnext == Pdst_list->Ptail)
-               {
-                  insert_area_after(Pdst_list, Pdst_list->Phead,
-                     nx1, ny1, nx2, ny2);
-               }
-               else
-               {
-                  Area_Ptr Ptemp = Pdst_list->Phead->Pnext;
-                  if ((Ptemp->x1 == nx1) && (Ptemp->x2 == nx2))
-                  {
-                     if (Ptemp->y1 == (ny2+1))
-                     {
-                        Ptemp->y1 = ny1;
-                        goto next;
-                     }
-                     else if (Ptemp->y2 == (ny1-1))
-                     {
-                        Ptemp->y2 = ny2;
-                        goto next;
-                     }
-                  }
-                  else if ((Ptemp->y1 == ny1) && (Ptemp->y2 == ny2))
-                  {
-                     if (Ptemp->x1 == (nx2+1))
-                     {
-                        Ptemp->x1 = nx1;
-                        goto next;
-                     }
-                     else if (Ptemp->x2 == (nx1-1))
-                     {
-                        Ptemp->x2 = nx2;
-                        goto next;
-                     }
-                  }
-
-                  insert_area_after(Pdst_list, Pdst_list->Phead,
-                     nx1, ny1, nx2, ny2);
-               }
-            }
-
-   next:
-
-            Parea2 = Parea2->Pnext;
-         }
-
-         Parea1 = Parea1->Pnext;
-      }
-   }
-   #endif
-
-   Area_List_Ptr Area_List_create_optimal(Area_List_Ptr Plist)
-   {
-      Area_Ptr Parea = Plist->Phead->Pnext, Parea_after;
-      int num = 2;
-      Area_List_Ptr Pnew_list;
-
-      while (Parea != Plist->Ptail)
-      {
-         num++;
-         Parea = Parea->Pnext;
-      }
-
-      Pnew_list = Area_List_init(num);
-
-      Parea = Plist->Phead->Pnext;
-
-      Parea_after = Pnew_list->Phead;
-
-      while (Parea != Plist->Ptail)
-      {
-         Parea_after = insert_area_after(Pnew_list, Parea_after,
-            Parea->x1, Parea->y1,
-            Parea->x2, Parea->y2);
-
-         Parea = Parea->Pnext;
-      }
-
-      return (Pnew_list);
-   }
-
-} // namespace crnlib

+ 0 - 74
Source/ThirdParty/crunch/crnlib/crn_arealist.h

@@ -1,74 +0,0 @@
-// File: crn_arealist.h - 2D shape algebra
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   struct Area
-   {
-      struct Area *Pprev, *Pnext;
-
-      int x1, y1, x2, y2;
-      
-      uint get_width() const { return x2 - x1 + 1; }
-      uint get_height() const { return y2 - y1 + 1; }
-      uint get_area() const { return get_width() * get_height(); }
-   };
-
-   typedef Area * Area_Ptr;
-
-   struct Area_List
-   {
-      int total_areas;
-      int next_free;
-
-      Area *Phead, *Ptail, *Pfree;
-   };
-
-   typedef Area_List * Area_List_Ptr;
-
-   Area_List * Area_List_init(int max_areas);
-   void Area_List_deinit(Area_List* Pobj_base);
-
-   void Area_List_print(Area_List *Plist);
-
-   Area_List * Area_List_dup_new(Area_List *Plist,
-                                 int x_ofs, int y_ofs);
-                                 
-   uint Area_List_get_num(Area_List* Plist);                                 
-
-   // src and dst area lists must have the same number of total areas.
-   void Area_List_dup(Area_List *Psrc_list,
-                      Area_List *Pdst_list,
-                      int x_ofs, int y_ofs);
-
-   void Area_List_copy(Area_List *Psrc_list,
-                       Area_List *Pdst_list,
-                       int x_ofs, int y_ofs);
-
-   void Area_List_clear(Area_List *Plist);
-
-   void Area_List_set(Area_List *Plist,
-                      int x1, int y1, int x2, int y2);
-
-   // logical: x and (not y)
-   void Area_List_remove(Area_List *Plist,
-                         int x1, int y1, int x2, int y2);
-
-   // logical: x or y
-   void Area_List_insert(Area_List *Plist,
-                         int x1, int y1, int x2, int y2,
-                         bool combine); 
-
-   // logical: x and y
-   void Area_List_intersect_area(Area_List *Plist,
-                                 int x1, int y1, int x2, int y2);
-
-   // logical: x and y
-   void Area_List_intersect_Area_List(Area_List *Pouter_list,
-                                      Area_List *Pinner_list,
-                                      Area_List *Pdst_list);
-
-   Area_List_Ptr Area_List_create_optimal(Area_List_Ptr Plist);
-
-} // namespace crnlib

+ 0 - 69
Source/ThirdParty/crunch/crnlib/crn_assert.cpp

@@ -1,69 +0,0 @@
-// 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"
-#endif
-
-static bool g_fail_exceptions;
-static bool g_exit_on_failure = true;
-
-void crnlib_enable_fail_exceptions(bool enabled)
-{
-   g_fail_exceptions = enabled;
-}
-
-void crnlib_assert(const char* pExp, const char* pFile, unsigned line)
-{
-   char buf[512];
-
-   sprintf_s(buf, sizeof(buf), "%s(%u): Assertion failed: \"%s\"\n", pFile, line, pExp);
-
-   crnlib_output_debug_string(buf);
-
-   fputs(buf, stderr);
-
-   if (crnlib_is_debugger_present())
-      crnlib_debug_break();
-}
-
-void crnlib_fail(const char* pExp, const char* pFile, unsigned line)
-{
-   char buf[512];
-
-   sprintf_s(buf, sizeof(buf), "%s(%u): Failure: \"%s\"\n", pFile, line, pExp);
-
-   crnlib_output_debug_string(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
-#endif
-   if (g_exit_on_failure)
-      exit(EXIT_FAILURE);
-}
-
-void trace(const char* pFmt, va_list args)
-{
-   if (crnlib_is_debugger_present())
-   {
-      char buf[512];
-      vsprintf_s(buf, sizeof(buf), pFmt, args);
-
-      crnlib_output_debug_string(buf);
-   }
-};
-
-void trace(const char* pFmt, ...)
-{
-   va_list args;
-   va_start(args, pFmt);
-   trace(pFmt, args);
-   va_end(args);
-};

+ 0 - 61
Source/ThirdParty/crunch/crnlib/crn_assert.h

@@ -1,61 +0,0 @@
-// File: crn_assert.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-const unsigned int CRNLIB_FAIL_EXCEPTION_CODE = 256U;
-void crnlib_enable_fail_exceptions(bool enabled);
-
-void crnlib_assert(const char* pExp, const char* pFile, unsigned line);
-void crnlib_fail(const char* pExp, const char* pFile, unsigned line);
-
-#ifdef NDEBUG
-   #define CRNLIB_ASSERT(x) ((void)0)
-   #undef  CRNLIB_ASSERTS_ENABLED
-#else
-   #define CRNLIB_ASSERT(_exp) (void)( (!!(_exp)) || (crnlib_assert(#_exp, __FILE__, __LINE__), 0) )
-   #define CRNLIB_ASSERTS_ENABLED
-#endif
-
-#define CRNLIB_VERIFY(_exp) (void)( (!!(_exp)) || (crnlib_assert(#_exp, __FILE__, __LINE__), 0) )
-
-#define CRNLIB_FAIL(msg) do { crnlib_fail(#msg, __FILE__, __LINE__); } while(0)
-
-#define CRNLIB_ASSERT_OPEN_RANGE(x, l, h) CRNLIB_ASSERT((x >= l) && (x < h))
-#define CRNLIB_ASSERT_CLOSED_RANGE(x, l, h) CRNLIB_ASSERT((x >= l) && (x <= h))
-
-void trace(const char* pFmt, va_list args);
-void trace(const char* pFmt, ...);
-
-// Borrowed from boost libraries.
-template <bool x>  struct crnlib_assume_failure;
-template <> struct crnlib_assume_failure<true> { enum { blah = 1 }; };
-template<int x> struct crnlib_assume_try { };
-
-#define CRNLIB_JOINER_FINAL(a, b) a##b
-#define CRNLIB_JOINER(a, b) CRNLIB_JOINER_FINAL(a, b)
-#define CRNLIB_JOIN(a, b) CRNLIB_JOINER(a, b)
-#define CRNLIB_ASSUME(p) typedef crnlib_assume_try < sizeof(crnlib_assume_failure< (bool)(p) > ) > CRNLIB_JOIN(crnlib_assume_typedef, __COUNTER__)
-
-#ifdef NDEBUG
-template<typename T> inline T crnlib_assert_range(T i, T m)
-{
-   m;
-   return i;
-}
-template<typename T> inline T crnlib_assert_range_incl(T i, T m)
-{
-   m;
-   return i;
-}
-#else
-template<typename T> inline T crnlib_assert_range(T i, T m)
-{
-   CRNLIB_ASSERT((i >= 0) && (i < m));
-   return i;
-}
-template<typename T> inline T crnlib_assert_range_incl(T i, T m)
-{
-   CRNLIB_ASSERT((i >= 0) && (i <= m));
-   return i;
-}
-#endif

+ 0 - 208
Source/ThirdParty/crunch/crnlib/crn_atomics.h

@@ -1,208 +0,0 @@
-// File: crn_atomics.h
-#ifndef CRN_ATOMICS_H
-#define CRN_ATOMICS_H
-
-#ifdef WIN32
-#pragma once
-#endif
-
-#ifdef WIN32
-#include "crn_winhdr.h"
-#endif
-
-#if defined(__GNUC__) && CRNLIB_PLATFORM_PC
-extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) void crnlib_yield_processor()
-{
-   __asm__ __volatile__("pause");
-}
-#else
-CRNLIB_FORCE_INLINE void crnlib_yield_processor()
-{
-#if CRNLIB_USE_MSVC_INTRINSICS
-   #if CRNLIB_PLATFORM_PC_X64
-      _mm_pause();
-   #else
-      YieldProcessor();
-   #endif
-#else
-   // No implementation
-#endif
-}
-#endif
-
-#if CRNLIB_USE_WIN32_ATOMIC_FUNCTIONS
-   extern "C" __int64 _InterlockedCompareExchange64(__int64 volatile * Destination, __int64 Exchange, __int64 Comperand);
-   #if defined(_MSC_VER)
-      #pragma intrinsic(_InterlockedCompareExchange64)
-   #endif
-#endif // CRNLIB_USE_WIN32_ATOMIC_FUNCTIONS
-
-namespace crnlib
-{
-#if CRNLIB_USE_WIN32_ATOMIC_FUNCTIONS
-   typedef LONG atomic32_t;
-   typedef LONGLONG atomic64_t;
-
-   // Returns the original value.
-   inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return InterlockedCompareExchange(pDest, exchange, comparand);
-   }
-
-   // Returns the original value.
-   inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
-      return _InterlockedCompareExchange64(pDest, exchange, comparand);
-   }
-
-   // Returns the resulting incremented value.
-   inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return InterlockedIncrement(pDest);
-   }
-
-   // Returns the resulting decremented value.
-   inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return InterlockedDecrement(pDest);
-   }
-
-   // Returns the original value.
-   inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return InterlockedExchange(pDest, val);
-   }
-
-   // Returns the resulting value.
-   inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return InterlockedExchangeAdd(pDest, val) + val;
-   }
-
-   // Returns the original value.
-   inline atomic32_t atomic_exchange_add32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return InterlockedExchangeAdd(pDest, val);
-   }
-#elif CRNLIB_USE_GCC_ATOMIC_BUILTINS
-   typedef long atomic32_t;
-   typedef long long atomic64_t;
-
-   // Returns the original value.
-   inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return __sync_val_compare_and_swap(pDest, comparand, exchange);
-   }
-
-   // Returns the original value.
-   inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
-      return __sync_val_compare_and_swap(pDest, comparand, exchange);
-   }
-
-   // Returns the resulting incremented value.
-   inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return __sync_add_and_fetch(pDest, 1);
-   }
-
-   // Returns the resulting decremented value.
-   inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return __sync_sub_and_fetch(pDest, 1);
-   }
-
-   // Returns the original value.
-   inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return __sync_lock_test_and_set(pDest, val);
-   }
-
-   // Returns the resulting value.
-   inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return __sync_add_and_fetch(pDest, val);
-   }
-
-   // Returns the original value.
-   inline atomic32_t atomic_exchange_add32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return __sync_fetch_and_add(pDest, val);
-   }
-#else
-   #define CRNLIB_NO_ATOMICS 1
-
-   // Atomic ops not supported - but try to do something reasonable. Assumes no threading at all.
-   typedef long atomic32_t;
-   typedef long long atomic64_t;
-
-   inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      atomic32_t cur = *pDest;
-      if (cur == comparand)
-         *pDest = exchange;
-      return cur;
-   }
-
-   inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
-      atomic64_t cur = *pDest;
-      if (cur == comparand)
-         *pDest = exchange;
-      return cur;
-   }
-
-   inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return (*pDest += 1);
-   }
-
-   inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return (*pDest -= 1);
-   }
-
-   inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      atomic32_t cur = *pDest;
-      *pDest = val;
-      return cur;
-   }
-
-   inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      return (*pDest += val);
-   }
-
-   inline atomic32_t atomic_exchange_add32(atomic32_t volatile *pDest, atomic32_t val)
-   {
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
-      atomic32_t cur = *pDest;
-      *pDest += val;
-      return cur;
-   }
-#endif
-
-} // namespace crnlib
-
-#endif // CRN_ATOMICS_H

+ 0 - 196
Source/ThirdParty/crunch/crnlib/crn_buffer_stream.h

@@ -1,196 +0,0 @@
-// File: crn_buffer_stream.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_data_stream.h"
-
-namespace crnlib
-{
-   class buffer_stream : public data_stream
-   {
-   public:
-      buffer_stream() :
-         data_stream(),
-         m_pBuf(NULL),
-         m_size(0),
-         m_ofs(0)
-      {
-      }
-
-      buffer_stream(void* p, uint size) :
-         data_stream(),
-         m_pBuf(NULL),
-         m_size(0),
-         m_ofs(0)
-      {
-         open(p, size);
-      }
-
-      buffer_stream(const void* p, uint size) :
-         data_stream(),
-         m_pBuf(NULL),
-         m_size(0),
-         m_ofs(0)
-      {
-         open(p, size);
-      }
-
-      virtual ~buffer_stream()
-      {
-      }
-
-      bool open(const void* p, uint size)
-      {
-         CRNLIB_ASSERT(p);
-
-         close();
-
-         if ((!p) || (!size))
-            return false;
-
-         m_opened = true;
-         m_pBuf = (uint8*)(p);
-         m_size = size;
-         m_ofs = 0;
-         m_attribs = cDataStreamSeekable | cDataStreamReadable;
-         return true;
-      }
-
-      bool open(void* p, uint size)
-      {
-         CRNLIB_ASSERT(p);
-
-         close();
-
-         if ((!p) || (!size))
-            return false;
-
-         m_opened = true;
-         m_pBuf = static_cast<uint8*>(p);
-         m_size = size;
-         m_ofs = 0;
-         m_attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable;
-         return true;
-      }
-
-      virtual bool close()
-      {
-         if (m_opened)
-         {
-            m_opened = false;
-            m_pBuf = NULL;
-            m_size = 0;
-            m_ofs = 0;
-            return true;
-         }
-
-         return false;
-      }
-
-      const void* get_buf() const   { return m_pBuf; }
-            void* get_buf()         { return m_pBuf; }
-
-      virtual const void* get_ptr() const { return m_pBuf; }
-
-      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_size);
-
-         uint bytes_left = m_size - m_ofs;
-
-         len = math::minimum<uint>(len, bytes_left);
-
-         if (len)
-            memcpy(pBuf, &m_pBuf[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_size);
-
-         uint bytes_left = m_size - m_ofs;
-
-         len = math::minimum<uint>(len, bytes_left);
-
-         if (len)
-            memcpy(&m_pBuf[m_ofs], pBuf, len);
-
-         m_ofs += len;
-
-         return len;
-      }
-
-      virtual bool flush()
-      {
-         if (!m_opened)
-            return false;
-
-         return true;
-      }
-
-      virtual uint64 get_size()
-      {
-         if (!m_opened)
-            return 0;
-
-         return m_size;
-      }
-
-      virtual uint64 get_remaining()
-      {
-         if (!m_opened)
-            return 0;
-
-         CRNLIB_ASSERT(m_ofs <= m_size);
-
-         return m_size - m_ofs;
-      }
-
-      virtual uint64 get_ofs()
-      {
-         if (!m_opened)
-            return 0;
-
-         return m_ofs;
-      }
-
-      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_size)
-            return false;
-
-         m_ofs = static_cast<uint>(new_ofs);
-
-         post_seek();
-
-         return true;
-      }
-
-   private:
-      uint8*   m_pBuf;
-      uint     m_size;
-      uint     m_ofs;
-   };
-
-} // namespace crnlib
-

+ 0 - 241
Source/ThirdParty/crunch/crnlib/crn_cfile_stream.h

@@ -1,241 +0,0 @@
-// File: crn_cfile_stream.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_data_stream.h"
-
-namespace crnlib
-{
-   class cfile_stream : public data_stream
-   {
-   public:
-      cfile_stream() : data_stream(), m_pFile(NULL), m_size(0), m_ofs(0), m_has_ownership(false)
-      {
-      }
-
-      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 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);
-      }
-
-      virtual ~cfile_stream()
-      {
-         close();
-      }
-
-      virtual bool close()
-      {
-         clear_error();
-
-         if (m_opened)
-         {
-            bool status = true;
-            if (m_has_ownership)
-            {
-               if (EOF == fclose(m_pFile))
-                  status = false;
-            }
-
-            m_pFile = NULL;
-            m_opened = false;
-            m_size = 0;
-            m_ofs = 0;
-            m_has_ownership = false;
-
-            return status;
-         }
-
-         return false;
-      }
-
-      bool open(FILE* pFile, const char* pFilename, uint attribs, bool has_ownership)
-      {
-         CRNLIB_ASSERT(pFile);
-         CRNLIB_ASSERT(pFilename);
-
-         close();
-
-         set_name(pFilename);
-         m_pFile = pFile;
-         m_has_ownership = has_ownership;
-         m_attribs = static_cast<uint16>(attribs);
-
-         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 char* pFilename, uint attribs = cDataStreamReadable | cDataStreamSeekable, bool open_existing = false)
-      {
-         CRNLIB_ASSERT(pFilename);
-
-         close();
-
-         m_attribs = static_cast<uint16>(attribs);
-
-         const char* pMode;
-         if ((is_readable()) && (is_writable()))
-            pMode = open_existing ? "r+b" : "w+b";
-         else if (is_writable())
-            pMode = open_existing ? "ab" : "wb";
-         else if (is_readable())
-            pMode = "rb";
-         else
-         {
-            set_error();
-            return false;
-         }
-
-         FILE* pFile = NULL;
-         crn_fopen(&pFile, pFilename, pMode);
-         m_has_ownership = true;
-
-         if (!pFile)
-         {
-            set_error();
-            return false;
-         }
-
-         // TODO: Change stream class to support UCS2 filenames.
-
-         return open(pFile, pFilename, attribs, true);
-      }
-
-      FILE* get_file() const { return m_pFile; }
-
-      virtual uint read(void* pBuf, uint len)
-      {
-         CRNLIB_ASSERT(pBuf && (len <= 0x7FFFFFFF));
-
-         if (!m_opened || (!is_readable()) || (!len))
-            return 0;
-
-         len = static_cast<uint>(math::minimum<uint64>(len, get_remaining()));
-
-         if (fread(pBuf, 1, len, m_pFile) != len)
-         {
-            set_error();
-            return 0;
-         }
-
-         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;
-
-         if (fwrite(pBuf, 1, len, m_pFile) != len)
-         {
-            set_error();
-            return 0;
-         }
-
-         m_ofs += len;
-         m_size = math::maximum(m_size, m_ofs);
-
-         return len;
-      }
-
-      virtual bool flush()
-      {
-         if ((!m_opened) || (!is_writable()))
-            return false;
-
-         if (EOF == fflush(m_pFile))
-         {
-            set_error();
-            return false;
-         }
-
-         return true;
-      }
-
-      virtual uint64 get_size()
-      {
-         if (!m_opened)
-            return 0;
-
-         return m_size;
-      }
-
-      virtual uint64 get_remaining()
-      {
-         if (!m_opened)
-            return 0;
-
-         CRNLIB_ASSERT(m_ofs <= m_size);
-         return m_size - m_ofs;
-      }
-
-      virtual uint64 get_ofs()
-      {
-         if (!m_opened)
-            return 0;
-
-         return m_ofs;
-      }
-
-      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 (static_cast<uint64>(new_ofs) > m_size)
-            return false;
-
-         if (static_cast<uint64>(new_ofs) != m_ofs)
-         {
-            if (crn_fseek(m_pFile, new_ofs, SEEK_SET) != 0)
-            {
-               set_error();
-               return false;
-            }
-
-            m_ofs = new_ofs;
-         }
-
-         return true;
-      }
-
-      static bool read_file_into_array(const char* pFilename, vector<uint8>& buf)
-      {
-         cfile_stream in_stream(pFilename);
-         if (!in_stream.is_opened())
-            return false;
-         return in_stream.read_array(buf);
-      }
-
-      static bool write_array_to_file(const char* pFilename, const vector<uint8>& buf)
-      {
-         cfile_stream out_stream(pFilename, cDataStreamWritable|cDataStreamSeekable);
-         if (!out_stream.is_opened())
-            return false;
-         return out_stream.write_array(buf);
-      }
-
-   private:
-      FILE* m_pFile;
-      uint64 m_size, m_ofs;
-      bool m_has_ownership;
-   };
-
-} // namespace crnlib

+ 0 - 63
Source/ThirdParty/crunch/crnlib/crn_checksum.cpp

@@ -1,63 +0,0 @@
-// File: crn_checksum.cpp
-#include "crn_core.h"
-
-namespace crnlib
-{
-   // From the public domain stb.h header.
-   uint adler32(const void* pBuf, size_t buflen, uint adler32)
-   {
-      const uint8* buffer = static_cast<const uint8*>(pBuf);
-      
-      const unsigned long ADLER_MOD = 65521;
-      unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
-      size_t blocklen;
-      unsigned long i;
-
-      blocklen = buflen % 5552;
-      while (buflen) {
-         for (i=0; i + 7 < blocklen; i += 8) {
-            s1 += buffer[0], s2 += s1;
-            s1 += buffer[1], s2 += s1;
-            s1 += buffer[2], s2 += s1;
-            s1 += buffer[3], s2 += s1;
-            s1 += buffer[4], s2 += s1;
-            s1 += buffer[5], s2 += s1;
-            s1 += buffer[6], s2 += s1;
-            s1 += buffer[7], s2 += s1;
-
-            buffer += 8;
-         }
-
-         for (; i < blocklen; ++i)
-            s1 += *buffer++, s2 += s1;
-
-         s1 %= ADLER_MOD, s2 %= ADLER_MOD;
-         buflen -= blocklen;
-         blocklen = 5552;
-      }
-      return (s2 << 16) + s1;
-   }
-   
-   uint16 crc16(const void* pBuf, size_t len, uint16 crc)
-   {
-      crc = ~crc;
-
-      const uint8* p = reinterpret_cast<const uint8*>(pBuf);
-      while (len)
-      {
-         const uint16 q = *p++ ^ (crc >> 8);
-         crc <<= 8U;
-         uint16 r = (q >> 4) ^ q;
-         crc ^= r;
-         r <<= 5U;
-         crc ^= r;
-         r <<= 7U;
-         crc ^= r; 
-         len--;
-      }
-
-      return static_cast<uint16>(~crc);
-   }
-
-} // namespace crnlib
-

+ 0 - 13
Source/ThirdParty/crunch/crnlib/crn_checksum.h

@@ -1,13 +0,0 @@
-// File: crn_checksum.h
-#pragma once
-
-namespace crnlib
-{
-   const uint cInitAdler32 = 1U;
-   uint adler32(const void* pBuf, size_t buflen, uint adler32 = cInitAdler32);
-   
-   // crc16() intended for small buffers - doesn't use an acceleration table.
-   const uint cInitCRC16 = 0;
-   uint16 crc16(const void* pBuf, size_t len, uint16 crc = cInitCRC16);
-   
-}  // namespace crnlib

+ 0 - 764
Source/ThirdParty/crunch/crnlib/crn_clusterizer.h

@@ -1,764 +0,0 @@
-// File: crn_clusterizer.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_matrix.h"
-
-namespace crnlib
-{
-   template<typename VectorType>
-   class clusterizer
-   {
-   public:
-      clusterizer() :
-         m_overall_variance(0.0f),
-         m_split_index(0),
-         m_heap_size(0),
-         m_quick(false)
-      {
-      }
-
-      void clear()
-      {
-         m_training_vecs.clear();
-         m_codebook.clear();
-         m_nodes.clear();
-         m_overall_variance = 0.0f;
-         m_split_index = 0;
-         m_heap_size = 0;
-         m_quick = false;
-      }
-
-      void reserve_training_vecs(uint num_expected)
-      {
-         m_training_vecs.reserve(num_expected);
-      }
-
-      void add_training_vec(const VectorType& v, uint weight)
-      {
-         m_training_vecs.push_back( std::make_pair(v, weight) );
-      }
-
-      typedef bool (*progress_callback_func_ptr)(uint percentage_completed, void* pData);
-
-      bool generate_codebook(uint max_size, progress_callback_func_ptr pProgress_callback = NULL, void* pProgress_data = NULL, bool quick = false)
-      {
-         if (m_training_vecs.empty())
-            return false;
-
-         m_quick = quick;
-
-         double ttsum = 0.0f;
-
-         vq_node root;
-         root.m_vectors.reserve(m_training_vecs.size());
-
-         for (uint i = 0; i < m_training_vecs.size(); i++)
-         {
-            const VectorType& v = m_training_vecs[i].first;
-            const uint weight = m_training_vecs[i].second;
-
-            root.m_centroid += (v * (float)weight);
-            root.m_total_weight += weight;
-            root.m_vectors.push_back(i);
-
-            ttsum += v.dot(v) * weight;
-         }
-
-         root.m_variance = (float)(ttsum - (root.m_centroid.dot(root.m_centroid) / root.m_total_weight));
-
-         root.m_centroid *= (1.0f / root.m_total_weight);
-
-         m_nodes.clear();
-         m_nodes.reserve(max_size * 2 + 1);
-
-         m_nodes.push_back(root);
-
-         m_heap.resize(max_size + 1);
-         m_heap[1] = 0;
-         m_heap_size = 1;
-
-         m_split_index = 0;
-
-         uint total_leaves = 1;
-
-         m_left_children.reserve(m_training_vecs.size() + 1);
-         m_right_children.reserve(m_training_vecs.size() + 1);
-
-         int prev_percentage = -1;
-         while ((total_leaves < max_size) && (m_heap_size))
-         {
-            int worst_node_index = m_heap[1];
-
-            m_heap[1] = m_heap[m_heap_size];
-            m_heap_size--;
-            if (m_heap_size)
-               down_heap(1);
-
-            split_node(worst_node_index);
-            total_leaves++;
-
-            if ((pProgress_callback) && ((total_leaves & 63) == 0) && (max_size))
-            {
-               int cur_percentage = (total_leaves * 100U + (max_size / 2U)) / max_size;
-               if (cur_percentage != prev_percentage)
-               {
-                  if (!(*pProgress_callback)(cur_percentage, pProgress_data))
-                     return false;
-
-                  prev_percentage = cur_percentage;
-               }
-            }
-         }
-
-         m_codebook.clear();
-
-         m_overall_variance = 0.0f;
-
-         for (uint i = 0; i < m_nodes.size(); i++)
-         {
-            vq_node& node = m_nodes[i];
-            if (node.m_left != -1)
-            {
-               CRNLIB_ASSERT(node.m_right != -1);
-               continue;
-            }
-
-            CRNLIB_ASSERT((node.m_left == -1) && (node.m_right == -1));
-
-            node.m_codebook_index = m_codebook.size();
-            m_codebook.push_back(node.m_centroid);
-
-            m_overall_variance += node.m_variance;
-         }
-
-         m_heap.clear();
-         m_left_children.clear();
-         m_right_children.clear();
-
-         return true;
-      }
-
-      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; }
-      uint get_training_vec_weight(uint index) const { return m_training_vecs[index].second; }
-
-      typedef crnlib::vector< std::pair<VectorType, uint> > training_vec_array;
-
-      const training_vec_array& get_training_vecs() const   { return m_training_vecs; }
-            training_vec_array& get_training_vecs()         { return m_training_vecs; }
-
-      inline float get_overall_variance() const { return m_overall_variance; }
-
-      inline uint get_codebook_size() const
-      {
-         return m_codebook.size();
-      }
-
-      inline const VectorType& get_codebook_entry(uint index) const
-      {
-         return m_codebook[index];
-      }
-
-      VectorType& get_codebook_entry(uint index)
-      {
-         return m_codebook[index];
-      }
-
-      typedef crnlib::vector<VectorType> vector_vec_type;
-      inline const vector_vec_type& get_codebook() const
-      {
-         return m_codebook;
-      }
-
-      uint find_best_codebook_entry(const VectorType& v) const
-      {
-         uint cur_node_index = 0;
-
-         for ( ; ; )
-         {
-            const vq_node& cur_node = m_nodes[cur_node_index];
-
-            if (cur_node.m_left == -1)
-               return cur_node.m_codebook_index;
-
-            const vq_node& left_node = m_nodes[cur_node.m_left];
-            const vq_node& right_node = m_nodes[cur_node.m_right];
-
-            float left_dist = left_node.m_centroid.squared_distance(v);
-            float right_dist = right_node.m_centroid.squared_distance(v);
-
-            if (left_dist < right_dist)
-               cur_node_index = cur_node.m_left;
-            else
-               cur_node_index = cur_node.m_right;
-         }
-      }
-
-      const VectorType& find_best_codebook_entry(const VectorType& v, uint max_codebook_size) const
-      {
-         uint cur_node_index = 0;
-
-         for ( ; ; )
-         {
-            const vq_node& cur_node = m_nodes[cur_node_index];
-
-            if ((cur_node.m_left == -1) || ((cur_node.m_codebook_index + 1) >= (int)max_codebook_size))
-               return cur_node.m_centroid;
-
-            const vq_node& left_node = m_nodes[cur_node.m_left];
-            const vq_node& right_node = m_nodes[cur_node.m_right];
-
-            float left_dist = left_node.m_centroid.squared_distance(v);
-            float right_dist = right_node.m_centroid.squared_distance(v);
-
-            if (left_dist < right_dist)
-               cur_node_index = cur_node.m_left;
-            else
-               cur_node_index = cur_node.m_right;
-         }
-      }
-
-      uint find_best_codebook_entry_fs(const VectorType& v) const
-      {
-         float best_dist = math::cNearlyInfinite;
-         uint best_index = 0;
-
-         for (uint i = 0; i < m_codebook.size(); i++)
-         {
-            float dist = m_codebook[i].squared_distance(v);
-            if (dist < best_dist)
-            {
-               best_dist = dist;
-               best_index = i;
-               if (best_dist == 0.0f)
-                  break;
-            }
-         }
-
-         return best_index;
-      }
-
-      void retrieve_clusters(uint max_clusters, crnlib::vector< crnlib::vector<uint> >& clusters) const
-      {
-         clusters.resize(0);
-         clusters.reserve(max_clusters);
-
-         crnlib::vector<uint> stack;
-         stack.reserve(512);
-
-         uint cur_node_index = 0;
-
-         for ( ; ; )
-         {
-            const vq_node& cur_node = m_nodes[cur_node_index];
-
-            if ( (cur_node.is_leaf()) || ((cur_node.m_codebook_index + 2) > (int)max_clusters) )
-            {
-               clusters.resize(clusters.size() + 1);
-               clusters.back() = cur_node.m_vectors;
-
-               if (stack.empty())
-                  break;
-               cur_node_index = stack.back();
-               stack.pop_back();
-               continue;
-            }
-
-            cur_node_index = cur_node.m_left;
-            stack.push_back(cur_node.m_right);
-         }
-      }
-
-   private:
-      training_vec_array m_training_vecs;
-
-      struct vq_node
-      {
-         vq_node() : m_centroid(cClear), m_total_weight(0), m_left(-1), m_right(-1), m_codebook_index(-1), m_unsplittable(false) { }
-
-         VectorType        m_centroid;
-         uint64            m_total_weight;
-
-         float             m_variance;
-
-         crnlib::vector<uint> m_vectors;
-
-         int               m_left;
-         int               m_right;
-
-         int               m_codebook_index;
-
-         bool              m_unsplittable;
-
-         bool is_leaf() const { return m_left < 0; }
-      };
-
-      typedef crnlib::vector<vq_node> node_vec_type;
-
-      node_vec_type m_nodes;
-
-      vector_vec_type m_codebook;
-
-      float m_overall_variance;
-
-      uint m_split_index;
-
-      crnlib::vector<uint> m_heap;
-      uint m_heap_size;
-
-      bool m_quick;
-
-      void insert_heap(uint node_index)
-      {
-         const float variance = m_nodes[node_index].m_variance;
-         uint pos = ++m_heap_size;
-
-         if (m_heap_size >= m_heap.size())
-            m_heap.resize(m_heap_size + 1);
-
-         for ( ; ; )
-         {
-            uint parent = pos >> 1;
-            if (!parent)
-               break;
-
-            float parent_variance = m_nodes[m_heap[parent]].m_variance;
-            if (parent_variance > variance)
-               break;
-
-            m_heap[pos] = m_heap[parent];
-
-            pos = parent;
-         }
-
-         m_heap[pos] = node_index;
-      }
-
-      void down_heap(uint pos)
-      {
-         uint child;
-         uint orig = m_heap[pos];
-
-         const float orig_variance = m_nodes[orig].m_variance;
-
-         while ((child = (pos << 1)) <= m_heap_size)
-         {
-            if (child < m_heap_size)
-            {
-               if (m_nodes[m_heap[child]].m_variance < m_nodes[m_heap[child + 1]].m_variance)
-                  child++;
-            }
-
-            if (orig_variance > m_nodes[m_heap[child]].m_variance)
-               break;
-
-            m_heap[pos] = m_heap[child];
-
-            pos = child;
-         }
-
-         m_heap[pos] = orig;
-      }
-
-      void compute_split_estimate(VectorType& left_child_res, VectorType& right_child_res, const vq_node& parent_node)
-      {
-         VectorType furthest(0);
-         double furthest_dist = -1.0f;
-
-         for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-         {
-            const VectorType& v = m_training_vecs[parent_node.m_vectors[i]].first;
-
-            double dist = v.squared_distance(parent_node.m_centroid);
-            if (dist > furthest_dist)
-            {
-               furthest_dist = dist;
-               furthest = v;
-            }
-         }
-
-         VectorType opposite(0);
-         double opposite_dist = -1.0f;
-
-         for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-         {
-            const VectorType& v = m_training_vecs[parent_node.m_vectors[i]].first;
-
-            double dist = v.squared_distance(furthest);
-            if (dist > opposite_dist)
-            {
-               opposite_dist = dist;
-               opposite = v;
-            }
-         }
-
-         left_child_res = (furthest + parent_node.m_centroid) * .5f;
-         right_child_res = (opposite + parent_node.m_centroid) * .5f;
-      }
-
-      void compute_split_pca(VectorType& left_child_res, VectorType& right_child_res, const vq_node& parent_node)
-      {
-         if (parent_node.m_vectors.size() == 2)
-         {
-            left_child_res = m_training_vecs[parent_node.m_vectors[0]].first;
-            right_child_res = m_training_vecs[parent_node.m_vectors[1]].first;
-            return;
-         }
-
-         const uint N = VectorType::num_elements;
-
-         matrix<N, N, float> covar;
-         covar.clear();
-
-         for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-         {
-            const VectorType v(m_training_vecs[parent_node.m_vectors[i]].first - parent_node.m_centroid);
-            const VectorType w(v * (float)m_training_vecs[parent_node.m_vectors[i]].second);
-
-            for (uint x = 0; x < N; x++)
-               for (uint y = x; y < N; y++)
-                  covar[x][y] = covar[x][y] + v[x] * w[y];
-         }
-
-         float one_over_total_weight = 1.0f / parent_node.m_total_weight;
-
-         for (uint x = 0; x < N; x++)
-            for (uint y = x; y < N; y++)
-               covar[x][y] *= one_over_total_weight;
-
-         for (uint x = 0; x < (N - 1); x++)
-            for (uint y = x + 1; y < N; y++)
-               covar[y][x] = covar[x][y];
-
-         VectorType axis;//(1.0f);
-         if (N == 1)
-            axis.set(1.0f);
-         else
-         {
-            for (uint i = 0; i < N; i++)
-               axis[i] = math::lerp(.75f, 1.25f, i * (1.0f / math::maximum<int>(N - 1, 1)));
-         }
-
-         VectorType prev_axis(axis);
-
-         for (uint iter = 0; iter < 10; iter++)
-         {
-            VectorType x;
-
-            double max_sum = 0;
-
-            for (uint i = 0; i < N; i++)
-            {
-               double sum = 0;
-
-               for (uint j = 0; j < N; j++)
-                  sum += axis[j] * covar[i][j];
-
-               x[i] = static_cast<float>(sum);
-
-               max_sum = math::maximum(max_sum, fabs(sum));
-            }
-
-            if (max_sum != 0.0f)
-               x *= static_cast<float>(1.0f / max_sum);
-
-            VectorType delta_axis(prev_axis - x);
-
-            prev_axis = axis;
-            axis = x;
-
-            if (delta_axis.norm() < .0025f)
-               break;
-         }
-
-         axis.normalize();
-
-         VectorType left_child(0.0f);
-         VectorType right_child(0.0f);
-
-         double left_weight = 0.0f;
-         double right_weight = 0.0f;
-
-         for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-         {
-            const float weight = (float)m_training_vecs[parent_node.m_vectors[i]].second;
-
-            const VectorType& v = m_training_vecs[parent_node.m_vectors[i]].first;
-
-            double t = (v - parent_node.m_centroid) * axis;
-            if (t < 0.0f)
-            {
-               left_child += v * weight;
-               left_weight += weight;
-            }
-            else
-            {
-               right_child += v * weight;
-               right_weight += weight;
-            }
-         }
-
-         if ((left_weight > 0.0f) && (right_weight > 0.0f))
-         {
-            left_child_res = left_child * (float)(1.0f / left_weight);
-            right_child_res = right_child * (float)(1.0f / right_weight);
-         }
-         else
-         {
-            compute_split_estimate(left_child_res, right_child_res, parent_node);
-         }
-      }
-
-#if 0
-      void compute_split_pca2(VectorType& left_child_res, VectorType& right_child_res, const vq_node& parent_node)
-      {
-         if (parent_node.m_vectors.size() == 2)
-         {
-            left_child_res = m_training_vecs[parent_node.m_vectors[0]].first;
-            right_child_res = m_training_vecs[parent_node.m_vectors[1]].first;
-            return;
-         }
-
-         const uint N = VectorType::num_elements;
-
-         VectorType furthest;
-         double furthest_dist = -1.0f;
-
-         for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-         {
-            const VectorType& v = m_training_vecs[parent_node.m_vectors[i]].first;
-
-            double dist = v.squared_distance(parent_node.m_centroid);
-            if (dist > furthest_dist)
-            {
-               furthest_dist = dist;
-               furthest = v;
-            }
-         }
-
-         VectorType opposite;
-         double opposite_dist = -1.0f;
-
-         for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-         {
-            const VectorType& v = m_training_vecs[parent_node.m_vectors[i]].first;
-
-            double dist = v.squared_distance(furthest);
-            if (dist > opposite_dist)
-            {
-               opposite_dist = dist;
-               opposite = v;
-            }
-         }
-
-         VectorType axis(opposite - furthest);
-         if (axis.normalize() < .000125f)
-         {
-            left_child_res = (furthest + parent_node.m_centroid) * .5f;
-            right_child_res = (opposite + parent_node.m_centroid) * .5f;
-            return;
-         }
-
-         for (uint iter = 0; iter < 2; iter++)
-         {
-            double next_axis[N];
-            utils::zero_object(next_axis);
-
-            for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-            {
-               const double weight = m_training_vecs[parent_node.m_vectors[i]].second;
-
-               VectorType v(m_training_vecs[parent_node.m_vectors[i]].first - parent_node.m_centroid);
-
-               double dot = (v * axis) * weight;
-
-               for (uint j = 0; j < N; j++)
-                  next_axis[j] += dot * v[j];
-            }
-
-            double w = 0.0f;
-            for (uint j = 0; j < N; j++)
-               w += next_axis[j] * next_axis[j];
-
-            if (w > 0.0f)
-            {
-               w = 1.0f / sqrt(w);
-               for (uint j = 0; j < N; j++)
-                  axis[j] = static_cast<float>(next_axis[j] * w);
-            }
-            else
-               break;
-         }
-
-         VectorType left_child(0.0f);
-         VectorType right_child(0.0f);
-
-         double left_weight = 0.0f;
-         double right_weight = 0.0f;
-
-         for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-         {
-            const float weight = (float)m_training_vecs[parent_node.m_vectors[i]].second;
-
-            const VectorType& v = m_training_vecs[parent_node.m_vectors[i]].first;
-
-            double t = (v - parent_node.m_centroid) * axis;
-            if (t < 0.0f)
-            {
-               left_child += v * weight;
-               left_weight += weight;
-            }
-            else
-            {
-               right_child += v * weight;
-               right_weight += weight;
-            }
-         }
-
-         if ((left_weight > 0.0f) && (right_weight > 0.0f))
-         {
-            left_child_res = left_child * (float)(1.0f / left_weight);
-            right_child_res = right_child * (float)(1.0f / right_weight);
-         }
-         else
-         {
-            left_child_res = (furthest + parent_node.m_centroid) * .5f;
-            right_child_res = (opposite + parent_node.m_centroid) * .5f;
-         }
-      }
-#endif
-
-      // thread safety warning: shared state!
-      crnlib::vector<uint> m_left_children;
-      crnlib::vector<uint> m_right_children;
-
-      void split_node(uint index)
-      {
-         vq_node& parent_node = m_nodes[index];
-
-         if (parent_node.m_vectors.size() == 1)
-            return;
-
-         VectorType left_child, right_child;
-         if (m_quick)
-            compute_split_estimate(left_child, right_child, parent_node);
-         else
-            compute_split_pca(left_child, right_child, parent_node);
-
-         uint64 left_weight = 0;
-         uint64 right_weight = 0;
-
-         float prev_total_variance = 1e+10f;
-
-         float left_variance = 0.0f;
-         float right_variance = 0.0f;
-
-         const uint cMaxLoops = m_quick ? 2 : 8;
-         for (uint total_loops = 0; total_loops < cMaxLoops; total_loops++)
-         {
-            m_left_children.resize(0);
-            m_right_children.resize(0);
-
-            VectorType new_left_child(cClear);
-            VectorType new_right_child(cClear);
-
-            double left_ttsum = 0.0f;
-            double right_ttsum = 0.0f;
-
-            left_weight = 0;
-            right_weight = 0;
-
-            for (uint i = 0; i < parent_node.m_vectors.size(); i++)
-            {
-               const VectorType& v = m_training_vecs[parent_node.m_vectors[i]].first;
-               const uint weight = m_training_vecs[parent_node.m_vectors[i]].second;
-
-               double left_dist2 = left_child.squared_distance(v);
-               double right_dist2 = right_child.squared_distance(v);
-
-               if (left_dist2 < right_dist2)
-               {
-                  m_left_children.push_back(parent_node.m_vectors[i]);
-
-                  new_left_child += (v * (float)weight);
-                  left_weight += weight;
-
-                  left_ttsum += v.dot(v) * weight;
-               }
-               else
-               {
-                  m_right_children.push_back(parent_node.m_vectors[i]);
-
-                  new_right_child += (v * (float)weight);
-                  right_weight += weight;
-
-                  right_ttsum += v.dot(v) * weight;
-               }
-            }
-
-            if ((!left_weight) || (!right_weight))
-            {
-               parent_node.m_unsplittable = true;
-               return;
-            }
-
-            left_variance = (float)(left_ttsum - (new_left_child.dot(new_left_child) / left_weight));
-            right_variance = (float)(right_ttsum - (new_right_child.dot(new_right_child) / right_weight));
-
-            new_left_child *= (1.0f / left_weight);
-            new_right_child *= (1.0f / right_weight);
-
-            left_child = new_left_child;
-            left_weight = left_weight;
-
-            right_child = new_right_child;
-            right_weight = right_weight;
-
-            float total_variance = left_variance + right_variance;
-            if (total_variance < .00001f)
-               break;
-
-            //const float variance_delta_thresh = .00001f;
-            const float variance_delta_thresh = .00125f;
-            if (((prev_total_variance - total_variance) / total_variance) < variance_delta_thresh)
-               break;
-
-            prev_total_variance = total_variance;
-         }
-
-         const uint left_child_index = m_nodes.size();
-         const uint right_child_index = m_nodes.size() + 1;
-
-         parent_node.m_left = m_nodes.size();
-         parent_node.m_right = m_nodes.size() + 1;
-         parent_node.m_codebook_index = m_split_index;
-         m_split_index++;
-
-         m_nodes.resize(m_nodes.size() + 2);
-
-         // parent_node is invalid now, because m_nodes has been changed
-
-         vq_node& left_child_node = m_nodes[left_child_index];
-         vq_node& right_child_node = m_nodes[right_child_index];
-
-         left_child_node.m_centroid = left_child;
-         left_child_node.m_total_weight = left_weight;
-         left_child_node.m_vectors.swap(m_left_children);
-         left_child_node.m_variance = left_variance;
-         if ((left_child_node.m_vectors.size() > 1) && (left_child_node.m_variance > 0.0f))
-            insert_heap(left_child_index);
-
-         right_child_node.m_centroid = right_child;
-         right_child_node.m_total_weight = right_weight;
-         right_child_node.m_vectors.swap(m_right_children);
-         right_child_node.m_variance = right_variance;
-         if ((right_child_node.m_vectors.size() > 1) && (right_child_node.m_variance > 0.0f))
-            insert_heap(right_child_index);
-      }
-
-   };
-
-} // namespace crnlib
-
-
-

+ 0 - 994
Source/ThirdParty/crunch/crnlib/crn_color.h

@@ -1,994 +0,0 @@
-// File: crn_color.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_core.h"
-
-namespace crnlib
-{
-   template<typename component_type> struct color_quad_component_traits
-   {
-      enum
-      {
-         cSigned = false,
-         cFloat = false,
-         cMin = cUINT8_MIN,
-         cMax = cUINT8_MAX
-      };
-   };
-
-   template<> struct color_quad_component_traits<int8>
-   {
-      enum
-      {
-         cSigned = true,
-         cFloat = false,
-         cMin = cINT8_MIN,
-         cMax = cINT8_MAX
-      };
-   };
-
-   template<> struct color_quad_component_traits<int16>
-   {
-      enum
-      {
-         cSigned = true,
-         cFloat = false,
-         cMin = cINT16_MIN,
-         cMax = cINT16_MAX
-      };
-   };
-
-   template<> struct color_quad_component_traits<uint16>
-   {
-      enum
-      {
-         cSigned = false,
-         cFloat = false,
-         cMin = cUINT16_MIN,
-         cMax = cUINT16_MAX
-      };
-   };
-
-   template<> struct color_quad_component_traits<int32>
-   {
-      enum
-      {
-         cSigned = true,
-         cFloat = false,
-         cMin = cINT32_MIN,
-         cMax = cINT32_MAX
-      };
-   };
-
-   template<> struct color_quad_component_traits<uint32>
-   {
-      enum
-      {
-         cSigned = false,
-         cFloat = false,
-         cMin = cUINT32_MIN,
-         cMax = cUINT32_MAX
-      };
-   };
-
-   template<> struct color_quad_component_traits<float>
-   {
-      enum
-      {
-         cSigned = false,
-         cFloat = true,
-         cMin = cINT32_MIN,
-         cMax = cINT32_MAX
-      };
-   };
-
-   template<> struct color_quad_component_traits<double>
-   {
-      enum
-      {
-         cSigned = false,
-         cFloat = true,
-         cMin = cINT32_MIN,
-         cMax = cINT32_MAX
-      };
-   };
-
-   template<typename component_type, typename parameter_type>
-   class color_quad : public helpers::rel_ops<color_quad<component_type, parameter_type> >
-   {
-      template<typename T>
-      static inline parameter_type clamp(T v)
-      {
-         parameter_type result = static_cast<parameter_type>(v);
-         if (!component_traits::cFloat)
-         {
-            if (v < component_traits::cMin)
-               result = static_cast<parameter_type>(component_traits::cMin);
-            else if (v > component_traits::cMax)
-               result = static_cast<parameter_type>(component_traits::cMax);
-         }
-         return result;
-      }
-
-#ifdef _MSC_VER
-      template<>
-      static inline parameter_type clamp(int v)
-      {
-         if (!component_traits::cFloat)
-         {
-            if ((!component_traits::cSigned) && (component_traits::cMin == 0) && (component_traits::cMax == 0xFF))
-            {
-               if (v & 0xFFFFFF00U)
-                  v = (~(static_cast<int>(v) >> 31)) & 0xFF;
-            }
-            else
-            {
-               if (v < component_traits::cMin)
-                  v = component_traits::cMin;
-               else if (v > component_traits::cMax)
-                  v = component_traits::cMax;
-            }
-         }
-         return static_cast<parameter_type>(v);
-      }
-#endif
-
-   public:
-      typedef component_type component_t;
-      typedef parameter_type parameter_t;
-      typedef color_quad_component_traits<component_type> component_traits;
-
-      enum { cNumComps = 4 };
-
-      union
-      {
-         struct
-         {
-            component_type r;
-            component_type g;
-            component_type b;
-            component_type a;
-         };
-
-         component_type c[cNumComps];
-
-         uint32 m_u32;
-      };
-
-      inline color_quad()
-      {
-      }
-
-      inline color_quad(eClear) :
-         r(0), g(0), b(0), a(0)
-      {
-      }
-
-      inline color_quad(const color_quad& other) :
-         r(other.r), g(other.g), b(other.b), a(other.a)
-      {
-      }
-
-      explicit inline color_quad(parameter_type y, parameter_type alpha = component_traits::cMax)
-      {
-         set(y, alpha);
-      }
-
-      inline color_quad(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax)
-      {
-         set(red, green, blue, alpha);
-      }
-
-      explicit inline color_quad(eNoClamp, parameter_type y, parameter_type alpha = component_traits::cMax)
-      {
-         set_noclamp_y_alpha(y, alpha);
-      }
-
-      inline color_quad(eNoClamp, parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax)
-      {
-         set_noclamp_rgba(red, green, blue, alpha);
-      }
-
-      template<typename other_component_type, typename other_parameter_type>
-      inline color_quad(const color_quad<other_component_type, other_parameter_type>& other) :
-         r(static_cast<component_type>(clamp(other.r))), g(static_cast<component_type>(clamp(other.g))), b(static_cast<component_type>(clamp(other.b))), a(static_cast<component_type>(clamp(other.a)))
-      {
-      }
-
-      inline void clear()
-      {
-         r = 0;
-         g = 0;
-         b = 0;
-         a = 0;
-      }
-
-      inline color_quad& operator= (const color_quad& other)
-      {
-         r = other.r;
-         g = other.g;
-         b = other.b;
-         a = other.a;
-         return *this;
-      }
-
-      inline color_quad& set_rgb(const color_quad& other)
-      {
-         r = other.r;
-         g = other.g;
-         b = other.b;
-         return *this;
-      }
-
-      template<typename other_component_type, typename other_parameter_type>
-      inline color_quad& operator=(const color_quad<other_component_type, other_parameter_type>& other)
-      {
-         r = static_cast<component_type>(clamp(other.r));
-         g = static_cast<component_type>(clamp(other.g));
-         b = static_cast<component_type>(clamp(other.b));
-         a = static_cast<component_type>(clamp(other.a));
-         return *this;
-      }
-
-      inline color_quad& operator= (parameter_type y)
-      {
-         set(y, component_traits::cMax);
-         return *this;
-      }
-
-      inline color_quad& set(parameter_type y, parameter_type alpha = component_traits::cMax)
-      {
-         y = clamp(y);
-         alpha = clamp(alpha);
-         r = static_cast<component_type>(y);
-         g = static_cast<component_type>(y);
-         b = static_cast<component_type>(y);
-         a = static_cast<component_type>(alpha);
-         return *this;
-      }
-
-      inline color_quad& set_noclamp_y_alpha(parameter_type y, parameter_type alpha = component_traits::cMax)
-      {
-         CRNLIB_ASSERT( (y >= component_traits::cMin) && (y <= component_traits::cMax) );
-         CRNLIB_ASSERT( (alpha >= component_traits::cMin) && (alpha <= component_traits::cMax) );
-
-         r = static_cast<component_type>(y);
-         g = static_cast<component_type>(y);
-         b = static_cast<component_type>(y);
-         a = static_cast<component_type>(alpha);
-         return *this;
-      }
-
-      inline color_quad& set(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax)
-      {
-         r = static_cast<component_type>(clamp(red));
-         g = static_cast<component_type>(clamp(green));
-         b = static_cast<component_type>(clamp(blue));
-         a = static_cast<component_type>(clamp(alpha));
-         return *this;
-      }
-
-      inline color_quad& set_noclamp_rgba(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha)
-      {
-         CRNLIB_ASSERT( (red >= component_traits::cMin) && (red <= component_traits::cMax) );
-         CRNLIB_ASSERT( (green >= component_traits::cMin) && (green <= component_traits::cMax) );
-         CRNLIB_ASSERT( (blue >= component_traits::cMin) && (blue <= component_traits::cMax) );
-         CRNLIB_ASSERT( (alpha >= component_traits::cMin) && (alpha <= component_traits::cMax) );
-
-         r = static_cast<component_type>(red);
-         g = static_cast<component_type>(green);
-         b = static_cast<component_type>(blue);
-         a = static_cast<component_type>(alpha);
-         return *this;
-      }
-
-      inline color_quad& set_noclamp_rgb(parameter_type red, parameter_type green, parameter_type blue)
-      {
-         CRNLIB_ASSERT( (red >= component_traits::cMin) && (red <= component_traits::cMax) );
-         CRNLIB_ASSERT( (green >= component_traits::cMin) && (green <= component_traits::cMax) );
-         CRNLIB_ASSERT( (blue >= component_traits::cMin) && (blue <= component_traits::cMax) );
-
-         r = static_cast<component_type>(red);
-         g = static_cast<component_type>(green);
-         b = static_cast<component_type>(blue);
-         return *this;
-      }
-
-      static inline parameter_type get_min_comp() { return component_traits::cMin; }
-      static inline parameter_type get_max_comp() { return component_traits::cMax; }
-      static inline bool get_comps_are_signed() { return component_traits::cSigned; }
-
-      inline component_type operator[] (uint i) const { CRNLIB_ASSERT(i < cNumComps); return c[i]; }
-      inline component_type& operator[] (uint i) { CRNLIB_ASSERT(i < cNumComps); return c[i]; }
-
-      inline color_quad& set_component(uint i, parameter_type f)
-      {
-         CRNLIB_ASSERT(i < cNumComps);
-
-         c[i] = static_cast<component_type>(clamp(f));
-
-         return *this;
-      }
-
-      inline color_quad& set_grayscale(parameter_t l)
-      {
-         component_t x = static_cast<component_t>(clamp(l));
-         c[0] = x;
-         c[1] = x;
-         c[2] = x;
-         return *this;
-      }
-
-      inline color_quad& clamp(const color_quad& l, const color_quad& h)
-      {
-         for (uint i = 0; i < cNumComps; i++)
-            c[i] = static_cast<component_type>(math::clamp<parameter_type>(c[i], l[i], h[i]));
-         return *this;
-      }
-
-      inline color_quad& clamp(parameter_type l, parameter_type h)
-      {
-         for (uint i = 0; i < cNumComps; i++)
-            c[i] = static_cast<component_type>(math::clamp<parameter_type>(c[i], l, h));
-         return *this;
-      }
-
-      // Returns CCIR 601 luma (consistent with color_utils::RGB_To_Y).
-      inline parameter_type get_luma() const
-      {
-         return static_cast<parameter_type>((19595U * r + 38470U * g + 7471U * b + 32768U) >> 16U);
-      }
-
-      // Returns REC 709 luma.
-      inline parameter_type get_luma_rec709() const
-      {
-         return static_cast<parameter_type>((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U);
-      }
-
-      // Beware of endianness!
-      inline uint32 get_uint32() const
-      {
-         CRNLIB_ASSERT(sizeof(*this) == sizeof(uint32));
-         return *reinterpret_cast<const uint32*>(this);
-      }
-
-      // Beware of endianness!
-      inline uint64 get_uint64() const
-      {
-         CRNLIB_ASSERT(sizeof(*this) == sizeof(uint64));
-         return *reinterpret_cast<const uint64*>(this);
-      }
-
-      inline uint squared_distance(const color_quad& c, bool alpha = true) const
-      {
-         return math::square(r - c.r) + math::square(g - c.g) + math::square(b - c.b) + (alpha ? math::square(a - c.a) : 0);
-      }
-
-      inline bool rgb_equals(const color_quad& rhs) const
-      {
-         return (r == rhs.r) && (g == rhs.g) && (b == rhs.b);
-      }
-
-      inline bool operator== (const color_quad& rhs) const
-      {
-         if (sizeof(color_quad) == sizeof(uint32))
-            return m_u32 == rhs.m_u32;
-         else
-            return (r == rhs.r) && (g == rhs.g) && (b == rhs.b) && (a == rhs.a);
-      }
-
-      inline bool operator< (const color_quad& rhs) const
-      {
-         for (uint i = 0; i < cNumComps; i++)
-         {
-            if (c[i] < rhs.c[i])
-               return true;
-            else if (!(c[i] == rhs.c[i]))
-               return false;
-         }
-         return false;
-      }
-
-      color_quad& operator+= (const color_quad& other)
-      {
-         for (uint i = 0; i < 4; i++)
-            c[i] = static_cast<component_type>(clamp(c[i] + other.c[i]));
-         return *this;
-      }
-
-      color_quad& operator-= (const color_quad& other)
-      {
-         for (uint i = 0; i < 4; i++)
-            c[i] = static_cast<component_type>(clamp(c[i] - other.c[i]));
-         return *this;
-      }
-
-      color_quad& operator*= (parameter_type v)
-      {
-         for (uint i = 0; i < 4; i++)
-            c[i] = static_cast<component_type>(clamp(c[i] * v));
-         return *this;
-      }
-
-      color_quad& operator/= (parameter_type v)
-      {
-         for (uint i = 0; i < 4; i++)
-            c[i] = static_cast<component_type>(c[i] / v);
-         return *this;
-      }
-
-      color_quad get_swizzled(uint x, uint y, uint z, uint w) const
-      {
-         CRNLIB_ASSERT((x | y | z | w) < 4);
-         return color_quad(c[x], c[y], c[z], c[w]);
-      }
-
-      friend color_quad operator+ (const color_quad& lhs, const color_quad& rhs)
-      {
-         color_quad result(lhs);
-         result += rhs;
-         return result;
-      }
-
-      friend color_quad operator- (const color_quad& lhs, const color_quad& rhs)
-      {
-         color_quad result(lhs);
-         result -= rhs;
-         return result;
-      }
-
-      friend color_quad operator* (const color_quad& lhs, parameter_type v)
-      {
-         color_quad result(lhs);
-         result *= v;
-         return result;
-      }
-
-      friend color_quad operator/ (const color_quad& lhs, parameter_type v)
-      {
-         color_quad result(lhs);
-         result /= v;
-         return result;
-      }
-
-      friend color_quad operator* (parameter_type v, const color_quad& rhs)
-      {
-         color_quad result(rhs);
-         result *= v;
-         return result;
-      }
-
-      inline bool is_grayscale() const
-      {
-         return (c[0] == c[1]) && (c[1] == c[2]);
-      }
-
-      uint get_min_component_index(bool alpha = true) const
-      {
-         uint index = 0;
-         uint limit = alpha ? cNumComps : (cNumComps - 1);
-         for (uint i = 1; i < limit; i++)
-            if (c[i] < c[index])
-               index = i;
-         return index;
-      }
-
-      uint get_max_component_index(bool alpha = true) const
-      {
-         uint index = 0;
-         uint limit = alpha ? cNumComps : (cNumComps - 1);
-         for (uint i = 1; i < limit; i++)
-            if (c[i] > c[index])
-               index = i;
-         return index;
-      }
-
-      operator size_t() const
-      {
-         return (size_t)fast_hash(this, sizeof(*this));
-      }
-
-      void get_float4(float* pDst)
-      {
-         for (uint i = 0; i < 4; i++)
-            pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin);
-      }
-
-      void get_float3(float* pDst)
-      {
-         for (uint i = 0; i < 3; i++)
-            pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin);
-      }
-
-      static color_quad component_min(const color_quad& a, const color_quad& b)
-      {
-         color_quad result;
-         for (uint i = 0; i < 4; i++)
-            result[i] = static_cast<component_type>(math::minimum(a[i], b[i]));
-         return result;
-      }
-
-      static color_quad component_max(const color_quad& a, const color_quad& b)
-      {
-         color_quad result;
-         for (uint i = 0; i < 4; i++)
-            result[i] = static_cast<component_type>(math::maximum(a[i], b[i]));
-         return result;
-      }
-
-      static color_quad make_black()
-      {
-         return color_quad(0, 0, 0, component_traits::cMax);
-      }
-
-      static color_quad make_white()
-      {
-         return color_quad(component_traits::cMax, component_traits::cMax, component_traits::cMax, component_traits::cMax);
-      }
-   }; // class color_quad
-
-   template<typename c, typename q>
-   struct scalar_type< color_quad<c, q> >
-   {
-      enum { cFlag = true };
-      static inline void construct(color_quad<c, q>* p) { }
-      static inline void construct(color_quad<c, q>* p, const color_quad<c, q>& init) { memcpy(p, &init, sizeof(color_quad<c, q>)); }
-      static inline void construct_array(color_quad<c, q>* p, uint n) { p, n; }
-      static inline void destruct(color_quad<c, q>* p) { p; }
-      static inline void destruct_array(color_quad<c, q>* p, uint n) { p, n; }
-   };
-
-   typedef color_quad<uint8, int>      color_quad_u8;
-   typedef color_quad<int8, int>       color_quad_i8;
-   typedef color_quad<int16, int>      color_quad_i16;
-   typedef color_quad<uint16, int>     color_quad_u16;
-   typedef color_quad<int32, int>      color_quad_i32;
-   typedef color_quad<uint32, uint>    color_quad_u32;
-   typedef color_quad<float, float>    color_quad_f;
-   typedef color_quad<double, double>  color_quad_d;
-
-   namespace color
-   {
-      inline uint elucidian_distance(uint r0, uint g0, uint b0, uint r1, uint g1, uint b1)
-      {
-         int dr = (int)r0 - (int)r1;
-         int dg = (int)g0 - (int)g1;
-         int db = (int)b0 - (int)b1;
-
-         return static_cast<uint>(dr * dr + dg * dg + db * db);
-      }
-
-      inline uint elucidian_distance(uint r0, uint g0, uint b0, uint a0, uint r1, uint g1, uint b1, uint a1)
-      {
-         int dr = (int)r0 - (int)r1;
-         int dg = (int)g0 - (int)g1;
-         int db = (int)b0 - (int)b1;
-         int da = (int)a0 - (int)a1;
-
-         return static_cast<uint>(dr * dr + dg * dg + db * db + da * da);
-      }
-
-      inline uint elucidian_distance(const color_quad_u8& c0, const color_quad_u8& c1, bool alpha)
-      {
-         if (alpha)
-            return elucidian_distance(c0.r, c0.g, c0.b, c0.a, c1.r, c1.g, c1.b, c1.a);
-         else
-            return elucidian_distance(c0.r, c0.g, c0.b, c1.r, c1.g, c1.b);
-      }
-
-      inline uint weighted_elucidian_distance(uint r0, uint g0, uint b0, uint r1, uint g1, uint b1, uint wr, uint wg, uint wb)
-      {
-         int dr = (int)r0 - (int)r1;
-         int dg = (int)g0 - (int)g1;
-         int db = (int)b0 - (int)b1;
-
-         return static_cast<uint>((wr * dr * dr) + (wg * dg * dg) + (wb * db * db));
-      }
-
-      inline uint weighted_elucidian_distance(
-         uint r0, uint g0, uint b0, uint a0,
-         uint r1, uint g1, uint b1, uint a1,
-         uint wr, uint wg, uint wb, uint wa)
-      {
-         int dr = (int)r0 - (int)r1;
-         int dg = (int)g0 - (int)g1;
-         int db = (int)b0 - (int)b1;
-         int da = (int)a0 - (int)a1;
-
-         return static_cast<uint>((wr * dr * dr) + (wg * dg * dg) + (wb * db * db) + (wa * da * da));
-      }
-
-      inline uint weighted_elucidian_distance(const color_quad_u8& c0, const color_quad_u8& c1, uint wr, uint wg, uint wb, uint wa)
-      {
-         return weighted_elucidian_distance(c0.r, c0.g, c0.b, c0.a, c1.r, c1.g, c1.b, c1.a, wr, wg, wb, wa);
-      }
-
-      //const uint cRWeight = 8;//24;
-      //const uint cGWeight = 24;//73;
-      //const uint cBWeight = 1;//3;
-
-      const uint cRWeight = 8;//24;
-      const uint cGWeight = 25;//73;
-      const uint cBWeight = 1;//3;
-
-      inline uint color_distance(bool perceptual, const color_quad_u8& e1, const color_quad_u8& e2, bool alpha)
-      {
-         if (perceptual)
-         {
-            if (alpha)
-               return weighted_elucidian_distance(e1, e2, cRWeight, cGWeight, cBWeight, cRWeight+cGWeight+cBWeight);
-            else
-               return weighted_elucidian_distance(e1, e2, cRWeight, cGWeight, cBWeight, 0);
-         }
-         else
-            return elucidian_distance(e1, e2, alpha);
-      }
-
-      inline uint peak_color_error(const color_quad_u8& e1, const color_quad_u8& e2)
-      {
-         return math::maximum<uint>(labs(e1[0] - e2[0]), labs(e1[1] - e2[1]), labs(e1[2] - e2[2]));
-         //return math::square<int>(e1[0] - e2[0]) + math::square<int>(e1[1] - e2[1]) + math::square<int>(e1[2] - e2[2]);
-      }
-
-      // y - [0,255]
-      // co - [-127,127]
-      // cg - [-126,127]
-      inline void RGB_to_YCoCg(int r, int g, int b, int& y, int& co, int& cg)
-      {
-         y  =  (r >> 2) + (g >> 1) + (b >> 2);
-         co =  (r >> 1)            - (b >> 1);
-         cg = -(r >> 2) + (g >> 1) - (b >> 2);
-      }
-
-      inline void YCoCg_to_RGB(int y, int co, int cg, int& r, int& g, int& b)
-      {
-         int tmp = y - cg;
-         g = y + cg;
-         r = tmp + co;
-         b = tmp - co;
-      }
-
-      static inline uint8 clamp_component(int i) { if (static_cast<uint>(i) > 255U) { if (i < 0) i = 0; else if (i > 255) i = 255; } return static_cast<uint8>(i); }
-
-      // RGB->YCbCr constants, scaled by 2^16
-      const int YR = 19595, YG = 38470, YB = 7471, CB_R = -11059, CB_G = -21709, CB_B = 32768, CR_R = 32768, CR_G = -27439, CR_B = -5329;
-      // YCbCr->RGB constants, scaled by 2^16
-      const int R_CR = 91881, B_CB = 116130, G_CR = -46802, G_CB = -22554;
-
-      inline int RGB_to_Y(const color_quad_u8& rgb)
-      {
-         const int r = rgb[0], g = rgb[1], b = rgb[2];
-         return (r * YR + g * YG + b * YB + 32768) >> 16;
-      }
-
-      // RGB to YCbCr (same as JFIF JPEG).
-      // Odd default biases account for 565 endpoint packing.
-      inline void RGB_to_YCC(color_quad_u8& ycc, const color_quad_u8& rgb, int cb_bias = 123, int cr_bias = 125)
-      {
-         const int r = rgb[0], g = rgb[1], b = rgb[2];
-         ycc.a = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
-         ycc.r = clamp_component(cb_bias + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16));
-         ycc.g = clamp_component(cr_bias + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16));
-         ycc.b = 0;
-      }
-
-      // YCbCr to RGB.
-      // Odd biases account for 565 endpoint packing.
-      inline void YCC_to_RGB(color_quad_u8& rgb, const color_quad_u8& ycc, int cb_bias = 123, int cr_bias = 125)
-      {
-         const int y = ycc.a;
-         const int cb = ycc.r - cb_bias;
-         const int cr = ycc.g - cr_bias;
-         rgb.r = clamp_component(y + ((R_CR * cr             + 32768) >> 16));
-         rgb.g = clamp_component(y + ((G_CR * cr + G_CB * cb + 32768) >> 16));
-         rgb.b = clamp_component(y + ((B_CB * cb             + 32768) >> 16));
-         rgb.a = 255;
-      }
-
-      // Float RGB->YCbCr constants
-      const float S = 1.0f/65536.0f;
-      const float F_YR = S*YR, F_YG = S*YG, F_YB = S*YB, F_CB_R = S*CB_R, F_CB_G = S*CB_G, F_CB_B = S*CB_B, F_CR_R = S*CR_R, F_CR_G = S*CR_G, F_CR_B = S*CR_B;
-      // Float YCbCr->RGB constants
-      const float F_R_CR = S*R_CR, F_B_CB = S*B_CB, F_G_CR = S*G_CR, F_G_CB = S*G_CB;
-
-      inline void RGB_to_YCC_float(color_quad_f& ycc, const color_quad_u8& rgb)
-      {
-         const int r = rgb[0], g = rgb[1], b = rgb[2];
-         ycc.a = r * F_YR   + g * F_YG   + b * F_YB;
-         ycc.r = r * F_CB_R + g * F_CB_G + b * F_CB_B;
-         ycc.g = r * F_CR_R + g * F_CR_G + b * F_CR_B;
-         ycc.b = 0;
-      }
-
-      inline void YCC_float_to_RGB(color_quad_u8& rgb, const color_quad_f& ycc)
-      {
-         float y = ycc.a, cb = ycc.r, cr = ycc.g;
-         rgb.r = color::clamp_component(static_cast<int>(.5f + y + F_R_CR * cr));
-         rgb.g = color::clamp_component(static_cast<int>(.5f + y + F_G_CR * cr + F_G_CB * cb));
-         rgb.b = color::clamp_component(static_cast<int>(.5f + y               + F_B_CB * cb));
-         rgb.a = 255;
-      }
-
-   } // namespace color
-
-   // This class purposely trades off speed for extremely flexibility. It can handle any component swizzle, any pixel type from 1-4 components and 1-32 bits/component,
-   // any pixel size between 1-16 bytes/pixel, any pixel stride, any color_quad data type (signed/unsigned/float 8/16/32 bits/component), and scaled/non-scaled components.
-   // On the downside, it's freaking slow.
-   class pixel_packer
-   {
-   public:
-      pixel_packer()
-      {
-         clear();
-      }
-
-      pixel_packer(uint num_comps, uint bits_per_comp, int pixel_stride = -1, bool reversed = false)
-      {
-         init(num_comps, bits_per_comp, pixel_stride, reversed);
-      }
-
-      pixel_packer(const char* pComp_map, int pixel_stride = -1, int force_comp_size = -1)
-      {
-         init(pComp_map, pixel_stride, force_comp_size);
-      }
-
-      void clear()
-      {
-         utils::zero_this(this);
-      }
-
-      inline bool is_valid() const { return m_pixel_stride > 0; }
-
-      inline uint get_pixel_stride() const { return m_pixel_stride; }
-      void set_pixel_stride(uint n) { m_pixel_stride = n; }
-
-      uint get_num_comps() const { return m_num_comps; }
-      uint get_comp_size(uint index) const { CRNLIB_ASSERT(index < 4); return m_comp_size[index]; }
-      uint get_comp_ofs(uint index) const { CRNLIB_ASSERT(index < 4); return m_comp_ofs[index]; }
-      uint get_comp_max(uint index) const { CRNLIB_ASSERT(index < 4); return m_comp_max[index]; }
-      bool get_rgb_is_luma() const { return m_rgb_is_luma; }
-
-      template<typename color_quad_type>
-      const void* unpack(const void* p, color_quad_type& color, bool rescale = true) const
-      {
-         const uint8* pSrc = static_cast<const uint8*>(p);
-
-         for (uint i = 0; i < 4; i++)
-         {
-            const uint comp_size = m_comp_size[i];
-            if (!comp_size)
-            {
-               if (color_quad_type::component_traits::cFloat)
-                  color[i] = static_cast< typename color_quad_type::parameter_t >((i == 3) ? 1 : 0);
-               else
-                  color[i] = static_cast< typename color_quad_type::parameter_t >((i == 3) ? color_quad_type::component_traits::cMax : 0);
-               continue;
-            }
-
-            uint n = 0, dst_bit_ofs = 0;
-            uint src_bit_ofs = m_comp_ofs[i];
-            while (dst_bit_ofs < comp_size)
-            {
-               const uint byte_bit_ofs = src_bit_ofs & 7;
-               n |= ((pSrc[src_bit_ofs >> 3] >> byte_bit_ofs) << dst_bit_ofs);
-
-               const uint bits_read = 8 - byte_bit_ofs;
-               src_bit_ofs += bits_read;
-               dst_bit_ofs += bits_read;
-            }
-
-            const uint32 mx = m_comp_max[i];
-            n &= mx;
-
-            const uint32 h = static_cast<uint32>(color_quad_type::component_traits::cMax);
-
-            if (color_quad_type::component_traits::cFloat)
-               color.set_component(i, static_cast<typename color_quad_type::parameter_t>(n));
-            else if (rescale)
-               color.set_component(i, static_cast<typename color_quad_type::parameter_t>( (static_cast<uint64>(n) * h + (mx >> 1U)) / mx ) );
-            else if (color_quad_type::component_traits::cSigned)
-               color.set_component(i, static_cast<typename color_quad_type::parameter_t>(math::minimum<uint32>(n, h)));
-            else
-               color.set_component(i, static_cast<typename color_quad_type::parameter_t>(n));
-         }
-
-         if (m_rgb_is_luma)
-         {
-            color[0] = color[1];
-            color[2] = color[1];
-         }
-
-         return pSrc + m_pixel_stride;
-      }
-
-      template<typename color_quad_type>
-      void* pack(const color_quad_type& color, void* p, bool rescale = true) const
-      {
-         uint8* pDst = static_cast<uint8*>(p);
-
-         for (uint i = 0; i < 4; i++)
-         {
-            const uint comp_size = m_comp_size[i];
-            if (!comp_size)
-               continue;
-
-            uint32 mx = m_comp_max[i];
-
-            uint32 n;
-            if (color_quad_type::component_traits::cFloat)
-            {
-               typename color_quad_type::parameter_t t = color[i];
-               if (t < 0.0f)
-                  n = 0;
-               else if (t > static_cast<typename color_quad_type::parameter_t>(mx))
-                  n = mx;
-               else
-                  n = math::minimum<uint32>(static_cast<uint32>(floor(t + .5f)), mx);
-            }
-            else if (rescale)
-            {
-               if (color_quad_type::component_traits::cSigned)
-                  n = math::maximum<int>(static_cast<int>(color[i]), 0);
-               else
-                  n = static_cast<uint32>(color[i]);
-
-               const uint32 h = static_cast<uint32>(color_quad_type::component_traits::cMax);
-               n = static_cast<uint32>((static_cast<uint64>(n) * mx + (h >> 1)) / h);
-            }
-            else
-            {
-               if (color_quad_type::component_traits::cSigned)
-                  n = math::minimum<uint32>(static_cast<uint32>(math::maximum<int>(static_cast<int>(color[i]), 0)), mx);
-               else
-                  n = math::minimum<uint32>(static_cast<uint32>(color[i]), mx);
-            }
-
-            uint src_bit_ofs = 0;
-            uint dst_bit_ofs = m_comp_ofs[i];
-            while (src_bit_ofs < comp_size)
-            {
-               const uint cur_byte_bit_ofs = (dst_bit_ofs & 7);
-               const uint cur_byte_bits = 8 - cur_byte_bit_ofs;
-
-               uint byte_val = pDst[dst_bit_ofs >> 3];
-               uint bit_mask = (mx << cur_byte_bit_ofs) & 0xFF;
-               byte_val &= ~bit_mask;
-               byte_val |= (n << cur_byte_bit_ofs);
-               pDst[dst_bit_ofs >> 3] = static_cast<uint8>(byte_val);
-
-               mx >>= cur_byte_bits;
-               n >>= cur_byte_bits;
-
-               dst_bit_ofs += cur_byte_bits;
-               src_bit_ofs += cur_byte_bits;
-            }
-         }
-
-         return pDst + m_pixel_stride;
-      }
-
-      bool init(uint num_comps, uint bits_per_comp, int pixel_stride = -1, bool reversed = false)
-      {
-         clear();
-
-         if ((num_comps < 1) || (num_comps > 4) || (bits_per_comp < 1) || (bits_per_comp > 32))
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         for (uint i = 0; i < num_comps; i++)
-         {
-            m_comp_size[i] = bits_per_comp;
-            m_comp_ofs[i] = i * bits_per_comp;
-            if (reversed)
-               m_comp_ofs[i] = ((num_comps - 1) * bits_per_comp) - m_comp_ofs[i];
-         }
-
-         for (uint i = 0; i < 4; i++)
-            m_comp_max[i] = static_cast<uint32>((1ULL << m_comp_size[i]) - 1ULL);
-
-         m_pixel_stride = (pixel_stride >= 0) ? pixel_stride : (num_comps * bits_per_comp + 7) / 8;
-
-         return true;
-      }
-
-      // Format examples:
-      // R16G16B16
-      // B5G6R5
-      // B5G5R5x1
-      // Y8A8
-      // A8R8G8B8
-      // First component is at LSB in memory. Assumes unsigned integer components, 1-32bits each.
-      bool init(const char* pComp_map, int pixel_stride = -1, int force_comp_size = -1)
-      {
-         clear();
-
-         uint cur_bit_ofs = 0;
-
-         while (*pComp_map)
-         {
-            char c = *pComp_map++;
-
-            int comp_index = -1;
-            if (c == 'R')
-               comp_index = 0;
-            else if (c == 'G')
-               comp_index = 1;
-            else if (c == 'B')
-               comp_index = 2;
-            else if (c == 'A')
-               comp_index = 3;
-            else if (c == 'Y')
-               comp_index = 4;
-            else if (c != 'x')
-               return false;
-
-            uint comp_size = 0;
-
-            uint n = *pComp_map;
-            if ((n >= '0') && (n <= '9'))
-            {
-               comp_size = n - '0';
-               pComp_map++;
-
-               n = *pComp_map;
-               if ((n >= '0') && (n <= '9'))
-               {
-                  comp_size = (comp_size * 10) + (n - '0');
-                  pComp_map++;
-               }
-            }
-
-            if (force_comp_size != -1)
-               comp_size = force_comp_size;
-
-            if ((!comp_size) || (comp_size > 32))
-               return false;
-
-            if (comp_index == 4)
-            {
-               if (m_comp_size[0] || m_comp_size[1] || m_comp_size[2])
-                  return false;
-
-               //m_comp_ofs[0] = m_comp_ofs[1] = m_comp_ofs[2] = cur_bit_ofs;
-               //m_comp_size[0] = m_comp_size[1] = m_comp_size[2] = comp_size;
-               m_comp_ofs[1] = cur_bit_ofs;
-               m_comp_size[1] = comp_size;
-               m_rgb_is_luma = true;
-               m_num_comps++;
-            }
-            else if (comp_index >= 0)
-            {
-               if (m_comp_size[comp_index])
-                  return false;
-
-               m_comp_ofs[comp_index] = cur_bit_ofs;
-               m_comp_size[comp_index] = comp_size;
-               m_num_comps++;
-            }
-
-            cur_bit_ofs += comp_size;
-         }
-
-         for (uint i = 0; i < 4; i++)
-            m_comp_max[i] = static_cast<uint32>((1ULL << m_comp_size[i]) - 1ULL);
-
-         if (pixel_stride >= 0)
-            m_pixel_stride = pixel_stride;
-         else
-            m_pixel_stride = (cur_bit_ofs + 7) / 8;
-         return true;
-      }
-
-   private:
-      uint m_pixel_stride;
-      uint m_num_comps;
-      uint m_comp_size[4];
-      uint m_comp_ofs[4];
-      uint m_comp_max[4];
-      bool m_rgb_is_luma;
-   };
-
-} // namespace crnlib
-

+ 0 - 119
Source/ThirdParty/crunch/crnlib/crn_colorized_console.cpp

@@ -1,119 +0,0 @@
-// File: crn_colorized_console.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_colorized_console.h"
-#ifdef CRNLIB_USE_WIN32_API
-#include "crn_winhdr.h"
-#endif
-
-namespace crnlib
-{
-   void colorized_console::init()
-   {
-      console::init();
-      console::add_console_output_func(console_output_func, NULL);
-   }
-
-   void colorized_console::deinit()
-   {
-      console::remove_console_output_func(console_output_func);
-      console::deinit();
-   }
-
-   void colorized_console::tick()
-   {
-   }
-
-#ifdef CRNLIB_USE_WIN32_API
-   bool colorized_console::console_output_func(eConsoleMessageType type, const char* pMsg, void* pData)
-   {
-      pData;
-
-      if (console::get_output_disabled())
-         return true;
-
-      HANDLE cons = GetStdHandle(STD_OUTPUT_HANDLE);
-
-      DWORD attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
-      switch (type)
-      {
-         case cDebugConsoleMessage:    attr = FOREGROUND_BLUE | FOREGROUND_INTENSITY; break;
-         case cMessageConsoleMessage:  attr = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; break;
-         case cWarningConsoleMessage:  attr = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break;
-         case cErrorConsoleMessage:    attr = FOREGROUND_RED | FOREGROUND_INTENSITY; break;
-         default: break;
-      }
-
-      if (INVALID_HANDLE_VALUE != cons)
-         SetConsoleTextAttribute(cons, (WORD)attr);
-
-      if ((console::get_prefixes()) && (console::get_at_beginning_of_line()))
-      {
-         switch (type)
-         {
-            case cDebugConsoleMessage:
-               printf("Debug: %s", pMsg);
-               break;
-            case cWarningConsoleMessage:
-               printf("Warning: %s", pMsg);
-               break;
-            case cErrorConsoleMessage:
-               printf("Error: %s", pMsg);
-               break;
-            default:
-               printf("%s", pMsg);
-               break;
-         }
-      }
-      else
-      {
-         printf("%s", pMsg);
-      }
-
-      if (console::get_crlf())
-         printf("\n");
-
-      if (INVALID_HANDLE_VALUE != cons)
-         SetConsoleTextAttribute(cons, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
-
-      return true;
-   }
-#else
-   bool colorized_console::console_output_func(eConsoleMessageType type, const char* pMsg, void* pData)
-   {
-      pData;
-      if (console::get_output_disabled())
-         return true;
-
-      if ((console::get_prefixes()) && (console::get_at_beginning_of_line()))
-      {
-         switch (type)
-         {
-         case cDebugConsoleMessage:
-            printf("Debug: %s", pMsg);
-            break;
-         case cWarningConsoleMessage:
-            printf("Warning: %s", pMsg);
-            break;
-         case cErrorConsoleMessage:
-            printf("Error: %s", pMsg);
-            break;
-         default:
-            printf("%s", pMsg);
-            break;
-         }
-      }
-      else
-      {
-         printf("%s", pMsg);
-      }
-
-      if (console::get_crlf())
-         printf("\n");
-
-      return true;
-   }
-#endif
-
-} // namespace crnlib
-

+ 0 - 19
Source/ThirdParty/crunch/crnlib/crn_colorized_console.h

@@ -1,19 +0,0 @@
-// File: crn_colorized_console.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_console.h"
-
-namespace crnlib
-{
-   class colorized_console
-   {
-   public:
-      static void init();
-      static void deinit();
-      static void tick();
-
-   private:
-      static bool console_output_func(eConsoleMessageType type, const char* pMsg, void* pData);
-   };
-
-} // namespace crnlib

+ 0 - 472
Source/ThirdParty/crunch/crnlib/crn_command_line_params.cpp

@@ -1,472 +0,0 @@
-// File: crn_command_line_params.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_command_line_params.h"
-#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_as_single_string(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 char* p, dynamic_string_array& params)
-   {
-      bool within_param = false;
-      bool within_quote = false;
-
-      uint ofs = 0;
-      dynamic_string str;
-
-      while (p[ofs])
-      {
-         const char c = p[ofs];
-
-         if (within_param)
-         {
-            if (within_quote)
-            {
-               if (c == '"')
-                  within_quote = false;
-
-               str.append_char(c);
-            }
-            else if ((c == ' ') || (c == '\t'))
-            {
-               if (!str.is_empty())
-               {
-                  params.push_back(str);
-                  str.clear();
-               }
-               within_param = false;
-            }
-            else
-            {
-               if (c == '"')
-                  within_quote = true;
-
-               str.append_char(c);
-            }
-         }
-         else if ((c != ' ') && (c != '\t'))
-         {
-            within_param = true;
-
-            if (c == '"')
-               within_quote = true;
-
-            str.append_char(c);
-         }
-
-         ofs++;
-      }
-
-      if (within_quote)
-      {
-         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 char* pFilename, dynamic_string_array& strings)
-   {
-      cfile_stream in_stream;
-      if (!in_stream.open(pFilename, cDataStreamReadable | cDataStreamSeekable))
-      {
-         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_string(ansi_str.get_ptr()));
-      }
-
-      return true;
-   }
-
-   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_string& src_param = params[arg_index++];
-
-         if (src_param.is_empty())
-            continue;
-#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("Invalid command line parameter: \"%s\"", src_param.get_ptr());
-               return false;
-            }
-
-            dynamic_string key_str(src_param);
-
-            key_str.right(1);
-
-            int modifier = 0;
-            char c = key_str[key_str.get_len() - 1];
-            if (c == '+')
-               modifier = 1;
-            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("Unrecognized command line parameter: \"%s\"", src_param.get_ptr());
-               return false;
-            }
-
-            const param_desc& desc = pParam_desc[param_index];
-
-            const uint cMaxValues = 16;
-            dynamic_string val_str[cMaxValues];
-            uint num_val_strs = 0;
-            if (desc.m_num_values)
-            {
-               CRNLIB_ASSERT(desc.m_num_values <= cMaxValues);
-
-               if ((arg_index + desc.m_num_values) > params.size())
-               {
-                  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_string_array strings;
-
-            if ((desc.m_support_listing_file) && (val_str[0].get_len() >= 2) && (val_str[0][0] == '@'))
-            {
-               dynamic_string filename(val_str[0]);
-               filename.right(1);
-               filename.unquote();
-
-               if (!load_string_file(filename.get_ptr(), strings))
-               {
-                  console::error("Failed loading listing file \"%s\"!", filename.get_ptr());
-                  return false;
-               }
-            }
-            else
-            {
-               for (uint v = 0; v < num_val_strs; v++)
-               {
-                  val_str[v].unquote();
-                  strings.push_back(val_str[v]);
-               }
-            }
-
-            param_value pv;
-            pv.m_values.swap(strings);
-            pv.m_index = cur_arg_index;
-            pv.m_modifier = (int8)modifier;
-            m_param_map.insert(std::make_pair(key_str, pv));
-         }
-         else
-         {
-            param_value pv;
-            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_string, pv));
-         }
-      }
-
-      return true;
-   }
-
-   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_string_array p;
-      if (!split_params(pCmd_line, p))
-         return 0;
-
-      if (p.empty())
-         return 0;
-
-      if (skip_first_param)
-         p.erase(0U);
-
-      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_string& w = m_params[index];
-      if (w.is_empty())
-         return false;
-
-#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 char** ppKeys, crnlib::vector<param_map_const_iterator>* pIterators, crnlib::vector<uint>* 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 char* pKey = ppKeys[i];
-
-         param_map_const_iterator begin, end;
-         find(pKey, begin, end);
-
-         while (begin != end)
-         {
-            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 char* pKey, param_map_const_iterator& begin, param_map_const_iterator& end) const
-   {
-      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 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 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 char* pKey, uint index) const
-   {
-      return get_num_values(pKey, index) != 0;
-   }
-
-   uint command_line_params::get_num_values(const char* pKey, uint index) const
-   {
-      param_map_const_iterator it = get_param(pKey, index);
-
-      if (it == end())
-         return 0;
-
-      return it->second.m_values.size();
-   }
-
-   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 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 char* p = it->second.m_values[value_index].get_ptr();
-      if (!string_to_int(p, val))
-      {
-         crnlib::console::warning("Invalid value specified for parameter \"%s\", using default value of %i", pKey, def);
-         return def;
-      }
-
-      if (val < 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("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 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 char* p = it->second.m_values[value_index].get_ptr();
-      if (!string_to_float(p, val))
-      {
-         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("Value %f for parameter \"%s\" is out of range, clamping to %f", val, pKey, l);
-         val = l;
-      }
-      else if (val > 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 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()))
-      {
-         value.empty();
-         return false;
-      }
-
-      value = it->second.m_values[value_index];
-      return true;
-   }
-
-   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_string;
-
-      return it->second.m_values[value_index];
-   }
-
-} // namespace crnlib
-

+ 0 - 86
Source/ThirdParty/crunch/crnlib/crn_command_line_params.h

@@ -1,86 +0,0 @@
-// File: crn_command_line_params.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_value.h"
-#include <map>
-
-namespace crnlib
-{
-   // Returns the command line passed to the app as a string.
-   // On systems where this isn't trivial, this function combines together the separate arguments, quoting and adding spaces as needed.
-   void get_command_line_as_single_string(dynamic_string& cmd_line, int argc, char *argv[]);
-
-   class command_line_params
-   {
-   public:
-      struct param_value
-      {
-         inline param_value() : m_index(0), m_modifier(0) { }
-
-         dynamic_string_array    m_values;
-         uint                    m_index;
-         int8                    m_modifier;
-      };
-
-      typedef std::multimap<dynamic_string, param_value>    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 char* p, dynamic_string_array& params);
-
-      struct param_desc
-      {
-         const char*    m_pName;
-         uint           m_num_values;
-         bool           m_support_listing_file;
-      };
-
-      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<uint>(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 char** ppKeys, crnlib::vector<param_map_const_iterator>* pIterators, crnlib::vector<uint>* 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 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_string_array   m_params;
-
-      param_map              m_param_map;
-
-      static bool load_string_file(const char* pFilename, dynamic_string_array& strings);
-   };
-
-} // namespace crnlib

+ 0 - 2178
Source/ThirdParty/crunch/crnlib/crn_comp.cpp

@@ -1,2178 +0,0 @@
-// File: crn_comp.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_console.h"
-#include "crn_comp.h"
-#include "crn_zeng.h"
-#include "crn_checksum.h"
-
-#define CRNLIB_CREATE_DEBUG_IMAGES 0
-#define CRNLIB_ENABLE_DEBUG_MESSAGES 0
-
-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<dxt_hc*>(pContext);
-
-      uint endpoint_a = hvq.get_color_endpoint(index_a);
-      uint endpoint_b = hvq.get_color_endpoint(index_b);
-
-      color_quad_u8 a[2];
-      a[0] = dxt1_block::unpack_color((uint16)(endpoint_a & 0xFFFF), true);
-      a[1] = dxt1_block::unpack_color((uint16)((endpoint_a >> 16) & 0xFFFF), true);
-
-      color_quad_u8 b[2];
-      b[0] = dxt1_block::unpack_color((uint16)(endpoint_b & 0xFFFF), true);
-      b[1] = dxt1_block::unpack_color((uint16)((endpoint_b >> 16) & 0xFFFF), true);
-
-      uint total_error = color::elucidian_distance(a[0], b[0], false) + color::elucidian_distance(a[1], b[1], false);
-
-      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<dxt_hc*>(pContext);
-
-      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);
-
-      int total_error = math::square(endpoint_a_lo - endpoint_b_lo) + math::square(endpoint_a_hi - endpoint_b_hi);
-
-      float weight = 1.0f - math::clamp(total_error * 1.0f/256.0f, 0.0f, 1.0f);
-      return weight;
-   }
-
-   void crn_comp::sort_color_endpoint_codebook(crnlib::vector<uint>& remapping, const crnlib::vector<uint>& endpoints)
-   {
-      remapping.resize(endpoints.size());
-
-      uint lowest_energy = UINT_MAX;
-      uint lowest_energy_index = 0;
-
-      for (uint i = 0; i < endpoints.size(); i++)
-      {
-         color_quad_u8 a(dxt1_block::unpack_color(static_cast<uint16>(endpoints[i] & 0xFFFF), true));
-         color_quad_u8 b(dxt1_block::unpack_color(static_cast<uint16>((endpoints[i] >> 16) & 0xFFFF), true));
-
-         uint total = a.r + a.g + a.b + b.r + b.g + b.b;
-
-         if (total < lowest_energy)
-         {
-            lowest_energy = total;
-            lowest_energy_index = i;
-         }
-      }
-
-      uint cur_index = lowest_energy_index;
-
-      crnlib::vector<bool> chosen_flags(endpoints.size());
-
-      uint n = 0;
-      for ( ; ; )
-      {
-         chosen_flags[cur_index] = true;
-
-         remapping[cur_index] = n;
-         n++;
-         if (n == endpoints.size())
-            break;
-
-         uint lowest_error = UINT_MAX;
-         uint lowest_error_index = 0;
-
-         color_quad_u8 a(dxt1_block::unpack_endpoint(endpoints[cur_index], 0, true));
-         color_quad_u8 b(dxt1_block::unpack_endpoint(endpoints[cur_index], 1, true));
-
-         for (uint i = 0; i < endpoints.size(); i++)
-         {
-            if (chosen_flags[i])
-               continue;
-
-            color_quad_u8 c(dxt1_block::unpack_endpoint(endpoints[i], 0, true));
-            color_quad_u8 d(dxt1_block::unpack_endpoint(endpoints[i], 1, true));
-
-            uint total = color::elucidian_distance(a, c, false) + color::elucidian_distance(b, d, false);
-
-            if (total < lowest_error)
-            {
-               lowest_error = total;
-               lowest_error_index = i;
-            }
-         }
-
-         cur_index = lowest_error_index;
-      }
-   }
-
-   void crn_comp::sort_alpha_endpoint_codebook(crnlib::vector<uint>& remapping, const crnlib::vector<uint>& endpoints)
-   {
-      remapping.resize(endpoints.size());
-
-      uint lowest_energy = UINT_MAX;
-      uint lowest_energy_index = 0;
-
-      for (uint i = 0; i < endpoints.size(); i++)
-      {
-         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)
-         {
-            lowest_energy = total;
-            lowest_energy_index = i;
-         }
-      }
-
-      uint cur_index = lowest_energy_index;
-
-      crnlib::vector<bool> chosen_flags(endpoints.size());
-
-      uint n = 0;
-      for ( ; ; )
-      {
-         chosen_flags[cur_index] = true;
-
-         remapping[cur_index] = n;
-         n++;
-         if (n == endpoints.size())
-            break;
-
-         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);
-
-         for (uint i = 0; i < endpoints.size(); i++)
-         {
-            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);
-
-            uint total = math::square(a - c) + math::square(b - d);
-
-            if (total < lowest_error)
-            {
-               lowest_error = total;
-               lowest_error_index = i;
-            }
-         }
-
-         cur_index = lowest_error_index;
-      }
-   }
-
-   // The indices are only used for statistical purposes.
-   bool crn_comp::pack_color_endpoints(
-      crnlib::vector<uint8>& data,
-      const crnlib::vector<uint>& remapping,
-      const crnlib::vector<uint>& endpoint_indices,
-      uint trial_index)
-   {
-      trial_index;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("pack_color_endpoints: %u", trial_index);
-#endif
-
-      crnlib::vector<uint> remapped_endpoints(m_hvq.get_color_endpoint_codebook_size());
-
-      for (uint i = 0; i < m_hvq.get_color_endpoint_codebook_size(); i++)
-         remapped_endpoints[remapping[i]] = m_hvq.get_color_endpoint(i);
-
-      const uint component_limits[6] = { 31, 63, 31,  31, 63, 31 };
-
-      symbol_histogram hist[2];
-      hist[0].resize(32);
-      hist[1].resize(64);
-
-#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
-
-      crnlib::vector<uint> residual_syms;
-      residual_syms.reserve(m_hvq.get_color_endpoint_codebook_size()*2*3);
-
-      color_quad_u8 prev[2];
-      prev[0].clear();
-      prev[1].clear();
-
-      int total_residuals = 0;
-
-      for (uint endpoint_index = 0; endpoint_index < m_hvq.get_color_endpoint_codebook_size(); endpoint_index++)
-      {
-         const uint endpoint = remapped_endpoints[endpoint_index];
-
-         color_quad_u8 cur[2];
-         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
-         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
-
-         for (uint j = 0; j < 2; j++)
-         {
-            for (uint k = 0; k < 3; k++)
-            {
-               int delta = cur[j][k] - prev[j][k];
-               total_residuals += delta*delta;
-
-               int sym = delta & component_limits[j*3+k];
-               int table = (k == 1) ? 1 : 0;
-
-               hist[table].inc_freq(sym);
-
-               residual_syms.push_back(sym);
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-               endpoint_residual_image(j, endpoint_index)[k] = static_cast<uint8>(sym);
-#endif
-            }
-         }
-
-         prev[0] = cur[0];
-         prev[1] = cur[1];
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("Total endpoint residuals: %i", total_residuals);
-#endif
-
-      if (endpoint_indices.size() > 1)
-      {
-         uint prev_index = remapping[endpoint_indices[0]];
-         int64 total_delta = 0;
-         for (uint i = 1; i < endpoint_indices.size(); i++)
-         {
-            uint cur_index = remapping[endpoint_indices[i]];
-            int delta = cur_index - prev_index;
-            prev_index = cur_index;
-            total_delta += delta * delta;
-         }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-         if (m_pParams->m_flags & cCRNCompFlagDebugging)
-            console::debug("Total endpoint index delta: " CRNLIB_INT64_FORMAT_SPECIFIER, total_delta);
-#endif
-      }
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-      image_utils::write_to_file(dynamic_string(cVarArg, "color_endpoint_residuals_%u.tga", trial_index).get_ptr(), endpoint_residual_image);
-      image_utils::write_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
-      for (uint i = 0; i < 2; i++)
-      {
-         if (!residual_dm[i].init(true, hist[i], 15))
-            return false;
-
-         if (!codec.encode_transmit_static_huffman_data_model(residual_dm[i], false))
-            return false;
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         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;
-
-      for (uint i = 0; i < residual_syms.size(); i++)
-      {
-         const uint sym = residual_syms[i];
-         const uint table = ((i % 3) == 1) ? 1 : 0;
-         codec.encode(sym, residual_dm[table]);
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-      {
-         console::debug("Wrote a total of %u bits for color endpoint codebook", codec.encode_get_total_bits_written());
-
-         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.
-   bool crn_comp::pack_alpha_endpoints(
-      crnlib::vector<uint8>& data,
-      const crnlib::vector<uint>& remapping,
-      const crnlib::vector<uint>& endpoint_indices,
-      uint trial_index)
-   {
-      trial_index;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("pack_alpha_endpoints: %u", trial_index);
-#endif
-
-      crnlib::vector<uint> remapped_endpoints(m_hvq.get_alpha_endpoint_codebook_size());
-
-      for (uint i = 0; i < m_hvq.get_alpha_endpoint_codebook_size(); i++)
-         remapped_endpoints[remapping[i]] = m_hvq.get_alpha_endpoint(i);
-
-      symbol_histogram hist;
-      hist.resize(256);
-
-#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
-
-      crnlib::vector<uint> residual_syms;
-      residual_syms.reserve(m_hvq.get_alpha_endpoint_codebook_size()*2*3);
-
-      uint prev[2];
-      utils::zero_object(prev);
-
-      int total_residuals = 0;
-
-      for (uint endpoint_index = 0; endpoint_index < m_hvq.get_alpha_endpoint_codebook_size(); endpoint_index++)
-      {
-         const uint endpoint = remapped_endpoints[endpoint_index];
-
-         uint cur[2];
-         cur[0] = dxt5_block::unpack_endpoint(endpoint, 0);
-         cur[1] = dxt5_block::unpack_endpoint(endpoint, 1);
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-         endpoint_image(0, endpoint_index) = cur[0];
-         endpoint_image(1, endpoint_index) = cur[1];
-#endif
-
-         for (uint j = 0; j < 2; j++)
-         {
-            int delta = cur[j] - prev[j];
-            total_residuals += delta*delta;
-
-            int sym = delta & 255;
-
-            hist.inc_freq(sym);
-
-            residual_syms.push_back(sym);
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-            endpoint_residual_image(j, endpoint_index) = static_cast<uint8>(sym);
-#endif
-         }
-
-         prev[0] = cur[0];
-         prev[1] = cur[1];
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("Total endpoint residuals: %i", total_residuals);
-#endif
-
-      if (endpoint_indices.size() > 1)
-      {
-         uint prev_index = remapping[endpoint_indices[0]];
-         int64 total_delta = 0;
-         for (uint i = 1; i < endpoint_indices.size(); i++)
-         {
-            uint cur_index = remapping[endpoint_indices[i]];
-            int delta = cur_index - prev_index;
-            prev_index = cur_index;
-            total_delta += delta * delta;
-         }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-         if (m_pParams->m_flags & cCRNCompFlagDebugging)
-            console::debug("Total endpoint index delta: " CRNLIB_INT64_FORMAT_SPECIFIER, total_delta);
-#endif
-      }
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-      image_utils::write_to_file(dynamic_string(cVarArg, "alpha_endpoint_residuals_%u.tga", trial_index).get_ptr(), endpoint_residual_image);
-      image_utils::write_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
-      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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-         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;
-
-      for (uint i = 0; i < residual_syms.size(); i++)
-      {
-         const uint sym = residual_syms[i];
-         codec.encode(sym, residual_dm);
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-      {
-         console::debug("Wrote a total of %u bits for alpha endpoint codebook", codec.encode_get_total_bits_written());
-
-         console::debug("Wrote %f bits per each alpha endpoint", data.size() * 8.0f / m_hvq.get_alpha_endpoint_codebook_size());
-      }
-#endif
-
-      return true;
-   }
-
-   float crn_comp::color_selector_similarity_func(uint index_a, uint index_b, void* pContext)
-   {
-      const crnlib::vector<dxt_hc::selectors>& selectors = *static_cast< const crnlib::vector<dxt_hc::selectors>* >(pContext);
-
-      const dxt_hc::selectors& selectors_a = selectors[index_a];
-      const dxt_hc::selectors& selectors_b = selectors[index_b];
-
-      int total = 0;
-      for (uint i = 0; i < 16; i++)
-      {
-         int a = g_dxt1_to_linear[selectors_a.get_by_index(i)];
-         int b = g_dxt1_to_linear[selectors_b.get_by_index(i)];
-
-         int delta = a - b;
-         total += delta*delta;
-      }
-
-      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<dxt_hc::selectors>& selectors = *static_cast< const crnlib::vector<dxt_hc::selectors>* >(pContext);
-
-      const dxt_hc::selectors& selectors_a = selectors[index_a];
-      const dxt_hc::selectors& selectors_b = selectors[index_b];
-
-      int total = 0;
-      for (uint i = 0; i < 16; i++)
-      {
-         int a = g_dxt5_to_linear[selectors_a.get_by_index(i)];
-         int b = g_dxt5_to_linear[selectors_b.get_by_index(i)];
-
-         int delta = a - b;
-         total += delta*delta;
-      }
-
-      float weight = 1.0f - math::clamp(total * 1.0f/100.0f, 0.0f, 1.0f);
-      return weight;
-   }
-
-   void crn_comp::sort_selector_codebook(crnlib::vector<uint>& remapping, const crnlib::vector<dxt_hc::selectors>& selectors, const uint8* pTo_linear)
-   {
-      remapping.resize(selectors.size());
-
-      uint lowest_energy = UINT_MAX;
-      uint lowest_energy_index = 0;
-
-      for (uint i = 0; i < selectors.size(); i++)
-      {
-         uint total = 0;
-         for (uint j = 0; j < 16; j++)
-         {
-            int a = pTo_linear[selectors[i].get_by_index(j)];
-
-            total += a*a;
-         }
-
-         if (total < lowest_energy)
-         {
-            lowest_energy = total;
-            lowest_energy_index = i;
-         }
-      }
-
-      uint cur_index = lowest_energy_index;
-
-      crnlib::vector<bool> chosen_flags(selectors.size());
-
-      uint n = 0;
-      for ( ; ; )
-      {
-         chosen_flags[cur_index] = true;
-
-         remapping[cur_index] = n;
-         n++;
-         if (n == selectors.size())
-            break;
-
-         uint lowest_error = UINT_MAX;
-         uint lowest_error_index = 0;
-
-         for (uint i = 0; i < selectors.size(); i++)
-         {
-            if (chosen_flags[i])
-               continue;
-
-            uint total = 0;
-            for (uint j = 0; j < 16; j++)
-            {
-               int a = pTo_linear[selectors[cur_index].get_by_index(j)];
-               int b = pTo_linear[selectors[i].get_by_index(j)];
-
-               int delta = a - b;
-               total += delta*delta;
-            }
-
-            if (total < lowest_error)
-            {
-               lowest_error = total;
-               lowest_error_index = i;
-            }
-         }
-
-         cur_index = lowest_error_index;
-      }
-   }
-
-   // The indices are only used for statistical purposes.
-   bool crn_comp::pack_selectors(
-      crnlib::vector<uint8>& packed_data,
-      const crnlib::vector<uint>& selector_indices,
-      const crnlib::vector<dxt_hc::selectors>& selectors,
-      const crnlib::vector<uint>& remapping,
-      uint max_selector_value,
-      const uint8* pTo_linear,
-      uint trial_index)
-   {
-      trial_index;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("pack_selectors: %u", trial_index);
-#endif
-
-      crnlib::vector<dxt_hc::selectors> remapped_selectors(selectors.size());
-
-      for (uint i = 0; i < selectors.size(); i++)
-         remapped_selectors[remapping[i]] = selectors[i];
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-      image_u8 residual_image(16, selectors.size());;
-      image_u8 selector_image(16, selectors.size());;
-#endif
-
-      crnlib::vector<uint> residual_syms;
-      residual_syms.reserve(selectors.size() * 8);
-
-      const uint num_baised_selector_values = (max_selector_value * 2 + 1);
-      symbol_histogram hist(num_baised_selector_values * num_baised_selector_values);
-
-      dxt_hc::selectors prev_selectors;
-      utils::zero_object(prev_selectors);
-      int total_residuals = 0;
-      for (uint selector_index = 0; selector_index < selectors.size(); selector_index++)
-      {
-         const dxt_hc::selectors& s = remapped_selectors[selector_index];
-
-         uint prev_sym = 0;
-         for (uint i = 0; i < 16; i++)
-         {
-            int p = pTo_linear[crnlib_assert_range_incl<uint>(prev_selectors.get_by_index(i), max_selector_value)];
-
-            int r = pTo_linear[crnlib_assert_range_incl<uint>(s.get_by_index(i), max_selector_value)] - p;
-
-            total_residuals += r*r;
-
-            uint sym = r + max_selector_value;
-
-            CRNLIB_ASSERT(sym < num_baised_selector_values);
-            if (i & 1)
-            {
-               uint paired_sym = (sym * num_baised_selector_values) + prev_sym;
-               residual_syms.push_back(paired_sym);
-               hist.inc_freq(paired_sym);
-            }
-            else
-               prev_sym = sym;
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-            selector_image(i, selector_index) = (pTo_linear[crnlib_assert_range_incl<uint>(s.get_by_index(i), max_selector_value)] * 255) / max_selector_value;
-            residual_image(i, selector_index) = sym;
-#endif
-         }
-
-         prev_selectors = s;
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("Total selector endpoint residuals: %u", total_residuals);
-#endif
-
-      if (selector_indices.size() > 1)
-      {
-         uint prev_index = remapping[selector_indices[1]];
-         int64 total_delta = 0;
-         for (uint i = 1; i < selector_indices.size(); i++)
-         {
-            uint cur_index = remapping[selector_indices[i]];
-            int delta = cur_index - prev_index;
-            prev_index = cur_index;
-            total_delta += delta * delta;
-         }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-         if (m_pParams->m_flags & cCRNCompFlagDebugging)
-            console::debug("Total selector index delta: " CRNLIB_INT64_FORMAT_SPECIFIER, total_delta);
-#endif
-      }
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-      image_utils::write_to_file(dynamic_string(cVarArg, "selectors_%u_%u.tga", trial_index, max_selector_value).get_ptr(), selector_image);
-      image_utils::write_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
-      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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-         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;
-
-      for (uint i = 0; i < residual_syms.size(); i++)
-      {
-         const uint sym = residual_syms[i];
-         codec.encode(sym, residual_dm);
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-      {
-         console::debug("Wrote a total of %u bits for selector codebook", codec.encode_get_total_bits_written());
-
-         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<uint>* pColor_endpoint_remap,
-      const crnlib::vector<uint>* pColor_selector_remap,
-      const crnlib::vector<uint>* pAlpha_endpoint_remap,
-      const crnlib::vector<uint>* pAlpha_selector_remap)
-   {
-      if (!pCodec)
-      {
-         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());
-            m_endpoint_index_hist[0].resize(pColor_endpoint_remap->size());
-            if (clear_histograms)
-               m_endpoint_index_hist[0].set_all(0);
-         }
-
-         if (pColor_selector_remap)
-         {
-            CRNLIB_ASSERT(pColor_selector_remap->size() == m_hvq.get_color_selector_codebook_size());
-            m_selector_index_hist[0].resize(pColor_selector_remap->size());
-            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());
-            m_endpoint_index_hist[1].resize(pAlpha_endpoint_remap->size());
-            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());
-            m_selector_index_hist[1].resize(pAlpha_selector_remap->size());
-            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)
-         {
-            uint index = 0;
-            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 chunk_detail& details = m_chunk_details[chunk_index];
-
-         const uint comp_order[3] = { cAlpha0, cAlpha1, cColor };
-         for (uint c = 0; c < 3; c++)
-         {
-            const uint comp_index = comp_order[c];
-            if (!m_has_comp[comp_index])
-               continue;
-
-            // endpoints
-            if (comp_index == cColor)
-            {
-               if (pColor_endpoint_remap)
-               {
-                  for (uint i = 0; i < encoding.m_num_tiles; i++)
-                  {
-                     uint cur_endpoint_index = (*pColor_endpoint_remap)[ m_endpoint_indices[cColor][details.m_first_endpoint_index + i] ];
-                     int endpoint_delta = cur_endpoint_index - prev_endpoint_index[cColor];
-
-                     int sym = endpoint_delta;
-                     if (sym < 0)
-                        sym += pColor_endpoint_remap->size();
-
-                     CRNLIB_ASSERT(sym >= 0 && sym < (int)pColor_endpoint_remap->size());
-
-                     if (!pCodec)
-                        m_endpoint_index_hist[cColor].inc_freq(sym);
-                     else
-                        pCodec->encode(sym, m_endpoint_index_dm[0]);
-
-                     prev_endpoint_index[cColor] = cur_endpoint_index;
-                  }
-               }
-            }
-            else
-            {
-               if (pAlpha_endpoint_remap)
-               {
-                  for (uint i = 0; i < encoding.m_num_tiles; i++)
-                  {
-                     uint cur_endpoint_index = (*pAlpha_endpoint_remap)[m_endpoint_indices[comp_index][details.m_first_endpoint_index + i]];
-                     int endpoint_delta = cur_endpoint_index - prev_endpoint_index[comp_index];
-
-                     int sym = endpoint_delta;
-                     if (sym < 0)
-                        sym += pAlpha_endpoint_remap->size();
-
-                     CRNLIB_ASSERT(sym >= 0 && sym < (int)pAlpha_endpoint_remap->size());
-
-                     if (!pCodec)
-                        m_endpoint_index_hist[1].inc_freq(sym);
-                     else
-                        pCodec->encode(sym, m_endpoint_index_dm[1]);
-
-                     prev_endpoint_index[comp_index] = cur_endpoint_index;
-                  }
-               }
-            }
-         } // c
-
-         // selectors
-         for (uint y = 0; y < 2; y++)
-         {
-            for (uint x = 0; x < 2; x++)
-            {
-               for (uint c = 0; c < 3; c++)
-               {
-                  const uint comp_index = comp_order[c];
-                  if (!m_has_comp[comp_index])
-                     continue;
-
-                  if (comp_index == cColor)
-                  {
-                     if (pColor_selector_remap)
-                     {
-                        uint cur_selector_index = (*pColor_selector_remap)[ m_selector_indices[cColor][details.m_first_selector_index + x + y * 2] ];
-                        int selector_delta = cur_selector_index - prev_selector_index[cColor];
-
-                        int sym = selector_delta;
-                        if (sym < 0)
-                           sym += pColor_selector_remap->size();
-
-                        CRNLIB_ASSERT(sym >= 0 && sym < (int)pColor_selector_remap->size());
-
-                        if (!pCodec)
-                           m_selector_index_hist[cColor].inc_freq(sym);
-                        else
-                           pCodec->encode(sym, m_selector_index_dm[cColor]);
-
-                        prev_selector_index[cColor] = cur_selector_index;
-                     }
-                  }
-                  else if (pAlpha_selector_remap)
-                  {
-                     uint cur_selector_index = (*pAlpha_selector_remap)[ m_selector_indices[comp_index][details.m_first_selector_index + x + y * 2] ];
-                     int selector_delta = cur_selector_index - prev_selector_index[comp_index];
-
-                     int sym = selector_delta;
-                     if (sym < 0)
-                        sym += pAlpha_selector_remap->size();
-
-                     CRNLIB_ASSERT(sym >= 0 && sym < (int)pAlpha_selector_remap->size());
-
-                     if (!pCodec)
-                        m_selector_index_hist[1].inc_freq(sym);
-                     else
-                        pCodec->encode(sym, m_selector_index_dm[1]);
-
-                     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<uint>* pColor_endpoint_remap,
-      const crnlib::vector<uint>* pColor_selector_remap,
-      const crnlib::vector<uint>* pAlpha_endpoint_remap,
-      const crnlib::vector<uint>* 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())
-         {
-            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<uint8>& a, const void* p, uint size)
-   {
-      if (size)
-      {
-         uint ofs = a.size();
-         a.resize(ofs + size);
-
-         memcpy(&a[ofs], p, size);
-      }
-   }
-
-   void crn_comp::append_vec(crnlib::vector<uint8>& a, const crnlib::vector<uint8>& b)
-   {
-      if (!b.empty())
-      {
-         uint ofs = a.size();
-         a.resize(ofs + b.size());
-
-         memcpy(&a[ofs], &b[0], b.size());
-      }
-   }
-
-#if 0
-   bool crn_comp::init_chunk_encoding_dm()
-   {
-      symbol_histogram hist(1 << (3 * cEncodingMapNumChunksPerCode));
-
-      for (uint chunk_index = 0; chunk_index < m_hvq.get_num_chunks(); chunk_index += cEncodingMapNumChunksPerCode)
-      {
-         uint index = 0;
-         for (uint i = 0; i < cEncodingMapNumChunksPerCode; i++)
-         {
-            if ((chunk_index + i) >= m_hvq.get_num_chunks())
-               break;
-            const dxt_hc::chunk_encoding& encoding = m_hvq.get_chunk_encoding(chunk_index + i);
-
-            index |= (encoding.m_encoding_index << (i * 3));
-         }
-
-         hist.inc_freq(index);
-      }
-
-      if (!m_chunk_encoding_dm.init(true, hist, 16))
-         return false;
-
-      return true;
-   }
-#endif
-
-   bool crn_comp::alias_images()
-   {
-      for (uint face_index = 0; face_index < m_pParams->m_faces; face_index++)
-      {
-         for (uint level_index = 0; level_index < m_pParams->m_levels; level_index++)
-         {
-            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)
-      {
-         for (uint face_index = 0; face_index < m_pParams->m_faces; face_index++)
-         {
-            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; (void)mip_group_chunk_index;
-      for (uint level_index = 0; level_index < m_pParams->m_levels; level_index++)
-      {
-         const uint width = math::maximum(1U, m_pParams->m_width >> level_index);
-         const uint height = math::maximum(1U, m_pParams->m_height >> level_index);
-         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;
-         m_levels[level_index].m_chunk_height = chunk_height;
-         m_levels[level_index].m_first_chunk = chunk_index;
-         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++)
-      {
-         int x_start = 0;
-         int x_end = num_chunks_x;
-         int x_dir = 1;
-         if (y & 1)
-         {
-            x_start = num_chunks_x - 1;
-            x_end = -1;
-            x_dir = -1;
-         }
-
-         for (int x = x_start; x != x_end; x += x_dir)
-         {
-            chunks.resize(chunks.size() + 1);
-
-            dxt_hc::pixel_chunk& chunk = chunks.back();
-            chunk.m_weight = weight;
-
-            for (uint cy = 0; cy < cChunkPixelHeight; cy++)
-            {
-               uint py = y * cChunkPixelHeight + cy;
-               py = math::minimum(py, img.get_height() - 1);
-
-               for (uint cx = 0; cx < cChunkPixelWidth; cx++)
-               {
-                  uint px = x * cChunkPixelWidth + cx;
-                  px = math::minimum(px, img.get_width() - 1);
-
-                  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++)
-         {
-            if (!face)
-            {
-               CRNLIB_ASSERT(m_levels[level].m_first_chunk == m_chunks.size());
-            }
-
-            float mip_weight = math::minimum(12.0f, powf( 1.3f, static_cast<float>(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_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++)
-      {
-         m_endpoint_index_hist[i].clear();
-         m_endpoint_index_dm[i].clear();
-         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_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<int>(m_pParams->m_crn_color_endpoint_palette_size, cCRNMinPaletteSize, cCRNMaxPaletteSize);
-         params.m_color_selector_codebook_size = math::clamp<int>(m_pParams->m_crn_color_selector_palette_size, cCRNMinPaletteSize, cCRNMaxPaletteSize);
-         params.m_alpha_endpoint_codebook_size = math::clamp<int>(m_pParams->m_crn_alpha_endpoint_palette_size, cCRNMinPaletteSize, cCRNMaxPaletteSize);
-         params.m_alpha_selector_codebook_size = math::clamp<int>(m_pParams->m_crn_alpha_selector_palette_size, cCRNMinPaletteSize, cCRNMaxPaletteSize);
-      }
-      else
-      {
-         uint max_codebook_entries = ((m_pParams->m_width + 3) / 4) * ((m_pParams->m_height + 3) / 4);
-
-         max_codebook_entries = math::clamp<uint>(max_codebook_entries, cCRNMinPaletteSize, cCRNMaxPaletteSize);
-
-         float quality = math::clamp<float>((float)m_pParams->m_quality_level / cCRNMaxQualityLevel, 0.0f, 1.0f);
-         float color_quality_power_mul = 1.0f;
-         float alpha_quality_power_mul = 1.0f;
-         if (m_pParams->m_format == cCRNFmtDXT5_CCxY)
-         {
-            color_quality_power_mul = 3.5f;
-            alpha_quality_power_mul = .35f;
-            params.m_adaptive_tile_color_psnr_derating = 5.0f;
-         }
-         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<uint>(math::float_to_uint(.5f + math::lerp<float>(math::maximum<float>(64, cCRNMinPaletteSize), (float)max_codebook_entries, color_endpoint_quality)), cCRNMinPaletteSize, cCRNMaxPaletteSize);
-         params.m_color_selector_codebook_size = math::clamp<uint>(math::float_to_uint(.5f + math::lerp<float>(math::maximum<float>(96, cCRNMinPaletteSize), (float)max_codebook_entries, color_selector_quality)), cCRNMinPaletteSize, cCRNMaxPaletteSize);
-
-         float alpha_endpoint_quality = powf(quality, 2.1f * alpha_quality_power_mul);
-         float alpha_selector_quality = powf(quality, 1.65f * alpha_quality_power_mul);
-         params.m_alpha_endpoint_codebook_size = math::clamp<uint>(math::float_to_uint(.5f + math::lerp<float>(math::maximum<float>(24, cCRNMinPaletteSize), (float)max_codebook_entries, alpha_endpoint_quality)), cCRNMinPaletteSize, cCRNMaxPaletteSize);;
-         params.m_alpha_selector_codebook_size = math::clamp<uint>(math::float_to_uint(.5f + math::lerp<float>(math::maximum<float>(48, cCRNMinPaletteSize), (float)max_codebook_entries, alpha_selector_quality)), cCRNMinPaletteSize, cCRNMaxPaletteSize);;
-      }
-
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-      {
-         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:
-         {
-            params.m_format = cDXT1;
-            m_has_comp[cColor] = true;
-            break;
-         }
-         case cCRNFmtDXT3:
-         {
-            m_has_comp[cAlpha0] = true;
-            return false;
-         }
-         case cCRNFmtDXT5:
-         {
-            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:
-         {
-            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:
-         {
-            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;
-         }
-         case cCRNFmtDXN_XY:
-         {
-            params.m_format = cDXN_XY;
-            params.m_alpha_component_indices[0] = 0;
-            params.m_alpha_component_indices[1] = 1;
-            m_has_comp[cAlpha0] = true;
-            m_has_comp[cAlpha1] = true;
-            params.m_perceptual = false;
-            break;
-         }
-         case cCRNFmtDXN_YX:
-         {
-            params.m_format = cDXN_YX;
-            params.m_alpha_component_indices[0] = 1;
-            params.m_alpha_component_indices[1] = 0;
-            m_has_comp[cAlpha0] = true;
-            m_has_comp[cAlpha1] = true;
-            params.m_perceptual = false;
-            break;
-         }
-         case cCRNFmtDXT5A:
-         {
-            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;
-         }
-         case cCRNFmtETC1:
-         {
-            console::warning("crn_comp::quantize_chunks: This class does not support ETC1");
-            return false;
-         }
-         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;
-      }
-
-      if (!m_hvq.compress(params, m_total_chunks, &m_chunks[0], m_task_pool))
-         return false;
-
-#if CRNLIB_CREATE_DEBUG_IMAGES
-      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::write_to_file("quantized_chunks.tga", img);
-      }
-#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])
-            {
-               m_chunk_details[chunk_index].m_first_endpoint_index = m_endpoint_indices[i].size();
-               m_chunk_details[chunk_index].m_first_selector_index = m_selector_indices[i].size();
-               break;
-            }
-         }
-
-         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<uint>* m_pTrial_color_endpoint_remap;
-      uint m_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<optimize_color_endpoint_codebook_params*>(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());
-      }
-      else
-      {
-         float f = pParams->m_iter_index / static_cast<float>(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,
-            f);
-      }
-
-      crnlib_delete(pParams);
-   }
-
-   bool crn_comp::optimize_color_endpoint_codebook(crnlib::vector<uint>& remapping)
-   {
-      if (m_pParams->m_flags & cCRNCompFlagQuick)
-      {
-         remapping.resize(m_hvq.get_color_endpoint_vec().size());
-         for (uint i = 0; i < m_hvq.get_color_endpoint_vec().size(); i++)
-            remapping[i] = i;
-
-         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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("----- Begin optimization of color endpoint codebook");
-#endif
-
-      crnlib::vector<uint> trial_color_endpoint_remaps[cMaxEndpointRemapIters + 1];
-
-      for (uint i = 0; i <= cMaxEndpointRemapIters; i++)
-      {
-         optimize_color_endpoint_codebook_params* pParams = crnlib_new<optimize_color_endpoint_codebook_params>();
-         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<uint>& trial_color_endpoint_remap = trial_color_endpoint_remaps[i];
-
-         crnlib::vector<uint8> packed_data;
-         if (!pack_color_endpoints(packed_data, trial_color_endpoint_remap, m_endpoint_indices[cColor], i))
-            return false;
-
-         uint total_packed_chunk_bits;
-         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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-            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
-         if (m_pParams->m_flags & cCRNCompFlagDebugging)
-            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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("End optimization of color endpoint codebook");
-#endif
-
-      return true;
-   }
-
-   struct optimize_color_selector_codebook_params
-   {
-      crnlib::vector<uint>* m_pTrial_color_selector_remap;
-      uint m_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<optimize_color_selector_codebook_params*>(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);
-      }
-      else
-      {
-         float f = pParams->m_iter_index / static_cast<float>(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,
-            (void*)&m_hvq.get_color_selectors_vec(),
-            f);
-      }
-
-      crnlib_delete(pParams);
-   }
-
-   bool crn_comp::optimize_color_selector_codebook(crnlib::vector<uint>& remapping)
-   {
-      if (m_pParams->m_flags & cCRNCompFlagQuick)
-      {
-         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(),
-            remapping,
-            3,
-            g_dxt1_to_linear, 0))
-         {
-            return false;
-         }
-
-         return true;
-      }
-
-      const uint cMaxSelectorRemapIters = 3;
-
-      uint best_bits = UINT_MAX;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("----- Begin optimization of color selector codebook");
-#endif
-
-      crnlib::vector<uint> trial_color_selector_remaps[cMaxSelectorRemapIters + 1];
-
-      for (uint i = 0; i <= cMaxSelectorRemapIters; i++)
-      {
-         optimize_color_selector_codebook_params* pParams = crnlib_new<optimize_color_selector_codebook_params>();
-         pParams->m_iter_index = i;
-         pParams->m_max_iter_index = cMaxSelectorRemapIters;
-         pParams->m_pTrial_color_selector_remap = &trial_color_selector_remaps[i];
-
-         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<uint>& trial_color_selector_remap = trial_color_selector_remaps[i];
-
-         crnlib::vector<uint8> packed_data;
-         if (!pack_selectors(
-            packed_data,
-            m_selector_indices[cColor],
-            m_hvq.get_color_selectors_vec(),
-            trial_color_selector_remap,
-            3,
-            g_dxt1_to_linear, i))
-         {
-            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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-            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
-         if (m_pParams->m_flags & cCRNCompFlagDebugging)
-            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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("End optimization of color selector codebook");
-#endif
-
-      return true;
-   }
-
-   struct optimize_alpha_endpoint_codebook_params
-   {
-      crnlib::vector<uint>* m_pAlpha_indices;
-      crnlib::vector<uint>* m_pTrial_alpha_endpoint_remap;
-      uint m_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<optimize_alpha_endpoint_codebook_params*>(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());
-      }
-      else
-      {
-         float f = pParams->m_iter_index / static_cast<float>(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,
-            f);
-      }
-
-      crnlib_delete(pParams);
-   }
-
-   bool crn_comp::optimize_alpha_endpoint_codebook(crnlib::vector<uint>& remapping)
-   {
-      crnlib::vector<uint> alpha_indices;
-      alpha_indices.reserve(m_endpoint_indices[cAlpha0].size() + m_endpoint_indices[cAlpha1].size());
-      for (uint i = 0; i < m_endpoint_indices[cAlpha0].size(); i++)
-         alpha_indices.push_back(m_endpoint_indices[cAlpha0][i]);
-      for (uint i = 0; i < m_endpoint_indices[cAlpha1].size(); i++)
-         alpha_indices.push_back(m_endpoint_indices[cAlpha1][i]);
-
-      if (m_pParams->m_flags & cCRNCompFlagQuick)
-      {
-         remapping.resize(m_hvq.get_alpha_endpoint_vec().size());
-         for (uint i = 0; i < m_hvq.get_alpha_endpoint_vec().size(); i++)
-            remapping[i] = i;
-
-         if (!pack_alpha_endpoints(m_packed_alpha_endpoints, remapping, alpha_indices, 0))
-            return false;
-
-         return true;
-      }
-
-      const uint cMaxEndpointRemapIters = 3;
-      uint best_bits = UINT_MAX;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("----- Begin optimization of alpha endpoint codebook");
-#endif
-
-      crnlib::vector<uint> trial_alpha_endpoint_remaps[cMaxEndpointRemapIters + 1];
-
-      for (uint i = 0; i <= cMaxEndpointRemapIters; i++)
-      {
-         optimize_alpha_endpoint_codebook_params* pParams = crnlib_new<optimize_alpha_endpoint_codebook_params>();
-         pParams->m_pAlpha_indices = &alpha_indices;
-         pParams->m_iter_index = i;
-         pParams->m_max_iter_index = cMaxEndpointRemapIters;
-         pParams->m_pTrial_alpha_endpoint_remap = &trial_alpha_endpoint_remaps[i];
-
-         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<uint>& trial_alpha_endpoint_remap = trial_alpha_endpoint_remaps[i];
-
-         crnlib::vector<uint8> packed_data;
-         if (!pack_alpha_endpoints(packed_data, trial_alpha_endpoint_remap, alpha_indices, i))
-            return false;
-
-         uint total_packed_chunk_bits;
-         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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-            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
-         if (m_pParams->m_flags & cCRNCompFlagDebugging)
-            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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("End optimization of alpha endpoint codebook");
-#endif
-
-      return true;
-   }
-
-   struct optimize_alpha_selector_codebook_params
-   {
-      crnlib::vector<uint>* m_pAlpha_indices;
-      crnlib::vector<uint>* m_pTrial_alpha_selector_remap;
-      uint m_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<optimize_alpha_selector_codebook_params*>(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);
-      }
-      else
-      {
-         float f = pParams->m_iter_index / static_cast<float>(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,
-            (void*)&m_hvq.get_alpha_selectors_vec(),
-            f);
-      }
-   }
-
-   bool crn_comp::optimize_alpha_selector_codebook(crnlib::vector<uint>& remapping)
-   {
-      crnlib::vector<uint> alpha_indices;
-      alpha_indices.reserve(m_selector_indices[cAlpha0].size() + m_selector_indices[cAlpha1].size());
-      for (uint i = 0; i < m_selector_indices[cAlpha0].size(); i++)
-         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());
-         for (uint i = 0; i < m_hvq.get_alpha_selectors_vec().size(); i++)
-            remapping[i] = i;
-
-         if (!pack_selectors(
-            m_packed_alpha_selectors,
-            alpha_indices,
-            m_hvq.get_alpha_selectors_vec(),
-            remapping,
-            7,
-            g_dxt5_to_linear, 0))
-         {
-            return false;
-         }
-
-         return true;
-      }
-
-      const uint cMaxSelectorRemapIters = 3;
-
-      uint best_bits = UINT_MAX;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_pParams->m_flags & cCRNCompFlagDebugging)
-         console::debug("----- Begin optimization of alpha selector codebook");
-#endif
-
-      crnlib::vector<uint> trial_alpha_selector_remaps[cMaxSelectorRemapIters + 1];
-
-      for (uint i = 0; i <= cMaxSelectorRemapIters; i++)
-      {
-         optimize_alpha_selector_codebook_params* pParams = crnlib_new<optimize_alpha_selector_codebook_params>();
-         pParams->m_pAlpha_indices = &alpha_indices;
-         pParams->m_iter_index = i;
-         pParams->m_max_iter_index = cMaxSelectorRemapIters;
-         pParams->m_pTrial_alpha_selector_remap = &trial_alpha_selector_remaps[i];
-
-         m_task_pool.queue_object_task(this, &crn_comp::optimize_alpha_selector_codebook_task, 0, pParams);
-      }
-
-      m_task_pool.join();
-
-      for (uint i = 0; i <= cMaxSelectorRemapIters; i++)
-      {
-         if (!update_progress(23, i, cMaxSelectorRemapIters+1))
-            return false;
-
-         crnlib::vector<uint>& trial_alpha_selector_remap = trial_alpha_selector_remaps[i];
-
-         crnlib::vector<uint8> packed_data;
-         if (!pack_selectors(
-            packed_data,
-            alpha_indices,
-            m_hvq.get_alpha_selectors_vec(),
-            trial_alpha_selector_remap,
-            7,
-            g_dxt5_to_linear, i))
-         {
-            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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-            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
-         if (m_pParams->m_flags & cCRNCompFlagDebugging)
-            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 (m_pParams->m_flags & cCRNCompFlagDebugging)
-         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())
-         {
-            if (!codec.encode_transmit_static_huffman_data_model(m_endpoint_index_dm[i], false))
-               return false;
-         }
-
-         if (m_selector_index_dm[i].get_total_syms())
-         {
-            if (!codec.encode_transmit_static_huffman_data_model(m_selector_index_dm[i], false))
-               return false;
-         }
-      }
-
-      codec.stop_encoding(false);
-
-      m_packed_data_models.swap(codec.get_encoding_buf());
-
-      return true;
-   }
-
-   bool crn_comp::create_comp_data()
-   {
-      utils::zero_object(m_crn_header);
-
-      m_crn_header.m_width = static_cast<uint16>(m_pParams->m_width);
-      m_crn_header.m_height = static_cast<uint16>(m_pParams->m_height);
-      m_crn_header.m_levels = static_cast<uint8>(m_pParams->m_levels);
-      m_crn_header.m_faces = static_cast<uint8>(m_pParams->m_faces);
-      m_crn_header.m_format = static_cast<uint8>(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<uint16>(m_hvq.get_color_endpoint_codebook_size());
-         m_crn_header.m_color_endpoints.m_size = m_packed_color_endpoints.size();
-         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<uint16>(m_hvq.get_color_selector_codebook_size());
-         m_crn_header.m_color_selectors.m_size = m_packed_color_selectors.size();
-         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<uint16>(m_hvq.get_alpha_endpoint_codebook_size());
-         m_crn_header.m_alpha_endpoints.m_size = m_packed_alpha_endpoints.size();
-         m_crn_header.m_alpha_endpoints.m_ofs = m_comp_data.size();
-         append_vec(m_comp_data, m_packed_alpha_endpoints);
-      }
-
-      if (m_packed_alpha_selectors.size())
-      {
-         m_crn_header.m_alpha_selectors.m_num = static_cast<uint16>(m_hvq.get_alpha_selector_codebook_size());
-         m_crn_header.m_alpha_selectors.m_size = m_packed_alpha_selectors.size();
-         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)
-         return true;
-#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<uint> endpoint_remap[2];
-      crnlib::vector<uint> selector_remap[2];
-
-      if (m_has_comp[cColor])
-      {
-         if (!optimize_color_endpoint_codebook(endpoint_remap[0]))
-            return false;
-         if (!optimize_color_selector_codebook(selector_remap[0]))
-            return false;
-      }
-
-      if (m_has_comp[cAlpha0])
-      {
-         if (!optimize_alpha_endpoint_codebook(endpoint_remap[1]))
-            return false;
-         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_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[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)
-      {
-         crnlib_print_mem_stats();
-      }
-
-      return true;
-   }
-
-   bool crn_comp::compress_init(const crn_comp_params& params)
-   {
-      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 = &params;
-
-      if ((math::minimum(m_pParams->m_width, m_pParams->m_height) < 1) || (math::maximum(m_pParams->m_width, m_pParams->m_height) > cCRNMaxLevelResolution))
-         return false;
-
-      if (!m_task_pool.init(params.m_num_helper_threads))
-         return false;
-
-      bool status = compress_internal();
-
-      m_task_pool.deinit();
-
-      if ((status) && (pEffective_bitrate))
-      {
-         uint total_pixels = 0;
-
-         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;
-      }
-
-      return status;
-   }
-
-   void crn_comp::compress_deinit()
-   {
-   }
-
-} // namespace crnlib
-

+ 0 - 181
Source/ThirdParty/crunch/crnlib/crn_comp.h

@@ -1,181 +0,0 @@
-// File: crn_comp.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-#define CRND_HEADER_FILE_ONLY
-#include "../inc/crn_decomp.h"
-#undef CRND_HEADER_FILE_ONLY
-
-#include "../inc/crnlib.h"
-#include "crn_symbol_codec.h"
-#include "crn_dxt_hc.h"
-#include "crn_image.h"
-#include "crn_image_utils.h"
-#include "crn_texture_comp.h"
-
-namespace crnlib
-{
-   class crn_comp : public itexture_comp
-   {
-      CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(crn_comp);
-
-   public:
-      crn_comp();
-      virtual ~crn_comp();
-
-      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<uint8>& get_comp_data() const  { return m_comp_data; }
-      virtual       crnlib::vector<uint8>& 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 level_tag
-      {
-         uint m_width, m_height;
-         uint m_chunk_width, m_chunk_height;
-         uint m_group_index;
-         uint m_num_chunks;
-         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<mip_group> m_mip_groups;
-
-      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> chunk_detail_vec;
-      chunk_detail_vec              m_chunk_details;
-
-      crnlib::vector<uint>          m_endpoint_indices[cNumComps];
-      crnlib::vector<uint>          m_selector_indices[cNumComps];
-
-      uint                          m_total_chunks;
-      dxt_hc::pixel_chunk_vec       m_chunks;
-
-      crnd::crn_header              m_crn_header;
-      crnlib::vector<uint8>         m_comp_data;
-
-      dxt_hc                        m_hvq;
-
-      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];
-      static_huffman_data_model     m_selector_index_dm[2]; // color, alpha
-
-      crnlib::vector<uint8>         m_packed_chunks[cCRNMaxLevels];
-      crnlib::vector<uint8>         m_packed_data_models;
-      crnlib::vector<uint8>         m_packed_color_endpoints;
-      crnlib::vector<uint8>         m_packed_color_selectors;
-      crnlib::vector<uint8>         m_packed_alpha_endpoints;
-      crnlib::vector<uint8>         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<uint>& remapping, const crnlib::vector<uint>& endpoints);
-      void sort_alpha_endpoint_codebook(crnlib::vector<uint>& remapping, const crnlib::vector<uint>& endpoints);
-
-      bool pack_color_endpoints(crnlib::vector<uint8>& data, const crnlib::vector<uint>& remapping, const crnlib::vector<uint>& endpoint_indices, uint trial_index);
-      bool pack_alpha_endpoints(crnlib::vector<uint8>& data, const crnlib::vector<uint>& remapping, const crnlib::vector<uint>& 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<uint>& remapping, const crnlib::vector<dxt_hc::selectors>& selectors, const uint8* pTo_linear);
-
-      bool pack_selectors(
-         crnlib::vector<uint8>& packed_data,
-         const crnlib::vector<uint>& selector_indices,
-         const crnlib::vector<dxt_hc::selectors>& selectors,
-         const crnlib::vector<uint>& 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<uint>* pColor_endpoint_remap,
-         const crnlib::vector<uint>* pColor_selector_remap,
-         const crnlib::vector<uint>* pAlpha_endpoint_remap,
-         const crnlib::vector<uint>* pAlpha_selector_remap);
-
-      bool pack_chunks_simulation(
-         uint first_chunk, uint num_chunks,
-         uint& total_bits,
-         const crnlib::vector<uint>* pColor_endpoint_remap,
-         const crnlib::vector<uint>* pColor_selector_remap,
-         const crnlib::vector<uint>* pAlpha_endpoint_remap,
-         const crnlib::vector<uint>* pAlpha_selector_remap);
-
-      void optimize_color_endpoint_codebook_task(uint64 data, void* pData_ptr);
-      bool optimize_color_endpoint_codebook(crnlib::vector<uint>& remapping);
-
-      void optimize_color_selector_codebook_task(uint64 data, void* pData_ptr);
-      bool optimize_color_selector_codebook(crnlib::vector<uint>& remapping);
-
-      void optimize_alpha_endpoint_codebook_task(uint64 data, void* pData_ptr);
-      bool optimize_alpha_endpoint_codebook(crnlib::vector<uint>& remapping);
-
-      void optimize_alpha_selector_codebook_task(uint64 data, void* pData_ptr);
-      bool optimize_alpha_selector_codebook(crnlib::vector<uint>& 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<uint8>& a, const void* p, uint size);
-      static void append_vec(crnlib::vector<uint8>& a, const crnlib::vector<uint8>& b);
-   };
-
-} // namespace crnlib

+ 0 - 222
Source/ThirdParty/crunch/crnlib/crn_console.cpp

@@ -1,222 +0,0 @@
-// File: crn_console.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_console.h"
-#include "crn_data_stream.h"
-#include "crn_threading.h"
-
-namespace crnlib
-{
-   eConsoleMessageType                       console::m_default_category = cInfoConsoleMessage;
-   crnlib::vector<console::console_func>      console::m_output_funcs;
-   bool                                      console::m_crlf = true;
-   bool                                      console::m_prefixes = true;
-   bool                                      console::m_output_disabled;
-   data_stream*                              console::m_pLog_stream;
-   mutex*                                    console::m_pMutex;
-   uint                                      console::m_num_messages[cCMTTotal];
-   bool                                      console::m_at_beginning_of_line = true;
-
-   const uint cConsoleBufSize = 4096;
-
-   void console::init()
-   {
-      if (!m_pMutex)
-      {
-         m_pMutex = crnlib_new<mutex>();
-      }
-   }
-
-   void console::deinit()
-   {
-      if (m_pMutex)
-      {
-         crnlib_delete(m_pMutex);
-         m_pMutex = NULL;
-      }
-   }
-
-   void console::disable_crlf()
-   {
-      init();
-
-      m_crlf = false;
-   }
-
-   void console::enable_crlf()
-   {
-      init();
-
-      m_crlf = true;
-   }
-
-   void console::vprintf(eConsoleMessageType type, const char* p, va_list args)
-   {
-      init();
-
-      scoped_mutex lock(*m_pMutex);
-
-      m_num_messages[type]++;
-
-      char buf[cConsoleBufSize];
-      vsprintf_s(buf, cConsoleBufSize, p, args);
-
-      bool handled = false;
-
-      if (m_output_funcs.size())
-      {
-         for (uint i = 0; i < m_output_funcs.size(); i++)
-            if (m_output_funcs[i].m_func(type, buf, m_output_funcs[i].m_pData))
-               handled = true;
-      }
-
-      const char* pPrefix = NULL;
-      if ((m_prefixes) && (m_at_beginning_of_line))
-      {
-         switch (type)
-         {
-            case cDebugConsoleMessage:    pPrefix = "Debug: ";   break;
-            case cWarningConsoleMessage:  pPrefix = "Warning: "; break;
-            case cErrorConsoleMessage:    pPrefix = "Error: ";   break;
-            default: break;
-         }
-      }
-
-      if ((!m_output_disabled) && (!handled))
-      {
-         if (pPrefix)
-            ::printf("%s", pPrefix);
-         ::printf(m_crlf ? "%s\n" : "%s", buf);
-      }
-
-      uint n = strlen(buf);
-      m_at_beginning_of_line = (m_crlf) || ((n) && (buf[n - 1] == '\n'));
-
-      if ((type != cProgressConsoleMessage) && (m_pLog_stream))
-      {
-         // Yes this is bad.
-         dynamic_string tmp_buf(buf);
-
-         tmp_buf.translate_lf_to_crlf();
-
-         m_pLog_stream->printf(m_crlf ? "%s\r\n" : "%s", tmp_buf.get_ptr());
-         m_pLog_stream->flush();
-      }
-   }
-
-   void console::printf(eConsoleMessageType type, const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(type, p, args);
-      va_end(args);
-   }
-
-   void console::printf(const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(m_default_category, p, args);
-      va_end(args);
-   }
-
-   void console::set_default_category(eConsoleMessageType category)
-   {
-      init();
-
-      m_default_category = category;
-   }
-
-   eConsoleMessageType console::get_default_category()
-   {
-      init();
-
-      return m_default_category;
-   }
-
-   void console::add_console_output_func(console_output_func pFunc, void* pData)
-   {
-      init();
-
-      scoped_mutex lock(*m_pMutex);
-
-      m_output_funcs.push_back(console_func(pFunc, pData));
-   }
-
-   void console::remove_console_output_func(console_output_func pFunc)
-   {
-      init();
-
-      scoped_mutex lock(*m_pMutex);
-
-      for (int i = m_output_funcs.size() - 1; i >= 0; i--)
-      {
-         if (m_output_funcs[i].m_func == pFunc)
-         {
-            m_output_funcs.erase(m_output_funcs.begin() + i);
-         }
-      }
-
-      if (!m_output_funcs.size())
-      {
-         m_output_funcs.clear();
-      }
-   }
-
-   void console::progress(const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(cProgressConsoleMessage, p, args);
-      va_end(args);
-   }
-
-   void console::info(const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(cInfoConsoleMessage, p, args);
-      va_end(args);
-   }
-
-   void console::message(const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(cMessageConsoleMessage, p, args);
-      va_end(args);
-   }
-
-   void console::cons(const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(cConsoleConsoleMessage, p, args);
-      va_end(args);
-   }
-
-   void console::debug(const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(cDebugConsoleMessage, p, args);
-      va_end(args);
-   }
-
-   void console::warning(const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(cWarningConsoleMessage, p, args);
-      va_end(args);
-   }
-
-   void console::error(const char* p, ...)
-   {
-      va_list args;
-      va_start(args, p);
-      vprintf(cErrorConsoleMessage, p, args);
-      va_end(args);
-   }
-
-} // namespace crnlib

+ 0 - 128
Source/ThirdParty/crunch/crnlib/crn_console.h

@@ -1,128 +0,0 @@
-// File: crn_console.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dynamic_string.h"
-
-#ifdef WIN32
-#include <tchar.h>
-#include <conio.h>
-#endif
-namespace crnlib
-{
-   class dynamic_string;
-   class data_stream;
-   class mutex;
-
-   enum eConsoleMessageType
-   {
-      cDebugConsoleMessage,      // debugging messages
-      cProgressConsoleMessage,   // progress 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 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 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 bool get_at_beginning_of_line() { return m_at_beginning_of_line; }
-
-      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:
-      static eConsoleMessageType m_default_category;
-
-      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<console_func> 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];
-
-      static bool m_at_beginning_of_line;
-   };
-
-#if defined(WIN32)
-   inline int crn_getch()
-   {
-      return _getch();
-   }
-#elif defined(__GNUC__)
-   #include <termios.h>
-   #include <unistd.h>
-   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
-

+ 0 - 14
Source/ThirdParty/crunch/crnlib/crn_core.cpp

@@ -1,14 +0,0 @@
-// File: crn_core.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
-
-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

+ 0 - 178
Source/ThirdParty/crunch/crnlib/crn_core.h

@@ -1,178 +0,0 @@
-// File: crn_core.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-#if defined(WIN32) && defined(_MSC_VER)
-   #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) && !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. Note: Be sure anything else that links against this lib also #define's this stuff, or remove this crap!
-      #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 speed boost.
-      #define _HAS_EXCEPTIONS 0
-   #endif
-   #define NOMINMAX
-
-   #define CRNLIB_USE_WIN32_API 1
-
-   #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
-      #define CRNLIB_LITTLE_ENDIAN_CPU 1
-   #else
-      #define CRNLIB_PLATFORM_PC_X86 1
-      #define CRNLIB_64BIT_POINTERS 0
-      #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 <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-#include <math.h>
-#include <stdarg.h>
-#include <string.h>
-#include <algorithm>
-#include <locale>
-#include <memory.h>
-#include <limits.h>
-#include <algorithm>
-#include <errno.h>
-
-#ifdef min
-   #undef min
-#endif
-
-#ifdef max
-   #undef max
-#endif
-
-#define CRNLIB_FALSE (0)
-#define CRNLIB_TRUE (1)
-#define CRNLIB_MAX_PATH (260)
-
-#ifdef _DEBUG
-   #define CRNLIB_BUILD_DEBUG
-#else
-   #define CRNLIB_BUILD_RELEASE
-
-   #ifndef NDEBUG
-      #define NDEBUG
-   #endif
-
-    #ifdef DEBUG
-      #error DEBUG cannot be defined in CRNLIB_BUILD_RELEASE
-   #endif
-#endif
-
-#include "crn_types.h"
-#include "crn_assert.h"
-#include "crn_platform.h"
-#include "crn_helpers.h"
-#include "crn_traits.h"
-#include "crn_mem.h"
-#include "crn_math.h"
-#include "crn_utils.h"
-#include "crn_hash.h"
-#include "crn_vector.h"
-#include "crn_timer.h"
-#include "crn_dynamic_string.h"

+ 0 - 128
Source/ThirdParty/crunch/crnlib/crn_data_stream.cpp

@@ -1,128 +0,0 @@
-// File: crn_data_stream.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_data_stream.h"
-
-namespace crnlib
-{
-   data_stream::data_stream() :
-      m_attribs(0),
-      m_opened(false), m_error(false), m_got_cr(false)
-   {
-   }
-
-   data_stream::data_stream(const char* pName, uint attribs) :
-      m_name(pName),
-      m_attribs(static_cast<uint16>(attribs)),
-      m_opened(false), m_error(false), m_got_cr(false)
-   {
-   }
-
-   uint64 data_stream::skip(uint64 len)
-   {
-      uint64 total_bytes_read = 0;
-
-      const uint cBufSize = 1024;
-      uint8 buf[cBufSize];
-
-      while (len)
-      {
-         const uint64 bytes_to_read = math::minimum<uint64>(sizeof(buf), len);
-         const uint64 bytes_read = read(buf, static_cast<uint>(bytes_to_read));
-         total_bytes_read += bytes_read;
-
-         if (bytes_read != bytes_to_read)
-            break;
-
-         len -= bytes_read;
-      }
-
-      return total_bytes_read;
-   }
-
-   bool data_stream::read_line(dynamic_string& str)
-   {
-      str.empty();
-
-      for ( ; ; )
-      {
-         const int c = read_byte();
-
-         const bool prev_got_cr = m_got_cr;
-         m_got_cr = false;
-
-         if (c < 0)
-         {
-            if (!str.is_empty())
-               break;
-
-            return false;
-         }
-         else if ((26 == c) || (!c))
-            continue;
-         else if (13 == c)
-         {
-            m_got_cr = true;
-            break;
-         }
-         else if (10 == c)
-         {
-            if (prev_got_cr)
-               continue;
-
-            break;
-         }
-
-         str.append_char(static_cast<char>(c));
-      }
-
-      return true;
-   }
-
-   bool data_stream::printf(const char* p, ...)
-   {
-      va_list args;
-
-      va_start(args, p);
-      dynamic_string buf;
-      buf.format_args(p, args);
-      va_end(args);
-
-      return write(buf.get_ptr(), buf.get_len() * sizeof(char)) == buf.get_len() * sizeof(char);
-   }
-
-   bool data_stream::write_line(const dynamic_string& str)
-   {
-      if (!str.is_empty())
-         return write(str.get_ptr(), str.get_len()) == str.get_len();
-
-      return true;
-   }
-
-   bool data_stream::read_array(vector<uint8>& buf)
-   {
-      if (buf.size() < get_remaining())
-      {
-         if (get_remaining() > 1024U*1024U*1024U)
-            return false;
-
-         buf.resize((uint)get_remaining());
-      }
-
-      if (!get_remaining())
-      {
-         buf.resize(0);
-         return true;
-      }
-
-      return read(&buf[0], buf.size()) == buf.size();
-   }
-
-   bool data_stream::write_array(const vector<uint8>& buf)
-   {
-      if (!buf.empty())
-         return write(&buf[0], buf.size()) == buf.size();
-      return true;
-   }
-
-} // namespace crnlib

+ 0 - 89
Source/ThirdParty/crunch/crnlib/crn_data_stream.h

@@ -1,89 +0,0 @@
-// File: crn_data_stream.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   enum data_stream_attribs
-   {
-      cDataStreamReadable = 1,
-      cDataStreamWritable = 2,
-      cDataStreamSeekable = 4
-   };
-
-   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 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;
-      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_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 write_line(const dynamic_string& str);
-      bool write_bom() { uint16 bom = 0xFEFF; return write(&bom, sizeof(bom)) == sizeof(bom); }
-
-      bool read_array(vector<uint8>& buf);
-      bool write_array(const vector<uint8>& buf);
-
-   protected:
-      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
-

+ 0 - 468
Source/ThirdParty/crunch/crnlib/crn_data_stream_serializer.h

@@ -1,468 +0,0 @@
-// File: data_stream_serializer.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_data_stream.h"
-
-namespace crnlib
-{
-   // Defaults to little endian mode.
-   class data_stream_serializer
-   {
-   public:
-      data_stream_serializer() : m_pStream(NULL), m_little_endian(true) { }
-      data_stream_serializer(data_stream* pStream) : m_pStream(pStream), m_little_endian(true) { }
-      data_stream_serializer(data_stream& stream) : m_pStream(&stream), m_little_endian(true) { }
-      data_stream_serializer(const data_stream_serializer& other) : m_pStream(other.m_pStream), m_little_endian(other.m_little_endian) { }
-      
-      data_stream_serializer& operator= (const data_stream_serializer& rhs) { m_pStream = rhs.m_pStream; m_little_endian = rhs.m_little_endian; return *this; }
-
-      data_stream* get_stream() const { return m_pStream; }
-      void set_stream(data_stream* pStream) { m_pStream = pStream; }
-
-      const dynamic_string& get_name() const { return m_pStream ? m_pStream->get_name() : g_empty_dynamic_string; }
-
-      bool get_error() { return m_pStream ? m_pStream->get_error() : false; }
-      
-      bool get_little_endian() const { return m_little_endian; }
-      void set_little_endian(bool little_endian) { m_little_endian = little_endian; }
-      
-      bool write(const void* pBuf, uint len)
-      {
-         return m_pStream->write(pBuf, len) == len;
-      }
-                  
-      bool read(void* pBuf, uint len)
-      {
-         return m_pStream->read(pBuf, len) == len;
-      }
-      
-      // size = size of each element, count = number of elements, returns actual count of elements written
-      uint write(const void* pBuf, uint size, uint count)
-      {
-         uint actual_size = size * count;
-         if (!actual_size)
-            return 0;
-         uint n = m_pStream->write(pBuf, actual_size);
-         if (n == actual_size)
-            return count;
-         return n / size;
-      }
-
-      // size = size of each element, count = number of elements, returns actual count of elements read
-      uint read(void* pBuf, uint size, uint count)
-      {
-         uint actual_size = size * count;
-         if (!actual_size)
-            return 0;
-         uint n = m_pStream->read(pBuf, actual_size);
-         if (n == actual_size)
-            return count;
-         return n / size;
-      }
-      
-      bool write_chars(const char* pBuf, uint len)
-      {
-         return write(pBuf, len);
-      }
-      
-      bool read_chars(char* pBuf, uint len)
-      {
-         return read(pBuf, len);
-      }
-      
-      bool skip(uint len)
-      {
-         return m_pStream->skip(len) == len;
-      }
-      
-      template<typename T>
-      bool write_object(const T& obj)
-      {
-         if (m_little_endian == c_crnlib_little_endian_platform)
-            return write(&obj, sizeof(obj));
-         else
-         {
-            uint8 buf[sizeof(T)];
-            uint buf_size = sizeof(T);
-            void* pBuf = buf;
-            utils::write_obj(obj, pBuf, buf_size, m_little_endian);
-            
-            return write(buf, sizeof(T));
-         }
-      }
-      
-      template<typename T>
-      bool read_object(T& obj)
-      {
-         if (m_little_endian == c_crnlib_little_endian_platform)
-            return read(&obj, sizeof(obj));
-         else
-         {
-            uint8 buf[sizeof(T)];
-            if (!read(buf, sizeof(T)))
-               return false;
-            
-            uint buf_size = sizeof(T);
-            const void* pBuf = buf;
-            utils::read_obj(obj, pBuf, buf_size, m_little_endian);
-            
-            return true;
-         }
-      }
-         
-      template<typename T>
-      bool write_value(T value)
-      {
-         return write_object(value);
-      }
-      
-      template<typename T>
-      T read_value(const T& on_error_value = T())
-      {
-         T result;
-         if (!read_object(result))
-            result = on_error_value;
-         return result;
-      }
-      
-      template<typename T>
-      bool write_enum(T e)
-      {
-         int val = static_cast<int>(e);
-         return write_object(val);
-      }
-
-      template<typename T>
-      T read_enum()
-      {
-         return static_cast<T>(read_value<int>());
-      }
-      
-      // Writes uint using a simple variable length code (VLC).
-      bool write_uint_vlc(uint val)
-      {
-         do
-         {
-            uint8 c = static_cast<uint8>(val) & 0x7F;
-            if (val <= 0x7F)
-               c |= 0x80;
-               
-            if (!write_value(c))
-               return false;
-            
-            val >>= 7;
-         } while (val);
-         
-         return true;
-      }
-      
-      // Reads uint using a simple variable length code (VLC).
-      bool read_uint_vlc(uint& val)
-      {
-         val = 0;
-         uint shift = 0;
-         
-         for ( ; ; )
-         {
-            if (shift >= 32)
-               return false;
-               
-            uint8 c;
-            if (!read_object(c))
-               return false;
-            
-            val |= ((c & 0x7F) << shift);
-            shift += 7;
-            
-            if (c & 0x80)
-               break;
-         }
-         
-         return true;
-      }
-      
-      bool write_c_str(const char* p)
-      {
-         uint len = static_cast<uint>(strlen(p));
-         if (!write_uint_vlc(len))
-            return false;
-         
-         return write_chars(p, len);
-      }
-      
-      bool read_c_str(char* pBuf, uint buf_size)
-      {
-         uint len;
-         if (!read_uint_vlc(len))
-            return false;
-         if ((len + 1) > buf_size)
-            return false;
-         
-         pBuf[len] = '\0';
-         
-         return read_chars(pBuf, len);
-      }
-      
-      bool write_string(const dynamic_string& str)
-      {
-         if (!write_uint_vlc(str.get_len()))
-            return false;
-
-         return write_chars(str.get_ptr(), str.get_len());
-      }
-      
-      bool read_string(dynamic_string& str)
-      {
-         uint len;
-         if (!read_uint_vlc(len))
-            return false;
-         
-         if (!str.set_len(len))
-            return false;
-         
-         if (len)
-         {
-            if (!read_chars(str.get_ptr_raw(), len))
-               return false;
-            
-            if (memchr(str.get_ptr(), 0, len) != NULL)
-            {
-               str.truncate(0);
-               return false;
-            }
-         }
-         
-         return true;
-      }
-                  
-      template<typename T>
-      bool write_vector(const T& vec)
-      {
-         if (!write_uint_vlc(vec.size()))
-            return false;
-         
-         for (uint i = 0; i < vec.size(); i++)
-         {
-            *this << vec[i];
-            if (get_error())
-               return false;
-         }
-         
-         return true;            
-      };
-      
-      template<typename T>
-      bool read_vector(T& vec, uint num_expected = UINT_MAX)
-      {
-         uint size;
-         if (!read_uint_vlc(size))
-            return false;
-         
-         if ((size * sizeof(T::value_type)) >= 2U*1024U*1024U*1024U)
-            return false;
-         
-         if ((num_expected != UINT_MAX) && (size != num_expected))
-            return false;
-       
-         vec.resize(size);
-         for (uint i = 0; i < vec.size(); i++)
-         {
-            *this >> vec[i];
-            
-            if (get_error())
-               return false;
-         }
-         
-         return true;
-      }
-
-      bool read_entire_file(crnlib::vector<uint8>& buf)
-      {
-         return m_pStream->read_array(buf);
-      }
-
-      bool write_entire_file(const crnlib::vector<uint8>& buf)
-      {
-         return m_pStream->write_array(buf);
-      }
-      
-      // Got this idea from the Molly Rocket forums.
-      // fmt may contain the characters "1", "2", or "4".
-      bool writef(char *fmt, ...) 
-      { 
-         va_list v; 
-         va_start(v, fmt); 
-         
-         while (*fmt) 
-         { 
-            switch (*fmt++) 
-            { 
-               case '1': 
-               { 
-                  const uint8 x = static_cast<uint8>(va_arg(v, uint)); 
-                  if (!write_value(x))
-                     return false;
-               } 
-               case '2': 
-               { 
-                  const uint16 x = static_cast<uint16>(va_arg(v, uint)); 
-                  if (!write_value(x))
-                     return false;
-               } 
-               case '4': 
-               { 
-                  const uint32 x = static_cast<uint32>(va_arg(v, uint)); 
-                  if (!write_value(x))
-                     return false;
-               } 
-               case ' ':
-               case ',':
-               {
-                  break;
-               }
-               default: 
-               {
-                  CRNLIB_ASSERT(0); 
-                  return false;
-               }                  
-            } 
-         } 
-         
-         va_end(v); 
-         return true;
-      } 
-      
-      // Got this idea from the Molly Rocket forums.
-      // fmt may contain the characters "1", "2", or "4".
-      bool readf(char *fmt, ...) 
-      { 
-         va_list v; 
-         va_start(v, fmt); 
-
-         while (*fmt) 
-         { 
-            switch (*fmt++) 
-            { 
-               case '1': 
-               { 
-                  uint8* x = va_arg(v, uint8*); 
-                  CRNLIB_ASSERT(x);
-                  if (!read_object(*x))
-                     return false;
-               } 
-               case '2': 
-               { 
-                  uint16* x = va_arg(v, uint16*); 
-                  CRNLIB_ASSERT(x);
-                  if (!read_object(*x))
-                     return false;
-               } 
-               case '4': 
-               { 
-                  uint32* x = va_arg(v, uint32*);
-                  CRNLIB_ASSERT(x);
-                  if (!read_object(*x))
-                     return false;
-               }
-               case ' ':
-               case ',':
-               {
-                  break;
-               }
-               default: 
-               {
-                  CRNLIB_ASSERT(0); 
-                  return false;
-               }                  
-            } 
-         } 
-
-         va_end(v); 
-         return true;
-      } 
-            
-   private:
-      data_stream* m_pStream;
-
-      bool m_little_endian;
-   };
-   
-   // Write operators
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, bool val)           { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, int8 val)           { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, uint8 val)          { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, int16 val)          { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, uint16 val)         { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, int32 val)          { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, uint32 val)         { serializer.write_uint_vlc(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, int64 val)          { serializer.write_value(val); return serializer; } 
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, uint64 val)         { serializer.write_value(val); return serializer; } 
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, long val)           { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, unsigned long val)  { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, float val)          { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, double val)         { serializer.write_value(val); return serializer; }
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, const char* p)      { serializer.write_c_str(p); return serializer; }
-   
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, const dynamic_string& str)
-   {
-      serializer.write_string(str);
-      return serializer;
-   }
-   
-   template<typename T>
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, const crnlib::vector<T>& vec)
-   {
-      serializer.write_vector(vec);
-      return serializer;
-   }
-   
-   template<typename T>
-   inline data_stream_serializer& operator<< (data_stream_serializer& serializer, const T* p)
-   {
-      serializer.write_object(*p);
-      return serializer;
-   }
-   
-   // Read operators
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, bool& val)           { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, int8& val)           { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, uint8& val)          { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, int16& val)          { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, uint16& val)         { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, int32& val)          { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, uint32& val)         { serializer.read_uint_vlc(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, int64& val)          { serializer.read_object(val); return serializer; } 
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, uint64& val)         { serializer.read_object(val); return serializer; } 
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, long& val)           { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, unsigned long& val)  { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, float& val)          { serializer.read_object(val); return serializer; }
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, double& val)         { serializer.read_object(val); return serializer; }
-      
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, dynamic_string& str)
-   {
-      serializer.read_string(str);
-      return serializer;
-   }
-   
-   template<typename T>
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, crnlib::vector<T>& vec)
-   {
-      serializer.read_vector(vec);
-      return serializer;
-   }
-   
-   template<typename T>
-   inline data_stream_serializer& operator>> (data_stream_serializer& serializer, T* p)
-   {
-      serializer.read_object(*p);
-      return serializer;
-   }
-
-} // namespace crnlib
-
-
-
-
-
-
-

+ 0 - 259
Source/ThirdParty/crunch/crnlib/crn_dds_comp.cpp

@@ -1,259 +0,0 @@
-// File: crn_dds_comp.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_dds_comp.h"
-#include "crn_dynamic_stream.h"
-#include "crn_lzma_codec.h"
-
-namespace crnlib
-{
-   dds_comp::dds_comp() :
-      m_pParams(NULL),
-      m_pixel_fmt(PIXEL_FMT_INVALID),
-      m_pQDXT_state(NULL)
-   {
-   }
-
-   dds_comp::~dds_comp()
-   {
-      crnlib_delete(m_pQDXT_state);
-   }
-
-   void dds_comp::clear()
-   {
-      m_src_tex.clear();
-      m_packed_tex.clear();
-      m_comp_data.clear();
-      m_pParams = NULL;
-      m_pixel_fmt = PIXEL_FMT_INVALID;
-      m_task_pool.deinit();
-      if (m_pQDXT_state)
-      {
-         crnlib_delete(m_pQDXT_state);
-         m_pQDXT_state = NULL;
-      }
-   }
-   
-   bool dds_comp::create_dds_tex(mipmapped_texture &dds_tex)
-   {
-      image_u8 images[cCRNMaxFaces][cCRNMaxLevels];
-
-      bool has_alpha = false;
-      for (uint face_index = 0; face_index < m_pParams->m_faces; face_index++)
-      {
-         for (uint level_index = 0; level_index < m_pParams->m_levels; level_index++)
-         {
-            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;
-
-            images[face_index][level_index].alias((color_quad_u8*)m_pParams->m_pImages[face_index][level_index], width, height);
-            if (!has_alpha)
-               has_alpha = image_utils::has_alpha(images[face_index][level_index]);
-         }
-      }
-      
-      for (uint face_index = 0; face_index < m_pParams->m_faces; face_index++)
-         for (uint level_index = 0; level_index < m_pParams->m_levels; level_index++)
-            images[face_index][level_index].set_component_valid(3, has_alpha);
-
-      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)
-      {
-         for (uint face_index = 0; face_index < m_pParams->m_faces; face_index++)
-         {
-            for (uint level_index = 0; level_index < m_pParams->m_levels; level_index++)
-            {
-               image_u8 cooked_image(images[face_index][level_index]);
-
-               image_utils::convert_image(cooked_image, conv_type);
-
-               images[face_index][level_index].swap(cooked_image);
-            }
-         }
-      }
-
-      face_vec faces(m_pParams->m_faces);
-
-      for (uint face_index = 0; face_index < m_pParams->m_faces; face_index++)
-      {
-         for (uint level_index = 0; level_index < m_pParams->m_levels; level_index++)
-         {
-            mip_level *pMip = crnlib_new<mip_level>();
-
-            image_u8 *pImage = crnlib_new<image_u8>();
-            pImage->swap(images[face_index][level_index]);
-            pMip->assign(pImage);
-
-            faces[face_index].push_back(pMip);
-         }
-      }
-
-      dds_tex.assign(faces);
-#ifdef CRNLIB_BUILD_DEBUG
-      CRNLIB_ASSERT(dds_tex.check());
-#endif
-
-      return true;
-   } 
-
-   static bool progress_callback_func(uint percentage_complete, void* pUser_data_ptr)
-   {
-      const crn_comp_params& params = *(const crn_comp_params*)pUser_data_ptr;
-      return params.m_pProgress_func(0, 1, percentage_complete, 100, params.m_pProgress_func_data) != 0;
-   }
-
-   static bool progress_callback_func_phase_0(uint percentage_complete, void* pUser_data_ptr)
-   {
-      const crn_comp_params& params = *(const crn_comp_params*)pUser_data_ptr;
-      return params.m_pProgress_func(0, 2, percentage_complete, 100, params.m_pProgress_func_data) != 0;
-   }
-
-   static bool progress_callback_func_phase_1(uint percentage_complete, void* pUser_data_ptr)
-   {
-      const crn_comp_params& params = *(const crn_comp_params*)pUser_data_ptr;
-      return params.m_pProgress_func(1, 2, percentage_complete, 100, params.m_pProgress_func_data) != 0;
-   }
-
-   bool dds_comp::convert_to_dxt(const crn_comp_params& params)
-   {
-      if ((params.m_quality_level == cCRNMaxQualityLevel) || (params.m_format == cCRNFmtDXT3))
-      {
-         m_packed_tex = m_src_tex;
-         if (!m_packed_tex.convert(m_pixel_fmt, false, m_pack_params))
-            return false;
-      }
-      else
-      {
-         const bool hierarchical = (params.m_flags & cCRNCompFlagHierarchical) != 0;
-         
-         m_q1_params.m_quality_level = params.m_quality_level;
-         m_q1_params.m_hierarchical = hierarchical;
-
-         m_q5_params.m_quality_level = params.m_quality_level;
-         m_q5_params.m_hierarchical = hierarchical;
-
-         if (!m_pQDXT_state)
-         {
-            m_pQDXT_state = crnlib_new<mipmapped_texture::qdxt_state>(m_task_pool);
-                        
-            if (params.m_pProgress_func)
-            {
-               m_q1_params.m_pProgress_func = progress_callback_func_phase_0;
-               m_q1_params.m_pProgress_data = (void*)&params;
-               m_q5_params.m_pProgress_func = progress_callback_func_phase_0;
-               m_q5_params.m_pProgress_data = (void*)&params;
-            }
-
-            if (!m_src_tex.qdxt_pack_init(*m_pQDXT_state, m_packed_tex, m_q1_params, m_q5_params, m_pixel_fmt, false))
-               return false;
-            
-            if (params.m_pProgress_func)
-            {
-               m_q1_params.m_pProgress_func = progress_callback_func_phase_1;
-               m_q5_params.m_pProgress_func = progress_callback_func_phase_1;
-            }
-         }
-         else
-         {
-            if (params.m_pProgress_func)
-            {
-               m_q1_params.m_pProgress_func = progress_callback_func;
-               m_q1_params.m_pProgress_data = (void*)&params;
-               m_q5_params.m_pProgress_func = progress_callback_func;
-               m_q5_params.m_pProgress_data = (void*)&params;
-            }
-         }
-
-         if (!m_src_tex.qdxt_pack(*m_pQDXT_state, m_packed_tex, m_q1_params, m_q5_params))
-            return false;
-      }
-      
-      return true;
-   }
-         
-   bool dds_comp::compress_init(const crn_comp_params& params)
-   {
-      clear();
-
-      m_pParams = &params;
-
-      if ((math::minimum(m_pParams->m_width, m_pParams->m_height) < 1) || (math::maximum(m_pParams->m_width, m_pParams->m_height) > cCRNMaxLevelResolution))
-         return false;
-
-      if (math::minimum(m_pParams->m_faces, m_pParams->m_levels) < 1)
-         return false;
-      
-      if (!create_dds_tex(m_src_tex))
-         return false;
-
-      m_pack_params.init(*m_pParams);
-      if (params.m_pProgress_func)
-      {
-         m_pack_params.m_pProgress_callback = progress_callback_func;
-         m_pack_params.m_pProgress_callback_user_data_ptr = (void*)&params;
-      }
-      
-      m_pixel_fmt = pixel_format_helpers::convert_crn_format_to_pixel_format(static_cast<crn_format>(m_pParams->m_format));
-      if (m_pixel_fmt == PIXEL_FMT_INVALID)
-         return false;
-      if ((m_pixel_fmt == PIXEL_FMT_DXT1) && (m_src_tex.has_alpha()) && (m_pack_params.m_use_both_block_types) && (m_pParams->m_flags & cCRNCompFlagDXT1AForTransparency))
-         m_pixel_fmt = PIXEL_FMT_DXT1A;
-      
-      if (!m_task_pool.init(m_pParams->m_num_helper_threads))
-         return false;
-      m_pack_params.m_pTask_pool = &m_task_pool;
-
-      const bool hierarchical = (params.m_flags & cCRNCompFlagHierarchical) != 0;
-      m_q1_params.init(m_pack_params, params.m_quality_level, hierarchical);
-      m_q5_params.init(m_pack_params, params.m_quality_level, hierarchical);
-      
-      return true;
-   }
-
-   bool dds_comp::compress_pass(const crn_comp_params& params, float *pEffective_bitrate)
-   {
-      if (pEffective_bitrate) *pEffective_bitrate = 0.0f;
-      
-      if (!m_pParams)
-         return false;
-
-      if (!convert_to_dxt(params))
-         return false;
-
-      dynamic_stream out_stream;
-      out_stream.reserve(512*1024);
-      data_stream_serializer serializer(out_stream);
-
-      if (!m_packed_tex.write_dds(serializer))
-         return false;
-      out_stream.reserve(0);
-
-      m_comp_data.swap(out_stream.get_buf());
-
-      if (pEffective_bitrate)
-      {
-         lzma_codec lossless_codec;
-
-         crnlib::vector<uint8> cmp_tex_bytes;
-         if (lossless_codec.pack(m_comp_data.get_ptr(), m_comp_data.size(), cmp_tex_bytes))
-         {
-            uint comp_size = cmp_tex_bytes.size();
-            if (comp_size)
-            {
-               *pEffective_bitrate = (comp_size * 8.0f) / m_src_tex.get_total_pixels_in_all_faces_and_mips();
-            }
-         }
-      }
-
-      return true;
-   }
-
-   void dds_comp::compress_deinit()
-   {
-      clear();
-   }
-
-} // namespace crnlib

+ 0 - 48
Source/ThirdParty/crunch/crnlib/crn_dds_comp.h

@@ -1,48 +0,0 @@
-// File: crn_comp.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_comp.h"
-#include "crn_mipmapped_texture.h"
-#include "crn_texture_comp.h"
-
-namespace crnlib
-{
-   class dds_comp : public itexture_comp
-   {
-      CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(dds_comp);
-
-   public:
-      dds_comp();
-      virtual ~dds_comp();
-
-      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);
-      virtual void compress_deinit();
-
-      virtual const crnlib::vector<uint8>& get_comp_data() const  { return m_comp_data; }
-      virtual       crnlib::vector<uint8>& get_comp_data()        { return m_comp_data; }
-
-   private:
-      mipmapped_texture m_src_tex;
-      mipmapped_texture m_packed_tex;
-
-      crnlib::vector<uint8> m_comp_data;
-
-      const crn_comp_params* m_pParams;
-
-      pixel_format m_pixel_fmt;
-      dxt_image::pack_params m_pack_params;
-
-      task_pool m_task_pool;
-      qdxt1_params m_q1_params;
-      qdxt5_params m_q5_params;
-      mipmapped_texture::qdxt_state *m_pQDXT_state;
-
-      void clear();
-      bool create_dds_tex(mipmapped_texture &dds_tex);
-      bool convert_to_dxt(const crn_comp_params& params);
-   };
-
-} // namespace crnlib

+ 0 - 6
Source/ThirdParty/crunch/crnlib/crn_decomp.cpp

@@ -1,6 +0,0 @@
-// File: crn_decomp.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-
-// Include the single-file header library with no defines, which brings in the full CRN decompressor.
-#include "../inc/crn_decomp.h"

+ 0 - 386
Source/ThirdParty/crunch/crnlib/crn_dxt.cpp

@@ -1,386 +0,0 @@
-// File: crn_dxt.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_dxt.h"
-#include "crn_dxt1.h"
-#include "crn_ryg_dxt.hpp"
-#include "crn_dxt_fast.h"
-#include "crn_intersect.h"
-
-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 char* get_dxt_format_string(dxt_format fmt)
-   {
-      switch (fmt)
-      {
-         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";
-         case cETC1:    return "ETC1";
-         default: break;
-      }
-      CRNLIB_ASSERT(false);
-      return "?";
-   }
-
-   const char* get_dxt_compressor_name(crn_dxt_compressor_type c)
-   {
-      switch (c)
-      {
-         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 "?";
-   }
-
-   uint get_dxt_format_bits_per_pixel(dxt_format fmt)
-   {
-      switch (fmt)
-      {
-         case cDXT1:
-         case cDXT1A:
-         case cDXT5A:
-         case cETC1:
-            return 4;
-         case cDXT3:
-         case cDXT5:
-         case cDXN_XY:
-         case cDXN_YX:
-            return 8;
-         default: break;
-      }
-      CRNLIB_ASSERT(false);
-      return 0;
-   }
-
-   bool get_dxt_format_has_alpha(dxt_format fmt)
-   {
-      switch (fmt)
-      {
-         case cDXT1A:
-         case cDXT3:
-         case cDXT5:
-         case cDXT5A:
-            return true;
-         default: break;
-      }
-      return false;
-   }
-
-   uint16 dxt1_block::pack_color(const color_quad_u8& color, bool scaled, uint bias)
-   {
-      uint r = color.r;
-      uint g = color.g;
-      uint b = color.b;
-
-      if (scaled)
-      {
-         r = (r * 31U + bias) / 255U;
-         g = (g * 63U + bias) / 255U;
-         b = (b * 31U + bias) / 255U;
-      }
-
-      r = math::minimum(r, 31U);
-      g = math::minimum(g, 63U);
-      b = math::minimum(b, 31U);
-
-      return static_cast<uint16>(b | (g << 5U) | (r << 11U));
-   }
-
-   uint16 dxt1_block::pack_color(uint r, uint g, uint b, bool scaled, uint bias)
-   {
-      return pack_color(color_quad_u8(r, g, b, 0), scaled, bias);
-   }
-
-   color_quad_u8 dxt1_block::unpack_color(uint16 packed_color, bool scaled, uint alpha)
-   {
-      uint b = packed_color & 31U;
-      uint g = (packed_color >> 5U) & 63U;
-      uint r = (packed_color >> 11U) & 31U;
-
-      if (scaled)
-      {
-         b = (b << 3U) | (b >> 2U);
-         g = (g << 2U) | (g >> 4U);
-         r = (r << 3U) | (r >> 2U);
-      }
-
-      return color_quad_u8(cNoClamp, r, g, b, math::minimum(alpha, 255U));
-   }
-
-   void dxt1_block::unpack_color(uint& r, uint& g, uint& b, uint16 packed_color, bool scaled)
-   {
-      color_quad_u8 c(unpack_color(packed_color, scaled, 0));
-      r = c.r;
-      g = c.g;
-      b = c.b;
-   }
-
-   void dxt1_block::get_block_colors_NV5x(color_quad_u8* pDst, uint16 packed_col0, uint16 packed_col1, bool color4)
-   {
-      color_quad_u8 col0(unpack_color(packed_col0, false));
-      color_quad_u8 col1(unpack_color(packed_col1, false));
-
-      pDst[0].r = (3 * col0.r * 22) / 8;
-      pDst[0].b = (3 * col0.b * 22) / 8;
-      pDst[0].g = (col0.g << 2) | (col0.g >> 4);
-      pDst[0].a = 0xFF;
-
-      pDst[1].r = (3 * col1.r * 22) / 8;
-      pDst[1].g = (col1.g << 2) | (col1.g >> 4);
-      pDst[1].b = (3 * col1.b * 22) / 8;
-      pDst[1].a = 0xFF;
-
-      int gdiff = pDst[1].g - pDst[0].g;
-
-      if (color4) //(packed_col0 > packed_col1)
-      {
-         pDst[2].r = static_cast<uint8>(((2 * col0.r + col1.r) * 22) / 8);
-         pDst[2].g = static_cast<uint8>((256 * pDst[0].g + gdiff/4 + 128 + gdiff * 80) / 256);
-         pDst[2].b = static_cast<uint8>(((2 * col0.b + col1.b) * 22) / 8);
-         pDst[2].a = 0xFF;
-
-         pDst[3].r = static_cast<uint8>(((2 * col1.r + col0.r) * 22) / 8);
-         pDst[3].g = static_cast<uint8>((256 * pDst[1].g - gdiff/4 + 128 - gdiff * 80) / 256);
-         pDst[3].b = static_cast<uint8>(((2 * col1.b + col0.b) * 22) / 8);
-         pDst[3].a = 0xFF;
-      }
-      else {
-         pDst[2].r = static_cast<uint8>(((col0.r + col1.r) * 33) / 8);
-         pDst[2].g = static_cast<uint8>((256 * pDst[0].g + gdiff/4 + 128 + gdiff * 128) / 256);
-         pDst[2].b = static_cast<uint8>(((col0.b + col1.b) * 33) / 8);
-         pDst[2].a = 0xFF;
-
-         pDst[3].r = 0x00;
-         pDst[3].g = 0x00;
-         pDst[3].b = 0x00;
-         pDst[3].a = 0x00;
-      }
-   }
-
-   uint dxt1_block::get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1)
-   {
-      color_quad_u8 c0(unpack_color(color0, true));
-      color_quad_u8 c1(unpack_color(color1, true));
-
-      pDst[0] = c0;
-      pDst[1] = c1;
-      pDst[2].set_noclamp_rgba( (c0.r + c1.r) >> 1U, (c0.g + c1.g) >> 1U, (c0.b + c1.b) >> 1U, 255U);
-      pDst[3].set_noclamp_rgba(0, 0, 0, 0);
-
-      return 3;
-   }
-
-   uint dxt1_block::get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1)
-   {
-      color_quad_u8 c0(unpack_color(color0, true));
-      color_quad_u8 c1(unpack_color(color1, true));
-
-      pDst[0] = c0;
-      pDst[1] = c1;
-
-      // The compiler changes the div3 into a mul by recip+shift.
-      pDst[2].set_noclamp_rgba( (c0.r * 2 + c1.r) / 3, (c0.g * 2 + c1.g) / 3, (c0.b * 2 + c1.b) / 3, 255U);
-      pDst[3].set_noclamp_rgba( (c1.r * 2 + c0.r) / 3, (c1.g * 2 + c0.g) / 3, (c1.b * 2 + c0.b) / 3, 255U);
-
-      return 4;
-   }
-
-   uint dxt1_block::get_block_colors3_round(color_quad_u8* pDst, uint16 color0, uint16 color1)
-   {
-      color_quad_u8 c0(unpack_color(color0, true));
-      color_quad_u8 c1(unpack_color(color1, true));
-
-      pDst[0] = c0;
-      pDst[1] = c1;
-      pDst[2].set_noclamp_rgba( (c0.r + c1.r + 1) >> 1U, (c0.g + c1.g + 1) >> 1U, (c0.b + c1.b + 1) >> 1U, 255U);
-      pDst[3].set_noclamp_rgba(0, 0, 0, 0);
-
-      return 3;
-   }
-
-   uint dxt1_block::get_block_colors4_round(color_quad_u8* pDst, uint16 color0, uint16 color1)
-   {
-      color_quad_u8 c0(unpack_color(color0, true));
-      color_quad_u8 c1(unpack_color(color1, true));
-
-      pDst[0] = c0;
-      pDst[1] = c1;
-
-      // 12/14/08 - Supposed to round according to DX docs, but this conflicts with the OpenGL S3TC spec. ?
-      // The compiler changes the div3 into a mul by recip+shift.
-      pDst[2].set_noclamp_rgba( (c0.r * 2 + c1.r + 1) / 3, (c0.g * 2 + c1.g + 1) / 3, (c0.b * 2 + c1.b + 1) / 3, 255U);
-      pDst[3].set_noclamp_rgba( (c1.r * 2 + c0.r + 1) / 3, (c1.g * 2 + c0.g + 1) / 3, (c1.b * 2 + c0.b + 1) / 3, 255U);
-
-      return 4;
-   }
-
-   uint dxt1_block::get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1)
-   {
-      if (color0 > color1)
-         return get_block_colors4(pDst, color0, color1);
-      else
-         return get_block_colors3(pDst, color0, color1);
-   }
-
-   uint dxt1_block::get_block_colors_round(color_quad_u8* pDst, uint16 color0, uint16 color1)
-   {
-      if (color0 > color1)
-         return get_block_colors4_round(pDst, color0, color1);
-      else
-         return get_block_colors3_round(pDst, color0, color1);
-   }
-
-   color_quad_u8 dxt1_block::unpack_endpoint(uint32 endpoints, uint index, bool scaled, uint alpha)
-   {
-      CRNLIB_ASSERT(index < 2);
-      return unpack_color( static_cast<uint16>((endpoints >> (index * 16U)) & 0xFFFFU), scaled, alpha );
-   }
-
-   uint dxt1_block::pack_endpoints(uint lo, uint hi)
-   {
-      CRNLIB_ASSERT((lo <= 0xFFFFU) && (hi <= 0xFFFFU));
-      return lo | (hi << 16U);
-   }
-
-   void dxt3_block::set_alpha(uint x, uint y, uint value, bool scaled)
-   {
-      CRNLIB_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize));
-
-      if (scaled)
-      {
-         CRNLIB_ASSERT(value <= 0xFF);
-         value = (value * 15U + 128U) / 255U;
-      }
-      else
-      {
-         CRNLIB_ASSERT(value <= 0xF);
-      }
-
-      uint ofs = (y << 1U) + (x >> 1U);
-      uint c = m_alpha[ofs];
-
-      c &= ~(0xF << ((x & 1U) << 2U));
-      c |= (value << ((x & 1U) << 2U));
-
-      m_alpha[ofs] = static_cast<uint8>(c);
-   }
-
-   uint dxt3_block::get_alpha(uint x, uint y, bool scaled) const
-   {
-      CRNLIB_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize));
-
-      uint value = m_alpha[(y << 1U) + (x >> 1U)];
-      if (x & 1)
-         value >>= 4;
-      value &= 0xF;
-
-      if (scaled)
-         value = (value << 4U) | value;
-
-      return value;
-   }
-
-   uint dxt5_block::get_block_values6(color_quad_u8* pDst, uint l, uint h)
-   {
-      pDst[0].a = static_cast<uint8>(l);
-      pDst[1].a = static_cast<uint8>(h);
-      pDst[2].a = static_cast<uint8>((l * 4 + h    ) / 5);
-      pDst[3].a = static_cast<uint8>((l * 3 + h * 2) / 5);
-      pDst[4].a = static_cast<uint8>((l * 2 + h * 3) / 5);
-      pDst[5].a = static_cast<uint8>((l     + h * 4) / 5);
-      pDst[6].a = 0;
-      pDst[7].a = 255;
-      return 6;
-   }
-
-   uint dxt5_block::get_block_values8(color_quad_u8* pDst, uint l, uint h)
-   {
-      pDst[0].a = static_cast<uint8>(l);
-      pDst[1].a = static_cast<uint8>(h);
-      pDst[2].a = static_cast<uint8>((l * 6 + h    ) / 7);
-      pDst[3].a = static_cast<uint8>((l * 5 + h * 2) / 7);
-      pDst[4].a = static_cast<uint8>((l * 4 + h * 3) / 7);
-      pDst[5].a = static_cast<uint8>((l * 3 + h * 4) / 7);
-      pDst[6].a = static_cast<uint8>((l * 2 + h * 5) / 7);
-      pDst[7].a = static_cast<uint8>((l     + h * 6) / 7);
-      return 8;
-   }
-
-   uint dxt5_block::get_block_values(color_quad_u8* pDst, uint l, uint h)
-   {
-      if (l > h)
-         return get_block_values8(pDst, l, h);
-      else
-         return get_block_values6(pDst, l, h);
-   }
-
-   uint dxt5_block::get_block_values6(uint* pDst, uint l, uint h)
-   {
-      pDst[0] = l;
-      pDst[1] = h;
-      pDst[2] = (l * 4 + h    ) / 5;
-      pDst[3] = (l * 3 + h * 2) / 5;
-      pDst[4] = (l * 2 + h * 3) / 5;
-      pDst[5] = (l     + h * 4) / 5;
-      pDst[6] = 0;
-      pDst[7] = 255;
-      return 6;
-   }
-
-   uint dxt5_block::get_block_values8(uint* pDst, uint l, uint h)
-   {
-      pDst[0] = l;
-      pDst[1] = h;
-      pDst[2] = (l * 6 + h    ) / 7;
-      pDst[3] = (l * 5 + h * 2) / 7;
-      pDst[4] = (l * 4 + h * 3) / 7;
-      pDst[5] = (l * 3 + h * 4) / 7;
-      pDst[6] = (l * 2 + h * 5) / 7;
-      pDst[7] = (l     + h * 6) / 7;
-      return 8;
-   }
-
-   uint dxt5_block::unpack_endpoint(uint packed, uint index)
-   {
-      CRNLIB_ASSERT(index < 2);
-      return (packed >> (8 * index)) & 0xFF;
-   }
-
-   uint dxt5_block::pack_endpoints(uint lo, uint hi)
-   {
-      CRNLIB_ASSERT((lo <= 0xFF) && (hi <= 0xFF));
-      return lo | (hi << 8U);
-   }
-
-   uint dxt5_block::get_block_values(uint* pDst, uint l, uint h)
-   {
-      if (l > h)
-         return get_block_values8(pDst, l, h);
-      else
-         return get_block_values6(pDst, l, h);
-   }
-
-} // namespace crnlib
-

+ 0 - 361
Source/ThirdParty/crunch/crnlib/crn_dxt.h

@@ -1,361 +0,0 @@
-// File: crn_dxt.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "../inc/crnlib.h"
-#include "crn_color.h"
-#include "crn_vec.h"
-#include "crn_rand.h"
-#include "crn_sparse_bit_array.h"
-#include "crn_hash_map.h"
-#include <map>
-
-#define CRNLIB_DXT_ALT_ROUNDING 1
-
-namespace crnlib
-{
-   enum dxt_constants
-   {
-      cDXT1BytesPerBlock = 8U,
-      cDXT5NBytesPerBlock = 16U,
-
-      cDXT5SelectorBits = 3U,
-      cDXT5SelectorValues = 1U << cDXT5SelectorBits,
-      cDXT5SelectorMask = cDXT5SelectorValues - 1U,
-
-      cDXT1SelectorBits = 2U,
-      cDXT1SelectorValues = 1U << cDXT1SelectorBits,
-      cDXT1SelectorMask = cDXT1SelectorValues - 1U,
-
-      cDXTBlockShift = 2U,
-      cDXTBlockSize = 1U << cDXTBlockShift
-   };
-
-   enum dxt_format
-   {
-      cDXTInvalid = -1,
-
-      // cDXT1/1A must appear first!
-      cDXT1,
-      cDXT1A,
-
-      cDXT3,
-      cDXT5,
-      cDXT5A,
-
-      cDXN_XY,    // inverted relative to standard ATI2, 360's DXN
-      cDXN_YX,    // standard ATI2,
-
-      cETC1       // Ericsson texture compression (color only, 4x4 blocks, 4bpp, 64-bits/block)
-   };
-
-   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];
-
-   // Converts DXT1 linear color selector index to a raw value (inverse of g_dxt1_to_linear).
-   extern const uint8 g_dxt1_from_linear[cDXT1SelectorValues];
-
-   // 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 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 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
-      {
-         return m_low_color[0] | (m_low_color[1] << 8U);
-      }
-
-      inline uint get_high_color() const
-      {
-         return m_high_color[0] | (m_high_color[1] << 8U);
-      }
-
-      inline void set_low_color(uint16 c)
-      {
-         m_low_color[0] = static_cast<uint8>(c & 0xFF);
-         m_low_color[1] = static_cast<uint8>((c >> 8) & 0xFF);
-      }
-
-      inline void set_high_color(uint16 c)
-      {
-         m_high_color[0] = static_cast<uint8>(c & 0xFF);
-         m_high_color[1] = static_cast<uint8>((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));
-      }
-
-      inline void flip_x(uint w = 4, uint h = 4)
-      {
-         for (uint x = 0; x < (w / 2); x++)
-         {
-            for (uint y = 0; y < h; y++)
-            {
-               const uint c = get_selector(x, y);
-               set_selector(x, y, get_selector((w - 1) - x, y));
-               set_selector((w - 1) - x, y, c);
-            }
-         }
-      }
-
-      inline void flip_y(uint w = 4, uint h = 4)
-      {
-         for (uint y = 0; y < (h / 2); y++)
-         {
-            for (uint x = 0; x < w; x++)
-            {
-               const uint c = get_selector(x, y);
-               set_selector(x, y, get_selector(x, (h - 1) - y));
-               set_selector(x, (h - 1) - y, c);
-            }
-         }
-      }
-      
-      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;
-
-      inline void flip_x(uint w = 4, uint h = 4)
-      {
-         for (uint x = 0; x < (w / 2); x++)
-         {
-            for (uint y = 0; y < h; y++)
-            {
-               const uint c = get_alpha(x, y, false);
-               set_alpha(x, y, get_alpha((w - 1) - x, y, false), false);
-               set_alpha((w - 1) - x, y, c, false);
-            }
-         }
-      }
-
-      inline void flip_y(uint w = 4, uint h = 4)
-      {
-         for (uint y = 0; y < (h / 2); y++)
-         {
-            for (uint x = 0; x < w; x++)
-            {
-               const uint c = get_alpha(x, y, false);
-               set_alpha(x, y, get_alpha(x, (h - 1) - y, false), false);
-               set_alpha(x, (h - 1) - y, c, false);
-            }
-         }
-      }
-   };
-
-   CRNLIB_DEFINE_BITWISE_COPYABLE(dxt3_block);
-
-   struct dxt5_block
-   {
-      uint8 m_endpoints[2];
-
-      enum { cNumSelectorBytes = 6 };
-      uint8 m_selectors[cNumSelectorBytes];
-
-      inline void clear()
-      {
-         utils::zero_this(this);
-      }
-
-      inline uint get_low_alpha() const
-      {
-         return m_endpoints[0];
-      }
-
-      inline uint get_high_alpha() const
-      {
-         return m_endpoints[1];
-      }
-
-      inline void set_low_alpha(uint i)
-      {
-         CRNLIB_ASSERT(i <= cUINT8_MAX);
-         m_endpoints[0] = static_cast<uint8>(i);
-      }
-
-      inline void set_high_alpha(uint i)
-      {
-         CRNLIB_ASSERT(i <= cUINT8_MAX);
-         m_endpoints[1] = static_cast<uint8>(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));
-
-         uint selector_index = (y * 4) + x;
-         uint bit_index = selector_index * cDXT5SelectorBits;
-
-         uint byte_index = bit_index >> 3;
-         uint bit_ofs = bit_index & 7;
-
-         uint v = m_selectors[byte_index];
-         if (byte_index < (cNumSelectorBytes - 1))
-            v |= (m_selectors[byte_index + 1] << 8);
-
-         return (v >> bit_ofs) & 7;
-      }
-
-      inline void set_selector(uint x, uint y, uint val)
-      {
-         CRNLIB_ASSERT((x < 4U) && (y < 4U) && (val < 8U));
-
-         uint selector_index = (y * 4) + x;
-         uint bit_index = selector_index * cDXT5SelectorBits;
-
-         uint byte_index = bit_index >> 3;
-         uint bit_ofs = bit_index & 7;
-
-         uint v = m_selectors[byte_index];
-         if (byte_index < (cNumSelectorBytes - 1))
-            v |= (m_selectors[byte_index + 1] << 8);
-
-         v &= (~(7 << bit_ofs));
-         v |= (val << bit_ofs);
-
-         m_selectors[byte_index] = static_cast<uint8>(v);
-         if (byte_index < (cNumSelectorBytes - 1))
-            m_selectors[byte_index + 1] = static_cast<uint8>(v >> 8);
-      }
-
-      inline void flip_x(uint w = 4, uint h = 4)
-      {
-         for (uint x = 0; x < (w / 2); x++)
-         {
-            for (uint y = 0; y < h; y++)
-            {
-               const uint c = get_selector(x, y);
-               set_selector(x, y, get_selector((w - 1) - x, y));
-               set_selector((w - 1) - x, y, c);
-            }
-         }
-      }
-
-      inline void flip_y(uint w = 4, uint h = 4)
-      {
-         for (uint y = 0; y < (h / 2); y++)
-         {
-            for (uint x = 0; x < w; x++)
-            {
-               const uint c = get_selector(x, y);
-               set_selector(x, y, get_selector(x, (h - 1) - y));
-               set_selector(x, (h - 1) - y, c);
-            }
-         }
-      }
-
-      enum { cMaxSelectorValues = 8 };
-
-      // Results written to alpha channel.
-      static uint          get_block_values6(color_quad_u8* pDst, uint l, uint h);
-      static uint          get_block_values8(color_quad_u8* pDst, uint l, uint h);
-      static uint          get_block_values(color_quad_u8* pDst, uint l, uint h);
-
-      static uint          get_block_values6(uint* pDst, uint l, uint h);
-      static uint          get_block_values8(uint* pDst, uint l, uint h);
-      // pDst must point to an array at least cDXT5SelectorValues long.
-      static uint          get_block_values(uint* pDst, uint l, uint h);
-
-      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);
-      }
-   };
-
-   CRNLIB_DEFINE_BITWISE_COPYABLE(dxt_pixel_block);
-
-} // namespace crnlib
-
-
-

+ 0 - 2171
Source/ThirdParty/crunch/crnlib/crn_dxt1.cpp

@@ -1,2171 +0,0 @@
-// File: crn_dxt1.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-//
-// Notes:
-// This class is not optimized for performance on small blocks, unlike typical DXT1 compressors. It's optimized for scalability and quality:
-// - Very high quality in terms of avg. RMSE or Luma RMSE. Goal is to always match or beat every other known offline DXTc compressor: ATI_Compress, squish, NVidia texture tools, nvdxt.exe, etc.
-// - Reasonable scalability and stability with hundreds to many thousands of input colors (including inputs with many thousands of equal/nearly equal colors).
-// - Any quality optimization which results in even a tiny improvement is worth it -- as long as it's either a constant or linear slowdown.
-//   Tiny quality improvements can be extremely valuable in large clusters.
-// - Quality should scale well vs. CPU time cost, i.e. the more time you spend the higher the quality.
-#include "crn_core.h"
-#include "crn_dxt1.h"
-#include "crn_ryg_dxt.hpp"
-#include "crn_dxt_fast.h"
-#include "crn_intersect.h"
-#include "crn_vec_interval.h"
-
-namespace crnlib
-{
-   //-----------------------------------------------------------------------------------------------------------------------------------------
-
-   static const int16 g_fast_probe_table[] = { 0, 1, 2, 3 };
-   static const uint cFastProbeTableSize = sizeof(g_fast_probe_table) / sizeof(g_fast_probe_table[0]);
-
-   static const int16 g_normal_probe_table[] = { 0, 1, 3, 5, 7 };
-   static const uint cNormalProbeTableSize = sizeof(g_normal_probe_table) / sizeof(g_normal_probe_table[0]);
-
-   static const int16 g_better_probe_table[] = { 0, 1, 2, 3, 5, 9, 15, 19, 27, 43 };
-   static const uint cBetterProbeTableSize = sizeof(g_better_probe_table) / sizeof(g_better_probe_table[0]);
-
-   static const int16 g_uber_probe_table[] = { 0, 1, 2, 3, 5, 7, 9, 10, 13, 15, 19, 27, 43, 59, 91 };
-   static const uint cUberProbeTableSize = sizeof(g_uber_probe_table) / sizeof(g_uber_probe_table[0]);
-
-   //-----------------------------------------------------------------------------------------------------------------------------------------
-
-   dxt1_endpoint_optimizer::dxt1_endpoint_optimizer() :
-      m_pParams(NULL),
-      m_pResults(NULL),
-      m_pSolutions(NULL),
-      m_perceptual(false),
-      m_has_color_weighting(false),
-      m_all_pixels_grayscale(false)
-   {
-      m_low_coords.reserve(512);
-      m_high_coords.reserve(512);
-
-      m_unique_colors.reserve(512);
-      m_temp_unique_colors.reserve(512);
-      m_unique_packed_colors.reserve(512);
-
-      m_norm_unique_colors.reserve(512);
-      m_norm_unique_colors_weighted.reserve(512);
-
-      m_lo_cells.reserve(128);
-      m_hi_cells.reserve(128);
-   }
-
-   void dxt1_endpoint_optimizer::clear()
-   {
-      m_pParams = NULL;
-      m_pResults = NULL;
-      m_pSolutions = NULL;
-
-      if (m_unique_color_hash_map.get_table_size() > 8192)
-         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;
-      m_total_unique_color_weight = 0;
-
-      m_norm_unique_colors.resize(0);
-      m_mean_norm_color.clear();
-
-      m_norm_unique_colors_weighted.resize(0);
-      m_mean_norm_color_weighted.clear();
-
-      m_principle_axis.clear();
-
-      m_total_evals = 0;
-      m_all_pixels_grayscale = false;
-      m_has_color_weighting = false;
-      m_perceptual = false;
-   }
-
-   bool dxt1_endpoint_optimizer::handle_all_transparent_block()
-   {
-      m_pResults->m_low_color = 0;
-      m_pResults->m_high_color = 0;
-      m_pResults->m_alpha_block = true;
-
-      memset(m_pResults->m_pSelectors, 3, m_pParams->m_num_pixels);
-
-      return true;
-   }
-
-   // All selectors are equal. Try compressing as if it was solid, using the block's average color, using ryg's optimal single color compression tables.
-   bool dxt1_endpoint_optimizer::try_average_block_as_solid()
-   {
-      uint64 tot_r = 0;
-      uint64 tot_g = 0;
-      uint64 tot_b = 0;
-
-      uint total_weight = 0;
-      for (uint i = 0; i < m_unique_colors.size(); i++)
-      {
-         uint weight = m_unique_colors[i].m_weight;
-         total_weight += weight;
-
-         tot_r += m_unique_colors[i].m_color.r * static_cast<uint64>(weight);
-         tot_g += m_unique_colors[i].m_color.g * static_cast<uint64>(weight);
-         tot_b += m_unique_colors[i].m_color.b * static_cast<uint64>(weight);
-      }
-
-      const uint half_total_weight = total_weight >> 1;
-      uint ave_r = static_cast<uint>((tot_r + half_total_weight) / total_weight);
-      uint ave_g = static_cast<uint>((tot_g + half_total_weight) / total_weight);
-      uint ave_b = static_cast<uint>((tot_b + half_total_weight) / total_weight);
-
-      uint low_color = (ryg_dxt::OMatch5[ave_r][0]<<11) | (ryg_dxt::OMatch6[ave_g][0]<<5) | ryg_dxt::OMatch5[ave_b][0];
-      uint high_color = (ryg_dxt::OMatch5[ave_r][1]<<11) | (ryg_dxt::OMatch6[ave_g][1]<<5) | ryg_dxt::OMatch5[ave_b][1];
-      bool 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[ave_r][0]<<11) | (ryg_dxt::OMatch6_3[ave_g][0]<<5) | ryg_dxt::OMatch5_3[ave_b][0];
-         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)
-      {
-         // Try compressing as all-solid using the other (non-average) colors in the block in uber.
-         for (uint i = 0; i < m_unique_colors.size(); i++)
-         {
-            uint r = m_unique_colors[i].m_color[0];
-            uint g = m_unique_colors[i].m_color[1];
-            uint b = m_unique_colors[i].m_color[2];
-            if ((r == ave_r) && (g == ave_g) && (b == ave_b))
-               continue;
-
-            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];
-               high_color = (ryg_dxt::OMatch5_3[r][1]<<11) | (ryg_dxt::OMatch6_3[g][1]<<5) | ryg_dxt::OMatch5_3[b][1];
-               improved |= evaluate_solution(dxt1_solution_coordinates((uint16)low_color, (uint16)high_color), true, &m_best_solution);
-            }
-         }
-      }
-
-      return improved;
-   }
-
-   // Block is solid, trying using ryg's optimal single color tables.
-   bool dxt1_endpoint_optimizer::handle_solid_block()
-   {
-      int r = m_unique_colors[0].m_color.r;
-      int g = m_unique_colors[0].m_color.g;
-      int b = m_unique_colors[0].m_color.b;
-
-      //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;
-   }
-
-   void dxt1_endpoint_optimizer::compute_vectors(const vec3F& perceptual_weights)
-   {
-      m_norm_unique_colors.resize(0);
-      m_norm_unique_colors_weighted.resize(0);
-
-      m_mean_norm_color.clear();
-      m_mean_norm_color_weighted.clear();
-
-      for (uint i = 0; i < m_unique_colors.size(); i++)
-      {
-         const color_quad_u8& color = m_unique_colors[i].m_color;
-         const uint weight = m_unique_colors[i].m_weight;
-
-         vec3F norm_color(color.r * 1.0f/255.0f, color.g * 1.0f/255.0f, color.b * 1.0f/255.0f);
-         vec3F norm_color_weighted(vec3F::mul_components(perceptual_weights, norm_color));
-
-         m_norm_unique_colors.push_back(norm_color);
-         m_norm_unique_colors_weighted.push_back(norm_color_weighted);
-
-         m_mean_norm_color += norm_color * (float)weight;
-         m_mean_norm_color_weighted += norm_color_weighted * (float)weight;
-      }
-
-      if (m_total_unique_color_weight)
-      {
-         m_mean_norm_color *= (1.0f / m_total_unique_color_weight);
-         m_mean_norm_color_weighted *= (1.0f / m_total_unique_color_weight);
-      }
-
-      for (uint i = 0; i < m_unique_colors.size(); i++)
-      {
-         m_norm_unique_colors[i] -= m_mean_norm_color;
-         m_norm_unique_colors_weighted[i] -= m_mean_norm_color_weighted;
-      }
-   }
-
-   // Compute PCA (principle axis, i.e. direction of largest variance) of input vectors.
-   void dxt1_endpoint_optimizer::compute_pca(vec3F& axis, const vec3F_array& norm_colors, const vec3F& def)
-   {
-#if 0
-      axis.clear();
-
-      CRNLIB_ASSERT(m_unique_colors.size() == norm_colors.size());
-
-      // Incremental PCA
-      bool first = true;
-      for (uint i = 0; i < norm_colors.size(); i++)
-      {
-         const uint weight = m_unique_colors[i].m_weight;
-
-         for (uint j = 0; j < weight; j++)
-         {
-            vec3F x(norm_colors[i] * norm_colors[i][0]);
-            vec3F y(norm_colors[i] * norm_colors[i][1]);
-            vec3F z(norm_colors[i] * norm_colors[i][2]);
-
-            vec3F v(first ? norm_colors[0] : axis);
-            first = false;
-
-            v.normalize(&def);
-
-            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;
-            cov[3] += g*g*weight;
-            cov[4] += g*b*weight;
-            cov[5] += b*b*weight;
-         }
-         else
-         {
-            cov[0] += r*r;
-            cov[1] += r*g;
-            cov[2] += r*b;
-            cov[3] += g*g;
-            cov[4] += g*b;
-            cov[5] += b*b;
-         }
-      }
-
-      double vfr, vfg, vfb;
-      //vfr = hi[0] - lo[0];
-      //vfg = hi[1] - lo[1];
-      //vfb = hi[2] - lo[2];
-      // This is more stable.
-      vfr = .9f;
-      vfg = 1.0f;
-      vfb = .7f;
-
-      const uint cNumIters = 8;
-
-      for (uint iter = 0; iter < cNumIters; iter++)
-      {
-         double r = vfr*cov[0] + vfg*cov[1] + vfb*cov[2];
-         double g = vfr*cov[1] + vfg*cov[3] + vfb*cov[4];
-         double b = vfr*cov[2] + vfg*cov[4] + vfb*cov[5];
-
-         double m = math::maximum(fabs(r), fabs(g), fabs(b));
-         if (m > 1e-10)
-         {
-            m = 1.0f / m;
-            r *= m;
-            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;
-      }
-      else
-      {
-         len = 1.0f / sqrt(len);
-         vfr *= len;
-         vfg *= len;
-         vfb *= len;
-
-         axis.set(static_cast<float>(vfr), static_cast<float>(vfg), static_cast<float>(vfb));
-      }
-#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 };
-
-   // Computes a valid (encodable) DXT1 solution (low/high colors, swizzled selectors) from input.
-   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
-      {
-         CRNLIB_ASSERT(solution.m_coords.m_low_color != solution.m_coords.m_high_color);
-
-         invert_selectors = (solution.m_coords.m_low_color < solution.m_coords.m_high_color);
-      }
-
-      if (invert_selectors)
-      {
-         res.m_low_color = solution.m_coords.m_high_color;
-         res.m_high_color = solution.m_coords.m_low_color;
-      }
-      else
-      {
-         res.m_low_color = solution.m_coords.m_low_color;
-         res.m_high_color = solution.m_coords.m_high_color;
-      }
-
-      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<const uint32*>(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));
-         CRNLIB_ASSERT(it != m_unique_color_hash_map.end());
-
-         uint unique_color_index = it->second;
-
-         uint selector = pInvert_table[solution.m_selectors[unique_color_index]];
-
-         memset(pDst_selectors, selector, m_pParams->m_num_pixels);
-      }
-      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);
-            pSrc_pixels++;
-
-            uint8 selector = 3;
-
-            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);
-      }
-
-      res.m_alpha_block = solution.m_alpha_block;
-      res.m_error = solution.m_error;
-   }
-
-   inline vec3F dxt1_endpoint_optimizer::unpack_to_vec3F(uint16 packed_color)
-   {
-      color_quad_u8 c(dxt1_block::unpack_color(packed_color, false));
-
-      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));
-
-      return vec3F(c.r, c.g, c.b);
-   }
-
-   // Per-component 1D endpoint optimization.
-   void dxt1_endpoint_optimizer::optimize_endpoint_comps()
-   {
-      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;
-
-      color_quad_u8 orig_l_scaled(dxt1_block::unpack_color(m_best_solution.m_coords.m_low_color, true));
-      color_quad_u8 orig_h_scaled(dxt1_block::unpack_color(m_best_solution.m_coords.m_high_color, true));
-
-      color_quad_u8 min_color(0xFF, 0xFF, 0xFF, 0xFF);
-      color_quad_u8 max_color(0, 0, 0, 0);
-      for (uint i = 0; i < m_unique_colors.size(); i++)
-      {
-         min_color = color_quad_u8::component_min(min_color, m_unique_colors[i].m_color);
-         max_color = color_quad_u8::component_max(max_color, m_unique_colors[i].m_color);
-      }
-
-      // Try to separately optimize each component. This is a 1D problem so it's easy to compute accurate per-component error bounds.
-      for (uint comp_index = 0; comp_index < 3; comp_index++)
-      {
-         uint ll[4];
-         ll[0] = orig_l_scaled[comp_index];
-         ll[1] = orig_h_scaled[comp_index];
-         ll[2] = (ll[0]*2+ll[1])/3;
-         ll[3] = (ll[0]+ll[1]*2)/3;
-
-         uint64 error_to_beat = 0;
-         uint min_color_weight = 0;
-         uint max_color_weight = 0;
-         for (uint i = 0; i < m_unique_colors.size(); i++)
-         {
-            uint c = m_unique_colors[i].m_color[comp_index];
-            uint w = m_unique_colors[i].m_weight;
-
-            int delta = ll[m_best_solution.m_selectors[i]] - c;
-            error_to_beat += static_cast<int64>(w) * (delta * delta);
-
-            if (c == min_color[comp_index])
-               min_color_weight += w;
-            if (c == max_color[comp_index])
-               max_color_weight += w;
-         }
-
-         if (!error_to_beat)
-            continue;
-
-         CRNLIB_ASSERT((min_color_weight > 0) && (max_color_weight > 0));
-         const uint error_to_beat_div_min_color_weight = min_color_weight ? ((error_to_beat + min_color_weight - 1) / min_color_weight) : 0;
-         const uint error_to_beat_div_max_color_weight = max_color_weight ? ((error_to_beat + max_color_weight - 1) / max_color_weight) : 0;
-
-         const uint m = (comp_index == 1) ? 63 : 31;
-         const uint m_shift = (comp_index == 1) ? 3 : 2;
-
-         for (uint o = 0; o <= m; o++)
-         {
-            uint tl[4];
-
-            tl[0] = (comp_index == 1) ? ((o << 2) | (o >> 4)) : ((o << 3) | (o >> 2));
-
-            for (uint h = 0; h < 8; h++)
-            {
-               const uint pl = h << m_shift;
-               const uint ph = ((h + 1) << m_shift) - 1;
-
-               uint tl_l = (comp_index == 1) ? ((pl << 2) | (pl >> 4)) : ((pl << 3) | (pl >> 2));
-               uint tl_h = (comp_index == 1) ? ((ph << 2) | (ph >> 4)) : ((ph << 3) | (ph >> 2));
-
-               tl_l = math::minimum(tl_l, tl[0]);
-               tl_h = math::maximum(tl_h, tl[0]);
-
-               uint c_l = min_color[comp_index];
-               uint c_h = max_color[comp_index];
-
-               if (c_h < tl_l)
-               {
-                  uint min_possible_error = math::square<int>(tl_l - c_l);
-                  if (min_possible_error > error_to_beat_div_min_color_weight)
-                     continue;
-               }
-               else if (c_l > tl_h)
-               {
-                  uint min_possible_error = math::square<int>(c_h - tl_h);
-                  if (min_possible_error > error_to_beat_div_max_color_weight)
-                     continue;
-               }
-
-               for (uint p = pl; p <= ph; p++)
-               {
-                  tl[1] = (comp_index == 1) ? ((p << 2) | (p >> 4)) : ((p << 3) | (p >> 2));
-
-                  tl[2] = (tl[0]*2+tl[1])/3;
-                  tl[3] = (tl[0]+tl[1]*2)/3;
-
-                  uint64 trial_error = 0;
-                  for (uint i = 0; i < m_unique_colors.size(); i++)
-                  {
-                     int delta = tl[m_best_solution.m_selectors[i]] - m_unique_colors[i].m_color[comp_index];
-                     trial_error += static_cast<int64>(m_unique_colors[i].m_weight) * (delta * delta);
-                     if (trial_error >= error_to_beat)
-                        break;
-                  }
-
-                  //CRNLIB_ASSERT(trial_error >= min_possible_error);
-
-                  if (trial_error < error_to_beat)
-                  {
-                     color_quad_u8 l(dxt1_block::unpack_color(m_best_solution.m_coords.m_low_color, false));
-                     color_quad_u8 h(dxt1_block::unpack_color(m_best_solution.m_coords.m_high_color, false));
-                     l[comp_index] = static_cast<uint8>(o);
-                     h[comp_index] = static_cast<uint8>(p);
-
-                     bool better = evaluate_solution(
-                        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,
-                           orig_l[comp_index], orig_h[comp_index],
-                           l[comp_index], h[comp_index],
-                           orig_error, m_best_solution.m_error);
-#endif
-                        if (!m_best_solution.m_error)
-                           return;
-
-                        error_to_beat = 0;
-                        for (uint i = 0; i < m_unique_colors.size(); i++)
-                        {
-                           int delta = tl[m_best_solution.m_selectors[i]] - m_unique_colors[i].m_color[comp_index];
-                           error_to_beat += static_cast<int64>(m_unique_colors[i].m_weight) * (delta * delta);
-                        }
-
-                     } // better
-
-                     //goto early_out;
-                  } // if (trial_error < error_to_beat)
-
-               } // for (uint p = 0; p <= m; p++)
-            }
-
-         } // for (uint o = 0; o <= m; o++)
-
-      } // comp_index
-   }
-
-   // Voxel adjacency delta coordinations.
-   static const struct adjacent_coords
-   {
-      int8 x, y, z;
-   } g_adjacency[26] = {
-      {-1, -1, -1},
-      {0, -1, -1},
-      {1, -1, -1},
-      {-1, 0, -1},
-      {0, 0, -1},
-      {1, 0, -1},
-      {-1, 1, -1},
-      {0, 1, -1},
-
-      {1, 1, -1},
-      {-1, -1, 0},
-      {0, -1, 0},
-      {1, -1, 0},
-      {-1, 0, 0},
-      {1, 0, 0},
-      {-1, 1, 0},
-      {0, 1, 0},
-
-      {1, 1, 0},
-      {-1, -1, 1},
-      {0, -1, 1},
-      {1, -1, 1},
-      {-1, 0, 1},
-      {0, 0, 1},
-      {1, 0, 1},
-      {-1, 1, 1},
-
-      {0, 1, 1},
-      {1, 1, 1}
-   };
-
-   // Attempt to refine current solution's endpoints given the current selectors using least squares.
-   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 };
-      static const int prods_1[4] = { 0x00,0x09,0x01,0x04 };
-      static const int prods_2[4] = { 0x09,0x00,0x04,0x01 };
-
-      double akku_0 = 0;
-      double akku_1 = 0;
-      double akku_2 = 0;
-      double At1_r, At1_g, At1_b;
-      double At2_r, At2_g, At2_b;
-
-      At1_r = At1_g = At1_b = 0;
-      At2_r = At2_g = At2_b = 0;
-      for(uint i = 0; i < m_unique_colors.size(); i++)
-      {
-         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;
-         int step = m_best_solution.m_selectors[i]^1;
-
-         int w1 = w1Tab[step];
-
-         akku_0  += prods_0[step]*weight;
-         akku_1  += prods_1[step]*weight;
-         akku_2  += prods_2[step]*weight;
-         At1_r   += w1*r;
-         At1_g   += w1*g;
-         At1_b   += w1*b;
-         At2_r   += r;
-         At2_g   += g;
-         At2_b   += b;
-      }
-
-      At2_r = 3*At2_r - At1_r;
-      At2_g = 3*At2_g - At1_g;
-      At2_b = 3*At2_b - At1_b;
-
-      double xx = akku_2;
-      double yy = akku_1;
-      double xy = akku_0;
-
-      double t = xx * yy - xy * xy;
-      if (!yy || !xx || (fabs(t) < .0000125f))
-         return false;
-
-      double frb = (3.0f * 31.0f / 255.0f) / t;
-      double fg = frb * (63.0f / 31.0f);
-
-      bool improved = false;
-
-      if (refinement_level == 0)
-      {
-         uint max16;
-         max16 =   math::clamp<int>(static_cast<int>((At1_r*yy - At2_r*xy)*frb+0.5f),0,31) << 11;
-         max16 |=  math::clamp<int>(static_cast<int>((At1_g*yy - At2_g*xy)*fg +0.5f),0,63) << 5;
-         max16 |=  math::clamp<int>(static_cast<int>((At1_b*yy - At2_b*xy)*frb+0.5f),0,31) << 0;
-
-         uint min16;
-         min16 =   math::clamp<int>(static_cast<int>((At2_r*xx - At1_r*xy)*frb+0.5f),0,31) << 11;
-         min16 |=  math::clamp<int>(static_cast<int>((At2_g*xx - At1_g*xy)*fg +0.5f),0,63) << 5;
-         min16 |=  math::clamp<int>(static_cast<int>((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);
-      }
-      else if (refinement_level == 1)
-      {
-         // Try exploring the local lattice neighbors of the least squares optimized result.
-         color_quad_u8 e[2];
-
-         e[0].clear();
-         e[0][0] = (uint8)math::clamp<int>(static_cast<int>((At1_r*yy - At2_r*xy)*frb+0.5f),0,31);
-         e[0][1] = (uint8)math::clamp<int>(static_cast<int>((At1_g*yy - At2_g*xy)*fg +0.5f),0,63);
-         e[0][2] = (uint8)math::clamp<int>(static_cast<int>((At1_b*yy - At2_b*xy)*frb+0.5f),0,31);
-
-         e[1].clear();
-         e[1][0] = (uint8)math::clamp<int>(static_cast<int>((At2_r*xx - At1_r*xy)*frb+0.5f),0,31);
-         e[1][1] = (uint8)math::clamp<int>(static_cast<int>((At2_g*xx - At1_g*xy)*fg +0.5f),0,63);
-         e[1][2] = (uint8)math::clamp<int>(static_cast<int>((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++)
-            {
-               for (int gr = -1; gr <= 1; gr++)
-               {
-                  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<int>(c[i][0] + rr, 0, 31);
-                     c[i][1] = (uint8)math::clamp<int>(c[i][1] + gr, 0, 63);
-                     c[i][2] = (uint8)math::clamp<int>(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
-      {
-         // Try even harder to explore the local lattice neighbors of the least squares optimized result.
-         color_quad_u8 e[2];
-         e[0].clear();
-         e[0][0] = (uint8)math::clamp<int>(static_cast<int>((At1_r*yy - At2_r*xy)*frb+0.5f),0,31);
-         e[0][1] = (uint8)math::clamp<int>(static_cast<int>((At1_g*yy - At2_g*xy)*fg +0.5f),0,63);
-         e[0][2] = (uint8)math::clamp<int>(static_cast<int>((At1_b*yy - At2_b*xy)*frb+0.5f),0,31);
-
-         e[1].clear();
-         e[1][0] = (uint8)math::clamp<int>(static_cast<int>((At2_r*xx - At1_r*xy)*frb+0.5f),0,31);
-         e[1][1] = (uint8)math::clamp<int>(static_cast<int>((At2_g*xx - At1_g*xy)*fg +0.5f),0,63);
-         e[1][2] = (uint8)math::clamp<int>(static_cast<int>((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++)
-            {
-               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<int>(c[0][0] + orr, 0, 31);
-                  c[0][1] = (uint8)math::clamp<int>(c[0][1] + ogr, 0, 63);
-                  c[0][2] = (uint8)math::clamp<int>(c[0][2] + obr, 0, 31);
-
-                  for (int rr = -1; rr <= 1; rr++)
-                  {
-                     for (int gr = -1; gr <= 1; gr++)
-                     {
-                        for (int br = -1; br <= 1; br++)
-                        {
-                           c[1][0] = (uint8)math::clamp<int>(c[1][0] + rr, 0, 31);
-                           c[1][1] = (uint8)math::clamp<int>(c[1][1] + gr, 0, 63);
-                           c[1][2] = (uint8)math::clamp<int>(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();
-
-                           improved |= evaluate_solution(nc, true, &m_best_solution, false);
-                        }
-                     }
-                  }
-               }
-            }
-         }
-      }
-
-      return improved;
-   }
-
-   //-----------------------------------------------------------------------------------------------------------------------------------------
-
-   // Primary endpoint optimization entrypoint.
-   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;
-      const int16* pProbe_table = g_uber_probe_table;
-      uint probe_range;
-      float dist_per_trial = .015625f;
-
-      // How many probes, and the distance between each probe depends on the quality level.
-      switch (m_pParams->m_quality)
-      {
-         case cCRNDXTQualitySuperFast:
-            pProbe_table = g_fast_probe_table;
-            probe_range = cFastProbeTableSize;
-            dist_per_trial = .027063293f;
-            num_passes = 1;
-            break;
-         case cCRNDXTQualityFast:
-            pProbe_table = g_fast_probe_table;
-            probe_range = cFastProbeTableSize;
-            dist_per_trial = .027063293f;
-            num_passes = 2;
-            break;
-         case cCRNDXTQualityNormal:
-            pProbe_table = g_normal_probe_table;
-            probe_range = cNormalProbeTableSize;
-            dist_per_trial = .027063293f;
-            num_passes = 2;
-            break;
-         case cCRNDXTQualityBetter:
-            pProbe_table = g_better_probe_table;
-            probe_range = cBetterProbeTableSize;
-            num_passes = 2;
-            break;
-         default:
-            pProbe_table = g_uber_probe_table;
-            probe_range = cUberProbeTableSize;
-            num_passes = 4;
-            break;
-      }
-
-      m_solutions_tried.reset();
-
-      if (m_pParams->m_endpoint_caching)
-      {
-         // Try the previous X winning endpoints. This may not give us optimal results, but it may increase the probability of early outs while evaluating potential solutions.
-         const uint num_prev_results = math::minimum<uint>(cMaxPrevResults, m_num_prev_results);
-         for (uint i = 0; i < num_prev_results; i++)
-         {
-            const dxt1_solution_coordinates& coords = m_prev_results[i];
-
-            solution_hash_map::insert_result solution_res(m_solutions_tried.insert(coords.m_low_color | (coords.m_high_color << 16U)));
-            if (!solution_res.second)
-               continue;
-
-            evaluate_solution(coords, true, &m_best_solution);
-         }
-
-         if (!m_best_solution.m_error)
-         {
-            // Got lucky - one of the previous endpoints is optimal.
-            return_solution(*m_pResults, m_best_solution);
-            return true;
-         }
-      }
-
-      if (m_pParams->m_quality >= cCRNDXTQualityBetter)
-      {
-         //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;
-      //initial_ofs[2] += .5f;
-
-      low_color[0] = math::clamp(low_color[0] * 31.0f, 0.0f, 31.0f);
-      low_color[1] = math::clamp(low_color[1] * 63.0f, 0.0f, 63.0f);
-      low_color[2] = math::clamp(low_color[2] * 31.0f, 0.0f, 31.0f);
-
-      high_color[0] = math::clamp(high_color[0] * 31.0f, 0.0f, 31.0f);
-      high_color[1] = math::clamp(high_color[1] * 63.0f, 0.0f, 63.0f);
-      high_color[2] = math::clamp(high_color[2] * 31.0f, 0.0f, 31.0f);
-
-      for (uint pass = 0; pass < num_passes; pass++)
-      {
-         // Now separately sweep or probe the low and high colors along the principle axis, both positively and negatively.
-         // This results in two arrays of candidate low/high endpoints. Every unique combination of candidate endpoints is tried as a potential solution.
-         // In higher quality modes, the various nearby lattice neighbors of each candidate endpoint are also explored, which allows the current solution to "wobble" or "migrate"
-         // to areas with lower error.
-         // This entire process can be repeated up to X times (depending on the quality level) until a local minimum is established.
-         // This method is very stable and scalable. It could be implemented more elegantly, but I'm now very cautious of touching this code.
-         if (pass)
-         {
-            low_color = unpack_to_vec3F_raw(m_best_solution.m_coords.m_low_color);
-            high_color = unpack_to_vec3F_raw(m_best_solution.m_coords.m_high_color);
-         }
-
-         const uint64 prev_best_error = m_best_solution.m_error;
-         if (!prev_best_error)
-            break;
-
-         // Sweep low endpoint along principle axis, record positions
-         int prev_packed_color[2] = { -1, -1 };
-         uint num_low_trials = 0;
-         vec3F initial_probe_low_color(low_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_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);
-
-               int packed_color = b | (g << 5U) | (r << 11U);
-               if (packed_color != prev_packed_color[s])
-               {
-                  probe_low[num_low_trials++] = packed_color;
-                  prev_packed_color[s] = packed_color;
-               }
-            }
-         }
-
-         prev_packed_color[0] = -1;
-         prev_packed_color[1] = -1;
-
-         // Sweep high endpoint along principle axis, record positions
-         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);
-
-               int packed_color = b | (g << 5U) | (r << 11U);
-               if (packed_color != prev_packed_color[s])
-               {
-                  probe_high[num_high_trials++] = packed_color;
-                  prev_packed_color[s] = packed_color;
-               }
-            }
-         }
-
-         // Now try all unique combinations.
-         for (uint i = 0; i < num_low_trials; i++)
-         {
-            for (uint j = 0; j < num_high_trials; j++)
-            {
-               dxt1_solution_coordinates coords((uint16)probe_low[i], (uint16)probe_high[j]);
-               coords.canonicalize();
-
-               solution_hash_map::insert_result solution_res(m_solutions_tried.insert(coords.m_low_color | (coords.m_high_color << 16U)));
-               if (!solution_res.second)
-                  continue;
-
-               evaluate_solution(coords, true, &m_best_solution);
-            }
-         }
-
-         if (m_pParams->m_quality >= cCRNDXTQualityNormal)
-         {
-            // Generate new candidates by exploring the low color's direct lattice neighbors
-            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;
-
-               int g = lc.g + g_adjacency[i].y;
-               if ((g < 0) || (g > 63)) continue;
-
-               int b = lc.b + g_adjacency[i].z;
-               if ((b < 0) || (b > 31)) continue;
-
-               dxt1_solution_coordinates coords(dxt1_block::pack_color(r, g, b, false), m_best_solution.m_coords.m_high_color);
-               coords.canonicalize();
-
-               solution_hash_map::insert_result solution_res(m_solutions_tried.insert(coords.m_low_color | (coords.m_high_color << 16U)));
-               if (solution_res.second)
-                  evaluate_solution(coords, true, &m_best_solution);
-            }
-
-            if (m_pParams->m_quality == cCRNDXTQualityUber)
-            {
-               // Generate new candidates by exploring the low color's direct lattice neighbors - this time, explore much further separately on each axis.
-               lc = dxt1_block::unpack_color(m_best_solution.m_coords.m_low_color, false);
-
-               for (int a = 0; a < 3; a++)
-               {
-                  int limit = (a == 1) ? 63 : 31;
-
-                  for (int s = -2; s <= 2; s += 4)
-                  {
-                     color_quad_u8 c(lc);
-                     int q = c[a] + s;
-                     if ((q < 0) || (q > limit)) continue;
-
-                     c[a] = (uint8)q;
-
-                     dxt1_solution_coordinates coords(dxt1_block::pack_color(c, false), m_best_solution.m_coords.m_high_color);
-                     coords.canonicalize();
-
-                     solution_hash_map::insert_result solution_res(m_solutions_tried.insert(coords.m_low_color | (coords.m_high_color << 16U)));
-                     if (solution_res.second)
-                        evaluate_solution(coords, true, &m_best_solution);
-                  }
-               }
-            }
-
-            // Generate new candidates by exploring the high color's direct lattice neighbors
-            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;
-
-               int g = hc.g + g_adjacency[i].y;
-               if ((g < 0) || (g > 63)) continue;
-
-               int b = hc.b + g_adjacency[i].z;
-               if ((b < 0) || (b > 31)) continue;
-
-               dxt1_solution_coordinates coords(m_best_solution.m_coords.m_low_color, dxt1_block::pack_color(r, g, b, false));
-               coords.canonicalize();
-
-               solution_hash_map::insert_result solution_res(m_solutions_tried.insert(coords.m_low_color | (coords.m_high_color << 16U)));
-               if (solution_res.second)
-                  evaluate_solution(coords, true, &m_best_solution);
-            }
-
-            if (m_pParams->m_quality == cCRNDXTQualityUber)
-            {
-               // Generate new candidates by exploring the high color's direct lattice neighbors - this time, explore much further separately on each axis.
-               hc = dxt1_block::unpack_color(m_best_solution.m_coords.m_high_color, false);
-
-               for (int a = 0; a < 3; a++)
-               {
-                  int limit = (a == 1) ? 63 : 31;
-
-                  for (int s = -2; s <= 2; s += 4)
-                  {
-                     color_quad_u8 c(hc);
-                     int q = c[a] + s;
-                     if ((q < 0) || (q > limit)) continue;
-
-                     c[a] = (uint8)q;
-
-                     dxt1_solution_coordinates coords(m_best_solution.m_coords.m_low_color, dxt1_block::pack_color(c, false));
-                     coords.canonicalize();
-
-                     solution_hash_map::insert_result solution_res(m_solutions_tried.insert(coords.m_low_color | (coords.m_high_color << 16U)));
-                     if (solution_res.second)
-                        evaluate_solution(coords, true, &m_best_solution);
-                  }
-               }
-            }
-         }
-
-         if ((!m_best_solution.m_error) || ((pass) && (m_best_solution.m_error == prev_best_error)))
-            break;
-
-         if (m_pParams->m_quality >= cCRNDXTQualityUber)
-         {
-            // Attempt to refine current solution's endpoints given the current selectors using least squares.
-            refine_solution(1);
-         }
-      }
-
-      if (m_pParams->m_quality >= cCRNDXTQualityNormal)
-      {
-         if ((m_best_solution.m_error) && (!m_pParams->m_pixels_have_alpha))
-         {
-            bool choose_solid_block = false;
-            if (m_best_solution.are_selectors_all_equal())
-            {
-               // All selectors equal - try various solid-block optimizations
-               choose_solid_block = try_average_block_as_solid();
-            }
-
-            if ((!choose_solid_block) && (m_pParams->m_quality == cCRNDXTQualityUber))
-            {
-               // Per-component 1D endpoint optimization.
-               optimize_endpoint_comps();
-            }
-         }
-
-         if (m_pParams->m_quality == cCRNDXTQualityUber)
-         {
-            if (m_best_solution.m_error)
-            {
-               // The pixels may have already been DXTc compressed by another compressor.
-               // It's usually possible to recover the endpoints used to previously pack the block.
-               try_combinatorial_encoding();
-            }
-         }
-      }
-
-      return_solution(*m_pResults, m_best_solution);
-
-      if (m_pParams->m_endpoint_caching)
-      {
-         // Remember result for later reruse.
-         m_prev_results[m_num_prev_results & (cMaxPrevResults - 1)] = m_best_solution.m_coords;
-         m_num_prev_results++;
-      }
-
-      return true;
-   }
-
-   static inline int mul_8bit(int a, int b)
-   {
-      int t = a * b + 128;
-      return (t + (t >> 8)) >> 8;
-   }
-
-   bool dxt1_endpoint_optimizer::handle_multicolor_block()
-   {
-      uint num_passes = 1;
-      vec3F perceptual_weights(1.0f);
-
-      if (m_perceptual)
-      {
-         // Compute RGB weighting for use in perceptual mode.
-         // The more saturated the block, the more the weights deviate from (1,1,1).
-         float ave_redness = 0;
-         float ave_blueness = 0;
-         float ave_l = 0;
-
-         for (uint i = 0; i < m_unique_colors.size(); i++)
-         {
-            const color_quad_u8& c = m_unique_colors[i].m_color;
-            const float weight = (float)m_unique_colors[i].m_weight;
-
-            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<float>(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
-         {
-            num_passes = 2;
-            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
-         matrix44F m(matrix44F::make_scale_matrix(perceptual_weights[0], perceptual_weights[1], perceptual_weights[2]));
-         matrix44F im(m.get_inverse());
-         im.transpose_in_place();
-         m_principle_axis = m_principle_axis * im;
-#else
-         // Purposely scale the components of the principle axis by the perceptual weighting.
-         // There's probably a cleaner way to go about this, but it works (more competitive in perceptual mode against nvdxt.exe or ATI_Compress).
-         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();
-
-         if (num_passes > 1)
-         {
-            // Check for obviously wild principle axes and try to compensate by backing off the component weightings.
-            if (fabs(m_principle_axis[0]) >= .795f)
-               perceptual_weights.set(.424f, .6f, .072f);
-            else if (fabs(m_principle_axis[2]) >= .795f)
-               perceptual_weights.set(.212f, .6f, .212f);
-            else
-               break;
-         }
-      }
-
-      // Find bounds of projection onto (potentially skewed) principle axis.
-      float l = 1e+9;
-      float h = -1e+9;
-
-      for (uint i = 0; i < m_norm_unique_colors.size(); i++)
-      {
-         float d = m_norm_unique_colors[i] * m_principle_axis;
-         l = math::minimum(l, d);
-         h = math::maximum(h, d);
-      }
-
-      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))
-      {
-         // Low color is outside the lattice, so bring it back in by casting a ray.
-         vec3F coord;
-         float t;
-         aabb3F bounds(vec3F(0.0f), vec3F(1.0f));
-         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))
-      {
-         // High color is outside the lattice, so bring it back in by casting a ray.
-         vec3F coord;
-         float t;
-         aabb3F bounds(vec3F(0.0f), vec3F(1.0f));
-         intersection::result res = intersection::ray_aabb(coord, t, ray3F(high_color, -m_principle_axis), bounds);
-         if (res == intersection::cSuccess)
-            high_color = coord;
-      }
-
-      // Now optimize the endpoints using the projection bounds on the (potentially skewed) principle axis as a starting point.
-      if (!optimize_endpoints(low_color, high_color))
-         return false;
-
-      return true;
-   }
-
-   bool dxt1_endpoint_optimizer::handle_grayscale_block()
-   {
-      // TODO
-      return true;
-   }
-
-   // Tries quantizing the block to 4 colors using vanilla LBG. It tries all combinations of the quantized results as potential endpoints.
-   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++)
-            means[i] = m_norm_unique_colors[math::minimum<int>(m_norm_unique_colors.size() - 1, i)];
-      }
-      else
-      {
-         means[0] = low_color - m_mean_norm_color;
-         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++)
-         {
-            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++)
-            {
-               const vec3F& v = m_norm_unique_colors[i];
-
-               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);
-                  if (dist < best_dist)
-                  {
-                     best_dist = dist;
-                     best_index = j;
-                  }
-               }
-
-               total_dist += best_dist;
-
-               new_means[best_index] += v * (float)m_unique_colors[i].m_weight;
-               new_weights[best_index] += (float)m_unique_colors[i].m_weight;
-            }
-
-            uint highest_index = 0;
-            float highest_weight = 0;
-            bool empty_cell = false;
-            for (uint j = 0; j < 4; j++)
-            {
-               if (new_weights[j] > 0.0f)
-               {
-                  means[j] = new_means[j] / new_weights[j];
-                  if (new_weights[j] > highest_weight)
-                  {
-                     highest_weight = new_weights[j];
-                     highest_index = j;
-                  }
-               }
-               else
-                  empty_cell = true;
-            }
-
-            if (!empty_cell)
-            {
-               if (fabs(total_dist - prev_total_dist) < .00001f)
-                  break;
-
-               prev_total_dist = total_dist;
-            }
-            else
-               prev_total_dist = math::cNearlyInfinite;
-
-            if ((empty_cell) && (iter != (cMaxIters - 1)))
-            {
-               const uint ri = (highest_index + reassign_rover) & 3;
-               reassign_rover++;
-
-               for (uint j = 0; j < 4; j++)
-               {
-                  if (new_weights[j] == 0.0f)
-                  {
-                     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++)
-         {
-            const vec3F v0(means[i] + m_mean_norm_color);
-            const vec3F v1(means[j] + m_mean_norm_color);
-
-            dxt1_solution_coordinates sc(
-               color_quad_u8((int)floor(.5f + v0[0] * 31.0f), (int)floor(.5f + v0[1] * 63.0f), (int)floor(.5f + v0[2] * 31.0f), 255),
-               color_quad_u8((int)floor(.5f + v1[0] * 31.0f), (int)floor(.5f + v1[1] * 63.0f), (int)floor(.5f + v1[2] * 31.0f), 255), false );
-
-            sc.canonicalize();
-
-            improved |= evaluate_solution(sc, true, &m_best_solution, false);
-         }
-      }
-
-      improved |= refine_solution((m_pParams->m_quality == cCRNDXTQualityUber) ? 1 : 0);
-
-      return improved;
-   }
-
-   // Given candidate low/high endpoints, find the optimal selectors for 3 and 4 color blocks, compute the resulting error,
-   // and use the candidate if it results in less error than the best found result so far.
-   bool dxt1_endpoint_optimizer::evaluate_solution(
-      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)
-            return evaluate_solution_uber(m_trial_solution, coords, early_out, pBest_solution, alternate_rounding);
-         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);
-
-      // Caller has requested all considered candidate solutions for later analysis.
-      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)
-   {
-      if (perceptual)
-      {
-         return color::color_distance(true, e1, e2, alpha);
-      }
-      else if (m_pParams->m_grayscale_sampling)
-      {
-         // Computes error assuming shader will be converting the result to grayscale.
-         int y0 = color::RGB_to_Y(e1);
-         int y1 = color::RGB_to_Y(e2);
-         int yd = y0  - y1;
-         if (alpha)
-         {
-            int da = (int)e1[3] - (int)e2[3];
-            return yd * yd + da * da;
-         }
-         else
-         {
-            return yd * yd;
-         }
-      }
-      else if (m_has_color_weighting)
-      {
-         // Compute error using user provided color component weights.
-         int dr = (int)e1[0] - (int)e2[0];
-         int dg = (int)e1[1] - (int)e2[1];
-         int db = (int)e1[2] - (int)e2[2];
-
-         dr = (dr * dr) * m_pParams->m_color_weights[0];
-         dg = (dg * dg) * m_pParams->m_color_weights[1];
-         db = (db * db) * m_pParams->m_color_weights[2];
-
-         if (alpha)
-         {
-            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;
-         }
-         else
-         {
-            return dr + dg + db;
-         }
-      }
-      else
-      {
-         return color::color_distance(false, e1, e2, alpha);
-      }
-   }
-
-   bool dxt1_endpoint_optimizer::evaluate_solution_uber(
-      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 = cUINT64_MAX;
-
-      solution.m_alpha_block = false;
-      solution.m_valid = false;
-
-      uint first_block_type = 0;
-      uint last_block_type = 1;
-
-      if ((m_pParams->m_pixels_have_alpha) || (m_pParams->m_force_alpha_blocks))
-         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);
-
-      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--)
-               {
-                  const color_quad_u8& c = m_unique_colors[unique_color_index].m_color;
-
-                  uint best_error = color_distance(true, c, colors[0], false);
-                  uint best_color_index = 0;
-
-                  uint err = color_distance(true, c, colors[1], false);
-                  if (err < best_error) { best_error = err; best_color_index = 1; }
-
-                  err = color_distance(true, c, colors[2], false);
-                  if (err < best_error) { best_error = err; best_color_index = 2; }
-
-                  err = color_distance(true, c, colors[3], false);
-                  if (err < best_error) { best_error = err; best_color_index = 3; }
-
-                  trial_error += best_error * static_cast<uint64>(m_unique_colors[unique_color_index].m_weight);
-                  if (trial_error >= solution.m_error)
-                     break;
-
-                  m_trial_selectors[unique_color_index] = static_cast<uint8>(best_color_index);
-               }
-            }
-            else
-            {
-               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 * static_cast<uint64>(m_unique_colors[unique_color_index].m_weight);
-                  if (trial_error >= solution.m_error)
-                     break;
-
-                  m_trial_selectors[unique_color_index] = static_cast<uint8>(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--)
-               {
-                  const color_quad_u8& c = m_unique_colors[unique_color_index].m_color;
-
-                  uint best_error = color_distance(true, c, colors[0], false);
-                  uint best_color_index = 0;
-
-                  uint err = color_distance(true, c, colors[1], false);
-                  if (err < best_error) { best_error = err; best_color_index = 1; }
-
-                  err = color_distance(true, c, colors[2], false);
-                  if (err < best_error) { best_error = err; best_color_index = 2; }
-
-                  trial_error += best_error * static_cast<uint64>(m_unique_colors[unique_color_index].m_weight);
-                  if (trial_error >= solution.m_error)
-                     break;
-
-                  m_trial_selectors[unique_color_index] = static_cast<uint8>(best_color_index);
-               }
-            }
-            else
-            {
-               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; }
-
-                  trial_error += best_error * static_cast<uint64>(m_unique_colors[unique_color_index].m_weight);
-                  if (trial_error >= solution.m_error)
-                     break;
-
-                  m_trial_selectors[unique_color_index] = static_cast<uint8>(best_color_index);
-               }
-            }
-         }
-
-         if (trial_error < solution.m_error)
-         {
-            solution.m_error = trial_error;
-            solution.m_alpha_block = (block_type != 0);
-            solution.m_selectors = m_trial_selectors;
-            solution.m_valid = true;
-         }
-      }
-
-      if ((!solution.m_alpha_block) && (solution.m_coords.m_low_color == solution.m_coords.m_high_color))
-      {
-         uint s;
-         if ((solution.m_coords.m_low_color & 31) != 31)
-         {
-            solution.m_coords.m_low_color++;
-            s = 1;
-         }
-         else
-         {
-            solution.m_coords.m_high_color--;
-            s = 0;
-         }
-
-         for (uint i = 0; i < m_unique_colors.size(); i++)
-            solution.m_selectors[i] = static_cast<uint8>(s);
-      }
-
-      if ((pBest_solution) && (solution.m_error < pBest_solution->m_error))
-      {
-         *pBest_solution = solution;
-         return true;
-      }
-
-      return false;
-   }
-
-   bool dxt1_endpoint_optimizer::evaluate_solution_fast(
-      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 = cUINT64_MAX;
-
-      solution.m_alpha_block = false;
-      solution.m_valid = false;
-
-      uint first_block_type = 0;
-      uint last_block_type = 1;
-
-      if ((m_pParams->m_pixels_have_alpha) || (m_pParams->m_force_alpha_blocks))
-         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);
-
-      int vr = colors[1].r - colors[0].r;
-      int vg = colors[1].g - colors[0].g;
-      int vb = colors[1].b - colors[0].b;
-      if (m_perceptual)
-      {
-         vr *= 8;
-         vg *= 24;
-      }
-
-      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;
-
-         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, 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];
-            int c3Point = stops[2] + stops[0];
-
-            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;
-
-               int dot = c.r*dirr + c.g*dirg + c.b*dirb;
-
-               uint8 best_color_index;
-               if (dot < halfPoint)
-                  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 * static_cast<uint64>(m_unique_colors[unique_color_index].m_weight);
-               if (trial_error >= solution.m_error)
-                  break;
-
-               m_trial_selectors[unique_color_index] = static_cast<uint8>(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);
-
-            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;
-
-               int dot = c.r*dirr + c.g*dirg + c.b*dirb;
-
-               uint8 best_color_index;
-               if (dot < c02Point)
-                  best_color_index = 0;
-               else if (dot < c21Point)
-                  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 * static_cast<uint64>(m_unique_colors[unique_color_index].m_weight);
-               if (trial_error >= solution.m_error)
-                  break;
-
-               m_trial_selectors[unique_color_index] = static_cast<uint8>(best_color_index);
-            }
-         }
-
-         if (trial_error < solution.m_error)
-         {
-            solution.m_error = trial_error;
-            solution.m_alpha_block = (block_type != 0);
-            solution.m_selectors = m_trial_selectors;
-            solution.m_valid = true;
-         }
-      }
-
-      if ((!solution.m_alpha_block) && (solution.m_coords.m_low_color == solution.m_coords.m_high_color))
-      {
-         uint s;
-         if ((solution.m_coords.m_low_color & 31) != 31)
-         {
-            solution.m_coords.m_low_color++;
-            s = 1;
-         }
-         else
-         {
-            solution.m_coords.m_high_color--;
-            s = 0;
-         }
-
-         for (uint i = 0; i < m_unique_colors.size(); i++)
-            solution.m_selectors[i] = static_cast<uint8>(s);
-      }
-
-      if ((pBest_solution) && (solution.m_error < pBest_solution->m_error))
-      {
-         *pBest_solution = solution;
-         return true;
-      }
-
-      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<uint8>(math::clamp(math::float_to_int(r + math::lerp<float>(a[0], b[0], f)), 0, 255));
-      res[1] = static_cast<uint8>(math::clamp(math::float_to_int(r + math::lerp<float>(a[1], b[1], f)), 0, 255));
-      res[2] = static_cast<uint8>(math::clamp(math::float_to_int(r + math::lerp<float>(a[2], b[2], f)), 0, 255));
-      res[3] = 255;
-
-      return unique_color(res, 1);
-   }
-
-   // The block may have been already compressed using another DXTc compressor, such as squish, ATI_Compress, ryg_dxt, etc.
-   // Attempt to recover the endpoints used by that block compressor.
-   void dxt1_endpoint_optimizer::try_combinatorial_encoding()
-   {
-      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
-         // 0.0  1/3 2/3  1.0
-
-         for (uint k = 0; k < 2; k++)
-         {
-            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));
-
-               // 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)
-                  continue;
-
-               // 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);
-
-      for (uint i = 0; i < m_temp_unique_colors.size(); i++)
-      {
-         const color_quad_u8& unique_color = m_temp_unique_colors[i].m_color;
-         const uint16 packed_color = dxt1_block::pack_color(unique_color, true);
-
-         if (std::find(m_unique_packed_colors.begin(), m_unique_packed_colors.end(), packed_color) != m_unique_packed_colors.end())
-            continue;
-
-         m_unique_packed_colors.push_back(packed_color);
-      }
-
-      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++)
-         {
-            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,
-                  (alt_rounding != 0));
-
-               if (m_trial_solution.m_error == 0)
-               {
-                  if (alt_rounding)
-                     m_best_solution = m_trial_solution;
-
-                  return;
-               }
-            }
-         }
-      }
-
-      return;
-   }
-
-   // The fourth (transparent) color in 3 color "transparent" blocks is black, which can be optionally exploited for small gains in DXT1 mode if the caller
-   // doesn't actually use alpha. (But not in DXT5 mode, because 3-color blocks aren't permitted by GPU's for DXT5.)
-   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);
-      crnlib::vector<color_quad_u8> 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<uint8> 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;
-
-      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)
-         {
-            CRNLIB_ASSERT(trial_selectors[i] == 3);
-         }
-         else
-         {
-            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;
-   }
-
-   bool dxt1_endpoint_optimizer::compute_internal(const params& p, results& r, solution_vec* pSolutions)
-   {
-      clear();
-
-      m_pParams = &p;
-      m_pResults = &r;
-      m_pSolutions = pSolutions;
-
-      m_has_color_weighting = (m_pParams->m_color_weights[0] != 1) || (m_pParams->m_color_weights[1] != 1) || (m_pParams->m_color_weights[2] != 1);
-      m_perceptual = m_pParams->m_perceptual && !m_has_color_weighting && !m_pParams->m_grayscale_sampling;
-
-      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
-      {
-         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)
-         return false;
-
-      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;
-   }
-
-   // Build array of unique colors and their weights.
-   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<const uint32*>(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;
-            continue;
-         }
-
-         if (m_all_pixels_grayscale)
-         {
-            uint r = c & 0xFF;
-            uint g = (c >> 8) & 0xFF;
-            uint b = (c >> 16) & 0xFF;
-            if ((r != g) || (r != b))
-               m_all_pixels_grayscale = false;
-         }
-
-         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);
-            m_unique_colors[num_unique_colors].m_weight = 1;
-            num_unique_colors++;
-         }
-         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;
-   }
-
-} // namespace crnlib

+ 0 - 352
Source/ThirdParty/crunch/crnlib/crn_dxt1.h

@@ -1,352 +0,0 @@
-// File: crn_dxt1.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dxt.h"
-
-namespace crnlib
-{
-   struct dxt1_solution_coordinates
-   {
-      inline dxt1_solution_coordinates() : m_low_color(0), m_high_color(0){ }
-
-      inline dxt1_solution_coordinates(uint16 l, uint16 h) : m_low_color(l), m_high_color(h) { }
-
-      inline dxt1_solution_coordinates(const color_quad_u8& l, const color_quad_u8& h, bool scaled = true) :
-         m_low_color(dxt1_block::pack_color(l, scaled)),
-         m_high_color(dxt1_block::pack_color(h, scaled))
-      {
-      }
-
-      inline dxt1_solution_coordinates(vec3F nl, vec3F nh)
-      {
-#if CRNLIB_DXT_ALT_ROUNDING
-         // Umm, wtf?
-         nl.clamp(0.0f, .999f);
-         nh.clamp(0.0f, .999f);
-         color_quad_u8 l( (int)floor(nl[0] * 32.0f), (int)floor(nl[1] * 64.0f), (int)floor(nl[2] * 32.0f), 255);
-         color_quad_u8 h( (int)floor(nh[0] * 32.0f), (int)floor(nh[1] * 64.0f), (int)floor(nh[2] * 32.0f), 255);
-#else
-         // Fixes the bins
-         color_quad_u8 l( (int)floor(.5f + nl[0] * 31.0f), (int)floor(.5f + nl[1] * 63.0f), (int)floor(.5f + nl[2] * 31.0f), 255);
-         color_quad_u8 h( (int)floor(.5f + nh[0] * 31.0f), (int)floor(.5f + nh[1] * 63.0f), (int)floor(.5f + nh[2] * 31.0f), 255);
-#endif
-
-         m_low_color = dxt1_block::pack_color(l, false);
-         m_high_color = dxt1_block::pack_color(h, false);
-      }
-
-      uint16 m_low_color;
-      uint16 m_high_color;
-
-      inline void clear()
-      {
-         m_low_color = 0;
-         m_high_color = 0;
-      }
-
-      inline dxt1_solution_coordinates& canonicalize()
-      {
-         if (m_low_color < m_high_color)
-            utils::swap(m_low_color, m_high_color);
-         return *this;
-      }
-
-      inline operator size_t() const { return fast_hash(this, sizeof(*this)); }
-
-      inline bool operator== (const dxt1_solution_coordinates& other) const
-      {
-         uint16 l0 = math::minimum(m_low_color, m_high_color);
-         uint16 h0 = math::maximum(m_low_color, m_high_color);
-
-         uint16 l1 = math::minimum(other.m_low_color, other.m_high_color);
-         uint16 h1 = math::maximum(other.m_low_color, other.m_high_color);
-
-         return (l0 == l1) && (h0 == h1);
-      }
-
-      inline bool operator!= (const dxt1_solution_coordinates& other) const
-      {
-         return !(*this == other);
-      }
-
-      inline bool operator< (const dxt1_solution_coordinates& other) const
-      {
-         uint16 l0 = math::minimum(m_low_color, m_high_color);
-         uint16 h0 = math::maximum(m_low_color, m_high_color);
-
-         uint16 l1 = math::minimum(other.m_low_color, other.m_high_color);
-         uint16 h1 = math::maximum(other.m_low_color, other.m_high_color);
-
-         if (l0 < l1)
-            return true;
-         else if (l0 == l1)
-         {
-            if (h0 < h1)
-               return true;
-         }
-
-         return false;
-      }
-   };
-
-   typedef crnlib::vector<dxt1_solution_coordinates> dxt1_solution_coordinates_vec;
-
-   CRNLIB_DEFINE_BITWISE_COPYABLE(dxt1_solution_coordinates);
-
-   struct unique_color
-   {
-      inline unique_color() { }
-      inline unique_color(const color_quad_u8& color, uint weight) : m_color(color), m_weight(weight) { }
-
-      color_quad_u8  m_color;
-      uint           m_weight;
-
-      inline bool operator< (const unique_color& c) const
-      {
-         return *reinterpret_cast<const uint32*>(&m_color) < *reinterpret_cast<const uint32*>(&c.m_color);
-      }
-
-      inline bool operator== (const unique_color& c) const
-      {
-         return *reinterpret_cast<const uint32*>(&m_color) == *reinterpret_cast<const uint32*>(&c.m_color);
-      }
-   };
-
-   CRNLIB_DEFINE_BITWISE_COPYABLE(unique_color);
-
-   class dxt1_endpoint_optimizer
-   {
-   public:
-      dxt1_endpoint_optimizer();
-
-      struct params
-      {
-         params() :
-            m_block_index(0),
-            m_pPixels(NULL),
-            m_num_pixels(0),
-            m_dxt1a_alpha_threshold(128U),
-            m_quality(cCRNDXTQualityUber),
-            m_pixels_have_alpha(false),
-            m_use_alpha_blocks(true),
-            m_perceptual(true),
-            m_grayscale_sampling(false),
-            m_endpoint_caching(true),
-            m_use_transparent_indices_for_black(false),
-            m_force_alpha_blocks(false)
-         {
-            m_color_weights[0] = 1;
-            m_color_weights[1] = 1;
-            m_color_weights[2] = 1;
-         }
-
-         uint                 m_block_index;
-
-         const color_quad_u8* m_pPixels;
-         uint                 m_num_pixels;
-         uint                 m_dxt1a_alpha_threshold;
-
-         crn_dxt_quality      m_quality;
-
-         bool                 m_pixels_have_alpha;
-         bool                 m_use_alpha_blocks;
-         bool                 m_perceptual;
-         bool                 m_grayscale_sampling;
-         bool                 m_endpoint_caching;
-         bool                 m_use_transparent_indices_for_black;
-         bool                 m_force_alpha_blocks;
-         int                  m_color_weights[3];
-      };
-
-      struct results
-      {
-         inline results() : m_pSelectors(NULL) { }
-
-         uint64         m_error;
-
-         uint16         m_low_color;
-         uint16         m_high_color;
-
-         uint8*         m_pSelectors;
-         bool           m_alpha_block;
-      };
-
-      struct solution
-      {
-         solution() { }
-
-         solution(const solution& other)
-         {
-            m_results = other.m_results;
-            m_selectors = other.m_selectors;
-            m_results.m_pSelectors = m_selectors.begin();
-         }
-
-         solution& operator= (const solution& rhs)
-         {
-            if (this == &rhs)
-               return *this;
-
-            m_results = rhs.m_results;
-            m_selectors = rhs.m_selectors;
-            m_results.m_pSelectors = m_selectors.begin();
-
-            return *this;
-         }
-
-         results              m_results;
-         crnlib::vector<uint8> m_selectors;
-
-         inline bool operator< (const solution& other) const
-         {
-            return m_results.m_error < other.m_results.m_error;
-         }
-         static inline bool coords_equal(const solution& lhs, const solution& rhs)
-         {
-            return (lhs.m_results.m_low_color == rhs.m_results.m_low_color) && (lhs.m_results.m_high_color == rhs.m_results.m_high_color);
-         }
-      };
-      typedef crnlib::vector<solution> solution_vec;
-
-      bool compute(const params& p, results& r, solution_vec* pSolutions = NULL);
-
-   private:
-      const params*     m_pParams;
-      results*          m_pResults;
-      solution_vec*     m_pSolutions;
-
-      bool              m_perceptual;
-      bool              m_has_color_weighting;
-
-      typedef crnlib::vector<unique_color> unique_color_vec;
-
-      //typedef crnlib::hash_map<uint32, uint32, bit_hasher<uint32> > unique_color_hash_map;
-      typedef crnlib::hash_map<uint32, uint32> unique_color_hash_map;
-      unique_color_hash_map m_unique_color_hash_map;
-
-      unique_color_vec  m_unique_colors;                 // excludes transparent colors!
-      unique_color_vec  m_temp_unique_colors;
-
-      uint              m_total_unique_color_weight;
-
-      bool              m_has_transparent_pixels;
-
-      vec3F_array       m_norm_unique_colors;
-      vec3F             m_mean_norm_color;
-
-      vec3F_array       m_norm_unique_colors_weighted;
-      vec3F             m_mean_norm_color_weighted;
-
-      vec3F             m_principle_axis;
-
-      bool              m_all_pixels_grayscale;
-
-      crnlib::vector<uint16> m_unique_packed_colors;
-      crnlib::vector<uint8> m_trial_selectors;
-
-      crnlib::vector<vec3F> m_low_coords;
-      crnlib::vector<vec3F> m_high_coords;
-
-      enum { cMaxPrevResults = 4 };
-      dxt1_solution_coordinates m_prev_results[cMaxPrevResults];
-      uint m_num_prev_results;
-
-      crnlib::vector<vec3I> m_lo_cells;
-      crnlib::vector<vec3I> m_hi_cells;
-
-      uint m_total_evals;
-
-      struct potential_solution
-      {
-         potential_solution() : m_coords(), m_error(cUINT64_MAX), m_alpha_block(false), m_valid(false)
-         {
-         }
-
-         dxt1_solution_coordinates  m_coords;
-         crnlib::vector<uint8>      m_selectors;
-         uint64                     m_error;
-         bool                       m_alpha_block;
-         bool                       m_valid;
-
-         void clear()
-         {
-            m_coords.clear();
-            m_selectors.resize(0);
-            m_error = cUINT64_MAX;
-            m_alpha_block = false;
-            m_valid = false;
-         }
-
-         bool are_selectors_all_equal() const
-         {
-            if (m_selectors.empty())
-               return false;
-            const uint s = m_selectors[0];
-            for (uint i = 1; i < m_selectors.size(); i++)
-               if (m_selectors[i] != s)
-                  return false;
-            return true;
-         }
-      };
-
-      potential_solution m_trial_solution;
-      potential_solution m_best_solution;
-
-      typedef crnlib::hash_map<uint, empty_type> solution_hash_map;
-      solution_hash_map m_solutions_tried;
-      
-      bool refine_solution(int refinement_level = 0);
-
-      bool evaluate_solution(
-         const dxt1_solution_coordinates& coords,
-         bool early_out,
-         potential_solution* pBest_solution,
-         bool alternate_rounding = false);
-
-      bool evaluate_solution_uber(
-         potential_solution& solution,
-         const dxt1_solution_coordinates& coords,
-         bool early_out,
-         potential_solution* pBest_solution,
-         bool alternate_rounding = false);
-
-      bool evaluate_solution_fast(
-         potential_solution& solution,
-         const dxt1_solution_coordinates& coords,
-         bool early_out,
-         potential_solution* pBest_solution,
-         bool alternate_rounding = false);
-
-      void clear();
-      void find_unique_colors();
-      bool handle_all_transparent_block();
-      bool handle_solid_block();
-      bool handle_multicolor_block();
-      bool handle_grayscale_block();
-      void compute_pca(vec3F& axis, const vec3F_array& norm_colors, const vec3F& def);
-      void compute_vectors(const vec3F& perceptual_weights);
-      void return_solution(results& results, const potential_solution& solution);
-      void try_combinatorial_encoding();
-      void optimize_endpoint_comps();
-      bool optimize_endpoints(vec3F& low_color, vec3F& high_color);
-      bool try_alpha_as_black_optimization();
-      bool try_average_block_as_solid();
-      bool try_median4(const vec3F& low_color, const vec3F& high_color);
-
-      bool compute_internal(const params& p, results& r, solution_vec* pSolutions);
-      
-      unique_color lerp_color(const color_quad_u8& a, const color_quad_u8& b, float f, int rounding = 1);
-
-      inline uint color_distance(bool perceptual, const color_quad_u8& e1, const color_quad_u8& e2, bool alpha);
-
-      static inline vec3F unpack_to_vec3F_raw(uint16 packed_color);
-      static inline vec3F unpack_to_vec3F(uint16 packed_color);
-   };
-
-   inline void swap(dxt1_endpoint_optimizer::solution& a, dxt1_endpoint_optimizer::solution& b)
-   {
-      std::swap(a.m_results, b.m_results);
-      a.m_selectors.swap(b.m_selectors);
-   }
-
-} // namespace crnlib

+ 0 - 209
Source/ThirdParty/crunch/crnlib/crn_dxt5a.cpp

@@ -1,209 +0,0 @@
-// File: crn_dxt5a.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_dxt5a.h"
-#include "crn_ryg_dxt.hpp"
-#include "crn_dxt_fast.h"
-#include "crn_intersect.h"
-
-namespace crnlib
-{
-   dxt5_endpoint_optimizer::dxt5_endpoint_optimizer() :  
-      m_pParams(NULL),
-      m_pResults(NULL)
-   {
-      m_unique_values.reserve(16);
-      m_unique_value_weights.reserve(16);
-   }
-
-   bool dxt5_endpoint_optimizer::compute(const params& p, results& r)
-   {
-      m_pParams = &p;
-      m_pResults = &r;
-
-      if ((!p.m_num_pixels) || (!p.m_pPixels))
-         return false;
-
-      m_unique_values.resize(0);
-      m_unique_value_weights.resize(0);
-
-      for (uint i = 0; i < 256; i++)
-         m_unique_value_map[i] = -1;
-
-      for (uint i = 0; i < p.m_num_pixels; i++)
-      {
-         uint alpha = p.m_pPixels[i][p.m_comp_index];
-
-         int index = m_unique_value_map[alpha];
-
-         if (index == -1)
-         {
-            index = m_unique_values.size();
-
-            m_unique_value_map[alpha] = index;
-
-            m_unique_values.push_back(static_cast<uint8>(alpha));
-            m_unique_value_weights.push_back(0);
-         }
-
-         m_unique_value_weights[index]++;
-      }         
-
-      if (m_unique_values.size() == 1)
-      {
-         r.m_block_type = 0;
-         r.m_error = 0;
-         r.m_first_endpoint = m_unique_values[0];
-         r.m_second_endpoint = m_unique_values[0];
-         memset(r.m_pSelectors, 0, p.m_num_pixels);
-         return true;
-      }
-
-      m_trial_selectors.resize(m_unique_values.size());
-      m_best_selectors.resize(m_unique_values.size());
-
-      r.m_error = cUINT64_MAX;
-
-      for (uint i = 0; i < m_unique_values.size() - 1; i++)
-      {
-         const uint low_endpoint = m_unique_values[i];
-
-         for (uint j = i + 1; j < m_unique_values.size(); j++)
-         {
-            const uint high_endpoint = m_unique_values[j];
-
-            evaluate_solution(low_endpoint, high_endpoint);
-         }
-      }
-
-      if ((m_pParams->m_quality >= cCRNDXTQualityBetter) && (m_pResults->m_error))
-      {
-         m_flags.resize(256 * 256);
-         m_flags.clear_all_bits();
-
-         const int cProbeAmount = (m_pParams->m_quality == cCRNDXTQualityUber) ? 16 : 8;
-
-         for (int l_delta = -cProbeAmount; l_delta <= cProbeAmount; l_delta++)
-         {
-            const int l = m_pResults->m_first_endpoint + l_delta;
-            if (l < 0)
-               continue;
-            else if (l > 255)
-               break;
-
-            const uint bit_index = l * 256;
-
-            for (int h_delta = -cProbeAmount; h_delta <= cProbeAmount; h_delta++)
-            {
-               const int h = m_pResults->m_second_endpoint + h_delta;
-               if (h < 0)
-                  continue;
-               else if (h > 255)
-                  break;
-
-               //if (m_flags.get_bit(bit_index + h))
-               //   continue;
-               if ((m_flags.get_bit(bit_index + h)) || (m_flags.get_bit(h * 256 + l)))
-                  continue;
-               m_flags.set_bit(bit_index + h);
-
-               evaluate_solution(static_cast<uint>(l), static_cast<uint>(h));
-            }
-         }
-      }
-
-      if (m_pResults->m_first_endpoint == m_pResults->m_second_endpoint)
-      {
-         for (uint i = 0; i < m_best_selectors.size(); i++)
-            m_best_selectors[i] = 0;
-      }      
-      else if (m_pResults->m_block_type)
-      {
-         //if (l > h) 
-         //   eight alpha
-         // else 
-         //   six alpha
-
-         if (m_pResults->m_first_endpoint > m_pResults->m_second_endpoint)
-         {
-            utils::swap(m_pResults->m_first_endpoint, m_pResults->m_second_endpoint);
-            for (uint i = 0; i < m_best_selectors.size(); i++)
-               m_best_selectors[i] = g_six_alpha_invert_table[m_best_selectors[i]];
-         }
-      }
-      else if (!(m_pResults->m_first_endpoint > m_pResults->m_second_endpoint))
-      {
-         utils::swap(m_pResults->m_first_endpoint, m_pResults->m_second_endpoint);
-         for (uint i = 0; i < m_best_selectors.size(); i++)
-            m_best_selectors[i] = g_eight_alpha_invert_table[m_best_selectors[i]];
-      }
-
-      for (uint i = 0; i < m_pParams->m_num_pixels; i++)
-      {
-         uint alpha = m_pParams->m_pPixels[i][m_pParams->m_comp_index];
-
-         int index = m_unique_value_map[alpha];
-
-         m_pResults->m_pSelectors[i] = m_best_selectors[index];
-      }
-
-      return true;
-   }
-
-   void dxt5_endpoint_optimizer::evaluate_solution(uint low_endpoint, uint high_endpoint)
-   {
-      for (uint block_type = 0; block_type < (m_pParams->m_use_both_block_types ? 2U : 1U); block_type++)
-      {
-         uint selector_values[8];      
-
-         if (!block_type)
-            dxt5_block::get_block_values8(selector_values, low_endpoint, high_endpoint);
-         else
-            dxt5_block::get_block_values6(selector_values, low_endpoint, high_endpoint);
-
-         uint64 trial_error = 0;
-
-         for (uint i = 0; i < m_unique_values.size(); i++)
-         {
-            const uint val = m_unique_values[i];
-            const uint weight = m_unique_value_weights[i];
-
-            uint best_selector_error = UINT_MAX;
-            uint best_selector = 0;
-
-            for (uint j = 0; j < 8; j++)
-            {
-               int selector_error = val - selector_values[j];
-               selector_error = selector_error * selector_error * (int)weight;
-
-               if (static_cast<uint>(selector_error) < best_selector_error)
-               {
-                  best_selector_error = selector_error;
-                  best_selector = j;
-                  if (!best_selector_error)
-                     break;
-               }
-            }
-
-            m_trial_selectors[i] = static_cast<uint8>(best_selector);
-            trial_error += best_selector_error;
-
-            if (trial_error > m_pResults->m_error)
-               break;
-         }
-
-         if (trial_error < m_pResults->m_error)
-         {
-            m_pResults->m_error = trial_error;
-            m_pResults->m_first_endpoint = static_cast<uint8>(low_endpoint);
-            m_pResults->m_second_endpoint = static_cast<uint8>(high_endpoint);
-            m_pResults->m_block_type = static_cast<uint8>(block_type);
-            m_best_selectors.swap(m_trial_selectors);
-
-            if (!trial_error)
-               break;
-         }
-      }
-   }
-
-} // namespace crnlib

+ 0 - 66
Source/ThirdParty/crunch/crnlib/crn_dxt5a.h

@@ -1,66 +0,0 @@
-// File: crn_dxt5a.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dxt.h"
-
-namespace crnlib
-{
-   class dxt5_endpoint_optimizer
-   {
-   public:
-      dxt5_endpoint_optimizer();
-
-      struct params
-      {
-         params() :
-            m_block_index(0),
-            m_pPixels(NULL),
-            m_num_pixels(0),
-            m_comp_index(3),
-            m_quality(cCRNDXTQualityUber),
-            m_use_both_block_types(true)
-         {
-         }
-
-         uint                 m_block_index;
-
-         const color_quad_u8* m_pPixels;
-         uint                 m_num_pixels;
-         uint                 m_comp_index;
-
-         crn_dxt_quality      m_quality;
-
-         bool                 m_use_both_block_types;
-      };
-
-      struct results
-      {
-         uint8*   m_pSelectors;
-
-         uint64   m_error;
-
-         uint8    m_first_endpoint;
-         uint8    m_second_endpoint;
-
-         uint8    m_block_type; // 1 if 6-alpha, otherwise 8-alpha
-      };
-
-      bool compute(const params& p, results& r);
-
-   private:
-      const params*  m_pParams;
-      results*       m_pResults;
-
-      crnlib::vector<uint8> m_unique_values;
-      crnlib::vector<uint> m_unique_value_weights;
-
-      crnlib::vector<uint8> m_trial_selectors;
-      crnlib::vector<uint8> m_best_selectors;
-      int m_unique_value_map[256];
-
-      sparse_bit_array m_flags;
-
-      void evaluate_solution(uint low_endpoint, uint high_endpoint);
-   };
-
-} // namespace crnlib

+ 0 - 362
Source/ThirdParty/crunch/crnlib/crn_dxt_endpoint_refiner.cpp

@@ -1,362 +0,0 @@
-// File: crn_dxt_endpoint_refiner.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_dxt_endpoint_refiner.h"
-#include "crn_dxt1.h"
-
-namespace crnlib
-{
-   dxt_endpoint_refiner::dxt_endpoint_refiner() :
-      m_pParams(NULL),
-      m_pResults(NULL)
-   {
-   }
-
-   bool dxt_endpoint_refiner::refine(const params& p, results& r)
-   {
-      if (!p.m_num_pixels)
-         return false;
-
-      m_pParams = &p;
-      m_pResults = &r;
-
-      r.m_error = cUINT64_MAX;
-      r.m_low_color = 0;
-      r.m_high_color = 0;
-
-      double alpha2_sum = 0.0f;
-      double beta2_sum = 0.0f;
-      double alphabeta_sum = 0.0f;
-
-      vec<3, double> alphax_sum( 0.0f );
-      vec<3, double> betax_sum( 0.0f );
-
-      vec<3, double> first_color( 0.0f );
-
-      // This linear solver is from Squish.
-      for( uint i = 0; i < p.m_num_pixels; ++i )
-      {
-         uint8 c = p.m_pSelectors[i];
-
-         double k;
-         if (p.m_dxt1_selectors)
-            k = g_dxt1_to_linear[c] * 1.0f/3.0f;
-         else
-            k = g_dxt5_to_linear[c] * 1.0f/7.0f;
-
-         double alpha = 1.0f - k;
-         double beta = k;
-
-         vec<3, double> x;
-
-         if (p.m_dxt1_selectors)
-            x.set( p.m_pPixels[i][0] * 1.0f/255.0f, p.m_pPixels[i][1] * 1.0f/255.0f, p.m_pPixels[i][2] * 1.0f/255.0f );
-         else
-            x.set( p.m_pPixels[i][p.m_alpha_comp_index]/255.0f );
-
-         if (!i)
-            first_color = x;
-
-         alpha2_sum += alpha*alpha;
-         beta2_sum += beta*beta;
-         alphabeta_sum += alpha*beta;
-         alphax_sum += alpha*x;
-         betax_sum += beta*x;
-      }
-
-      // zero where non-determinate
-      vec<3, double> a, b;
-      if( beta2_sum == 0.0f )
-      {
-         a = alphax_sum / alpha2_sum;
-         b.clear();
-      }
-      else if( alpha2_sum == 0.0f )
-      {
-         a.clear();
-         b = betax_sum / beta2_sum;
-      }
-      else
-      {
-         double factor = alpha2_sum*beta2_sum - alphabeta_sum*alphabeta_sum;
-         if (factor != 0.0f)
-         {
-            a = ( alphax_sum*beta2_sum - betax_sum*alphabeta_sum ) / factor;
-            b = ( betax_sum*alpha2_sum - alphax_sum*alphabeta_sum ) / factor;
-         }
-         else
-         {
-            a = first_color;
-            b = first_color;
-         }
-      }
-
-      vec3F l(0.0f), h(0.0f);
-      l = a;
-      h = b;
-
-      l.clamp(0.0f, 1.0f);
-      h.clamp(0.0f, 1.0f);
-
-      if (p.m_dxt1_selectors)
-         optimize_dxt1(l, h);
-      else
-         optimize_dxt5(l, h);
-
-      //if (r.m_low_color < r.m_high_color)
-      //   utils::swap(r.m_low_color, r.m_high_color);
-
-      return r.m_error < p.m_error_to_beat;
-   }
-
-   void dxt_endpoint_refiner::optimize_dxt5(vec3F low_color, vec3F high_color)
-   {
-      float nl = low_color[0];
-      float nh = high_color[0];
-
-#if CRNLIB_DXT_ALT_ROUNDING
-      nl = math::clamp(nl, 0.0f, .999f);
-      nh = math::clamp(nh, 0.0f, .999f);
-      uint il = (int)floor(nl * 256.0f);
-      uint ih = (int)floor(nh * 256.0f);
-#else
-      uint il = (int)floor(.5f + math::clamp(nl, 0.0f, 1.0f) * 255.0f);
-      uint ih = (int)floor(.5f + math::clamp(nh, 0.0f, 1.0f) * 255.0f);
-#endif
-
-      crnlib::vector<uint> trial_solutions;
-      trial_solutions.reserve(256);
-      trial_solutions.push_back(il | (ih << 8));
-
-      sparse_bit_array flags;
-      flags.resize(256 * 256);
-
-      flags.set_bit((il * 256) + ih);
-
-      const int cProbeAmount = 11;
-
-      for (int l_delta = -cProbeAmount; l_delta <= cProbeAmount; l_delta++)
-      {
-         const int l = il + l_delta;
-         if (l < 0)
-            continue;
-         else if (l > 255)
-            break;
-
-         const uint bit_index = l * 256;
-
-         for (int h_delta = -cProbeAmount; h_delta <= cProbeAmount; h_delta++)
-         {
-            const int h = ih + h_delta;
-            if (h < 0)
-               continue;
-            else if (h > 255)
-               break;
-
-            if ((flags.get_bit(bit_index + h)) || (flags.get_bit(h * 256 + l)))
-               continue;
-
-            flags.set_bit(bit_index + h);
-
-            trial_solutions.push_back(l | (h << 8));
-         }
-      }
-
-      for (uint trial = 0; trial < trial_solutions.size(); trial++)
-      {
-         uint l = trial_solutions[trial] & 0xFF;
-         uint h = trial_solutions[trial] >> 8;
-
-         if (l == h)
-         {
-            if (h)
-               h--;
-            else
-               l++;
-         }
-         else if (l < h)
-         {
-            utils::swap(l, h);
-         }
-
-         CRNLIB_ASSERT(l > h);
-
-         uint values[cDXT5SelectorValues];
-         dxt5_block::get_block_values8(values, l, h);
-
-         uint total_error = 0;
-
-         for (uint j = 0; j < m_pParams->m_num_pixels; j++)
-         {
-            int p = m_pParams->m_pPixels[j][m_pParams->m_alpha_comp_index];
-            int c = values[m_pParams->m_pSelectors[j]];
-
-            int error = p - c;
-            error *= error;
-
-            total_error += error;
-
-            if (total_error > m_pResults->m_error)
-               break;
-         }
-
-         if (total_error < m_pResults->m_error)
-         {
-            m_pResults->m_error = total_error;
-            m_pResults->m_low_color = static_cast<uint16>(l);
-            m_pResults->m_high_color = static_cast<uint16>(h);
-
-            if (m_pResults->m_error == 0)
-               return;
-         }
-      }
-   }
-
-   void dxt_endpoint_refiner::optimize_dxt1(vec3F low_color, vec3F high_color)
-   {
-      uint selector_hist[4];
-      utils::zero_object(selector_hist);
-      for (uint i = 0; i < m_pParams->m_num_pixels; i++)
-         selector_hist[m_pParams->m_pSelectors[i]]++;
-
-      dxt1_solution_coordinates c(low_color, high_color);
-
-      for (uint pass = 0; pass < 8; pass++)
-      {
-         const uint64 initial_error = m_pResults->m_error;
-
-         dxt1_solution_coordinates_vec coords_to_try;
-
-         coords_to_try.resize(0);
-
-         color_quad_u8 lc(dxt1_block::unpack_color(c.m_low_color, false));
-         color_quad_u8 hc(dxt1_block::unpack_color(c.m_high_color, false));
-
-         for (int i = 0; i < 27; i++)
-         {
-            if (13 == i) continue;
-
-            const int ir = (i % 3) - 1;
-            const int ig = ((i / 3) % 3) - 1;
-            const int ib = ((i / 9) % 3) - 1;
-
-            int r = lc.r + ir;
-            int g = lc.g + ig;
-            int b = lc.b + ib;
-            if ((r < 0) || (r > 31)|| (g < 0) || (g > 63) || (b < 0) || (b > 31)) continue;
-
-            coords_to_try.push_back(
-               dxt1_solution_coordinates(dxt1_block::pack_color(r, g, b, false), c.m_high_color)
-               );
-         }
-
-         for (int i = 0; i < 27; i++)
-         {
-            if (13 == i) continue;
-
-            const int ir = (i % 3) - 1;
-            const int ig = ((i / 3) % 3) - 1;
-            const int ib = ((i / 9) % 3) - 1;
-
-            int r = hc.r + ir;
-            int g = hc.g + ig;
-            int b = hc.b + ib;
-            if ((r < 0) || (r > 31)|| (g < 0) || (g > 63) || (b < 0) || (b > 31)) continue;
-
-            coords_to_try.push_back(dxt1_solution_coordinates(c.m_low_color, dxt1_block::pack_color(r, g, b, false)));
-         }
-
-         std::sort(coords_to_try.begin(), coords_to_try.end());
-
-         dxt1_solution_coordinates_vec::const_iterator p_last = std::unique(coords_to_try.begin(), coords_to_try.end());
-         uint num_coords_to_try = (uint)(p_last - coords_to_try.begin());
-
-         for (uint i = 0; i < num_coords_to_try; i++)
-         {
-            color_quad_u8 block_colors[4];
-            uint16 l = coords_to_try[i].m_low_color;
-            uint16 h = coords_to_try[i].m_high_color;
-            if (l < h)
-               utils::swap(l, h);
-            else if (l == h)
-            {
-               color_quad_u8 lc(dxt1_block::unpack_color(l, false));
-               color_quad_u8 hc(dxt1_block::unpack_color(h, false));
-
-               bool retry = false;
-               if ((selector_hist[0] + selector_hist[2]) > (selector_hist[1] + selector_hist[3]))
-               {
-                  // l affects the output more than h, so muck with h
-                  if (hc[2] != 0)
-                     hc[2]--;
-                  else if (hc[0] != 0)
-                     hc[0]--;
-                  else if (hc[1] != 0)
-                     hc[1]--;
-                  else
-                     retry = true;
-               }
-               else
-               {
-                  // h affects the output more than l, so muck with l
-                  if (lc[2] != 31)
-                     lc[2]++;
-                  else if (lc[0] != 31)
-                     lc[0]++;
-                  else if (lc[1] != 63)
-                     lc[1]++;
-                  else
-                     retry = true;
-               }
-
-               if (retry)
-               {
-                  if (l == 0)
-                     l++;
-                  else
-                     h--;
-               }
-               else
-               {
-                  l = dxt1_block::pack_color(lc, false);
-                  h = dxt1_block::pack_color(hc, false);
-               }
-
-               CRNLIB_ASSERT(l > h);
-            }
-
-            dxt1_block::get_block_colors4(block_colors, l, h);
-
-            uint total_error = 0;
-
-            for (uint j = 0; j < m_pParams->m_num_pixels; j++)
-            {
-               const color_quad_u8& c = block_colors[m_pParams->m_pSelectors[j]];
-               total_error += color::color_distance(m_pParams->m_perceptual, c, m_pParams->m_pPixels[j], false);
-
-               if (total_error > m_pResults->m_error)
-                  break;
-            }
-
-            if (total_error < m_pResults->m_error)
-            {
-               m_pResults->m_error = total_error;
-               m_pResults->m_low_color = l;
-               m_pResults->m_high_color = h;
-               CRNLIB_ASSERT(l > h);
-               if (m_pResults->m_error == 0)
-                  return;
-            }
-         }
-
-         if (m_pResults->m_error == initial_error)
-            break;
-
-         c.m_low_color = m_pResults->m_low_color;
-         c.m_high_color = m_pResults->m_high_color;
-      }
-
-   }
-
-} // namespace crnlib
-

+ 0 - 62
Source/ThirdParty/crunch/crnlib/crn_dxt_endpoint_refiner.h

@@ -1,62 +0,0 @@
-// File: crn_dxt_endpoint_refiner.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dxt.h"
-
-namespace crnlib
-{
-   // TODO: Experimental/Not fully implemented
-   class dxt_endpoint_refiner
-   {
-   public:
-      dxt_endpoint_refiner();
-
-      struct params
-      {
-         params() :
-            m_block_index(0),
-            m_pPixels(NULL),
-            m_num_pixels(0),
-            m_pSelectors(NULL),
-            m_alpha_comp_index(0),
-            m_error_to_beat(cUINT64_MAX),
-            m_dxt1_selectors(true),
-            m_perceptual(true),
-            m_highest_quality(true)
-         {
-         }
-
-         uint                 m_block_index;
-
-         const color_quad_u8* m_pPixels;
-         uint                 m_num_pixels;
-
-         const uint8*         m_pSelectors;
-
-         uint                 m_alpha_comp_index;
-
-         uint64               m_error_to_beat;
-
-         bool                 m_dxt1_selectors;
-         bool                 m_perceptual;
-         bool                 m_highest_quality;
-      };
-
-      struct results
-      {
-         uint16   m_low_color;
-         uint16   m_high_color;
-         uint64   m_error;
-      };
-
-      bool refine(const params& p, results& r);
-
-   private:
-      const params* m_pParams;
-      results* m_pResults;
-
-      void optimize_dxt1(vec3F low_color, vec3F high_color);
-      void optimize_dxt5(vec3F low_color, vec3F high_color);
-   };
-
-} // namespace crnlib

+ 0 - 916
Source/ThirdParty/crunch/crnlib/crn_dxt_fast.cpp

@@ -1,916 +0,0 @@
-// File: crn_dxt_fast.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-// Parts of this module are derived from RYG's excellent public domain DXTx compressor.
-#include "crn_core.h"
-#include "crn_dxt_fast.h"
-#include "crn_ryg_dxt.hpp"
-
-namespace crnlib
-{
-   namespace dxt_fast
-   {
-      static inline int mul_8bit(int a, int b)
-      {
-         int t = a * b + 128;
-         return (t + (t >> 8)) >> 8;
-      }
-      
-      static inline color_quad_u8& unpack_color(color_quad_u8& c, uint v)
-      {
-         uint rv = (v & 0xf800) >> 11;
-         uint gv = (v & 0x07e0) >>  5;
-         uint bv = (v & 0x001f) >>  0;
-         
-         c.r = ryg_dxt::Expand5[rv];
-         c.g = ryg_dxt::Expand6[gv];
-         c.b = ryg_dxt::Expand5[bv];
-         c.a = 0;
-         
-         return c;
-      }
-      
-      static inline uint pack_color(const color_quad_u8& c)
-      {
-         return (mul_8bit(c.r, 31) << 11) + (mul_8bit(c.g, 63) << 5) + mul_8bit(c.b, 31);
-      }
-      
-      static inline void lerp_color(color_quad_u8& result, const color_quad_u8& p1, const color_quad_u8& p2, uint f)
-      {
-         CRNLIB_ASSERT(f <= 255);
-         
-         result.r = static_cast<uint8>(p1.r + mul_8bit(p2.r - p1.r, f));
-         result.g = static_cast<uint8>(p1.g + mul_8bit(p2.g - p1.g, f));
-         result.b = static_cast<uint8>(p1.b + mul_8bit(p2.b - p1.b, f));
-      }
-      
-      static inline void eval_colors(color_quad_u8* pColors, uint c0, uint c1)
-      {
-         unpack_color(pColors[0], c0);
-         unpack_color(pColors[1], c1);
-
-#if 0         
-         lerp_color(pColors[2], pColors[0], pColors[1], 0x55);
-         lerp_color(pColors[3], pColors[0], pColors[1], 0xAA);
-#else
-         pColors[2].r = (pColors[0].r*2+pColors[1].r)/3;
-         pColors[2].g = (pColors[0].g*2+pColors[1].g)/3;
-         pColors[2].b = (pColors[0].b*2+pColors[1].b)/3;
-         
-         pColors[3].r = (pColors[1].r*2+pColors[0].r)/3;
-         pColors[3].g = (pColors[1].g*2+pColors[0].g)/3;
-         pColors[3].b = (pColors[1].b*2+pColors[0].b)/3;
-#endif         
-      }
-      
-      // false if all selectors equal
-      static bool match_block_colors(uint n, const color_quad_u8* pBlock, const color_quad_u8* pColors, uint8* pSelectors)
-      {
-         int dirr = pColors[0].r - pColors[1].r;
-         int dirg = pColors[0].g - pColors[1].g;
-         int dirb = pColors[0].b - pColors[1].b;
-
-         int stops[4];
-         for(int i = 0; i < 4; i++)
-            stops[i] = pColors[i].r*dirr + pColors[i].g*dirg + pColors[i].b*dirb;
-
-         // 0 2 3 1
-         int c0Point = stops[1] + stops[3];
-         int halfPoint = stops[3] + stops[2];
-         int c3Point = stops[2] + stops[0];
-                           
-         //dirr *= 2;
-         //dirg *= 2;
-         //dirb *= 2;
-         c0Point >>= 1;
-         halfPoint >>= 1;
-         c3Point >>= 1;
-                  
-         bool status = false;
-         for (uint i = 0; i < n; i++)
-         {
-            int dot = pBlock[i].r*dirr + pBlock[i].g*dirg + pBlock[i].b*dirb;
-
-            uint8 s;
-            if (dot < halfPoint)
-               s = (dot < c0Point) ? 1 : 3;
-            else
-               s = (dot < c3Point) ? 2 : 0;
-            
-            pSelectors[i] = s;
-            
-            if (s != pSelectors[0])
-               status = true;
-         }
-         
-         return status;
-      }
-      
-      static bool optimize_block_colors(uint n, const color_quad_u8* block, uint& max16, uint& min16, uint ave_color[3], float axis[3])
-      {
-         int min[3], max[3];
-
-         for(uint ch = 0; ch < 3; ch++)
-         {
-            const uint8 *bp = ((const uint8 *) block) + ch;
-            int minv, maxv;
-
-            int64 muv = bp[0];
-            minv = maxv = bp[0];
-            
-            const uint l = n << 2;
-            for (uint i = 4; i < l; i += 4)
-            {
-               muv += bp[i];
-               minv = math::minimum<int>(minv, bp[i]);
-               maxv = math::maximum<int>(maxv, bp[i]);
-            }
-
-            ave_color[ch] = static_cast<int>((muv + (n / 2)) / n);
-            min[ch] = minv;
-            max[ch] = maxv;
-         }
-         
-         if ((min[0] == max[0]) && (min[1] == max[1]) && (min[2] == max[2]))
-            return false;
-
-         // determine covariance matrix
-         double cov[6];
-         for(int i=0;i<6;i++)
-            cov[i] = 0;
-
-         for(uint i=0;i<n;i++)
-         {
-            double r = (int)block[i].r - (int)ave_color[0];
-            double g = (int)block[i].g - (int)ave_color[1];
-            double b = (int)block[i].b - (int)ave_color[2];
-
-            cov[0] += r*r;
-            cov[1] += r*g;
-            cov[2] += r*b;
-            cov[3] += g*g;
-            cov[4] += g*b;
-            cov[5] += b*b;
-         }
-
-         double covf[6],vfr,vfg,vfb;
-         for(int i=0;i<6;i++)
-            covf[i] = cov[i] * (1.0f/255.0f);
-
-         vfr = max[0] - min[0];
-         vfg = max[1] - min[1];
-         vfb = max[2] - min[2];
-
-         static const uint nIterPower = 4;
-         for(uint iter = 0; iter < nIterPower; iter++)
-         {
-            double r = vfr*covf[0] + vfg*covf[1] + vfb*covf[2];
-            double g = vfr*covf[1] + vfg*covf[3] + vfb*covf[4];
-            double b = vfr*covf[2] + vfg*covf[4] + vfb*covf[5];
-
-            vfr = r;
-            vfg = g;
-            vfb = b;
-         }
-
-         double magn = math::maximum(math::maximum(fabs(vfr),fabs(vfg)),fabs(vfb));
-         int v_r, v_g, v_b;
-
-         if (magn < 4.0f) // too small, default to luminance
-         {
-            v_r = 148;
-            v_g = 300;
-            v_b = 58;
-            
-            axis[0] = (float)v_r;
-            axis[1] = (float)v_g;
-            axis[2] = (float)v_b;
-         }
-         else
-         {
-            magn = 512.0f / magn;
-            vfr *= magn;
-            vfg *= magn;
-            vfb *= magn;
-            v_r = static_cast<int>(vfr);
-            v_g = static_cast<int>(vfg);
-            v_b = static_cast<int>(vfb);
-            
-            axis[0] = (float)vfr;
-            axis[1] = (float)vfg;
-            axis[2] = (float)vfb;
-         }
-                  
-         int mind = block[0].r * v_r + block[0].g * v_g + block[0].b * v_b;
-         int maxd = mind;
-         color_quad_u8 minp(block[0]);
-         color_quad_u8 maxp(block[0]);
-
-         for(uint i = 1; i < n; i++)
-         {
-            int dot = block[i].r * v_r + block[i].g * v_g + block[i].b * v_b;
-
-            if (dot < mind)
-            {
-               mind = dot;
-               minp = block[i];
-            }
-
-            if (dot > maxd)
-            {
-               maxd = dot;
-               maxp = block[i];
-            }
-         }
-
-         max16 = pack_color(maxp);
-         min16 = pack_color(minp);
-         
-         return true;
-      }
-
-      // The refinement function. (Clever code, part 2)
-      // Tries to optimize colors to suit block contents better.
-      // (By solving a least squares system via normal equations+Cramer's rule)
-      static bool refine_block(uint n, const color_quad_u8 *block, uint &max16, uint &min16, const uint8* pSelectors)
-      {
-         static const int w1Tab[4] = { 3,0,2,1 };
-         
-         static const int prods_0[4] = { 0x00,0x00,0x02,0x02 };
-         static const int prods_1[4] = { 0x00,0x09,0x01,0x04 };
-         static const int prods_2[4] = { 0x09,0x00,0x04,0x01 };
-         
-         double akku_0 = 0;
-         double akku_1 = 0;
-         double akku_2 = 0;
-         double At1_r, At1_g, At1_b;
-         double At2_r, At2_g, At2_b;
-
-         At1_r = At1_g = At1_b = 0;
-         At2_r = At2_g = At2_b = 0;
-         for(uint i = 0; i < n; i++)
-         {
-            double r = block[i].r;
-            double g = block[i].g;
-            double b = block[i].b;
-            int step = pSelectors[i];
-                        
-            int w1 = w1Tab[step];
-
-            akku_0  += prods_0[step];
-            akku_1  += prods_1[step];
-            akku_2  += prods_2[step];
-            At1_r   += w1*r;
-            At1_g   += w1*g;
-            At1_b   += w1*b;
-            At2_r   += r;
-            At2_g   += g;
-            At2_b   += b;
-         }
-
-         At2_r = 3*At2_r - At1_r;
-         At2_g = 3*At2_g - At1_g;
-         At2_b = 3*At2_b - At1_b;
-
-         double xx = akku_2;
-         double yy = akku_1;
-         double xy = akku_0;
-
-         double t = xx * yy - xy * xy;
-         if (!yy || !xx || (fabs(t) < .0000125f))
-            return false;
-
-         double frb = (3.0f * 31.0f / 255.0f) / t;
-         double fg = frb * (63.0f / 31.0f);
-
-         uint oldMin = min16;
-         uint oldMax = max16;
-
-         // solve.
-         max16 =   math::clamp<int>(static_cast<int>((At1_r*yy - At2_r*xy)*frb+0.5f),0,31) << 11;
-         max16 |=  math::clamp<int>(static_cast<int>((At1_g*yy - At2_g*xy)*fg +0.5f),0,63) << 5;
-         max16 |=  math::clamp<int>(static_cast<int>((At1_b*yy - At2_b*xy)*frb+0.5f),0,31) << 0;
-
-         min16 =   math::clamp<int>(static_cast<int>((At2_r*xx - At1_r*xy)*frb+0.5f),0,31) << 11;
-         min16 |=  math::clamp<int>(static_cast<int>((At2_g*xx - At1_g*xy)*fg +0.5f),0,63) << 5;
-         min16 |=  math::clamp<int>(static_cast<int>((At2_b*xx - At1_b*xy)*frb+0.5f),0,31) << 0;
-
-         return (oldMin != min16) || (oldMax != max16);
-      }      
-      
-      // false if all selectors equal
-      static bool determine_selectors(uint n, const color_quad_u8* block, uint min16, uint max16, uint8* pSelectors)
-      {  
-         color_quad_u8 color[4];
-
-         if (max16 != min16)
-         {
-            eval_colors(color, min16, max16);
-
-            return match_block_colors(n, block, color, pSelectors);
-         }
-
-         memset(pSelectors, 0, n);
-         return false;
-      }
-      
-      static uint64 determine_error(uint n, const color_quad_u8* block, uint min16, uint max16, uint64 early_out_error)
-      {  
-         color_quad_u8 color[4];
-         
-         eval_colors(color, min16, max16);
-   
-         int dirr = color[0].r - color[1].r;
-         int dirg = color[0].g - color[1].g;
-         int dirb = color[0].b - color[1].b;
-
-         int stops[4];
-         for(int i = 0; i < 4; i++)
-            stops[i] = color[i].r*dirr + color[i].g*dirg + color[i].b*dirb;
-
-         // 0 2 3 1
-         int c0Point = stops[1] + stops[3];
-         int halfPoint = stops[3] + stops[2];
-         int c3Point = stops[2] + stops[0];
-
-         c0Point >>= 1;
-         halfPoint >>= 1;
-         c3Point >>= 1;
-
-         uint64 total_error = 0;
-         
-         for (uint i = 0; i < n; i++)
-         {
-            const color_quad_u8& a = block[i];
-            
-            uint s = 0;
-            if (min16 != max16)
-            {
-               int dot = a.r*dirr + a.g*dirg + a.b*dirb;
-
-               if (dot < halfPoint)
-                  s = (dot < c0Point) ? 1 : 3;
-               else
-                  s = (dot < c3Point) ? 2 : 0;
-            }                  
-         
-            const color_quad_u8& b = color[s];
-
-            int e = a[0] - b[0];
-            total_error += e * e;
-
-            e = a[1] - b[1];
-            total_error += e * e;
-
-            e = a[2] - b[2];
-            total_error += e * e;
-            
-            if (total_error >= early_out_error)
-               break;
-         }
-         
-         return total_error;
-      }
-                  
-      static bool refine_endpoints(uint n, const color_quad_u8* pBlock, uint& low16, uint& high16, uint8* pSelectors)
-      {
-         bool optimized = false;
-         
-         const int limits[3] = { 31, 63, 31 };                           
-         
-         for (uint trial = 0; trial < 2; trial++)
-         {
-            color_quad_u8 color[4];
-            eval_colors(color, low16, high16);
-            
-            uint64 total_error[3] = { 0, 0, 0 };
-            
-            for (uint i = 0; i < n; i++)
-            {
-               const color_quad_u8& a = pBlock[i];
-                                       
-               const uint s = pSelectors[i];
-               const color_quad_u8& b = color[s];
-                  
-               int e = a[0] - b[0];
-               total_error[0] += e * e;
-               
-               e = a[1] - b[1];
-               total_error[1] += e * e;
-               
-               e = a[2] - b[2];
-               total_error[2] += e * e;
-            }
-            
-            color_quad_u8 endpoints[2];
-            endpoints[0] = dxt1_block::unpack_color((uint16)low16, false);
-            endpoints[1] = dxt1_block::unpack_color((uint16)high16, false);
-            
-            color_quad_u8 expanded_endpoints[2];
-            expanded_endpoints[0] = dxt1_block::unpack_color((uint16)low16, true);
-            expanded_endpoints[1] = dxt1_block::unpack_color((uint16)high16, true);
-         
-            bool trial_optimized = false;
-                                    
-            for (uint axis = 0; axis < 3; axis++)
-            {
-               if (!total_error[axis])
-                  continue;
-                  
-               const sU8* const pExpand = (axis == 1) ? ryg_dxt::Expand6 : ryg_dxt::Expand5;
-            
-               for (uint e = 0; e < 2; e++)
-               {
-                  uint v[4];
-                  v[e^1] = expanded_endpoints[e^1][axis];
-               
-                  for (int t = -1; t <= 1; t += 2)
-                  {
-                     int a = endpoints[e][axis] + t;
-                     if ((a < 0) || (a > limits[axis]))
-                        continue;
-                     
-                     v[e] = pExpand[a];
-                     
-                     //int delta = v[1] - v[0];
-                     //v[2] = v[0] + mul_8bit(delta, 0x55);
-                     //v[3] = v[0] + mul_8bit(delta, 0xAA);
-                     
-                     v[2] = (v[0] * 2 + v[1]) / 3;
-                     v[3] = (v[0] + v[1] * 2) / 3;
-                     
-                     uint64 axis_error = 0;
-                     
-                     for (uint i = 0; i < n; i++)
-                     {
-                        const color_quad_u8& p = pBlock[i];
-                        
-                        int e = v[pSelectors[i]] - p[axis];
-                        
-                        axis_error += e * e;
-                        
-                        if (axis_error >= total_error[axis])
-                           break;
-                     }
-                                                               
-                     if (axis_error < total_error[axis])
-                     {
-                        //total_error[axis] = axis_error;
-                        
-                        endpoints[e][axis] = (uint8)a;
-                        expanded_endpoints[e][axis] = (uint8)v[e];
-                        
-                        if (e)
-                           high16 = dxt1_block::pack_color(endpoints[1], false);
-                        else
-                           low16 = dxt1_block::pack_color(endpoints[0], false);
-                        
-                        determine_selectors(n, pBlock, low16, high16, pSelectors);
-                        
-                        eval_colors(color, low16, high16);
-                        
-                        utils::zero_object(total_error);
-                        
-                        for (uint i = 0; i < n; i++)
-                        {
-                           const color_quad_u8& a = pBlock[i];
-
-                           const uint s = pSelectors[i];
-                           const color_quad_u8& b = color[s];
-
-                           int e = a[0] - b[0];
-                           total_error[0] += e * e;
-
-                           e = a[1] - b[1];
-                           total_error[1] += e * e;
-
-                           e = a[2] - b[2];
-                           total_error[2] += e * e;
-                        }
-                                                
-                        trial_optimized = true;
-                     }
-                  
-                  } // t
-                  
-               } // e
-            } // axis
-         
-            if (!trial_optimized)
-               break;
-               
-            optimized = true;
-            
-         } // for ( ; ; )
-         
-         return optimized;
-      }
-      
-      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, cUINT64_MAX);
-         if (!orig_error)
-            return;
-                           
-         float l = 1.0f / sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
-         vec3F principle_axis(axis[0] * l, axis[1] * l, axis[2] * l);
-         
-         const float dist_per_trial = 0.027063293f;
-
-         const uint cMaxProbeRange = 8;
-         uint probe_low[cMaxProbeRange * 2 + 1];
-         uint probe_high[cMaxProbeRange * 2 + 1];
-
-         int probe_range = 8;
-         uint num_iters = 4;
-
-         const uint num_trials = probe_range * 2 + 1;
-         
-         vec3F scaled_principle_axis(principle_axis * dist_per_trial);
-         scaled_principle_axis[0] *= 31.0f;
-         scaled_principle_axis[1] *= 63.0f;
-         scaled_principle_axis[2] *= 31.0f;
-         vec3F initial_ofs(scaled_principle_axis * (float)-probe_range);
-         initial_ofs[0] += .5f;
-         initial_ofs[1] += .5f;
-         initial_ofs[2] += .5f;
-         
-         uint64 cur_error = orig_error;
-                                    
-         for (uint iter = 0; iter < num_iters; iter++)
-         {
-            color_quad_u8 endpoints[2];
-            
-            endpoints[0] = dxt1_block::unpack_color((uint16)low16, false);
-            endpoints[1] = dxt1_block::unpack_color((uint16)high16, false);
-            
-            vec3F low_color(endpoints[0][0], endpoints[0][1], endpoints[0][2]);
-            vec3F high_color(endpoints[1][0], endpoints[1][1], endpoints[1][2]);
-                     
-            vec3F probe_low_color(low_color + initial_ofs);
-            for (uint i = 0; i < num_trials; i++)
-            {
-               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);
-               probe_low[i] = b | (g << 5U) | (r << 11U);
-
-               probe_low_color += scaled_principle_axis;
-            }
-
-            vec3F probe_high_color(high_color + initial_ofs);
-            for (uint i = 0; i < num_trials; i++)
-            {
-               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);
-               probe_high[i] = b | (g << 5U) | (r << 11U);
-
-               probe_high_color += scaled_principle_axis;
-            }
-         
-            uint best_l = low16;
-            uint best_h = high16;
-
-            enum { cMaxHash = 4 };         
-            uint64 hash[cMaxHash];
-            for (uint i = 0; i < cMaxHash; i++)
-               hash[i] = 0;
-            
-            uint c = best_l | (best_h << 16);
-            c = fast_hash(&c, sizeof(c));
-            hash[(c >> 6) & 3] = 1ULL << (c & 63);
-                     
-            for (uint i = 0; i < num_trials; i++)
-            {
-               for (uint j = 0; j < num_trials; j++)
-               {
-                  uint l = probe_low[i];
-                  uint h = probe_high[j];
-                  if (l < h)
-                     utils::swap(l, h);
-                  
-                  uint c = l | (h << 16);
-                  c = fast_hash(&c, sizeof(c));
-                  uint64 mask = 1ULL << (c & 63);
-                  uint ofs = (c >> 6) & 3;
-                  if (hash[ofs] & mask)
-                     continue;
-                  
-                  hash[ofs] |= mask;
-                  
-                  uint64 new_error = determine_error(n, pBlock, l, h, cur_error);
-                  if (new_error < cur_error)
-                  {
-                     best_l = l;
-                     best_h = h;
-                     cur_error = new_error;
-                  }
-               }
-            }
-                                    
-            bool improved = false;
-                                                
-            if ((best_l != low16) || (best_h != high16))
-            {
-               low16 = best_l;
-               high16 = best_h;
-               
-               determine_selectors(n, pBlock, low16, high16, pSelectors);
-               improved = true;
-            }
-
-            if (refine_endpoints(n, pBlock, low16, high16, pSelectors))
-            {
-               improved = true;
-               
-               uint64 cur_error = determine_error(n, pBlock, low16, high16, cUINT64_MAX);
-               if (!cur_error)
-                  return;
-            }
-            
-            if (!improved)
-               break;
-         
-         } // iter
-         
-         //uint64 end_error = determine_error(n, pBlock, low16, high16, UINT64_MAX);
-         //if (end_error > orig_error) DebugBreak();
-      }         
-                  
-      static void compress_solid_block(uint n, uint ave_color[3], uint& low16, uint& high16, uint8* pSelectors)
-      {
-         uint r = ave_color[0];
-         uint g = ave_color[1];
-         uint b = ave_color[2];
-
-         memset(pSelectors, 2, n);
-
-         low16 = (ryg_dxt::OMatch5[r][0]<<11) | (ryg_dxt::OMatch6[g][0]<<5) | ryg_dxt::OMatch5[b][0];
-         high16 = (ryg_dxt::OMatch5[r][1]<<11) | (ryg_dxt::OMatch6[g][1]<<5) | ryg_dxt::OMatch5[b][1];
-      }
-            
-      void compress_color_block(uint n, const color_quad_u8* block, uint& low16, uint& high16, uint8* pSelectors, bool refine)
-      {
-         CRNLIB_ASSERT((n & 15) == 0);
-         
-         uint ave_color[3];
-         float axis[3];
-         
-         if (!optimize_block_colors(n, block, low16, high16, ave_color, axis))
-         {
-            compress_solid_block(n, ave_color, low16, high16, pSelectors);  
-         }
-         else
-         {  
-            if (!determine_selectors(n, block, low16, high16, pSelectors))
-               compress_solid_block(n, ave_color, low16, high16, pSelectors);
-            else 
-            {
-               if (refine_block(n, block, low16, high16, pSelectors))
-                  determine_selectors(n, block, low16, high16, pSelectors);
-               
-               if (refine)
-                  refine_endpoints2(n, block, low16, high16, pSelectors, axis);
-            }                  
-         }
-
-         if (low16 < high16)
-         {
-            utils::swap(low16, high16);
-            for (uint i = 0; i < n; i++)
-               pSelectors[i] ^= 1;
-         }
-      }
-            
-      void compress_color_block(dxt1_block* pDXT1_block, const color_quad_u8* pBlock, bool refine)
-      {
-         uint8 color_selectors[16];
-         uint low16, high16;
-         dxt_fast::compress_color_block(16, pBlock, low16, high16, color_selectors, refine);            
-
-         pDXT1_block->set_low_color(static_cast<uint16>(low16));
-         pDXT1_block->set_high_color(static_cast<uint16>(high16));
-
-         uint mask = 0;
-         for (int i = 15; i >= 0; i--)
-         {
-            mask <<= 2;
-            mask |= color_selectors[i];
-         }
-
-         pDXT1_block->m_selectors[0] = (uint8)(mask & 0xFF);
-         pDXT1_block->m_selectors[1] = (uint8)((mask >> 8) & 0xFF);
-         pDXT1_block->m_selectors[2] = (uint8)((mask >> 16) & 0xFF);
-         pDXT1_block->m_selectors[3] = (uint8)((mask >> 24) & 0xFF);
-      }
-      
-      void compress_alpha_block(uint n, const color_quad_u8* block, uint& low8, uint& high8, uint8* pSelectors, uint comp_index)
-      {
-         int min, max;
-         min = max = block[0][comp_index];
-
-         for (uint i = 1; i < n; i++)
-         {
-            min = math::minimum<int>(min, block[i][comp_index]);
-            max = math::maximum<int>(max, block[i][comp_index]);
-         }
-
-         low8 = max;
-         high8 = min;
-
-         int dist = max-min;
-         int bias = min*7 - (dist >> 1);
-         int dist4 = dist*4;
-         int dist2 = dist*2;
-
-         for (uint i = 0; i < n; i++)
-         {
-            int a = block[i][comp_index]*7 - bias;
-            int ind,t;
-
-            t = (dist4 - a) >> 31;  ind =  t & 4; a -= dist4 & t;
-            t = (dist2 - a) >> 31;  ind += t & 2; a -= dist2 & t;
-            t = (dist - a) >> 31;   ind += t & 1;
-
-            ind = -ind & 7;
-            ind ^= (2 > ind);
-
-            pSelectors[i] = static_cast<uint8>(ind);
-         }
-      }
-      
-      void compress_alpha_block(dxt5_block* pDXT5_block, const color_quad_u8* pBlock, uint comp_index)
-      {
-         uint8 selectors[16];
-         uint low8, high8;
-         
-         compress_alpha_block(16, pBlock, low8, high8, selectors, comp_index);
-         
-         pDXT5_block->set_low_alpha(low8);
-         pDXT5_block->set_high_alpha(high8);
-         
-         uint mask = 0;
-         uint bits = 0;
-         uint8* pDst = pDXT5_block->m_selectors;
-         
-         for (uint i = 0; i < 16; i++)
-         {
-            mask |= (selectors[i] << bits);
-            
-            if ((bits += 3) >= 8)
-            {
-               *pDst++ = static_cast<uint8>(mask);
-               mask >>= 8;
-               bits -= 8;
-            }
-         }
-      }
-      
-      void find_representative_colors(uint n, const color_quad_u8* pBlock, color_quad_u8& lo, color_quad_u8& hi)
-      {
-         uint64 ave64[3];
-         ave64[0] = 0;
-         ave64[1] = 0;
-         ave64[2] = 0;
-         
-         for (uint i = 0; i < n; i++)
-         {
-            ave64[0] += pBlock[i].r;
-            ave64[1] += pBlock[i].g;
-            ave64[2] += pBlock[i].b;
-         }
-         
-         uint ave[3];
-         ave[0] = static_cast<uint>((ave64[0] + (n / 2)) / n);
-         ave[1] = static_cast<uint>((ave64[1] + (n / 2)) / n);
-         ave[2] = static_cast<uint>((ave64[2] + (n / 2)) / n);
-         
-         int furthest_dist = -1;
-         uint furthest_index = 0;
-         for (uint i = 0; i < n; i++)
-         {
-            int r = pBlock[i].r - ave[0];
-            int g = pBlock[i].g - ave[1];
-            int b = pBlock[i].b - ave[2];
-            int dist = r*r + g*g + b*b;
-            if (dist > furthest_dist)
-            {
-               furthest_dist = dist;
-               furthest_index = i;
-            }
-         }
-         
-         color_quad_u8 lo_color(pBlock[furthest_index]);
-
-         int opp_dist = -1;
-         uint opp_index = 0;
-         for (uint i = 0; i < n; i++)
-         {
-            int r = pBlock[i].r - lo_color.r;
-            int g = pBlock[i].g - lo_color.g;
-            int b = pBlock[i].b - lo_color.b;
-            int dist = r*r + g*g + b*b;
-            if (dist > opp_dist)
-            {
-               opp_dist = dist;
-               opp_index = i;
-            }
-         }
-         
-         color_quad_u8 hi_color(pBlock[opp_index]);
-                     
-         for (uint i = 0; i < 3; i++)
-         {
-            lo_color[i] = static_cast<uint8>((lo_color[i] + ave[i]) >> 1);
-            hi_color[i] = static_cast<uint8>((hi_color[i] + ave[i]) >> 1);
-         }
-         
-         const uint cMaxIters = 4;
-         for (uint iter_index = 0; iter_index < cMaxIters; iter_index++)
-         {
-            if ((lo_color[0] == hi_color[0]) && (lo_color[1] == hi_color[1]) && (lo_color[2] == hi_color[2]))
-               break;
-               
-            uint64 new_color[2][3];
-            uint weight[2];
-            
-            utils::zero_object(new_color);
-            utils::zero_object(weight);
-            
-            int vec_r = hi_color[0] - lo_color[0];
-            int vec_g = hi_color[1] - lo_color[1];
-            int vec_b = hi_color[2] - lo_color[2];
-            
-            int lo_dot = vec_r * lo_color[0] + vec_g * lo_color[1] + vec_b * lo_color[2];
-            int hi_dot = vec_r * hi_color[0] + vec_g * hi_color[1] + vec_b * hi_color[2];
-            int mid_dot = lo_dot + hi_dot;
-            
-            vec_r *= 2;
-            vec_g *= 2;
-            vec_b *= 2;
-                        
-            for (uint i = 0; i < n; i++)
-            {
-               const color_quad_u8& c = pBlock[i];
-               
-               const int dot = c[0] * vec_r + c[1] * vec_g + c[2] * vec_b;
-               const uint match_index = (dot > mid_dot);
-               
-               new_color[match_index][0] += c.r;
-               new_color[match_index][1] += c.g;
-               new_color[match_index][2] += c.b;
-               weight[match_index]++;
-            }
-            
-            if ((!weight[0]) || (!weight[1]))
-               break;
-            
-            uint8 new_color8[2][3];
-            
-            for (uint j = 0; j < 2; j++)
-               for (uint i = 0; i < 3; i++)  
-                  new_color8[j][i] = static_cast<uint8>((new_color[j][i] + (weight[j] / 2)) / weight[j]);
-                  
-            if ((new_color8[0][0] == lo_color[0]) && (new_color8[0][1] == lo_color[1]) && (new_color8[0][2] == lo_color[2]) &&
-                (new_color8[1][0] == hi_color[0]) && (new_color8[1][1] == hi_color[1]) && (new_color8[1][2] == hi_color[2]))
-               break;
-            
-            for (uint i = 0; i < 3; i++)
-            {
-               lo_color[i] = new_color8[0][i];
-               hi_color[i] = new_color8[1][i];
-            }
-         }
-         
-         uint energy[2] = { 0, 0 };
-         for (uint i = 0; i < 3; i++)
-         {
-            energy[0] += lo_color[i] * lo_color[i];
-            energy[1] += hi_color[i] * hi_color[i];
-         }
-         
-         if (energy[0] > energy[1])
-            utils::swap(lo_color, hi_color);
-         
-         lo = lo_color;
-         hi = hi_color;
-      }
-      
-   } // namespace dxt_fast
-
-} // namespace crnlib
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+ 0 - 21
Source/ThirdParty/crunch/crnlib/crn_dxt_fast.h

@@ -1,21 +0,0 @@
-// File: crn_dxt_fast.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_color.h"
-#include "crn_dxt.h"
-
-namespace crnlib
-{
-   namespace dxt_fast
-   {
-      void compress_color_block(uint n, const color_quad_u8* block, uint& low16, uint& high16, uint8* pSelectors, bool refine = false);
-      void compress_color_block(dxt1_block* pDXT1_block, const color_quad_u8* pBlock, bool refine = false);
-      
-      void compress_alpha_block(uint n, const color_quad_u8* block, uint& low8, uint& high8, uint8* pSelectors, uint comp_index);
-      void compress_alpha_block(dxt5_block* pDXT5_block, const color_quad_u8* pBlock, uint comp_index);
-      
-      void find_representative_colors(uint n, const color_quad_u8* pBlock, color_quad_u8& lo, color_quad_u8& hi);
-      
-   } // namespace dxt_fast
-
-} // namespace crnlib

+ 0 - 2544
Source/ThirdParty/crunch/crnlib/crn_dxt_hc.cpp

@@ -1,2544 +0,0 @@
-// File: crn_dxt_hc.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_dxt_hc.h"
-#include "crn_image_utils.h"
-#include "crn_console.h"
-#include "crn_dxt_fast.h"
-
-#define CRNLIB_USE_FAST_DXT 1
-#define CRNLIB_ENABLE_DEBUG_MESSAGES 0
-
-namespace crnlib
-{
-   static color_quad_u8 g_tile_layout_colors[cNumChunkTileLayouts] =
-   {
-      color_quad_u8(255,90,32,255),
-      color_quad_u8(64,210,192,255),
-      color_quad_u8(128,16,225,255),
-      color_quad_u8(255,192,200,255),
-
-      color_quad_u8(255,128,200,255),
-
-      color_quad_u8(255,0,0,255),
-      color_quad_u8(0,255,0,255),
-      color_quad_u8(0,0,255,255),
-      color_quad_u8(255,0,255,255)
-   };
-
-   dxt_hc::dxt_hc() :
-      m_num_chunks(0),
-      m_pChunks(NULL),
-      m_num_alpha_blocks(0),
-      m_has_color_blocks(false),
-      m_has_alpha0_blocks(false),
-      m_has_alpha1_blocks(false),
-      m_main_thread_id(crn_get_current_thread_id()),
-      m_canceled(false),
-      m_pTask_pool(NULL),
-      m_prev_phase_index(-1),
-      m_prev_percentage_complete(-1)
-   {
-      utils::zero_object(m_encoding_hist);
-   }
-
-   dxt_hc::~dxt_hc()
-   {
-   }
-
-   void dxt_hc::clear()
-   {
-      m_num_chunks = 0;
-      m_pChunks = NULL;
-
-      m_chunk_encoding.clear();
-
-      m_num_alpha_blocks = 0;
-      m_has_color_blocks = false;
-      m_has_alpha0_blocks = false;
-      m_has_alpha1_blocks = false;
-
-      m_color_selectors.clear();
-
-      m_alpha_selectors.clear();
-      for (uint i = 0; i < cNumCompressedChunkVecs; i++)
-         m_compressed_chunks[i].clear();
-
-      utils::zero_object(m_encoding_hist);
-
-      m_total_tiles = 0;
-
-      m_color_clusters.clear();
-      m_alpha_clusters.clear();
-      m_color_selectors.clear();
-      m_alpha_selectors.clear();
-
-      m_chunk_blocks_using_color_selectors.clear();
-      m_chunk_blocks_using_alpha_selectors.clear();
-
-      m_color_endpoints.clear();
-      m_alpha_endpoints.clear();
-
-      m_dbg_chunk_pixels.clear();
-      m_dbg_chunk_pixels_tile_vis.clear();
-      m_dbg_chunk_pixels_color_quantized.clear();
-      m_dbg_chunk_pixels_alpha_quantized.clear();
-
-      m_dbg_chunk_pixels_quantized_color_selectors.clear();
-      m_dbg_chunk_pixels_orig_color_selectors.clear();
-      m_dbg_chunk_pixels_final_color_selectors.clear();
-      m_dbg_chunk_pixels_final_alpha_selectors.clear();
-
-      m_dbg_chunk_pixels_quantized_alpha_selectors.clear();
-      m_dbg_chunk_pixels_orig_alpha_selectors.clear();
-      m_dbg_chunk_pixels_final_alpha_selectors.clear();
-
-      m_dbg_chunk_pixels_final.clear();
-
-      m_canceled = false;
-
-      m_prev_phase_index = -1;
-      m_prev_percentage_complete = -1;
-   }
-
-   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 = crn_get_current_thread_id();
-
-      bool result = compress_internal(p, num_chunks, pChunks);
-
-      m_pTask_pool = NULL;
-
-      return result;
-   }
-
-   bool dxt_hc::compress_internal(const params& p, uint num_chunks, const pixel_chunk* pChunks)
-   {
-      if ((!num_chunks) || (!pChunks))
-         return false;
-      if ((m_params.m_format == cDXT1A) || (m_params.m_format == cDXT3))
-         return false;
-
-      clear();
-
-      m_params = p;
-
-      m_num_chunks = num_chunks;
-      m_pChunks = pChunks;
-
-      switch (m_params.m_format)
-      {
-         case cDXT1:
-         {
-            m_has_color_blocks = true;
-            break;
-         }
-         case cDXT5:
-         {
-            m_has_color_blocks = true;
-            m_has_alpha0_blocks = true;
-            m_num_alpha_blocks = 1;
-            break;
-         }
-         case cDXT5A:
-         {
-            m_has_alpha0_blocks = true;
-            m_num_alpha_blocks = 1;
-            break;
-         }
-         case cDXN_XY:
-         case cDXN_YX:
-         {
-            m_has_alpha0_blocks = true;
-            m_has_alpha1_blocks = true;
-            m_num_alpha_blocks = 2;
-            break;
-         }
-         default:
-         {
-            return false;
-         }
-      }
-
-      determine_compressed_chunks();
-
-      if (m_has_color_blocks)
-      {
-         if (!determine_color_endpoint_clusters())
-            return false;
-         if (!determine_color_endpoint_codebook())
-            return false;
-      }
-
-      if (m_num_alpha_blocks)
-      {
-         if (!determine_alpha_endpoint_clusters())
-            return false;
-         if (!determine_alpha_endpoint_codebook())
-            return false;
-      }
-
-      create_quantized_debug_images();
-
-      if (m_has_color_blocks)
-      {
-         if (!create_selector_codebook(false))
-            return false;
-      }
-
-      if (m_num_alpha_blocks)
-      {
-         if (!create_selector_codebook(true))
-            return false;
-      }
-
-      if (m_has_color_blocks)
-      {
-         if (!refine_quantized_color_selectors())
-            return false;
-
-         if (!refine_quantized_color_endpoints())
-            return false;
-      }
-
-      if (m_num_alpha_blocks)
-      {
-         if (!refine_quantized_alpha_endpoints())
-            return false;
-
-         if (!refine_quantized_alpha_selectors())
-            return false;
-      }
-
-      create_final_debug_image();
-
-      if (!create_chunk_encodings())
-         return false;
-
-      return true;
-   }
-
-   void dxt_hc::compress_dxt1_block(
-      dxt1_endpoint_optimizer::results& results,
-      uint chunk_index, const image_u8& chunk, uint x_ofs, uint y_ofs, uint width, uint height,
-      uint8* pColor_Selectors)
-   {
-      chunk_index;
-
-      color_quad_u8 pixels[cChunkPixelWidth * cChunkPixelHeight];
-
-      for (uint y = 0; y < height; y++)
-         for (uint x = 0; x < width; x++)
-            pixels[x + y * width] = chunk(x_ofs + x, y_ofs + y);
-
-      //double s = image_utils::compute_std_dev(width * height, pixels, 0, 3);
-
-#if CRNLIB_USE_FAST_DXT
-      uint low16, high16;
-      dxt_fast::compress_color_block(width * height, pixels, low16, high16, pColor_Selectors);
-      results.m_low_color = static_cast<uint16>(low16);
-      results.m_high_color = static_cast<uint16>(high16);
-      results.m_alpha_block = false;
-      results.m_error = INT_MAX;
-      results.m_pSelectors = pColor_Selectors;
-#else
-      dxt1_endpoint_optimizer optimizer;
-
-      dxt1_endpoint_optimizer::params params;
-      params.m_block_index = chunk_index;
-      params.m_pPixels = pixels;
-      params.m_num_pixels = width * height;
-      params.m_pixels_have_alpha = false;
-      params.m_use_alpha_blocks = false;
-      params.m_perceptual = m_params.m_perceptual;
-      params.m_highest_quality = false;//false;
-      params.m_endpoint_caching = false;
-
-      results.m_pSelectors = pColor_Selectors;
-
-      optimizer.compute(params, results);
-#endif
-   }
-
-   void dxt_hc::compress_dxt5_block(
-      dxt5_endpoint_optimizer::results& results,
-      uint chunk_index, const image_u8& chunk, uint x_ofs, uint y_ofs, uint width, uint height, uint component_index,
-      uint8* pAlpha_selectors)
-   {
-      chunk_index;
-
-      color_quad_u8 pixels[cChunkPixelWidth * cChunkPixelHeight];
-
-      for (uint y = 0; y < height; y++)
-         for (uint x = 0; x < width; x++)
-            pixels[x + y * width] = chunk(x_ofs + x, y_ofs + y);
-
-#if 0 //CRNLIB_USE_FAST_DXT
-      uint low, high;
-      dxt_fast::compress_alpha_block(width * height, pixels, low, high, pAlpha_selectors, component_index);
-      results.m_pSelectors = pAlpha_selectors;
-      results.m_error = INT_MAX;
-      results.m_first_endpoint = static_cast<uint8>(low);
-      results.m_second_endpoint = static_cast<uint8>(high);
-      results.m_block_type = 0;
-#else
-      dxt5_endpoint_optimizer optimizer;
-      dxt5_endpoint_optimizer::params params;
-      params.m_block_index = chunk_index;
-      params.m_pPixels = pixels;
-      params.m_num_pixels = width * height;
-      params.m_comp_index = component_index;
-      params.m_use_both_block_types = false;
-      params.m_quality = cCRNDXTQualityNormal;
-
-      results.m_pSelectors = pAlpha_selectors;
-
-      optimizer.compute(params, results);
-#endif
-   }
-
-   void dxt_hc::determine_compressed_chunks_task(uint64 data, void* pData_ptr)
-   {
-      pData_ptr;
-      const uint thread_index = static_cast<uint>(data);
-
-      image_u8 orig_chunk;
-      image_u8 decomp_chunk[cNumChunkEncodings];
-
-      orig_chunk.resize(cChunkPixelWidth, cChunkPixelHeight);
-      for (uint i = 0; i < cNumChunkEncodings; i++)
-         decomp_chunk[i].resize(cChunkPixelWidth, cChunkPixelHeight);
-
-      image_utils::error_metrics color_error_metrics[cNumChunkEncodings];
-      dxt1_endpoint_optimizer::results color_optimizer_results[cNumChunkTileLayouts];
-      uint8 layout_color_selectors[cNumChunkTileLayouts][cChunkPixelWidth * cChunkPixelHeight];
-
-      image_utils::error_metrics alpha_error_metrics[2][cNumChunkEncodings];
-      dxt5_endpoint_optimizer::results alpha_optimizer_results[2][cNumChunkTileLayouts];
-      uint8 layout_alpha_selectors[2][cNumChunkTileLayouts][cChunkPixelWidth * cChunkPixelHeight];
-
-      uint first_layout = 0;
-      uint last_layout = cNumChunkTileLayouts;
-
-      uint first_encoding = 0;
-      uint last_encoding = cNumChunkEncodings;
-
-      if (!m_params.m_hierarchical)
-      {
-         first_layout = cFirst4x4ChunkTileLayout;
-         first_encoding = cNumChunkEncodings - 1;
-      }
-
-      for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-      {
-         if (m_canceled)
-            return;
-
-         if ((crn_get_current_thread_id() == m_main_thread_id) && ((chunk_index & 511) == 0))
-         {
-            if (!update_progress(0, chunk_index, m_num_chunks))
-               return;
-         }
-
-         if (m_pTask_pool->get_num_threads())
-         {
-            if ((chunk_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-               continue;
-         }
-
-         uint level_index = 0;
-         for (uint i = 0; i < m_params.m_num_levels; i++)
-         {
-            if ((chunk_index >= m_params.m_levels[i].m_first_chunk) && (chunk_index < m_params.m_levels[i].m_first_chunk + m_params.m_levels[i].m_num_chunks))
-            {
-               level_index = i;
-               break;
-            }
-         }
-
-         for (uint cy = 0; cy < cChunkPixelHeight; cy++)
-            for (uint cx = 0; cx < cChunkPixelWidth; cx++)
-               orig_chunk(cx, cy) = m_pChunks[chunk_index](cx, cy);
-
-         if (m_has_color_blocks)
-         {
-            for (uint l = first_layout; l < last_layout; l++)
-            {
-               utils::zero_object(layout_color_selectors[l]);
-
-               compress_dxt1_block(
-                  color_optimizer_results[l], chunk_index,
-                  orig_chunk,
-                  g_chunk_tile_layouts[l].m_x_ofs, g_chunk_tile_layouts[l].m_y_ofs,
-                  g_chunk_tile_layouts[l].m_width, g_chunk_tile_layouts[l].m_height,
-                  layout_color_selectors[l]);
-            }
-         }
-
-         float alpha_layout_std_dev[2][cNumChunkTileLayouts];
-         utils::zero_object(alpha_layout_std_dev);
-
-         for (uint a = 0; a < m_num_alpha_blocks; a++)
-         {
-            for (uint l = first_layout; l < last_layout; l++)
-            {
-               utils::zero_object(layout_alpha_selectors[a][l]);
-
-               compress_dxt5_block(
-                  alpha_optimizer_results[a][l], chunk_index,
-                  orig_chunk,
-                  g_chunk_tile_layouts[l].m_x_ofs, g_chunk_tile_layouts[l].m_y_ofs,
-                  g_chunk_tile_layouts[l].m_width, g_chunk_tile_layouts[l].m_height,
-                  m_params.m_alpha_component_indices[a],
-                  layout_alpha_selectors[a][l]);
-
-               for (uint a = 0; a < m_num_alpha_blocks; a++)
-               {
-                  float mean = 0.0f;
-                  float variance = 0.0f;
-
-                  for (uint cy = 0; cy < g_chunk_tile_layouts[l].m_height; cy++)
-                  {
-                     for (uint cx = 0; cx < g_chunk_tile_layouts[l].m_width; cx++)
-                     {
-                        uint s = orig_chunk(cx + g_chunk_tile_layouts[l].m_x_ofs, cy + g_chunk_tile_layouts[l].m_y_ofs)[m_params.m_alpha_component_indices[a]];
-
-                        mean += s;
-                        variance += s * s;
-                     } // cx
-                  } //cy
-
-                  float scale = 1.0f / (g_chunk_tile_layouts[l].m_width * g_chunk_tile_layouts[l].m_height);
-
-                  mean *= scale;
-                  variance *= scale;
-
-                  variance -= mean * mean;
-
-                  alpha_layout_std_dev[a][l] = sqrt(variance);
-
-               }  //a
-            }
-         }
-
-         for (uint e = first_encoding; e < last_encoding; e++)
-         {
-            for (uint t = 0; t < g_chunk_encodings[e].m_num_tiles; t++)
-            {
-               const uint layout_index = g_chunk_encodings[e].m_tiles[t].m_layout_index;
-               CRNLIB_ASSERT( (layout_index >= first_layout) && (layout_index < last_layout) );
-
-               if (m_has_color_blocks)
-               {
-                  const dxt1_endpoint_optimizer::results& color_results = color_optimizer_results[layout_index];
-                  const uint8* pColor_selectors = layout_color_selectors[layout_index];
-
-                  color_quad_u8 block_colors[cDXT1SelectorValues];
-                  CRNLIB_ASSERT(color_results.m_low_color >= color_results.m_high_color);
-                  // it's okay if color_results.m_low_color == color_results.m_high_color, because in this case only selector 0 should be used
-                  dxt1_block::get_block_colors4(block_colors, color_results.m_low_color, color_results.m_high_color);
-
-                  for (uint cy = 0; cy < g_chunk_encodings[e].m_tiles[t].m_height; cy++)
-                  {
-                     for (uint cx = 0; cx < g_chunk_encodings[e].m_tiles[t].m_width; cx++)
-                     {
-                        uint s = pColor_selectors[cx + cy * g_chunk_encodings[e].m_tiles[t].m_width];
-                        CRNLIB_ASSERT(s < cDXT1SelectorValues);
-
-                        decomp_chunk[e](cx + g_chunk_encodings[e].m_tiles[t].m_x_ofs, cy + g_chunk_encodings[e].m_tiles[t].m_y_ofs) = block_colors[s];
-                     }
-                  }
-               }
-
-               for (uint a = 0; a < m_num_alpha_blocks; a++)
-               {
-                  const dxt5_endpoint_optimizer::results& alpha_results = alpha_optimizer_results[a][layout_index];
-                  const uint8* pAlpha_selectors = layout_alpha_selectors[a][layout_index];
-
-                  uint block_values[cDXT5SelectorValues];
-                  CRNLIB_ASSERT(alpha_results.m_first_endpoint >= alpha_results.m_second_endpoint);
-                  dxt5_block::get_block_values8(block_values, alpha_results.m_first_endpoint, alpha_results.m_second_endpoint);
-
-                  for (uint cy = 0; cy < g_chunk_encodings[e].m_tiles[t].m_height; cy++)
-                  {
-                     for (uint cx = 0; cx < g_chunk_encodings[e].m_tiles[t].m_width; cx++)
-                     {
-                        uint s = pAlpha_selectors[cx + cy * g_chunk_encodings[e].m_tiles[t].m_width];
-                        CRNLIB_ASSERT(s < cDXT5SelectorValues);
-
-                        decomp_chunk[e](cx + g_chunk_encodings[e].m_tiles[t].m_x_ofs, cy + g_chunk_encodings[e].m_tiles[t].m_y_ofs)[m_params.m_alpha_component_indices[a]] =
-                           static_cast<uint8>(block_values[s]);
-                     }
-                  }
-
-               }
-            } // t
-
-            if (m_params.m_hierarchical)
-            {
-               if (m_has_color_blocks)
-                  color_error_metrics[e].compute(decomp_chunk[e], orig_chunk, 0, 3);
-
-               for (uint a = 0; a < m_num_alpha_blocks; a++)
-                  alpha_error_metrics[a][e].compute(decomp_chunk[e], orig_chunk, m_params.m_alpha_component_indices[a], 1);
-            }
-         } // e
-
-         uint best_encoding = cNumChunkEncodings - 1;
-
-         if (m_params.m_hierarchical)
-         {
-            float quality[cNumChunkEncodings];
-            utils::zero_object(quality);
-
-            float best_quality = 0.0f;
-
-            best_encoding = 0;
-
-            for (uint e = 0; e < cNumChunkEncodings; e++)
-            {
-               if (m_has_color_blocks)
-               {
-                  float adaptive_tile_color_psnr_derating = m_params.m_adaptive_tile_color_psnr_derating;
-                  if ((level_index) && (adaptive_tile_color_psnr_derating > .25f))
-                  {
-                     //adaptive_tile_color_psnr_derating = math::lerp(adaptive_tile_color_psnr_derating * .5f, .3f, (level_index - 1) / math::maximum(1.0f, float(m_params.m_num_levels - 2)));
-                     adaptive_tile_color_psnr_derating = math::maximum(.25f, adaptive_tile_color_psnr_derating / powf(3.0f, static_cast<float>(level_index)));
-                  }
-
-                  float color_derating = math::lerp( 0.0f, adaptive_tile_color_psnr_derating, (g_chunk_encodings[e].m_num_tiles - 1) / 3.0f );
-                  quality[e] = (float)math::maximum<double>(color_error_metrics[e].mPeakSNR - color_derating, 0.0f);
-               }
-
-               if (m_num_alpha_blocks)
-               {
-                  quality[e] *= m_params.m_adaptive_tile_color_alpha_weighting_ratio;
-                  float alpha_derating = math::lerp( 0.0f, m_params.m_adaptive_tile_alpha_psnr_derating, (g_chunk_encodings[e].m_num_tiles - 1) / 3.0f );
-
-                  float max_std_dev = 0.0f;
-
-                  for (uint a = 0; a < m_num_alpha_blocks; a++)
-                  {
-                     quality[e] += (float)math::maximum<double>(alpha_error_metrics[a][e].mPeakSNR - alpha_derating, 0.0f);
-
-                     for (uint t = 0; t < g_chunk_encodings[e].m_num_tiles; t++)
-                     {
-                        float std_dev = alpha_layout_std_dev[a][ g_chunk_encodings[e].m_tiles[t].m_layout_index ];
-                        max_std_dev = math::maximum(max_std_dev, std_dev);
-                     }
-                  }
-
-#if 0
-// rg [4/28/09] - disabling this because it's fucking up dxt5_xgbr normal maps
-                  const float l = 6.0f;
-                  const float k = .5f;
-
-                  if (max_std_dev > l)
-                  {
-                     float s = max_std_dev - l;
-                     quality[e] -= (k * s);
-                  }
-#endif
-               }
-
-               if (quality[e] > best_quality)
-               {
-                  best_quality = quality[e];
-                  best_encoding = e;
-               }
-            }
-         }
-
-         atomic_increment32(&m_encoding_hist[best_encoding]);
-
-         atomic_exchange_add32(&m_total_tiles, g_chunk_encodings[best_encoding].m_num_tiles);
-
-         for (uint q = 0; q < cNumCompressedChunkVecs; q++)
-         {
-            if (q == cColorChunks)
-            {
-               if (!m_has_color_blocks)
-                  continue;
-            }
-            else if (q > m_num_alpha_blocks)
-               continue;
-
-            compressed_chunk& output = m_compressed_chunks[q][chunk_index];
-
-            output.m_encoding_index = static_cast<uint8>(best_encoding);
-            output.m_num_tiles = static_cast<uint8>(g_chunk_encodings[best_encoding].m_num_tiles);
-
-            for (uint t = 0; t < g_chunk_encodings[best_encoding].m_num_tiles; t++)
-            {
-               const uint layout_index = g_chunk_encodings[best_encoding].m_tiles[t].m_layout_index;
-
-               output.m_tiles[t].m_layout_index = static_cast<uint8>(layout_index);
-               output.m_tiles[t].m_pixel_width = static_cast<uint8>(g_chunk_encodings[best_encoding].m_tiles[t].m_width);
-               output.m_tiles[t].m_pixel_height = static_cast<uint8>(g_chunk_encodings[best_encoding].m_tiles[t].m_height);
-
-               if (q == cColorChunks)
-               {
-                  const dxt1_endpoint_optimizer::results& color_results = color_optimizer_results[layout_index];
-                  const uint8* pColor_selectors = layout_color_selectors[layout_index];
-
-                  output.m_tiles[t].m_endpoint_cluster_index = 0;
-                  output.m_tiles[t].m_first_endpoint = color_results.m_low_color;
-                  output.m_tiles[t].m_second_endpoint = color_results.m_high_color;
-
-                  memcpy(output.m_tiles[t].m_selectors, pColor_selectors, cChunkPixelWidth * cChunkPixelHeight);
-                  output.m_tiles[t].m_alpha_encoding = color_results.m_alpha_block;
-               }
-               else
-               {
-                  const uint a = q - cAlpha0Chunks;
-
-                  const dxt5_endpoint_optimizer::results& alpha_results = alpha_optimizer_results[a][layout_index];
-                  const uint8* pAlpha_selectors = layout_alpha_selectors[a][layout_index];
-
-                  output.m_tiles[t].m_endpoint_cluster_index = 0;
-                  output.m_tiles[t].m_first_endpoint = alpha_results.m_first_endpoint;
-                  output.m_tiles[t].m_second_endpoint = alpha_results.m_second_endpoint;
-
-                  memcpy(output.m_tiles[t].m_selectors, pAlpha_selectors, cChunkPixelWidth * cChunkPixelHeight);
-                  output.m_tiles[t].m_alpha_encoding = alpha_results.m_block_type != 0;
-               }
-            } // t
-         } // q
-
-         if (m_params.m_debugging)
-         {
-            for (uint y = 0; y < cChunkPixelHeight; y++)
-               for (uint x = 0; x < cChunkPixelWidth; x++)
-                  m_dbg_chunk_pixels[chunk_index](x, y) = decomp_chunk[best_encoding](x, y);
-
-            for (uint t = 0; t < g_chunk_encodings[best_encoding].m_num_tiles; t++)
-            {
-               const uint layout_index = g_chunk_encodings[best_encoding].m_tiles[t].m_layout_index;
-
-               const chunk_tile_desc& tile_desc = g_chunk_tile_layouts[layout_index];
-
-               for (uint ty = 0; ty < tile_desc.m_height; ty++)
-                  for (uint tx = 0; tx < tile_desc.m_width; tx++)
-                     m_dbg_chunk_pixels_tile_vis[chunk_index](tile_desc.m_x_ofs + tx, tile_desc.m_y_ofs + ty) = g_tile_layout_colors[layout_index];
-            }
-         }
-
-      } // chunk_index
-   }
-
-   bool dxt_hc::determine_compressed_chunks()
-   {
-      utils::zero_object(m_encoding_hist);
-
-      for (uint i = 0; i < cNumCompressedChunkVecs; i++)
-         m_compressed_chunks[i].clear();
-
-      if (m_has_color_blocks)
-         m_compressed_chunks[cColorChunks].resize(m_num_chunks);
-
-      for (uint a = 0; a < m_num_alpha_blocks; a++)
-         m_compressed_chunks[cAlpha0Chunks + a].resize(m_num_chunks);
-
-      if (m_params.m_debugging)
-      {
-         m_dbg_chunk_pixels.resize(m_num_chunks);
-         m_dbg_chunk_pixels_tile_vis.resize(m_num_chunks);
-
-         for (uint i = 0; i < m_num_chunks; i++)
-         {
-            m_dbg_chunk_pixels[i].clear();
-            m_dbg_chunk_pixels_tile_vis[i].clear();
-         }
-      }
-
-      m_total_tiles = 0;
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &dxt_hc::determine_compressed_chunks_task, i);
-
-      m_pTask_pool->join();
-      if (m_canceled)
-         return false;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-      {
-         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("Chunk encoding type symbol_histogram: ");
-         for (uint e = 0; e < cNumChunkEncodings; e++)
-            console::info("%u ", m_encoding_hist[e]);
-
-         console::info("Blocks per chunk encoding type: ");
-         for (uint e = 0; e < cNumChunkEncodings; e++)
-            console::info("%u ", m_encoding_hist[e] * cChunkBlockWidth * cChunkBlockHeight);
-      }
-#endif
-
-      return true;
-   }
-
-   void dxt_hc::assign_color_endpoint_clusters_task(uint64 data, void* pData_ptr)
-   {
-      const uint thread_index = (uint)data;
-      assign_color_endpoint_clusters_state& state = *static_cast<assign_color_endpoint_clusters_state*>(pData_ptr);
-
-      for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-      {
-         if (m_canceled)
-            return;
-
-         if ((crn_get_current_thread_id() == m_main_thread_id) && ((chunk_index & 63) == 0))
-         {
-            if (!update_progress(2, chunk_index, m_num_chunks))
-               return;
-         }
-
-         if (m_pTask_pool->get_num_threads())
-         {
-            if ((chunk_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-               continue;
-         }
-
-         compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-
-         for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-         {
-            uint cluster_index = state.m_vq.find_best_codebook_entry_fs(state.m_training_vecs[chunk_index][tile_index]);
-
-            chunk.m_endpoint_cluster_index[tile_index] = static_cast<uint16>(cluster_index);
-         }
-      }
-   }
-
-   bool dxt_hc::determine_color_endpoint_clusters()
-   {
-      if (!m_has_color_blocks)
-         return true;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Generating color training vectors");
-#endif
-
-      const float r_scale = .5f;
-      const float b_scale = .25f;
-
-      vec6F_tree_vq vq;
-
-      crnlib::vector< crnlib::vector<vec6F> > training_vecs;
-
-      training_vecs.resize(m_num_chunks);
-
-      for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-      {
-         if ((chunk_index & 255) == 0)
-         {
-            if (!update_progress(1, chunk_index, m_num_chunks))
-               return false;
-         }
-
-         const compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-
-         training_vecs[chunk_index].resize(chunk.m_num_tiles);
-
-         for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-         {
-            const compressed_tile& tile = chunk.m_tiles[tile_index];
-
-            const chunk_tile_desc& layout = g_chunk_tile_layouts[tile.m_layout_index];
-
-            tree_clusterizer<vec3F> palettizer;
-            for (uint y = 0; y < layout.m_height; y++)
-            {
-               for (uint x = 0; x < layout.m_width; x++)
-               {
-                  const color_quad_u8& c =  m_pChunks[chunk_index](layout.m_x_ofs + x, layout.m_y_ofs + y);
-
-                  vec3F v;
-                  if (m_params.m_perceptual)
-                  {
-                     v.set(c[0] * 1.0f/255.0f, c[1] * 1.0f/255.0f, c[2] * 1.0f/255.0f);
-                     v[0] *= r_scale;
-                     v[2] *= b_scale;
-                  }
-                  else
-                  {
-                     v.set(c[0] * 1.0f/255.0f, c[1] * 1.0f/255.0f, c[2] * 1.0f/255.0f);
-                  }
-
-                  palettizer.add_training_vec(v, 1);
-               }
-            }
-
-            palettizer.generate_codebook(2);
-
-            uint tile_weight = tile.m_pixel_width * tile.m_pixel_height;
-            tile_weight = static_cast<uint>(tile_weight * m_pChunks[chunk_index].m_weight);
-
-            vec3F v[2];
-            utils::zero_object(v);
-
-            for (uint i = 0; i < palettizer.get_codebook_size(); i++)
-               v[i] = palettizer.get_codebook_entry(i);
-
-            if (palettizer.get_codebook_size() == 1)
-               v[1] = v[0];
-            if (v[0].length() > v[1].length())
-               utils::swap(v[0], v[1]);
-
-            vec6F vv;
-            for (uint i = 0; i < 2; i++)
-            {
-               vv[i*3+0] = v[i][0];
-               vv[i*3+1] = v[i][1];
-               vv[i*3+2] = v[i][2];
-            }
-
-            vq.add_training_vec(vv, tile_weight);
-
-            training_vecs[chunk_index][tile_index] = vv;
-         }
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Begin color cluster analysis");
-      timer t;
-      t.start();
-#endif
-
-      uint codebook_size = math::minimum<uint>(m_total_tiles, m_params.m_color_endpoint_codebook_size);
-      vq.generate_codebook(codebook_size);
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-      {
-         double total_time = t.get_elapsed_secs();
-         console::info("Codebook gen time: %3.3fs, Total color clusters: %u", total_time, vq.get_codebook_size());
-      }
-#endif
-
-      m_color_clusters.resize(vq.get_codebook_size());
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Begin color cluster assignment");
-#endif
-
-      assign_color_endpoint_clusters_state state(vq, training_vecs);
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &dxt_hc::assign_color_endpoint_clusters_task, i, &state);
-
-      m_pTask_pool->join();
-      if (m_canceled)
-         return false;
-
-      for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-      {
-         compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-
-         for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-         {
-            uint cluster_index = chunk.m_endpoint_cluster_index[tile_index];
-
-            m_color_clusters[cluster_index].m_tiles.push_back( std::make_pair(chunk_index, tile_index) );
-         }
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Completed color cluster assignment");
-#endif
-
-      return true;
-   }
-
-   void dxt_hc::determine_alpha_endpoint_clusters_task(uint64 data, void* pData_ptr)
-   {
-      const uint thread_index = static_cast<uint>(data);
-      const determine_alpha_endpoint_clusters_state& state = *static_cast<determine_alpha_endpoint_clusters_state*>(pData_ptr);
-
-      for (uint a = 0; a < m_num_alpha_blocks; a++)
-      {
-         for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-         {
-            if (m_canceled)
-               return;
-
-            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;
-            }
-
-            if (m_pTask_pool->get_num_threads())
-            {
-               if ((chunk_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-                  continue;
-            }
-
-            compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + a][chunk_index];
-
-            for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-            {
-               uint cluster_index = state.m_vq.find_best_codebook_entry_fs(state.m_training_vecs[a][chunk_index][tile_index]);
-
-               chunk.m_endpoint_cluster_index[tile_index] = static_cast<uint16>(cluster_index);
-            }
-         }
-      }
-   }
-
-   bool dxt_hc::determine_alpha_endpoint_clusters()
-   {
-      if (!m_num_alpha_blocks)
-         return true;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Generating alpha training vectors");
-#endif
-
-      determine_alpha_endpoint_clusters_state state;
-
-      for (uint a = 0; a < m_num_alpha_blocks; a++)
-      {
-         state.m_training_vecs[a].resize(m_num_chunks);
-
-         for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-         {
-            if ((chunk_index & 63) == 0)
-            {
-               if (!update_progress(6, m_num_chunks * a + chunk_index, m_num_chunks * m_num_alpha_blocks))
-                  return false;
-            }
-
-            const compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + a][chunk_index];
-
-            state.m_training_vecs[a][chunk_index].resize(chunk.m_num_tiles);
-
-            for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-            {
-               const compressed_tile& tile = chunk.m_tiles[tile_index];
-
-               const chunk_tile_desc& layout = g_chunk_tile_layouts[tile.m_layout_index];
-
-               tree_clusterizer<vec1F> palettizer;
-
-               for (uint y = 0; y < layout.m_height; y++)
-               {
-                  for (uint x = 0; x < layout.m_width; x++)
-                  {
-                     uint c = m_pChunks[chunk_index](layout.m_x_ofs + x, layout.m_y_ofs + y)[m_params.m_alpha_component_indices[a]];
-
-                     vec1F v(c * 1.0f/255.0f);
-
-                     palettizer.add_training_vec(v, 1);
-                  }
-               }
-               palettizer.generate_codebook(2);
-
-               const uint tile_weight = tile.m_pixel_width * tile.m_pixel_height;
-
-               vec1F v[2];
-               utils::zero_object(v);
-
-               for (uint i = 0; i < palettizer.get_codebook_size(); i++)
-                  v[i] = palettizer.get_codebook_entry(i);
-
-               if (palettizer.get_codebook_size() == 1)
-                  v[1] = v[0];
-               if (v[0] > v[1])
-                  utils::swap(v[0], v[1]);
-
-               vec2F vv(v[0][0], v[1][0]);
-
-               state.m_vq.add_training_vec(vv, tile_weight);
-
-               state.m_training_vecs[a][chunk_index][tile_index] = vv;
-
-            } // tile_index
-         } // chunk_index
-      } // a
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Begin alpha cluster analysis");
-      timer t;
-      t.start();
-#endif
-
-      uint codebook_size = math::minimum<uint>(m_total_tiles, m_params.m_alpha_endpoint_codebook_size);
-      state.m_vq.generate_codebook(codebook_size);
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-      {
-         double total_time = t.get_elapsed_secs();
-         console::info("Codebook gen time: %3.3fs, Total alpha clusters: %u", total_time, state.m_vq.get_codebook_size());
-      }
-#endif
-
-      m_alpha_clusters.resize(state.m_vq.get_codebook_size());
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Begin alpha cluster assignment");
-#endif
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &dxt_hc::determine_alpha_endpoint_clusters_task, i, &state);
-
-      m_pTask_pool->join();
-      if (m_canceled)
-         return false;
-
-      for (uint a = 0; a < m_num_alpha_blocks; a++)
-      {
-         for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-         {
-            compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + a][chunk_index];
-
-            for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-            {
-               const uint cluster_index = chunk.m_endpoint_cluster_index[tile_index];
-
-               m_alpha_clusters[cluster_index].m_tiles.push_back( std::make_pair(chunk_index, tile_index | (a << 16)) );
-            }
-         }
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Completed alpha cluster assignment");
-#endif
-
-      return true;
-   }
-
-   void dxt_hc::determine_color_endpoint_codebook_task(uint64 data, void* pData_ptr)
-   {
-      pData_ptr;
-      const uint thread_index = static_cast<uint>(data);
-
-      if (!m_has_color_blocks)
-         return;
-
-      crnlib::vector<color_quad_u8> pixels;
-      pixels.reserve(512);
-
-      crnlib::vector<uint8> selectors;
-
-      uint total_pixels = 0;
-
-      uint total_empty_clusters = 0;
-      for (uint cluster_index = 0; cluster_index < m_color_clusters.size(); cluster_index++)
-      {
-         if (m_canceled)
-            return;
-
-         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;
-         }
-
-         if (m_pTask_pool->get_num_threads())
-         {
-            if ((cluster_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-               continue;
-         }
-
-         tile_cluster& cluster = m_color_clusters[cluster_index];
-         if (cluster.m_tiles.empty())
-         {
-            total_empty_clusters++;
-            continue;
-         }
-
-         pixels.resize(0);
-
-         for (uint t = 0; t < cluster.m_tiles.size(); t++)
-         {
-            const uint chunk_index = cluster.m_tiles[t].first;
-            const uint tile_index = cluster.m_tiles[t].second;
-            CRNLIB_ASSERT(chunk_index < m_num_chunks);
-            CRNLIB_ASSERT(tile_index < cChunkMaxTiles);
-
-            const compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-
-            CRNLIB_ASSERT(tile_index < chunk.m_num_tiles);
-            const compressed_tile& tile = chunk.m_tiles[tile_index];
-
-            const chunk_tile_desc& layout = g_chunk_tile_layouts[tile.m_layout_index];
-
-            for (uint y = 0; y < layout.m_height; y++)
-               for (uint x = 0; x < layout.m_width; x++)
-                  pixels.push_back( m_pChunks[chunk_index](layout.m_x_ofs + x, layout.m_y_ofs + y) );
-         }
-
-         total_pixels += pixels.size();
-
-         selectors.resize(pixels.size());
-
-         dxt1_endpoint_optimizer::params params;
-         params.m_block_index = cluster_index;
-         params.m_pPixels = &pixels[0];
-         params.m_num_pixels = pixels.size();
-         params.m_pixels_have_alpha = false;
-         params.m_use_alpha_blocks = false;
-         params.m_perceptual = m_params.m_perceptual;
-         params.m_quality = cCRNDXTQualityUber;
-         params.m_endpoint_caching = false;
-
-         dxt1_endpoint_optimizer::results results;
-         results.m_pSelectors = &selectors[0];
-
-         dxt1_endpoint_optimizer optimizer;
-         const bool all_transparent = optimizer.compute(params, results);
-         all_transparent;
-
-         cluster.m_first_endpoint = results.m_low_color;
-         cluster.m_second_endpoint = results.m_high_color;
-         cluster.m_alpha_encoding = results.m_alpha_block;
-         cluster.m_error = results.m_error;
-
-         uint pixel_index = 0;
-
-         for (uint t = 0; t < cluster.m_tiles.size(); t++)
-         {
-            const uint chunk_index = cluster.m_tiles[t].first;
-            const uint tile_index = cluster.m_tiles[t].second;
-
-            CRNLIB_ASSERT(chunk_index < m_num_chunks);
-
-            compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-
-            CRNLIB_ASSERT(tile_index < chunk.m_num_tiles);
-
-            CRNLIB_ASSERT(chunk.m_endpoint_cluster_index[tile_index] == cluster_index);
-
-            const compressed_tile& tile = chunk.m_tiles[tile_index];
-
-            const chunk_tile_desc& layout = g_chunk_tile_layouts[tile.m_layout_index];
-            layout;
-
-            compressed_tile& quantized_tile = chunk.m_quantized_tiles[tile_index];
-
-            const uint total_pixels = tile.m_pixel_width * tile.m_pixel_height;
-
-            quantized_tile.m_endpoint_cluster_index = cluster_index;
-            quantized_tile.m_first_endpoint = results.m_low_color;
-            quantized_tile.m_second_endpoint = results.m_high_color;
-            //quantized_tile.m_error = results.m_error;
-            quantized_tile.m_alpha_encoding = results.m_alpha_block;
-            quantized_tile.m_pixel_width = tile.m_pixel_width;
-            quantized_tile.m_pixel_height = tile.m_pixel_height;
-            quantized_tile.m_layout_index = tile.m_layout_index;
-
-            memcpy(quantized_tile.m_selectors, &selectors[pixel_index], total_pixels);
-
-            pixel_index += total_pixels;
-         }
-      }
-
-      //CRNLIB_ASSERT(total_pixels == (m_num_chunks * cChunkPixelWidth * cChunkPixelHeight));
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-      {
-         if (total_empty_clusters)
-            console::warning("Total empty color clusters: %u", total_empty_clusters);
-      }
-#endif
-   }
-
-   bool dxt_hc::determine_color_endpoint_codebook()
-   {
-      if (!m_has_color_blocks)
-         return true;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Computing optimal color cluster endpoints");
-#endif
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &dxt_hc::determine_color_endpoint_codebook_task, i, NULL);
-
-      m_pTask_pool->join();
-
-      return !m_canceled;
-   }
-
-   void dxt_hc::determine_alpha_endpoint_codebook_task(uint64 data, void* pData_ptr)
-   {
-      pData_ptr;
-
-      const uint thread_index = static_cast<uint>(data);
-
-      crnlib::vector<color_quad_u8> pixels;
-      pixels.reserve(512);
-
-      crnlib::vector<uint8> selectors;
-      selectors.reserve(512);
-
-      uint total_empty_clusters = 0;
-      for (uint cluster_index = 0; cluster_index < m_alpha_clusters.size(); cluster_index++)
-      {
-         if (m_canceled)
-            return;
-
-         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;
-         }
-
-         if (m_pTask_pool->get_num_threads())
-         {
-            if ((cluster_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-               continue;
-         }
-
-         tile_cluster& cluster = m_alpha_clusters[cluster_index];
-         if (cluster.m_tiles.empty())
-         {
-            total_empty_clusters++;
-            continue;
-         }
-
-         pixels.resize(0);
-
-         for (uint tile_iter = 0; tile_iter < cluster.m_tiles.size(); tile_iter++)
-         {
-            const uint chunk_index = cluster.m_tiles[tile_iter].first;
-            const uint tile_index = cluster.m_tiles[tile_iter].second & 0xFFFFU;
-            const uint alpha_index = cluster.m_tiles[tile_iter].second >> 16U;
-
-            CRNLIB_ASSERT(chunk_index < m_num_chunks);
-            CRNLIB_ASSERT(tile_index < cChunkMaxTiles);
-            CRNLIB_ASSERT(alpha_index < m_num_alpha_blocks);
-
-            const compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + alpha_index][chunk_index];
-
-            CRNLIB_ASSERT(chunk.m_endpoint_cluster_index[tile_index] == cluster_index);
-
-            CRNLIB_ASSERT(tile_index < chunk.m_num_tiles);
-            const compressed_tile& tile = chunk.m_tiles[tile_index];
-
-            const chunk_tile_desc& layout = g_chunk_tile_layouts[tile.m_layout_index];
-
-            color_quad_u8 c(cClear);
-
-            for (uint y = 0; y < layout.m_height; y++)
-            {
-               for (uint x = 0; x < layout.m_width; x++)
-               {
-                  c[0] = m_pChunks[chunk_index](layout.m_x_ofs + x, layout.m_y_ofs + y)[ m_params.m_alpha_component_indices[alpha_index] ];
-
-                  pixels.push_back(c);
-               }
-            }
-         }
-
-         selectors.resize(pixels.size());
-
-         dxt5_endpoint_optimizer::params params;
-         params.m_block_index = cluster_index;
-         params.m_pPixels = &pixels[0];
-         params.m_num_pixels = pixels.size();
-         params.m_comp_index = 0;
-         params.m_quality = cCRNDXTQualityUber;
-         params.m_use_both_block_types = false;
-
-         dxt5_endpoint_optimizer::results results;
-         results.m_pSelectors = &selectors[0];
-
-         dxt5_endpoint_optimizer optimizer;
-         const bool all_transparent = optimizer.compute(params, results);
-         all_transparent;
-
-         cluster.m_first_endpoint = results.m_first_endpoint;
-         cluster.m_second_endpoint = results.m_second_endpoint;
-         cluster.m_alpha_encoding = results.m_block_type != 0;
-         cluster.m_error = results.m_error;
-
-         uint pixel_index = 0;
-
-         for (uint tile_iter = 0; tile_iter < cluster.m_tiles.size(); tile_iter++)
-         {
-            const uint chunk_index = cluster.m_tiles[tile_iter].first;
-            const uint tile_index = cluster.m_tiles[tile_iter].second & 0xFFFFU;
-            const uint alpha_index = cluster.m_tiles[tile_iter].second >> 16U;
-            CRNLIB_ASSERT(chunk_index < m_num_chunks);
-            CRNLIB_ASSERT(tile_index < cChunkMaxTiles);
-            CRNLIB_ASSERT(alpha_index < m_num_alpha_blocks);
-
-            compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + alpha_index][chunk_index];
-
-            CRNLIB_ASSERT(chunk.m_endpoint_cluster_index[tile_index] == cluster_index);
-
-            CRNLIB_ASSERT(tile_index < chunk.m_num_tiles);
-            const compressed_tile& tile = chunk.m_tiles[tile_index];
-
-            const chunk_tile_desc& layout = g_chunk_tile_layouts[tile.m_layout_index];
-            layout;
-
-            compressed_tile& quantized_tile = chunk.m_quantized_tiles[tile_index];
-
-            const uint total_pixels = tile.m_pixel_width * tile.m_pixel_height;
-
-            quantized_tile.m_endpoint_cluster_index = cluster_index;
-            quantized_tile.m_first_endpoint = results.m_first_endpoint;
-            quantized_tile.m_second_endpoint = results.m_second_endpoint;
-            //quantized_tile.m_error = results.m_error;
-            quantized_tile.m_alpha_encoding = results.m_block_type != 0;
-            quantized_tile.m_pixel_width = tile.m_pixel_width;
-            quantized_tile.m_pixel_height = tile.m_pixel_height;
-            quantized_tile.m_layout_index = tile.m_layout_index;
-
-            memcpy(quantized_tile.m_selectors, &selectors[pixel_index], total_pixels);
-
-            pixel_index += total_pixels;
-         }
-      } // cluster_index
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-      {
-         if (total_empty_clusters)
-            console::warning("Total empty alpha clusters: %u", total_empty_clusters);
-      }
-#endif
-   }
-
-   bool dxt_hc::determine_alpha_endpoint_codebook()
-   {
-      if (!m_num_alpha_blocks)
-         return true;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Computing optimal alpha cluster endpoints");
-#endif
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &dxt_hc::determine_alpha_endpoint_codebook_task, i, NULL);
-
-      m_pTask_pool->join();
-
-      return !m_canceled;
-   }
-
-   void dxt_hc::create_quantized_debug_images()
-   {
-      if (!m_params.m_debugging)
-         return;
-
-      if (m_has_color_blocks)
-      {
-         m_dbg_chunk_pixels_color_quantized.resize(m_num_chunks);
-         m_dbg_chunk_pixels_quantized_color_selectors.resize(m_num_chunks);
-         m_dbg_chunk_pixels_orig_color_selectors.resize(m_num_chunks);
-
-         for (uint i = 0; i < m_num_chunks; i++)
-         {
-            m_dbg_chunk_pixels_color_quantized[i].clear();
-            m_dbg_chunk_pixels_quantized_color_selectors[i].clear();
-            m_dbg_chunk_pixels_orig_color_selectors[i].clear();
-         }
-      }
-
-      if (m_num_alpha_blocks)
-      {
-         m_dbg_chunk_pixels_alpha_quantized.resize(m_num_chunks);
-         m_dbg_chunk_pixels_quantized_alpha_selectors.resize(m_num_chunks);
-         m_dbg_chunk_pixels_orig_alpha_selectors.resize(m_num_chunks);
-
-         for (uint i = 0; i < m_num_chunks; i++)
-         {
-            m_dbg_chunk_pixels_alpha_quantized[i].clear();
-            m_dbg_chunk_pixels_quantized_alpha_selectors[i].clear();
-            m_dbg_chunk_pixels_orig_alpha_selectors[i].clear();
-         }
-      }
-
-      for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-      {
-         if (m_has_color_blocks)
-         {
-            pixel_chunk& output_chunk_color_quantized = m_dbg_chunk_pixels_color_quantized[chunk_index];
-            pixel_chunk& output_chunk_selectors = m_dbg_chunk_pixels_quantized_color_selectors[chunk_index];
-            pixel_chunk& output_chunk_orig_selectors = m_dbg_chunk_pixels_orig_color_selectors[chunk_index];
-
-            const compressed_chunk& color_chunk = m_compressed_chunks[cColorChunks][chunk_index];
-
-            for (uint tile_index = 0; tile_index < color_chunk.m_num_tiles; tile_index++)
-            {
-               const compressed_tile& quantized_tile = color_chunk.m_quantized_tiles[tile_index];
-
-               const chunk_tile_desc& layout = g_chunk_tile_layouts[quantized_tile.m_layout_index];
-
-               const uint8* pColor_Selectors = quantized_tile.m_selectors;
-
-               color_quad_u8 block_colors[cDXT1SelectorValues];
-               CRNLIB_ASSERT(quantized_tile.m_first_endpoint >= quantized_tile.m_second_endpoint);
-               dxt1_block::get_block_colors(block_colors, static_cast<uint16>(quantized_tile.m_first_endpoint), static_cast<uint16>(quantized_tile.m_second_endpoint));
-
-               for (uint y = 0; y < layout.m_height; y++)
-               {
-                  for (uint x = 0; x < layout.m_width; x++)
-                  {
-                     const uint selector = pColor_Selectors[x + y * layout.m_width];
-
-                     output_chunk_selectors(x + layout.m_x_ofs, y + layout.m_y_ofs) = selector*255/(cDXT1SelectorValues-1);
-
-                     output_chunk_orig_selectors(x + layout.m_x_ofs, y + layout.m_y_ofs) = color_chunk.m_tiles[tile_index].m_selectors[x + y * layout.m_width] * 255 / (cDXT1SelectorValues-1);
-
-                     output_chunk_color_quantized(x + layout.m_x_ofs, y + layout.m_y_ofs) = block_colors[selector];
-                  }
-               }
-            }
-         }
-
-         for (uint a = 0; a < m_num_alpha_blocks; a++)
-         {
-            pixel_chunk& output_chunk_alpha_quantized = m_dbg_chunk_pixels_alpha_quantized[chunk_index];
-            pixel_chunk& output_chunk_selectors = m_dbg_chunk_pixels_quantized_alpha_selectors[chunk_index];
-            pixel_chunk& output_chunk_orig_selectors = m_dbg_chunk_pixels_orig_alpha_selectors[chunk_index];
-
-            const compressed_chunk& alpha_chunk = m_compressed_chunks[cAlpha0Chunks + a][chunk_index];
-
-            for (uint tile_index = 0; tile_index < alpha_chunk.m_num_tiles; tile_index++)
-            {
-               const compressed_tile& quantized_tile = alpha_chunk.m_quantized_tiles[tile_index];
-
-               const chunk_tile_desc& layout = g_chunk_tile_layouts[quantized_tile.m_layout_index];
-
-               const uint8* pAlpha_selectors = quantized_tile.m_selectors;
-
-               uint block_values[cDXT5SelectorValues];
-               CRNLIB_ASSERT(quantized_tile.m_first_endpoint >= quantized_tile.m_second_endpoint);
-               dxt5_block::get_block_values(block_values, quantized_tile.m_first_endpoint, quantized_tile.m_second_endpoint);
-
-               for (uint y = 0; y < layout.m_height; y++)
-               {
-                  for (uint x = 0; x < layout.m_width; x++)
-                  {
-                     const uint selector = pAlpha_selectors[x + y * layout.m_width];
-
-                     CRNLIB_ASSERT(selector < cDXT5SelectorValues);
-
-                     output_chunk_selectors(x + layout.m_x_ofs, y + layout.m_y_ofs)[m_params.m_alpha_component_indices[a]] = static_cast<uint8>(selector*255/(cDXT5SelectorValues-1));
-
-                     output_chunk_orig_selectors(x + layout.m_x_ofs, y + layout.m_y_ofs)[m_params.m_alpha_component_indices[a]] = static_cast<uint8>(alpha_chunk.m_tiles[tile_index].m_selectors[x + y * layout.m_width]*255/(cDXT5SelectorValues-1));
-
-                     output_chunk_alpha_quantized(x + layout.m_x_ofs, y + layout.m_y_ofs)[m_params.m_alpha_component_indices[a]] = static_cast<uint8>(block_values[selector]);
-                  }
-               }
-            }
-         } // a
-
-      }
-   }
-
-   void dxt_hc::create_selector_codebook_task(uint64 data, void* pData_ptr)
-   {
-      const uint thread_index = static_cast<uint>(data);
-      const create_selector_codebook_state& state = *static_cast<create_selector_codebook_state*>(pData_ptr);
-
-      for (uint comp_chunk_index = state.m_comp_index_start; comp_chunk_index <= state.m_comp_index_end; comp_chunk_index++)
-      {
-         const uint alpha_index = state.m_alpha_blocks ? (comp_chunk_index - cAlpha0Chunks) : 0;
-         const uint alpha_pixel_comp = state.m_alpha_blocks ? m_params.m_alpha_component_indices[alpha_index] : 0;
-
-         for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-         {
-            if (m_canceled)
-               return;
-
-            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;
-            }
-
-            if (m_pTask_pool->get_num_threads())
-            {
-               if ((chunk_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-                  continue;
-            }
-
-            compressed_chunk& chunk = m_compressed_chunks[comp_chunk_index][chunk_index];
-
-            for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-            {
-               compressed_tile& quantized_tile = chunk.m_quantized_tiles[tile_index];
-
-               const chunk_tile_desc& layout = g_chunk_tile_layouts[quantized_tile.m_layout_index];
-
-               const uint tile_blocks_x = layout.m_width >> 2;
-               const uint tile_blocks_y = layout.m_height >> 2;
-
-               const uint tile_block_ofs_x = layout.m_x_ofs >> 2;
-               const uint tile_block_ofs_y = layout.m_y_ofs >> 2;
-
-               if (state.m_alpha_blocks)
-               {
-                  uint block_values[cDXT5SelectorValues];
-                  dxt5_block::get_block_values(block_values, quantized_tile.m_first_endpoint, quantized_tile.m_second_endpoint);
-
-                  for (uint by = 0; by < tile_blocks_y; by++)
-                  {
-                     for (uint bx = 0; bx < tile_blocks_x; bx++)
-                     {
-   #if 0
-                        uint best_index = selector_vq.find_best_codebook_entry_fs(training_vecs[comp_chunk_index][(tile_block_ofs_x+bx)+(tile_block_ofs_y+by)*2][chunk_index]);
-   #else
-                        const dxt_pixel_block& block = m_pChunks[chunk_index].m_blocks[tile_block_ofs_y + by][tile_block_ofs_x + bx];
-
-                        uint best_error = UINT_MAX;
-                        uint best_index = 0;
-
-                        for (uint i = 0; i < state.m_selectors_cb.size(); i++)
-                        {
-                           const selectors& s = state.m_selectors_cb[i];
-
-                           uint total_error = 0;
-
-                           for (uint y = 0; y < cBlockPixelHeight; y++)
-                           {
-                              for (uint x = 0; x < cBlockPixelWidth; x++)
-                              {
-                                 int a = block.m_pixels[y][x][alpha_pixel_comp];
-                                 int b = block_values[s.m_selectors[y][x]];
-                                 int error = a - b;
-                                 error *= error;
-
-                                 total_error += error;
-                                 if (total_error > best_error)
-                                    goto early_out;
-                              } // x
-                           } //y
-
-   early_out:
-                           if (total_error < best_error)
-                           {
-                              best_error = total_error;
-                              best_index = i;
-
-                              if (best_error == 0)
-                                 break;
-                           }
-                        } // i
-   #endif
-
-                        CRNLIB_ASSERT( (tile_block_ofs_x + bx) < 2 );
-                        CRNLIB_ASSERT( (tile_block_ofs_y + by) < 2 );
-
-                        chunk.m_selector_cluster_index[tile_block_ofs_y + by][tile_block_ofs_x + bx] = static_cast<uint16>(best_index);
-
-                        {
-                           scoped_spinlock lock(state.m_chunk_blocks_using_selectors_lock);
-                           state.m_chunk_blocks_using_selectors[best_index].push_back( block_id(chunk_index, alpha_index, tile_index, tile_block_ofs_x + bx, tile_block_ofs_y + by ) );
-                        }
-                        //   std::make_pair(chunk_index, (tile_index << 16) | ((tile_block_ofs_y + by) << 8) | (tile_block_ofs_x + bx) ) );
-
-                     } // bx
-                  } // by
-
-               }
-               else
-               {
-                  color_quad_u8 block_colors[cDXT1SelectorValues];
-                  dxt1_block::get_block_colors4(block_colors, static_cast<uint16>(quantized_tile.m_first_endpoint), static_cast<uint16>(quantized_tile.m_second_endpoint));
-
-                  const bool block_with_alpha = quantized_tile.m_first_endpoint == quantized_tile.m_second_endpoint;
-
-                  for (uint by = 0; by < tile_blocks_y; by++)
-                  {
-                     for (uint bx = 0; bx < tile_blocks_x; bx++)
-                     {
-                        const dxt_pixel_block& block = m_pChunks[chunk_index].m_blocks[tile_block_ofs_y + by][tile_block_ofs_x + bx];
-
-                        uint best_error = UINT_MAX;
-                        uint best_index = 0;
-
-                        for (uint i = 0; i < state.m_selectors_cb.size(); i++)
-                        {
-                           const selectors& s = state.m_selectors_cb[i];
-
-                           uint total_error = 0;
-
-                           for (uint y = 0; y < cBlockPixelHeight; y++)
-                           {
-                              for (uint x = 0; x < cBlockPixelWidth; x++)
-                              {
-                                 const color_quad_u8& a = block.m_pixels[y][x];
-
-                                 uint selector_index = s.m_selectors[y][x];
-                                 if ((block_with_alpha) && (selector_index == 3))
-                                    total_error += 999999;
-
-                                 const color_quad_u8& b = block_colors[selector_index];
-
-                                 uint error = color::color_distance(m_params.m_perceptual, a, b, false);
-
-                                 total_error += error;
-                                 if (total_error > best_error)
-                                    goto early_out2;
-                              } // x
-                           } //y
-
-   early_out2:
-                           if (total_error < best_error)
-                           {
-                              best_error = total_error;
-                              best_index = i;
-
-                              if (best_error == 0)
-                                 break;
-                           }
-                        } // i
-
-                        CRNLIB_ASSERT( (tile_block_ofs_x + bx) < 2 );
-                        CRNLIB_ASSERT( (tile_block_ofs_y + by) < 2 );
-
-                        chunk.m_selector_cluster_index[tile_block_ofs_y + by][tile_block_ofs_x + bx] = static_cast<uint16>(best_index);
-
-                        {
-                           scoped_spinlock lock(state.m_chunk_blocks_using_selectors_lock);
-                           state.m_chunk_blocks_using_selectors[best_index].push_back( block_id(chunk_index, 0, tile_index, tile_block_ofs_x + bx, tile_block_ofs_y + by ) );
-                        }
-                        //   std::make_pair(chunk_index, (tile_index << 16) | ((tile_block_ofs_y + by) << 8) | (tile_block_ofs_x + bx) ) );
-
-                     } // bx
-                  } // by
-
-               } // if alpha_blocks
-
-            } // tile_index
-
-         } // chunk_index
-
-      } // comp_chunk_index
-   }
-
-   bool dxt_hc::create_selector_codebook(bool alpha_blocks)
-   {
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Computing selector training vectors");
-#endif
-
-      const uint cColorDistToWeight = 2000;
-      const uint cAlphaErrorToWeight = 8;
-
-      vec16F_tree_vq selector_vq;
-
-      uint comp_index_start = cColorChunks;
-      uint comp_index_end = cColorChunks;
-      if (alpha_blocks)
-      {
-         comp_index_start = cAlpha0Chunks;
-         comp_index_end = cAlpha0Chunks + m_num_alpha_blocks - 1;
-      }
-
-      crnlib::vector<vec16F> training_vecs[cNumCompressedChunkVecs][4];
-
-      for (uint comp_chunk_index = comp_index_start; comp_chunk_index <= comp_index_end; comp_chunk_index++)
-      {
-         for (uint i = 0; i < 4; i++)
-            training_vecs[comp_chunk_index][i].resize(m_num_chunks);
-
-         for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-         {
-            if ((chunk_index & 63) == 0)
-            {
-               if (!update_progress(9 + comp_chunk_index, chunk_index, m_num_chunks))
-                  return false;
-            }
-
-            const compressed_chunk& chunk = m_compressed_chunks[comp_chunk_index][chunk_index];
-
-            uint8 block_selectors[cChunkBlockWidth][cChunkBlockHeight][cBlockPixelWidth * cBlockPixelHeight];
-            uint block_weight[cChunkBlockWidth][cChunkBlockHeight];
-
-            for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-            {
-               const compressed_tile& quantized_tile = chunk.m_quantized_tiles[tile_index];
-
-               uint weight;
-               if (comp_chunk_index == cColorChunks)
-               {
-                  const color_quad_u8 first_color(dxt1_block::unpack_color(static_cast<uint16>(quantized_tile.m_first_endpoint), true));
-                  const color_quad_u8 second_color(dxt1_block::unpack_color(static_cast<uint16>(quantized_tile.m_second_endpoint), true));
-                  const uint dist = color::color_distance(m_params.m_perceptual, first_color, second_color, false);
-
-                  weight = dist / cColorDistToWeight;
-
-                  weight = static_cast<uint>(weight * m_pChunks[chunk_index].m_weight);
-               }
-               else
-               {
-                  int first_endpoint = quantized_tile.m_first_endpoint;
-                  int second_endpoint = quantized_tile.m_second_endpoint;
-                  int error = first_endpoint - second_endpoint;
-                  error = error * error;
-
-                  weight = static_cast<uint>(error / cAlphaErrorToWeight);
-               }
-
-               const uint cMaxWeight = 2048;
-
-               weight = math::clamp<uint>(weight, 1U, cMaxWeight);
-
-               // umm, this is a hack
-               float f = math::lerp(1.15f, 1.0f, chunk.m_encoding_index / float(cNumChunkEncodings - 1));
-               weight = (uint)(weight * f);
-
-               const chunk_tile_desc& layout = g_chunk_tile_layouts[quantized_tile.m_layout_index];
-
-               for (uint y = 0; y < (layout.m_height >> 2); y++)
-                  for (uint x = 0; x < (layout.m_width >> 2); x++)
-                     block_weight[x + (layout.m_x_ofs >> 2)][y + (layout.m_y_ofs >> 2)] = weight;
-
-               const uint8* pSelectors = quantized_tile.m_selectors;
-
-               for (uint y = 0; y < layout.m_height; y++)
-               {
-                  const uint cy = y + layout.m_y_ofs;
-
-                  for (uint x = 0; x < layout.m_width; x++)
-                  {
-                     const uint selector = pSelectors[x + y * layout.m_width];
-
-                     if (comp_chunk_index == cColorChunks)
-                        CRNLIB_ASSERT(selector < cDXT1SelectorValues);
-                     else
-                        CRNLIB_ASSERT(selector < cDXT5SelectorValues);
-
-                     const uint cx = x + layout.m_x_ofs;
-
-                     block_selectors[cx >> 2][cy >> 2][(cx & 3) + (cy & 3) * 4] = static_cast<uint8>(selector);
-                  } // x
-               } // y
-            } // tile_index
-
-            vec16F v;
-            for (uint y = 0; y < cChunkBlockHeight; y++)
-            {
-               for (uint x = 0; x < cChunkBlockWidth; x++)
-               {
-                  for (uint i = 0; i < cBlockPixelWidth * cBlockPixelHeight; i++)
-                  {
-                     uint s = block_selectors[x][y][i];
-
-                     float f;
-
-                     if (comp_chunk_index == cColorChunks)
-                     {
-                        CRNLIB_ASSERT(s < cDXT1SelectorValues);
-                        f = (g_dxt1_to_linear[s] + .5f) * 1.0f/4.0f;
-                     }
-                     else
-                     {
-                        CRNLIB_ASSERT(s < cDXT5SelectorValues);
-                        f = (g_dxt5_to_linear[s] + .5f) * 1.0f/8.0f;
-                     }
-
-                     CRNLIB_ASSERT((f >= 0.0f) && (f <= 1.0f));
-
-                     v[i] = f;
-                  } // i
-
-                  selector_vq.add_training_vec(v, block_weight[x][y]);
-
-                  training_vecs[comp_chunk_index][x+y*2][chunk_index] = v;
-               } // x
-            } // y
-
-         } // chunk_index
-
-      } // comp_chunk_index
-
-      timer t;
-      t.start();
-
-      selector_vq.generate_codebook(alpha_blocks ? m_params.m_alpha_selector_codebook_size : m_params.m_color_selector_codebook_size);
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-      {
-         double total_time = t.get_elapsed_secs();
-         console::info("Codebook gen time: %3.3fs, Selector codebook size: %u", total_time, selector_vq.get_codebook_size());
-      }
-#endif
-
-      selectors_vec& selectors_cb = alpha_blocks ? m_alpha_selectors : m_color_selectors;
-
-      selectors_cb.resize(selector_vq.get_codebook_size());
-
-      for (uint i = 0; i < selector_vq.get_codebook_size(); i++)
-      {
-         const vec16F& v = selector_vq.get_codebook_entry(i);
-
-         for (uint j = 0; j < cBlockPixelWidth * cBlockPixelHeight; j++)
-         {
-            int s;
-            if (alpha_blocks)
-            {
-               s = math::clamp<int>(static_cast<int>(v[j] * 8.0f), 0, 7);
-               s = g_dxt5_from_linear[s];
-            }
-            else
-            {
-               s = math::clamp<int>(static_cast<int>(v[j] * 4.0f), 0, 3);
-               s = g_dxt1_from_linear[s];
-            }
-
-            selectors_cb[i].m_selectors[j >> 2][j & 3] = static_cast<uint8>(s);
-         }  // j
-      } // i
-
-      chunk_blocks_using_selectors_vec& chunk_blocks_using_selectors = alpha_blocks ? m_chunk_blocks_using_alpha_selectors : m_chunk_blocks_using_color_selectors;
-
-      chunk_blocks_using_selectors.clear();
-      chunk_blocks_using_selectors.resize(selectors_cb.size());
-
-      create_selector_codebook_state state(*this, alpha_blocks, comp_index_start, comp_index_end, selector_vq, chunk_blocks_using_selectors, selectors_cb);
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &dxt_hc::create_selector_codebook_task, i, &state);
-
-      m_pTask_pool->join();
-
-      return !m_canceled;
-   }
-
-   bool dxt_hc::refine_quantized_color_selectors()
-   {
-      if (!m_has_color_blocks)
-         return true;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Refining quantized color selectors");
-#endif
-
-      uint total_refined_selectors = 0;
-      uint total_refined_pixels = 0;
-      uint total_selectors = 0;
-
-      for (uint selector_index = 0; selector_index < m_color_selectors.size(); selector_index++)
-      {
-         if ((selector_index & 255) == 0)
-         {
-            if (!update_progress(15, selector_index, m_color_selectors.size()))
-               return false;
-         }
-
-         if (m_chunk_blocks_using_color_selectors[selector_index].empty())
-            continue;
-
-         selectors& sel = m_color_selectors[selector_index];
-
-         for (uint y = 0; y < cBlockPixelHeight; y++)
-         {
-            for (uint x = 0; x < cBlockPixelWidth; x++)
-            {
-               uint best_s = 0;
-               uint best_error = UINT_MAX;
-
-               for (uint s = 0; s < cDXT1SelectorValues; s++)
-               {
-                  uint total_error = 0;
-
-                  for (uint block_iter = 0; block_iter < m_chunk_blocks_using_color_selectors[selector_index].size(); block_iter++)
-                  {
-                     const block_id& id = m_chunk_blocks_using_color_selectors[selector_index][block_iter];
-                     const uint chunk_index = id.m_chunk_index;
-                     const uint tile_index = id.m_tile_index;
-                     const uint chunk_block_x = id.m_block_x;
-                     const uint chunk_block_y = id.m_block_y;
-
-                     CRNLIB_ASSERT((chunk_block_x < cChunkBlockWidth) && (chunk_block_y < cChunkBlockHeight));
-
-                     const compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-                     CRNLIB_ASSERT(tile_index < chunk.m_num_tiles);
-
-                     CRNLIB_ASSERT(chunk.m_selector_cluster_index[chunk_block_y][chunk_block_x] == selector_index);
-
-                     const compressed_tile& tile = chunk.m_quantized_tiles[tile_index];
-
-                     //const chunk_tile_desc& tile_desc = g_chunk_tile_layouts[tile.m_layout_index];
-
-                     color_quad_u8 block_colors[cDXT1SelectorValues];
-                     CRNLIB_ASSERT(tile.m_first_endpoint >= tile.m_second_endpoint);
-                     dxt1_block::get_block_colors4(block_colors, static_cast<uint16>(tile.m_first_endpoint), static_cast<uint16>(tile.m_second_endpoint));
-
-                     if ((tile.m_first_endpoint == tile.m_second_endpoint) && (s == 3))
-                        total_error += 999999;
-
-                     const color_quad_u8& orig_pixel = m_pChunks[chunk_index](chunk_block_x * cBlockPixelWidth + x, chunk_block_y * cBlockPixelHeight + y);
-                     const color_quad_u8& quantized_pixel = block_colors[s];
-
-                     const uint error = color::color_distance(m_params.m_perceptual, orig_pixel, quantized_pixel, false);
-                     total_error += error;
-
-                  } // block_iter
-
-                  if (total_error < best_error)
-                  {
-                     best_error = total_error;
-                     best_s = s;
-                  }
-
-               } // s
-
-               if (sel.m_selectors[y][x] != best_s)
-               {
-                  total_refined_selectors++;
-                  total_refined_pixels += m_chunk_blocks_using_color_selectors[selector_index].size();
-                  sel.m_selectors[y][x] = static_cast<uint8>(best_s);
-               }
-
-               total_selectors++;
-
-            } //x
-
-         }  //y
-
-      } // selector_index
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Total refined pixels: %u, selectors: %u out of %u", total_refined_pixels, total_refined_selectors, total_selectors);
-#endif
-
-      return true;
-   }
-
-   bool dxt_hc::refine_quantized_alpha_selectors()
-   {
-      if (!m_num_alpha_blocks)
-         return true;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Refining quantized alpha selectors");
-#endif
-
-      uint total_refined_selectors = 0;
-      uint total_refined_pixels = 0;
-      uint total_selectors = 0;
-
-      for (uint selector_index = 0; selector_index < m_alpha_selectors.size(); selector_index++)
-      {
-         if ((selector_index & 255) == 0)
-         {
-            if (!update_progress(16, selector_index, m_alpha_selectors.size()))
-               return false;
-         }
-
-         if (m_chunk_blocks_using_alpha_selectors[selector_index].empty())
-            continue;
-
-         selectors& sel = m_alpha_selectors[selector_index];
-
-         for (uint y = 0; y < cBlockPixelHeight; y++)
-         {
-            for (uint x = 0; x < cBlockPixelWidth; x++)
-            {
-               uint best_s = 0;
-               uint best_error = UINT_MAX;
-
-               for (uint s = 0; s < cDXT5SelectorValues; s++)
-               {
-                  uint total_error = 0;
-
-                  for (uint block_iter = 0; block_iter < m_chunk_blocks_using_alpha_selectors[selector_index].size(); block_iter++)
-                  {
-                     const block_id& id = m_chunk_blocks_using_alpha_selectors[selector_index][block_iter];
-                     const uint chunk_index = id.m_chunk_index;
-                     const uint tile_index = id.m_tile_index;
-                     const uint chunk_block_x = id.m_block_x;
-                     const uint chunk_block_y = id.m_block_y;
-                     const uint alpha_index = id.m_alpha_index;
-                     CRNLIB_ASSERT(alpha_index < m_num_alpha_blocks);
-
-                     CRNLIB_ASSERT((chunk_block_x < cChunkBlockWidth) && (chunk_block_y < cChunkBlockHeight));
-
-                     const compressed_chunk& chunk = m_compressed_chunks[alpha_index + cAlpha0Chunks][chunk_index];
-                     CRNLIB_ASSERT(tile_index < chunk.m_num_tiles);
-
-                     CRNLIB_ASSERT(chunk.m_selector_cluster_index[chunk_block_y][chunk_block_x] == selector_index);
-
-                     const compressed_tile& tile = chunk.m_quantized_tiles[tile_index];
-
-                     //const chunk_tile_desc& tile_desc = g_chunk_tile_layouts[tile.m_layout_index];
-
-                     uint block_values[cDXT5SelectorValues];
-                     CRNLIB_ASSERT(tile.m_first_endpoint >= tile.m_second_endpoint);
-                     dxt5_block::get_block_values(block_values, tile.m_first_endpoint, tile.m_second_endpoint);
-
-                     int orig_value = m_pChunks[chunk_index](chunk_block_x * cBlockPixelWidth + x, chunk_block_y * cBlockPixelHeight + y)[m_params.m_alpha_component_indices[alpha_index]];
-                     int quantized_value = block_values[s];
-
-                     int error = (orig_value - quantized_value);
-                     error *= error;
-
-                     total_error += error;
-
-                  } // block_iter
-
-                  if (total_error < best_error)
-                  {
-                     best_error = total_error;
-                     best_s = s;
-                  }
-
-               } // s
-
-               if (sel.m_selectors[y][x] != best_s)
-               {
-                  total_refined_selectors++;
-                  total_refined_pixels += m_chunk_blocks_using_alpha_selectors[selector_index].size();
-                  sel.m_selectors[y][x] = static_cast<uint8>(best_s);
-               }
-
-               total_selectors++;
-
-            } //x
-
-         }  //y
-
-      } // selector_index
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Total refined pixels: %u, selectors: %u out of %u", total_refined_pixels, total_refined_selectors, total_selectors);
-#endif
-
-      return true;
-   }
-
-   bool dxt_hc::refine_quantized_color_endpoints()
-   {
-      if (!m_has_color_blocks)
-         return true;
-
-      uint total_refined_tiles = 0;
-      uint total_refined_pixels = 0;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Refining quantized color endpoints");
-#endif
-
-      for (uint cluster_index = 0; cluster_index < m_color_clusters.size(); cluster_index++)
-      {
-         if ((cluster_index & 255) == 0)
-         {
-            if (!update_progress(17, cluster_index, m_color_clusters.size()))
-               return false;
-         }
-
-         tile_cluster& cluster = m_color_clusters[cluster_index];
-
-         uint total_pixels = 0;
-         for (uint tile_iter = 0; tile_iter < cluster.m_tiles.size(); tile_iter++)
-         {
-            const uint chunk_index = cluster.m_tiles[tile_iter].first;
-            const uint tile_index = cluster.m_tiles[tile_iter].second;
-
-            compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-            compressed_tile& tile = chunk.m_quantized_tiles[tile_index];
-
-            CRNLIB_ASSERT(tile.m_first_endpoint == cluster.m_first_endpoint);
-            CRNLIB_ASSERT(tile.m_second_endpoint == cluster.m_second_endpoint);
-
-            total_pixels += (tile.m_pixel_width * tile.m_pixel_height);
-         }
-
-         if (!total_pixels)
-            continue;
-
-         crnlib::vector<color_quad_u8> pixels;
-         crnlib::vector<uint8> selectors;
-
-         pixels.reserve(total_pixels);
-         selectors.reserve(total_pixels);
-
-         for (uint tile_iter = 0; tile_iter < cluster.m_tiles.size(); tile_iter++)
-         {
-            const uint chunk_index = cluster.m_tiles[tile_iter].first;
-            const uint tile_index = cluster.m_tiles[tile_iter].second;
-
-            compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-            compressed_tile& tile = chunk.m_quantized_tiles[tile_index];
-
-            const pixel_chunk& src_pixels = m_pChunks[chunk_index];
-
-            CRNLIB_ASSERT(tile.m_first_endpoint == cluster.m_first_endpoint);
-            CRNLIB_ASSERT(tile.m_second_endpoint == cluster.m_second_endpoint);
-
-            const chunk_tile_desc& tile_layout = g_chunk_tile_layouts[tile.m_layout_index];
-
-            for (uint y = 0; y < tile.m_pixel_height; y++)
-            {
-               for (uint x = 0; x < tile.m_pixel_width; x++)
-               {
-                  selectors.push_back(tile.m_selectors[x + y * tile.m_pixel_width]);
-
-                  pixels.push_back(src_pixels(x + tile_layout.m_x_ofs, y + tile_layout.m_y_ofs));
-               }
-            }
-         }
-
-         dxt_endpoint_refiner refiner;
-         dxt_endpoint_refiner::params p;
-         dxt_endpoint_refiner::results r;
-
-         p.m_perceptual = m_params.m_perceptual;
-         p.m_pSelectors = &selectors[0];
-         p.m_pPixels = &pixels[0];
-         p.m_num_pixels = total_pixels;
-         p.m_dxt1_selectors = true;
-         p.m_error_to_beat = cluster.m_error;
-         p.m_block_index = cluster_index;
-
-         if (!refiner.refine(p, r))
-            continue;
-
-         total_refined_tiles++;
-         total_refined_pixels += total_pixels;
-
-         cluster.m_error = r.m_error;
-
-         cluster.m_first_endpoint = r.m_low_color;
-         cluster.m_second_endpoint = r.m_high_color;
-
-         for (uint tile_iter = 0; tile_iter < cluster.m_tiles.size(); tile_iter++)
-         {
-            const uint chunk_index = cluster.m_tiles[tile_iter].first;
-            const uint tile_index = cluster.m_tiles[tile_iter].second;
-
-            compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-            compressed_tile& tile = chunk.m_quantized_tiles[tile_index];
-
-            tile.m_first_endpoint = r.m_low_color;
-            tile.m_second_endpoint = r.m_high_color;
-         }
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Total refined pixels: %u, endpoints: %u out of %u", total_refined_pixels, total_refined_tiles, m_color_clusters.size());
-#endif
-
-      return true;
-   }
-
-   bool dxt_hc::refine_quantized_alpha_endpoints()
-   {
-      if (!m_num_alpha_blocks)
-         return true;
-
-      uint total_refined_tiles = 0;
-      uint total_refined_pixels = 0;
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Refining quantized alpha endpoints");
-#endif
-
-      for (uint cluster_index = 0; cluster_index < m_alpha_clusters.size(); cluster_index++)
-      {
-         if ((cluster_index & 255) == 0)
-         {
-            if (!update_progress(18, cluster_index, m_alpha_clusters.size()))
-               return false;
-         }
-
-         tile_cluster& cluster = m_alpha_clusters[cluster_index];
-
-         uint total_pixels = 0;
-         for (uint tile_iter = 0; tile_iter < cluster.m_tiles.size(); tile_iter++)
-         {
-            const uint chunk_index = cluster.m_tiles[tile_iter].first;
-            const uint tile_index = cluster.m_tiles[tile_iter].second & 0xFFFFU;
-            const uint alpha_index = cluster.m_tiles[tile_iter].second >> 16U;
-
-            compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + alpha_index][chunk_index];
-            compressed_tile& tile = chunk.m_quantized_tiles[tile_index];
-
-            CRNLIB_ASSERT(tile.m_first_endpoint == cluster.m_first_endpoint);
-            CRNLIB_ASSERT(tile.m_second_endpoint == cluster.m_second_endpoint);
-
-            total_pixels += (tile.m_pixel_width * tile.m_pixel_height);
-         }
-
-         if (!total_pixels)
-            continue;
-
-         crnlib::vector<color_quad_u8> pixels;
-         crnlib::vector<uint8> selectors;
-
-         pixels.reserve(total_pixels);
-         selectors.reserve(total_pixels);
-
-         for (uint tile_iter = 0; tile_iter < cluster.m_tiles.size(); tile_iter++)
-         {
-            const uint chunk_index = cluster.m_tiles[tile_iter].first;
-            const uint tile_index = cluster.m_tiles[tile_iter].second & 0xFFFFU;
-            const uint alpha_index = cluster.m_tiles[tile_iter].second >> 16U;
-
-            compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + alpha_index][chunk_index];
-            compressed_tile& tile = chunk.m_quantized_tiles[tile_index];
-
-            const pixel_chunk& src_pixels = m_pChunks[chunk_index];
-
-            CRNLIB_ASSERT(tile.m_first_endpoint == cluster.m_first_endpoint);
-            CRNLIB_ASSERT(tile.m_second_endpoint == cluster.m_second_endpoint);
-
-            const chunk_tile_desc& tile_layout = g_chunk_tile_layouts[tile.m_layout_index];
-
-            for (uint y = 0; y < tile.m_pixel_height; y++)
-            {
-               for (uint x = 0; x < tile.m_pixel_width; x++)
-               {
-                  selectors.push_back(tile.m_selectors[x + y * tile.m_pixel_width]);
-
-                  pixels.push_back(color_quad_u8(src_pixels(x + tile_layout.m_x_ofs, y + tile_layout.m_y_ofs)[m_params.m_alpha_component_indices[alpha_index]]));
-               }
-            }
-         }
-
-         dxt_endpoint_refiner refiner;
-         dxt_endpoint_refiner::params p;
-         dxt_endpoint_refiner::results r;
-
-         p.m_perceptual = m_params.m_perceptual;
-         p.m_pSelectors = &selectors[0];
-         p.m_pPixels = &pixels[0];
-         p.m_num_pixels = total_pixels;
-         p.m_dxt1_selectors = false;
-         p.m_error_to_beat = cluster.m_error;
-         p.m_block_index = cluster_index;
-
-         if (!refiner.refine(p, r))
-            continue;
-
-         total_refined_tiles++;
-         total_refined_pixels += total_pixels;
-
-         cluster.m_error = r.m_error;
-
-         cluster.m_first_endpoint = r.m_low_color;
-         cluster.m_second_endpoint = r.m_high_color;
-
-         for (uint tile_iter = 0; tile_iter < cluster.m_tiles.size(); tile_iter++)
-         {
-            const uint chunk_index = cluster.m_tiles[tile_iter].first;
-            const uint tile_index = cluster.m_tiles[tile_iter].second & 0xFFFFU;
-            const uint alpha_index = cluster.m_tiles[tile_iter].second >> 16U;
-
-            compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + alpha_index][chunk_index];
-            compressed_tile& tile = chunk.m_quantized_tiles[tile_index];
-
-            tile.m_first_endpoint = r.m_low_color;
-            tile.m_second_endpoint = r.m_high_color;
-         }
-      }
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         console::info("Total refined pixels: %u, endpoints: %u out of %u", total_refined_pixels, total_refined_tiles, m_alpha_clusters.size());
-#endif
-
-      return true;
-   }
-
-   void dxt_hc::create_final_debug_image()
-   {
-      if (!m_params.m_debugging)
-         return;
-
-      m_dbg_chunk_pixels_final.resize(m_num_chunks);
-      for (uint i = 0; i < m_num_chunks; i++)
-         m_dbg_chunk_pixels_final[i].clear();
-
-      if (m_has_color_blocks)
-      {
-         m_dbg_chunk_pixels_final_color_selectors.resize(m_num_chunks);
-         for (uint i = 0; i < m_num_chunks; i++)
-            m_dbg_chunk_pixels_final_color_selectors[i].clear();
-      }
-
-      if (m_num_alpha_blocks)
-      {
-         m_dbg_chunk_pixels_final_alpha_selectors.resize(m_num_chunks);
-         for (uint i = 0; i < m_num_chunks; i++)
-            m_dbg_chunk_pixels_final_alpha_selectors[i].clear();
-      }
-
-      for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-      {
-         pixel_chunk& output_chunk_final = m_dbg_chunk_pixels_final[chunk_index];
-
-         if (m_has_color_blocks)
-         {
-            const compressed_chunk& chunk = m_compressed_chunks[cColorChunks][chunk_index];
-
-            pixel_chunk& output_chunk_quantized_color_selectors = m_dbg_chunk_pixels_final_color_selectors[chunk_index];
-
-            for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-            {
-               const compressed_tile& quantized_tile = chunk.m_quantized_tiles[tile_index];
-
-               const chunk_tile_desc& layout = g_chunk_tile_layouts[quantized_tile.m_layout_index];
-
-               color_quad_u8 block_colors[cDXT1SelectorValues];
-               dxt1_block::get_block_colors(block_colors, static_cast<uint16>(quantized_tile.m_first_endpoint), static_cast<uint16>(quantized_tile.m_second_endpoint));
-
-               for (uint y = 0; y < layout.m_height; y++)
-               {
-                  for (uint x = 0; x < layout.m_width; x++)
-                  {
-                     const uint chunk_x_ofs = x + layout.m_x_ofs;
-                     const uint chunk_y_ofs = y + layout.m_y_ofs;
-                     const uint block_x = chunk_x_ofs >> 2;
-                     const uint block_y = chunk_y_ofs >> 2;
-                     const selectors& s = m_color_selectors[chunk.m_selector_cluster_index[block_y][block_x]];
-
-                     uint selector = s.m_selectors[chunk_y_ofs & 3][chunk_x_ofs & 3];
-
-                     output_chunk_final(x + layout.m_x_ofs, y + layout.m_y_ofs) = block_colors[selector];
-                     output_chunk_quantized_color_selectors(x + layout.m_x_ofs, y + layout.m_y_ofs) = g_tile_layout_colors[selector];
-                  }
-               }
-            }
-         }
-
-         if (m_num_alpha_blocks)
-         {
-            pixel_chunk& output_chunk_quantized_alpha_selectors = m_dbg_chunk_pixels_final_alpha_selectors[chunk_index];
-
-            for (uint a = 0; a < m_num_alpha_blocks; a++)
-            {
-               const compressed_chunk& chunk = m_compressed_chunks[cAlpha0Chunks + a][chunk_index];
-
-               for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-               {
-                  const compressed_tile& quantized_tile = chunk.m_quantized_tiles[tile_index];
-
-                  const chunk_tile_desc& layout = g_chunk_tile_layouts[quantized_tile.m_layout_index];
-
-                  uint block_values[cDXT5SelectorValues];
-
-                  // purposely call the general version to debug single color alpah6 blocks
-                  CRNLIB_ASSERT(quantized_tile.m_first_endpoint >= quantized_tile.m_second_endpoint);
-                  dxt5_block::get_block_values(block_values, quantized_tile.m_first_endpoint, quantized_tile.m_second_endpoint);
-
-                  for (uint y = 0; y < layout.m_height; y++)
-                  {
-                     for (uint x = 0; x < layout.m_width; x++)
-                     {
-                        const uint chunk_x_ofs = x + layout.m_x_ofs;
-                        const uint chunk_y_ofs = y + layout.m_y_ofs;
-                        const uint block_x = chunk_x_ofs >> 2;
-                        const uint block_y = chunk_y_ofs >> 2;
-                        const selectors& s = m_alpha_selectors[chunk.m_selector_cluster_index[block_y][block_x]];
-
-                        uint selector = s.m_selectors[chunk_y_ofs & 3][chunk_x_ofs & 3];
-
-                        CRNLIB_ASSERT(selector < cDXT5SelectorValues);
-
-                        output_chunk_final(x + layout.m_x_ofs, y + layout.m_y_ofs)[m_params.m_alpha_component_indices[a]] = static_cast<uint8>(block_values[selector]);
-
-                        output_chunk_quantized_alpha_selectors(x + layout.m_x_ofs, y + layout.m_y_ofs)[m_params.m_alpha_component_indices[a]] = static_cast<uint8>(selector*255/(cDXT5SelectorValues-1));
-                     } //x
-                  } // y
-               } // tile_index
-
-            } // a
-         }
-      } // chunk_index
-
-   }
-
-   bool dxt_hc::create_chunk_encodings()
-   {
-      m_chunk_encoding.resize(m_num_chunks);
-
-      for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++)
-      {
-         if ((chunk_index & 255) == 0)
-         {
-            if (!update_progress(19, chunk_index, m_num_chunks))
-               return false;
-         }
-
-         chunk_encoding& encoding = m_chunk_encoding[chunk_index];
-
-         for (uint q = 0; q < cNumCompressedChunkVecs; q++)
-         {
-            bool skip = true;
-            if (q == cColorChunks)
-            {
-               if (m_has_color_blocks)
-                  skip = false;
-            }
-            else if (q <= m_num_alpha_blocks)
-               skip = false;
-
-            if (skip)
-               continue;
-
-            CRNLIB_ASSERT(!m_compressed_chunks[q].empty());
-            const compressed_chunk& chunk = m_compressed_chunks[q][chunk_index];
-
-            CRNLIB_ASSERT(chunk.m_encoding_index < cNumChunkEncodings);
-            encoding.m_encoding_index = static_cast<uint8>(chunk.m_encoding_index);
-
-            CRNLIB_ASSERT(chunk.m_num_tiles <= cChunkMaxTiles);
-            encoding.m_num_tiles = static_cast<uint8>(chunk.m_num_tiles);
-
-            for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++)
-            {
-               const compressed_tile& quantized_tile = chunk.m_quantized_tiles[tile_index];
-
-               if (!q)
-               {
-                  CRNLIB_ASSERT(quantized_tile.m_endpoint_cluster_index < m_color_clusters.size());
-               }
-               else
-               {
-                  CRNLIB_ASSERT(quantized_tile.m_endpoint_cluster_index < m_alpha_clusters.size());
-               }
-
-               encoding.m_endpoint_indices[q][tile_index] = static_cast<uint16>(quantized_tile.m_endpoint_cluster_index);
-            }
-
-            for (uint y = 0; y < cChunkBlockHeight; y++)
-            {
-               for (uint x = 0; x < cChunkBlockWidth; x++)
-               {
-                  const uint selector_index = chunk.m_selector_cluster_index[y][x];
-
-                  if (!q)
-                  {
-                     CRNLIB_ASSERT(selector_index < m_color_selectors.size());
-                  }
-                  else
-                  {
-                     CRNLIB_ASSERT(selector_index < m_alpha_selectors.size());
-                  }
-
-                  encoding.m_selector_indices[q][y][x] = static_cast<uint16>(selector_index);
-               }
-            }
-
-         } // q
-
-      } // chunk_index
-
-      if (m_has_color_blocks)
-      {
-         m_color_endpoints.resize(m_color_clusters.size());
-         for (uint i = 0; i < m_color_clusters.size(); i++)
-            m_color_endpoints[i] = dxt1_block::pack_endpoints(m_color_clusters[i].m_first_endpoint, m_color_clusters[i].m_second_endpoint);
-      }
-
-      if (m_num_alpha_blocks)
-      {
-         m_alpha_endpoints.resize(m_alpha_clusters.size());
-         for (uint i = 0; i < m_alpha_clusters.size(); i++)
-            m_alpha_endpoints[i] = dxt5_block::pack_endpoints(m_alpha_clusters[i].m_first_endpoint, m_alpha_clusters[i].m_second_endpoint);
-      }
-
-      return true;
-   }
-
-   void dxt_hc::create_debug_image_from_chunks(uint num_chunks_x, uint num_chunks_y, const pixel_chunk_vec& chunks, const chunk_encoding_vec *pChunk_encodings, image_u8& img, bool serpentine_scan, int comp_index)
-   {
-      if (chunks.empty())
-      {
-         img.set_all(color_quad_u8::make_black());
-         return;
-      }
-
-      img.resize(num_chunks_x * cChunkPixelWidth, num_chunks_y * cChunkPixelHeight);
-
-      for (uint y = 0; y < num_chunks_y; y++)
-      {
-         for (uint x = 0; x < num_chunks_x; x++)
-         {
-            uint c = x + y * num_chunks_x;
-            if ((serpentine_scan) && (y & 1))
-               c = (num_chunks_x - 1 - x) + y * num_chunks_x;
-
-            if (comp_index >= 0)
-            {
-               for (uint cy = 0; cy < cChunkPixelHeight; cy++)
-                  for (uint cx = 0; cx < cChunkPixelWidth; cx++)
-                     img(x * cChunkPixelWidth + cx, y * cChunkPixelHeight + cy) = chunks[c](cx, cy)[comp_index];
-            }
-            else
-            {
-               for (uint cy = 0; cy < cChunkPixelHeight; cy++)
-                  for (uint cx = 0; cx < cChunkPixelWidth; cx++)
-                     img(x * cChunkPixelWidth + cx, y * cChunkPixelHeight + cy) = chunks[c](cx, cy);
-            }
-
-            if (pChunk_encodings)
-            {
-               const chunk_encoding& chunk = (*pChunk_encodings)[c];
-               const chunk_encoding_desc &encoding_desc = g_chunk_encodings[chunk.m_encoding_index];
-               CRNLIB_ASSERT(chunk.m_num_tiles == encoding_desc.m_num_tiles);
-               for (uint t = 0; t < chunk.m_num_tiles; t++)
-               {
-                  const chunk_tile_desc &tile_desc = encoding_desc.m_tiles[t];
-
-                  img.unclipped_fill_box(
-                     x*8 + tile_desc.m_x_ofs, y*8 + tile_desc.m_y_ofs,
-                     tile_desc.m_width + 1, tile_desc.m_height + 1, color_quad_u8(128, 128, 128, 255));
-               }
-            }
-         }
-      }
-   }
-
-   bool dxt_hc::update_progress(uint phase_index, uint subphase_index, uint subphase_total)
-   {
-      CRNLIB_ASSERT(crn_get_current_thread_id() == m_main_thread_id);
-
-      if (!m_params.m_pProgress_func)
-         return true;
-
-#if CRNLIB_ENABLE_DEBUG_MESSAGES
-      if (m_params.m_debugging)
-         return true;
-#endif
-
-      const int percentage_complete = (subphase_total > 1) ? ((100 * subphase_index) / (subphase_total - 1)) : 100;
-      if (((int)phase_index == m_prev_phase_index) && (m_prev_percentage_complete == percentage_complete))
-         return !m_canceled;
-
-      m_prev_percentage_complete = percentage_complete;
-
-      bool status = (*m_params.m_pProgress_func)(phase_index, cTotalCompressionPhases, subphase_index, subphase_total, m_params.m_pProgress_func_data) != 0;
-      if (!status)
-      {
-         m_canceled = true;
-         return false;
-      }
-
-      return true;
-   }
-
-} // namespace crnlib

+ 0 - 439
Source/ThirdParty/crunch/crnlib/crn_dxt_hc.h

@@ -1,439 +0,0 @@
-// File: crn_dxt_hc.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dxt1.h"
-#include "crn_dxt5a.h"
-#include "crn_dxt_endpoint_refiner.h"
-#include "crn_image.h"
-#include "crn_dxt.h"
-#include "crn_image.h"
-#include "crn_dxt_hc_common.h"
-#include "crn_tree_clusterizer.h"
-#include "crn_threading.h"
-
-#define CRN_NO_FUNCTION_DEFINITIONS
-#include "../inc/crnlib.h"
-
-namespace crnlib
-{
-   const uint cTotalCompressionPhases = 25;
-
-   class dxt_hc
-   {
-   public:
-      dxt_hc();
-      ~dxt_hc();
-
-      struct pixel_chunk
-      {
-         pixel_chunk() { clear(); }
-
-         dxt_pixel_block m_blocks[cChunkBlockHeight][cChunkBlockWidth];
-
-         const color_quad_u8& operator() (uint cx, uint cy) const
-         {
-            CRNLIB_ASSERT((cx < cChunkPixelWidth) && (cy < cChunkPixelHeight));
-
-            return m_blocks[cy >> cBlockPixelHeightShift][cx >> cBlockPixelWidthShift].m_pixels
-                           [cy & (cBlockPixelHeight - 1)][cx & (cBlockPixelWidth - 1)];
-         }
-
-         color_quad_u8& operator() (uint cx, uint cy)
-         {
-            CRNLIB_ASSERT((cx < cChunkPixelWidth) && (cy < cChunkPixelHeight));
-
-            return m_blocks[cy >> cBlockPixelHeightShift][cx >> cBlockPixelWidthShift].m_pixels
-                           [cy & (cBlockPixelHeight - 1)][cx & (cBlockPixelWidth - 1)];
-         }
-
-         inline void clear()
-         {
-            utils::zero_object(*this);
-            m_weight = 1.0f;
-         }
-
-         float m_weight;
-      };
-
-      typedef crnlib::vector<pixel_chunk> pixel_chunk_vec;
-
-      struct params
-      {
-         params() :
-            m_color_endpoint_codebook_size(3072),
-            m_color_selector_codebook_size(3072),
-            m_alpha_endpoint_codebook_size(3072),
-            m_alpha_selector_codebook_size(3072),
-            m_adaptive_tile_color_psnr_derating(2.0f), // was 3.4f
-            m_adaptive_tile_alpha_psnr_derating(2.0f),
-            m_adaptive_tile_color_alpha_weighting_ratio(3.0f),
-            m_num_levels(0),
-            m_format(cDXT1),
-            m_hierarchical(true),
-            m_perceptual(true),
-            m_debugging(false),
-            m_pProgress_func(NULL),
-            m_pProgress_func_data(NULL)
-         {
-            m_alpha_component_indices[0] = 3;
-            m_alpha_component_indices[1] = 0;
-
-            for (uint i = 0; i < cCRNMaxLevels; i++)
-            {
-               m_levels[i].m_first_chunk = 0;
-               m_levels[i].m_num_chunks = 0;
-            }
-         }
-
-         // Valid range for codebook sizes: [32,8192] (non-power of two values are okay)
-         uint        m_color_endpoint_codebook_size;
-         uint        m_color_selector_codebook_size;
-
-         uint        m_alpha_endpoint_codebook_size;
-         uint        m_alpha_selector_codebook_size;
-
-         // Higher values cause fewer 8x4, 4x8, and 4x4 blocks to be utilized less often (lower quality/smaller files).
-         // Lower values cause the encoder to use large tiles less often (better quality/larger files).
-         // Valid range: [0.0,100.0].
-         // A value of 0 will cause the encoder to only use tiles larger than 4x4 if doing so would incur to quality loss.
-         float       m_adaptive_tile_color_psnr_derating;
-
-         float       m_adaptive_tile_alpha_psnr_derating;
-
-         float       m_adaptive_tile_color_alpha_weighting_ratio;
-
-         uint        m_alpha_component_indices[2];
-
-         struct miplevel_desc
-         {
-            uint m_first_chunk;
-            uint m_num_chunks;
-         };
-         // The mip level data is optional!
-         miplevel_desc m_levels[cCRNMaxLevels];
-         uint        m_num_levels;
-
-         dxt_format  m_format;
-
-         // If m_hierarchical is false, only 4x4 blocks will be used by the encoder (leading to higher quality/larger files).
-         bool        m_hierarchical;
-
-         // If m_perceptual is true, perceptual color metrics will be used by the encoder.
-         bool        m_perceptual;
-
-         bool        m_debugging;
-
-         crn_progress_callback_func m_pProgress_func;
-         void*       m_pProgress_func_data;
-      };
-
-      void clear();
-
-      // Main compression function
-      bool compress(const params& p, uint num_chunks, const pixel_chunk* pChunks, task_pool& task_pool);
-
-      // Output accessors
-      inline uint get_num_chunks() const { return m_num_chunks; }
-
-      struct chunk_encoding
-      {
-         chunk_encoding() { utils::zero_object(*this); };
-
-         // Index into g_chunk_encodings.
-         uint8 m_encoding_index;
-
-         // Number of tiles, endpoint indices.
-         uint8 m_num_tiles;
-
-         // Color, alpha0, alpha1
-         enum { cColorIndex = 0, cAlpha0Index = 1, cAlpha1Index = 2 };
-         uint16 m_endpoint_indices[3][cChunkMaxTiles];
-         uint16 m_selector_indices[3][cChunkBlockHeight][cChunkBlockWidth];   // [block_y][block_x]
-      };
-
-      typedef crnlib::vector<chunk_encoding> chunk_encoding_vec;
-
-      inline const chunk_encoding& get_chunk_encoding(uint chunk_index) const { return m_chunk_encoding[chunk_index]; }
-      inline const chunk_encoding_vec& get_chunk_encoding_vec() const { return m_chunk_encoding; }
-
-      struct selectors
-      {
-         selectors() { utils::zero_object(*this); }
-
-         uint8 m_selectors[cBlockPixelHeight][cBlockPixelWidth];
-
-         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<uint8>(v); }
-      };
-      typedef crnlib::vector<selectors> selectors_vec;
-
-      // Color endpoints
-      inline uint get_color_endpoint_codebook_size() const { return m_color_endpoints.size(); }
-      inline uint get_color_endpoint(uint codebook_index) const { return m_color_endpoints[codebook_index]; }
-      const crnlib::vector<uint>& get_color_endpoint_vec() const { return m_color_endpoints; }
-
-      // Color selectors
-      uint get_color_selector_codebook_size() const { return m_color_selectors.size(); }
-      const selectors& get_color_selectors(uint codebook_index) const { return m_color_selectors[codebook_index]; }
-      const crnlib::vector<selectors>& get_color_selectors_vec() const { return m_color_selectors; }
-
-      // Alpha endpoints
-      inline uint get_alpha_endpoint_codebook_size() const { return m_alpha_endpoints.size(); }
-      inline uint get_alpha_endpoint(uint codebook_index) const { return m_alpha_endpoints[codebook_index]; }
-      const crnlib::vector<uint>& get_alpha_endpoint_vec() const { return m_alpha_endpoints; }
-
-      // Alpha selectors
-      uint get_alpha_selector_codebook_size() const { return m_alpha_selectors.size(); }
-      const selectors& get_alpha_selectors(uint codebook_index) const { return m_alpha_selectors[codebook_index]; }
-      const crnlib::vector<selectors>& get_alpha_selectors_vec() const { return m_alpha_selectors; }
-
-      // Debug images
-      const pixel_chunk_vec& get_compressed_chunk_pixels() const { return m_dbg_chunk_pixels; }
-      const pixel_chunk_vec& get_compressed_chunk_pixels_tile_vis() const { return m_dbg_chunk_pixels_tile_vis; }
-      const pixel_chunk_vec& get_compressed_chunk_pixels_color_quantized() const { return m_dbg_chunk_pixels_color_quantized; }
-      const pixel_chunk_vec& get_compressed_chunk_pixels_alpha_quantized() const { return m_dbg_chunk_pixels_alpha_quantized; }
-      const pixel_chunk_vec& get_compressed_chunk_pixels_final() const { return m_dbg_chunk_pixels_final; }
-
-      const pixel_chunk_vec& get_compressed_chunk_pixels_orig_color_selectors() const { return m_dbg_chunk_pixels_orig_color_selectors; }
-      const pixel_chunk_vec& get_compressed_chunk_pixels_quantized_color_selectors() const { return m_dbg_chunk_pixels_quantized_color_selectors; }
-      const pixel_chunk_vec& get_compressed_chunk_pixels_final_color_selectors() const { return m_dbg_chunk_pixels_final_color_selectors; }
-
-      const pixel_chunk_vec& get_compressed_chunk_pixels_orig_alpha_selectors() const { return m_dbg_chunk_pixels_orig_alpha_selectors; }
-      const pixel_chunk_vec& get_compressed_chunk_pixels_quantized_alpha_selectors() const { return m_dbg_chunk_pixels_quantized_alpha_selectors; }
-      const pixel_chunk_vec& get_compressed_chunk_pixels_final_alpha_selectors() const { return m_dbg_chunk_pixels_final_alpha_selectors; }
-
-      static void create_debug_image_from_chunks(uint num_chunks_x, uint num_chunks_y, const pixel_chunk_vec& chunks, const chunk_encoding_vec *pChunk_encodings, image_u8& img, bool serpentine_scan, int comp_index = -1);
-
-   private:
-      params               m_params;
-
-      uint                 m_num_chunks;
-      const pixel_chunk*   m_pChunks;
-
-      chunk_encoding_vec   m_chunk_encoding;
-
-      uint                 m_num_alpha_blocks; // 0, 1, or 2
-      bool                 m_has_color_blocks;
-      bool                 m_has_alpha0_blocks;
-      bool                 m_has_alpha1_blocks;
-
-      struct compressed_tile
-      {
-         uint m_endpoint_cluster_index;
-         uint m_first_endpoint;
-         uint m_second_endpoint;
-
-         uint8 m_selectors[cChunkPixelWidth * cChunkPixelHeight];
-
-         void set_selector(uint x, uint y, uint s)
-         {
-            CRNLIB_ASSERT((x < m_pixel_width) && (y < m_pixel_height));
-            m_selectors[x + y * m_pixel_width] = static_cast<uint8>(s);
-         }
-
-         uint get_selector(uint x, uint y) const
-         {
-            CRNLIB_ASSERT((x < m_pixel_width) && (y < m_pixel_height));
-            return m_selectors[x + y * m_pixel_width];
-         }
-
-         uint8 m_pixel_width;
-         uint8 m_pixel_height;
-
-         uint8 m_layout_index;
-
-         bool m_alpha_encoding;
-      };
-
-      struct compressed_chunk
-      {
-         compressed_chunk() { utils::zero_object(*this); }
-
-         uint8 m_encoding_index;
-
-         uint8 m_num_tiles;
-
-         compressed_tile m_tiles[cChunkMaxTiles];
-         compressed_tile m_quantized_tiles[cChunkMaxTiles];
-
-         uint16 m_endpoint_cluster_index[cChunkMaxTiles];
-         uint16 m_selector_cluster_index[cChunkBlockHeight][cChunkBlockWidth];
-      };
-
-      typedef crnlib::vector<compressed_chunk> compressed_chunk_vec;
-      enum
-      {
-         cColorChunks = 0,
-         cAlpha0Chunks = 1,
-         cAlpha1Chunks = 2,
-
-         cNumCompressedChunkVecs = 3
-      };
-      compressed_chunk_vec m_compressed_chunks[cNumCompressedChunkVecs];
-
-      volatile atomic32_t m_encoding_hist[cNumChunkEncodings];
-
-      atomic32_t m_total_tiles;
-
-      void compress_dxt1_block(
-         dxt1_endpoint_optimizer::results& results,
-         uint chunk_index, const image_u8& chunk, uint x_ofs, uint y_ofs, uint width, uint height,
-         uint8* pSelectors);
-
-      void compress_dxt5_block(
-         dxt5_endpoint_optimizer::results& results,
-         uint chunk_index, const image_u8& chunk, uint x_ofs, uint y_ofs, uint width, uint height, uint component_index,
-         uint8* pAlpha_selectors);
-
-      void determine_compressed_chunks_task(uint64 data, void* pData_ptr);
-      bool determine_compressed_chunks();
-
-      struct tile_cluster
-      {
-         tile_cluster() : m_first_endpoint(0), m_second_endpoint(0), m_error(0), m_alpha_encoding(false) { }
-
-         // first = chunk, second = tile
-         // if an alpha tile, second's upper 16 bits contains the alpha index (0 or 1)
-         crnlib::vector< std::pair<uint, uint> > m_tiles;
-
-         uint m_first_endpoint;
-         uint m_second_endpoint;
-         uint64 m_error;
-
-         bool m_alpha_encoding;
-      };
-
-      typedef crnlib::vector<tile_cluster> tile_cluster_vec;
-
-      tile_cluster_vec m_color_clusters;
-      tile_cluster_vec m_alpha_clusters;
-
-      selectors_vec m_color_selectors;
-      selectors_vec m_alpha_selectors;
-
-      // For each selector, this array indicates every chunk/tile/tile block that use this color selector.
-      struct block_id
-      {
-         block_id() { utils::zero_object(*this); }
-
-         block_id(uint chunk_index, uint alpha_index, uint tile_index, uint block_x, uint block_y) :
-            m_chunk_index(chunk_index), m_alpha_index((uint8)alpha_index), m_tile_index((uint8)tile_index), m_block_x((uint8)block_x), m_block_y((uint8)block_y) { }
-
-         uint m_chunk_index;
-         uint8 m_alpha_index;
-         uint8 m_tile_index;
-         uint8 m_block_x;
-         uint8 m_block_y;
-      };
-
-      typedef crnlib::vector< crnlib::vector< block_id > > chunk_blocks_using_selectors_vec;
-      chunk_blocks_using_selectors_vec m_chunk_blocks_using_color_selectors;
-      chunk_blocks_using_selectors_vec m_chunk_blocks_using_alpha_selectors; // second's upper 16 bits contain alpha index!
-
-      crnlib::vector<uint> m_color_endpoints;   // not valid until end, only for user access
-      crnlib::vector<uint> m_alpha_endpoints;   // not valid until end, only for user access
-
-      // Debugging
-      pixel_chunk_vec m_dbg_chunk_pixels;
-      pixel_chunk_vec m_dbg_chunk_pixels_tile_vis;
-      pixel_chunk_vec m_dbg_chunk_pixels_color_quantized;
-      pixel_chunk_vec m_dbg_chunk_pixels_alpha_quantized;
-
-      pixel_chunk_vec m_dbg_chunk_pixels_orig_color_selectors;
-      pixel_chunk_vec m_dbg_chunk_pixels_quantized_color_selectors;
-      pixel_chunk_vec m_dbg_chunk_pixels_final_color_selectors;
-
-      pixel_chunk_vec m_dbg_chunk_pixels_orig_alpha_selectors;
-      pixel_chunk_vec m_dbg_chunk_pixels_quantized_alpha_selectors;
-      pixel_chunk_vec m_dbg_chunk_pixels_final_alpha_selectors;
-
-      pixel_chunk_vec m_dbg_chunk_pixels_final;
-
-      crn_thread_id_t m_main_thread_id;
-      bool m_canceled;
-      task_pool* m_pTask_pool;
-
-      int m_prev_phase_index;
-      int m_prev_percentage_complete;
-
-      typedef vec<6, float> vec6F;
-      typedef vec<16, float> vec16F;
-      typedef tree_clusterizer<vec2F> vec2F_tree_vq;
-      typedef tree_clusterizer<vec6F> vec6F_tree_vq;
-      typedef tree_clusterizer<vec16F> vec16F_tree_vq;
-
-      struct assign_color_endpoint_clusters_state
-      {
-         CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(assign_color_endpoint_clusters_state);
-
-         assign_color_endpoint_clusters_state(vec6F_tree_vq& vq, crnlib::vector< crnlib::vector<vec6F> >& training_vecs) :
-            m_vq(vq), m_training_vecs(training_vecs) { }
-
-         vec6F_tree_vq& m_vq;
-         crnlib::vector< crnlib::vector<vec6F> >& m_training_vecs;
-      };
-
-      struct create_selector_codebook_state
-      {
-         CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(create_selector_codebook_state);
-
-         create_selector_codebook_state(dxt_hc& hc, bool alpha_blocks, uint comp_index_start, uint comp_index_end, vec16F_tree_vq& selector_vq, chunk_blocks_using_selectors_vec& chunk_blocks_using_selectors, selectors_vec& selectors_cb) :
-            m_hc(hc),
-            m_alpha_blocks(alpha_blocks),
-            m_comp_index_start(comp_index_start),
-            m_comp_index_end(comp_index_end),
-            m_selector_vq(selector_vq),
-            m_chunk_blocks_using_selectors(chunk_blocks_using_selectors),
-            m_selectors_cb(selectors_cb)
-         {
-         }
-
-         dxt_hc&                             m_hc;
-         bool                                m_alpha_blocks;
-         uint                                m_comp_index_start;
-         uint                                m_comp_index_end;
-         vec16F_tree_vq&                     m_selector_vq;
-         chunk_blocks_using_selectors_vec&   m_chunk_blocks_using_selectors;
-         selectors_vec&                      m_selectors_cb;
-
-         mutable spinlock                    m_chunk_blocks_using_selectors_lock;
-      };
-
-      void assign_color_endpoint_clusters_task(uint64 data, void* pData_ptr);
-      bool determine_color_endpoint_clusters();
-
-      struct determine_alpha_endpoint_clusters_state
-      {
-         vec2F_tree_vq m_vq;
-         crnlib::vector< crnlib::vector<vec2F> > m_training_vecs[2];
-      };
-
-      void determine_alpha_endpoint_clusters_task(uint64 data, void* pData_ptr);
-      bool determine_alpha_endpoint_clusters();
-
-      void determine_color_endpoint_codebook_task(uint64 data, void* pData_ptr);
-      bool determine_color_endpoint_codebook();
-
-      void determine_alpha_endpoint_codebook_task(uint64 data, void* pData_ptr);
-      bool determine_alpha_endpoint_codebook();
-
-      void create_quantized_debug_images();
-
-      void create_selector_codebook_task(uint64 data, void* pData_ptr);
-      bool create_selector_codebook(bool alpha_blocks);
-
-      bool refine_quantized_color_endpoints();
-      bool refine_quantized_color_selectors();
-      bool refine_quantized_alpha_endpoints();
-      bool refine_quantized_alpha_selectors();
-      void create_final_debug_image();
-      bool create_chunk_encodings();
-      bool update_progress(uint phase_index, uint subphase_index, uint subphase_total);
-      bool compress_internal(const params& p, uint num_chunks, const pixel_chunk* pChunks);
-   };
-
-   CRNLIB_DEFINE_BITWISE_COPYABLE(dxt_hc::pixel_chunk);
-   CRNLIB_DEFINE_BITWISE_COPYABLE(dxt_hc::chunk_encoding);
-   CRNLIB_DEFINE_BITWISE_COPYABLE(dxt_hc::selectors);
-
-} // namespace crnlib

+ 0 - 47
Source/ThirdParty/crunch/crnlib/crn_dxt_hc_common.cpp

@@ -1,47 +0,0 @@
-// File: crn_dxt_hc_common.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_dxt_hc_common.h"
-
-namespace crnlib
-{
-   chunk_encoding_desc g_chunk_encodings[cNumChunkEncodings] =
-   {
-      { 1, { { 0, 0, 8, 8, 0 } } },
-
-      { 2, { { 0, 0, 8, 4, 1 }, { 0, 4, 8, 4, 2 } } },
-      { 2, { { 0, 0, 4, 8, 3 }, { 4, 0, 4, 8, 4 } } },
-
-      { 3, { { 0, 0, 8, 4, 1 }, { 0, 4, 4, 4, 7 }, { 4, 4, 4, 4, 8 } } },
-      { 3, { { 0, 4, 8, 4, 2 }, { 0, 0, 4, 4, 5 }, { 4, 0, 4, 4, 6 } } },
-
-      { 3, { { 0, 0, 4, 8, 3 }, { 4, 0, 4, 4, 6 }, { 4, 4, 4, 4, 8 } } },
-      { 3, { { 4, 0, 4, 8, 4 }, { 0, 0, 4, 4, 5 }, { 0, 4, 4, 4, 7 } } },
-
-      { 4, { { 0, 0, 4, 4, 5 }, { 4, 0, 4, 4, 6 }, { 0, 4, 4, 4, 7 }, { 4, 4, 4, 4, 8 } } }
-   };
-
-   chunk_tile_desc g_chunk_tile_layouts[cNumChunkTileLayouts] = 
-   {
-      // 2x2
-      { 0, 0, 8, 8, 0 },
-
-      // 2x1
-      { 0, 0, 8, 4, 1 }, 
-      { 0, 4, 8, 4, 2 },
-
-      // 1x2
-      { 0, 0, 4, 8, 3 },
-      { 4, 0, 4, 8, 4 },
-
-      // 1x1
-      { 0, 0, 4, 4, 5 }, 
-      { 4, 0, 4, 4, 6 },
-      { 0, 4, 4, 4, 7 }, 
-      { 4, 4, 4, 4, 8 } 
-   };
-   
-} // namespace crnlib
-
-
-

+ 0 - 43
Source/ThirdParty/crunch/crnlib/crn_dxt_hc_common.h

@@ -1,43 +0,0 @@
-// File: crn_dxt_hc_common.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   struct chunk_tile_desc
-   {
-      // These values are in pixels, and always a multiple of cBlockPixelWidth/cBlockPixelHeight.
-      uint m_x_ofs;
-      uint m_y_ofs;
-      uint m_width;
-      uint m_height;
-      uint m_layout_index;
-   };
-
-   struct chunk_encoding_desc
-   {
-      uint m_num_tiles;
-      chunk_tile_desc m_tiles[4];
-   };
-
-   const uint cChunkPixelWidth = 8;
-   const uint cChunkPixelHeight = 8;
-   const uint cChunkBlockWidth = 2;
-   const uint cChunkBlockHeight = 2;
-
-   const uint cChunkMaxTiles = 4;
-
-   const uint cBlockPixelWidthShift = 2;
-   const uint cBlockPixelHeightShift = 2;
-
-   const uint cBlockPixelWidth = 4;
-   const uint cBlockPixelHeight = 4;
-
-   const uint cNumChunkEncodings = 8;
-   extern chunk_encoding_desc g_chunk_encodings[cNumChunkEncodings];
-
-   const uint cNumChunkTileLayouts = 9;
-   const uint cFirst4x4ChunkTileLayout = 5;
-   extern chunk_tile_desc g_chunk_tile_layouts[cNumChunkTileLayouts];
- 
-} // namespace crnlib

+ 0 - 1683
Source/ThirdParty/crunch/crnlib/crn_dxt_image.cpp

@@ -1,1683 +0,0 @@
-// File: crn_dxt_image.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_dxt_image.h"
-#if CRNLIB_SUPPORT_SQUISH
-#include "squish\squish.h"
-#endif
-#include "crn_ryg_dxt.hpp"
-#include "crn_dxt_fast.h"
-#include "crn_console.h"
-#include "crn_threading.h"
-
-#if CRNLIB_SUPPORT_ATI_COMPRESS
-   #ifdef _DLL
-      #pragma comment(lib, "ATI_Compress_MT_DLL_VC8.lib")
-   #else
-      #pragma comment(lib, "ATI_Compress_MT_VC8.lib")
-   #endif
-   #include "..\ext\ATI_Compress\ATI_Compress.h"
-#endif
-
-#include "crn_rg_etc1.h"
-#include "crn_etc.h"
-#define CRNLIB_USE_RG_ETC1 1
-
-namespace crnlib
-{
-   dxt_image::dxt_image() :
-      m_pElements(NULL),
-      m_width(0),
-      m_height(0),
-      m_blocks_x(0),
-      m_blocks_y(0),
-      m_total_blocks(0),
-      m_total_elements(0),
-      m_num_elements_per_block(0),
-      m_bytes_per_block(0),
-      m_format(cDXTInvalid)
-   {
-      utils::zero_object(m_element_type);
-      utils::zero_object(m_element_component_index);
-   }
-
-   dxt_image::dxt_image(const dxt_image& other) :
-      m_pElements(NULL)
-   {
-      *this = other;
-   }
-
-   dxt_image& dxt_image::operator= (const dxt_image& rhs)
-   {
-      if (this == &rhs)
-         return *this;
-
-      clear();
-
-      m_width = rhs.m_width;
-      m_height = rhs.m_height;
-      m_blocks_x = rhs.m_blocks_x;
-      m_blocks_y = rhs.m_blocks_y;
-      m_num_elements_per_block = rhs.m_num_elements_per_block;
-      m_bytes_per_block = rhs.m_bytes_per_block;
-      m_format = rhs.m_format;
-      m_total_blocks = rhs.m_total_blocks;
-      m_total_elements = rhs.m_total_elements;
-      m_pElements = NULL;
-      memcpy(m_element_type, rhs.m_element_type, sizeof(m_element_type));
-      memcpy(m_element_component_index, rhs.m_element_component_index, sizeof(m_element_component_index));
-
-      if (rhs.m_pElements)
-      {
-         m_elements.resize(m_total_elements);
-         memcpy(&m_elements[0], rhs.m_pElements, sizeof(element) * m_total_elements);
-         m_pElements = &m_elements[0];
-      }
-
-      return *this;
-   }
-
-   void dxt_image::clear()
-   {
-      m_elements.clear();
-      m_width = 0;
-      m_height = 0;
-      m_blocks_x = 0;
-      m_blocks_y = 0;
-      m_num_elements_per_block = 0;
-      m_bytes_per_block = 0;
-      m_format = cDXTInvalid;
-      utils::zero_object(m_element_type);
-      utils::zero_object(m_element_component_index);
-      m_total_blocks = 0;
-      m_total_elements = 0;
-      m_pElements = NULL;
-   }
-
-   bool dxt_image::init_internal(dxt_format fmt, uint width, uint height)
-   {
-      CRNLIB_ASSERT((fmt != cDXTInvalid) && (width > 0) && (height > 0));
-
-      clear();
-
-      m_width = width;
-      m_height = height;
-
-      m_blocks_x = (m_width + 3) >> cDXTBlockShift;
-      m_blocks_y = (m_height + 3) >> cDXTBlockShift;
-
-      m_num_elements_per_block = 2;
-      if ((fmt == cDXT1) || (fmt == cDXT1A) || (fmt == cDXT5A) || (fmt == cETC1))
-         m_num_elements_per_block = 1;
-
-      m_total_blocks = m_blocks_x * m_blocks_y;
-      m_total_elements = m_total_blocks * m_num_elements_per_block;
-
-      CRNLIB_ASSUME((uint)cDXT1BytesPerBlock == (uint)cETC1BytesPerBlock);
-      m_bytes_per_block = cDXT1BytesPerBlock * m_num_elements_per_block;
-
-      m_format = fmt;
-
-      switch (m_format)
-      {
-         case cDXT1:
-         case cDXT1A:
-         {
-            m_element_type[0] = cColorDXT1;
-            m_element_component_index[0] = -1;
-            break;
-         }
-         case cDXT3:
-         {
-            m_element_type[0] = cAlphaDXT3;
-            m_element_type[1] = cColorDXT1;
-            m_element_component_index[0] = 3;
-            m_element_component_index[1] = -1;
-            break;
-         }
-         case cDXT5:
-         {
-            m_element_type[0] = cAlphaDXT5;
-            m_element_type[1] = cColorDXT1;
-            m_element_component_index[0] = 3;
-            m_element_component_index[1] = -1;
-            break;
-         }
-         case cDXT5A:
-         {
-            m_element_type[0] = cAlphaDXT5;
-            m_element_component_index[0] = 3;
-            break;
-         }
-         case cDXN_XY:
-         {
-            m_element_type[0] = cAlphaDXT5;
-            m_element_type[1] = cAlphaDXT5;
-            m_element_component_index[0] = 0;
-            m_element_component_index[1] = 1;
-            break;
-         }
-         case cDXN_YX:
-         {
-            m_element_type[0] = cAlphaDXT5;
-            m_element_type[1] = cAlphaDXT5;
-            m_element_component_index[0] = 1;
-            m_element_component_index[1] = 0;
-            break;
-         }
-         case cETC1:
-         {
-            m_element_type[0] = cColorETC1;
-            m_element_component_index[0] = -1;
-            break;
-         }
-         default:
-         {
-            CRNLIB_ASSERT(0);
-            clear();
-            return false;
-         }
-      }
-
-      return true;
-   }
-
-   bool dxt_image::init(dxt_format fmt, uint width, uint height, bool clear_elements)
-   {
-      if (!init_internal(fmt, width, height))
-         return false;
-
-      m_elements.resize(m_total_elements);
-      m_pElements = &m_elements[0];
-
-      if (clear_elements)
-         memset(m_pElements, 0, sizeof(element) * m_total_elements);
-
-      return true;
-   }
-
-   bool dxt_image::init(dxt_format fmt, uint width, uint height, uint num_elements, element* pElements, bool create_copy)
-   {
-      CRNLIB_ASSERT(num_elements && pElements);
-
-      if (!init_internal(fmt, width, height))
-         return false;
-
-      if (num_elements != m_total_elements)
-      {
-         clear();
-         return false;
-      }
-
-      if (create_copy)
-      {
-         m_elements.resize(m_total_elements);
-         m_pElements = &m_elements[0];
-
-         memcpy(m_pElements, pElements, m_total_elements * sizeof(element));
-      }
-      else
-         m_pElements = pElements;
-
-      return true;
-   }
-
-   struct init_task_params
-   {
-      dxt_format                    m_fmt;
-      const image_u8*               m_pImg;
-      const dxt_image::pack_params* m_pParams;
-      crn_thread_id_t               m_main_thread;
-      atomic32_t                    m_canceled;
-   };
-
-   void dxt_image::init_task(uint64 data, void* pData_ptr)
-   {
-      const uint thread_index = static_cast<uint>(data);
-      init_task_params* pInit_params = static_cast<init_task_params*>(pData_ptr);
-
-      const image_u8& img = *pInit_params->m_pImg;
-      const pack_params& p = *pInit_params->m_pParams;
-      const bool is_main_thread = (crn_get_current_thread_id() == pInit_params->m_main_thread);
-
-      uint block_index = 0;
-
-      set_block_pixels_context optimizer_context;
-      int prev_progress_percentage = -1;
-
-      for (uint block_y = 0; block_y < m_blocks_y; block_y++)
-      {
-         const uint pixel_ofs_y = block_y * cDXTBlockSize;
-
-         for (uint block_x = 0; block_x < m_blocks_x; block_x++, block_index++)
-         {
-            if (pInit_params->m_canceled)
-               return;
-
-            if (p.m_pProgress_callback && is_main_thread && ((block_index & 63) == 63))
-            {
-               const uint progress_percentage = p.m_progress_start + ((block_index * p.m_progress_range + get_total_blocks() / 2) / get_total_blocks());
-               if ((int)progress_percentage != prev_progress_percentage)
-               {
-                  prev_progress_percentage = progress_percentage;
-                  if (!(p.m_pProgress_callback)(progress_percentage, p.m_pProgress_callback_user_data_ptr))
-                  {
-                     atomic_exchange32(&pInit_params->m_canceled, CRNLIB_TRUE);
-                     return;
-                  }
-               }
-            }
-
-            if (p.m_num_helper_threads)
-            {
-               if ((block_index % (p.m_num_helper_threads + 1)) != thread_index)
-                  continue;
-            }
-
-            color_quad_u8 pixels[cDXTBlockSize * cDXTBlockSize];
-
-            const uint pixel_ofs_x = block_x * cDXTBlockSize;
-
-            for (uint y = 0; y < cDXTBlockSize; y++)
-            {
-               const uint iy = math::minimum(pixel_ofs_y + y, img.get_height() - 1);
-
-               for (uint x = 0; x < cDXTBlockSize; x++)
-               {
-                  const uint ix = math::minimum(pixel_ofs_x + x, img.get_width() - 1);
-
-                  pixels[x + y * cDXTBlockSize] = img(ix, iy);
-               }
-            }
-
-            set_block_pixels(block_x, block_y, pixels, p, optimizer_context);
-         }
-      }
-   }
-
-#if CRNLIB_SUPPORT_ATI_COMPRESS
-   bool dxt_image::init_ati_compress(dxt_format fmt, const image_u8& img, const pack_params& p)
-   {
-      image_u8 tmp_img(img);
-      for (uint y = 0; y < img.get_height(); y++)
-      {
-         for (uint x = 0; x < img.get_width(); x++)
-         {
-            color_quad_u8 c(img(x, y));
-            std::swap(c.r, c.b);
-            tmp_img(x, y) = c;
-         }
-      }
-
-      ATI_TC_Texture src_tex;
-      utils::zero_object(src_tex);
-      src_tex.dwSize = sizeof(ATI_TC_Texture);
-      src_tex.dwWidth = tmp_img.get_width();
-      src_tex.dwHeight = tmp_img.get_height();
-      src_tex.dwPitch = tmp_img.get_pitch_in_bytes();
-      src_tex.format = ATI_TC_FORMAT_ARGB_8888;
-      src_tex.dwDataSize = src_tex.dwPitch * tmp_img.get_height();
-      src_tex.pData = (ATI_TC_BYTE*)tmp_img.get_ptr();
-
-      ATI_TC_Texture dst_tex;
-      utils::zero_object(dst_tex);
-      dst_tex.dwSize = sizeof(ATI_TC_Texture);
-      dst_tex.dwWidth = tmp_img.get_width();
-      dst_tex.dwHeight = tmp_img.get_height();
-      dst_tex.dwDataSize = get_size_in_bytes();
-      dst_tex.pData = (ATI_TC_BYTE*)get_element_ptr();
-
-      switch (fmt)
-      {
-         case cDXT1:
-         case cDXT1A:
-            dst_tex.format = ATI_TC_FORMAT_DXT1;
-            break;
-         case cDXT3:
-            dst_tex.format = ATI_TC_FORMAT_DXT3;
-            break;
-         case cDXT5:
-            dst_tex.format = ATI_TC_FORMAT_DXT5;
-            break;
-         case cDXT5A:
-            dst_tex.format = ATI_TC_FORMAT_ATI1N;
-            break;
-         case cDXN_XY:
-            dst_tex.format = ATI_TC_FORMAT_ATI2N_XY;
-            break;
-         case cDXN_YX:
-            dst_tex.format = ATI_TC_FORMAT_ATI2N;
-            break;
-         default:
-         {
-            CRNLIB_ASSERT(false);
-            return false;
-         }
-      }
-
-      ATI_TC_CompressOptions options;
-      utils::zero_object(options);
-      options.dwSize = sizeof(ATI_TC_CompressOptions);
-
-      if (fmt == cDXT1A)
-      {
-         options.bDXT1UseAlpha = true;
-         options.nAlphaThreshold = (ATI_TC_BYTE)p.m_dxt1a_alpha_threshold;
-      }
-      options.bDisableMultiThreading = (p.m_num_helper_threads == 0);
-      switch (p.m_quality)
-      {
-         case cCRNDXTQualityFast:
-            options.nCompressionSpeed = ATI_TC_Speed_Fast;
-            break;
-         case cCRNDXTQualitySuperFast:
-            options.nCompressionSpeed = ATI_TC_Speed_SuperFast;
-            break;
-         default:
-            options.nCompressionSpeed = ATI_TC_Speed_Normal;
-            break;
-      }
-
-      if (p.m_perceptual)
-      {
-         options.bUseChannelWeighting = true;
-         options.fWeightingRed =   .212671f;
-         options.fWeightingGreen = .715160f;
-         options.fWeightingBlue =  .072169f;
-      }
-
-      ATI_TC_ERROR err = ATI_TC_ConvertTexture(&src_tex, &dst_tex, &options, NULL, NULL, NULL);
-      return err == ATI_TC_OK;
-   }
-#endif
-
-   bool dxt_image::init(dxt_format fmt, const image_u8& img, const pack_params& p)
-   {
-      if (!init(fmt, img.get_width(), img.get_height(), false))
-         return false;
-
-#if CRNLIB_SUPPORT_ATI_COMPRESS
-      if (p.m_compressor == cCRNDXTCompressorATI)
-         return init_ati_compress(fmt, img, p);
-#endif
-
-      task_pool *pPool = p.m_pTask_pool;
-
-      task_pool tmp_pool;
-      if (!pPool)
-      {
-         if (!tmp_pool.init(p.m_num_helper_threads))
-            return false;
-         pPool = &tmp_pool;
-      }
-
-      init_task_params init_params;
-      init_params.m_fmt = fmt;
-      init_params.m_pImg = &img;
-      init_params.m_pParams = &p;
-      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++)
-         pPool->queue_object_task(this, &dxt_image::init_task, i, &init_params);
-
-      pPool->join();
-
-      if (init_params.m_canceled)
-         return false;
-
-      return true;
-   }
-
-   bool dxt_image::unpack(image_u8& img) const
-   {
-      if (!m_total_elements)
-         return false;
-
-      img.resize(m_width, m_height);
-
-      color_quad_u8 pixels[cDXTBlockSize * cDXTBlockSize];
-      for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-         pixels[i].set(0, 0, 0, 255);
-
-      bool all_blocks_valid = true;
-      for (uint block_y = 0; block_y < m_blocks_y; block_y++)
-      {
-         const uint pixel_ofs_y = block_y * cDXTBlockSize;
-         const uint limit_y = math::minimum<uint>(cDXTBlockSize, img.get_height() - pixel_ofs_y);
-
-         for (uint block_x = 0; block_x < m_blocks_x; block_x++)
-         {
-            if (!get_block_pixels(block_x, block_y, pixels))
-               all_blocks_valid = false;
-
-            const uint pixel_ofs_x = block_x * cDXTBlockSize;
-
-            const uint limit_x = math::minimum<uint>(cDXTBlockSize, img.get_width() - pixel_ofs_x);
-
-            for (uint y = 0; y < limit_y; y++)
-            {
-               const uint iy = pixel_ofs_y + y;
-
-               for (uint x = 0; x < limit_x; x++)
-               {
-                  const uint ix = pixel_ofs_x + x;
-
-                  img(ix, iy) = pixels[x + (y << cDXTBlockShift)];
-               }
-            }
-         }
-      }
-
-      if (!all_blocks_valid)
-         console::error("dxt_image::unpack: One or more invalid blocks encountered!");
-
-      img.reset_comp_flags();
-      img.set_component_valid(0, false);
-      img.set_component_valid(1, false);
-      img.set_component_valid(2, false);
-      for (uint i = 0; i < m_num_elements_per_block; i++)
-      {
-         if (m_element_component_index[i] < 0)
-         {
-            img.set_component_valid(0, true);
-            img.set_component_valid(1, true);
-            img.set_component_valid(2, true);
-         }
-         else
-            img.set_component_valid(m_element_component_index[i], true);
-      }
-
-      img.set_component_valid(3, get_dxt_format_has_alpha(m_format));
-
-      return true;
-   }
-
-   void dxt_image::endian_swap()
-   {
-      utils::endian_switch_words(reinterpret_cast<uint16*>(m_elements.get_ptr()), m_elements.size_in_bytes() / sizeof(uint16));
-   }
-
-   const dxt_image::element& dxt_image::get_element(uint block_x, uint block_y, uint element_index) const
-   {
-      CRNLIB_ASSERT((block_x < m_blocks_x) && (block_y < m_blocks_y) && (element_index < m_num_elements_per_block));
-      return m_pElements[(block_x + block_y * m_blocks_x) * m_num_elements_per_block + element_index];
-   }
-
-   dxt_image::element& dxt_image::get_element(uint block_x, uint block_y, uint element_index)
-   {
-      CRNLIB_ASSERT((block_x < m_blocks_x) && (block_y < m_blocks_y) && (element_index < m_num_elements_per_block));
-      return m_pElements[(block_x + block_y * m_blocks_x) * m_num_elements_per_block + element_index];
-   }
-
-   bool dxt_image::has_alpha() const
-   {
-      switch (m_format)
-      {
-         case cDXT1:
-         {
-            for (uint i = 0; i < m_total_elements; i++)
-            {
-               const dxt1_block& blk = *(dxt1_block*)&m_pElements[i];
-
-               if (blk.get_low_color() <= blk.get_high_color())
-               {
-                  for (uint y = 0; y < cDXTBlockSize; y++)
-                     for (uint x = 0; x < cDXTBlockSize; x++)
-                        if (blk.get_selector(x, y) == 3)
-                           return true;
-               }
-            }
-
-            break;
-         }
-         case cDXT1A:
-         case cDXT3:
-         case cDXT5:
-         case cDXT5A:
-            return true;
-         default: break;
-      }
-
-      return false;
-   }
-
-   color_quad_u8 dxt_image::get_pixel(uint x, uint y) const
-   {
-      CRNLIB_ASSERT((x < m_width) && (y < m_height));
-
-      const uint block_x = x >> cDXTBlockShift;
-      const uint block_y = y >> cDXTBlockShift;
-
-      const element* pElement = reinterpret_cast<const element*>(&get_element(block_x, block_y, 0));
-
-      color_quad_u8 result(0, 0, 0, 255);
-
-      for (uint element_index = 0; element_index < m_num_elements_per_block; element_index++, pElement++)
-      {
-         switch (m_element_type[element_index])
-         {
-            case cColorETC1:
-            {
-               const etc1_block& block = *reinterpret_cast<const etc1_block*>(&get_element(block_x, block_y, element_index));
-
-               const bool diff_flag = block.get_diff_bit();
-               const bool flip_flag = block.get_flip_bit();
-               const uint table_index0 = block.get_inten_table(0);
-               const uint table_index1 = block.get_inten_table(1);
-               color_quad_u8 subblock_colors0[4], subblock_colors1[4];
-
-               if (diff_flag)
-               {
-                  const uint16 base_color5 = block.get_base5_color();
-                  const uint16 delta_color3 = block.get_delta3_color();
-                  etc1_block::get_diff_subblock_colors(subblock_colors0, base_color5, table_index0);
-                  etc1_block::get_diff_subblock_colors(subblock_colors1, base_color5, delta_color3, table_index1);
-               }
-               else
-               {
-                  const uint16 base_color4_0 = block.get_base4_color(0);
-                  etc1_block::get_abs_subblock_colors(subblock_colors0, base_color4_0, table_index0);
-                  const uint16 base_color4_1 = block.get_base4_color(1);
-                  etc1_block::get_abs_subblock_colors(subblock_colors1, base_color4_1, table_index1);
-               }
-
-               const uint bx = x & 3;
-               const uint by = y & 3;
-
-               const uint selector_index = block.get_selector(bx, by);
-               if (flip_flag)
-               {
-                  if (by <= 2)
-                     result = subblock_colors0[selector_index];
-                  else
-                     result = subblock_colors1[selector_index];
-               }
-               else
-               {
-                  if (bx <= 2)
-                     result = subblock_colors0[selector_index];
-                  else
-                     result = subblock_colors1[selector_index];
-               }
-
-               break;
-            }
-            case cColorDXT1:
-            {
-               const dxt1_block* pBlock = reinterpret_cast<const dxt1_block*>(&get_element(block_x, block_y, element_index));
-
-               const uint l = pBlock->get_low_color();
-               const uint h = pBlock->get_high_color();
-
-               color_quad_u8 c0(dxt1_block::unpack_color(static_cast<uint16>(l), true));
-               color_quad_u8 c1(dxt1_block::unpack_color(static_cast<uint16>(h), true));
-
-               const uint s = pBlock->get_selector(x & 3, y & 3);
-
-               if (l > h)
-               {
-                  switch (s)
-                  {
-                     case 0: result.set_noclamp_rgb(c0.r, c0.g, c0.b); break;
-                     case 1: result.set_noclamp_rgb(c1.r, c1.g, c1.b); break;
-                     case 2: result.set_noclamp_rgb( (c0.r * 2 + c1.r) / 3, (c0.g * 2 + c1.g) / 3, (c0.b * 2 + c1.b) / 3); break;
-                     case 3: result.set_noclamp_rgb( (c1.r * 2 + c0.r) / 3, (c1.g * 2 + c0.g) / 3, (c1.b * 2 + c0.b) / 3); break;
-                  }
-               }
-               else
-               {
-                  switch (s)
-                  {
-                     case 0: result.set_noclamp_rgb(c0.r, c0.g, c0.b); break;
-                     case 1: result.set_noclamp_rgb(c1.r, c1.g, c1.b); break;
-                     case 2: result.set_noclamp_rgb( (c0.r + c1.r) >> 1U, (c0.g + c1.g) >> 1U, (c0.b + c1.b) >> 1U); break;
-                     case 3:
-                     {
-                        if (m_format <= cDXT1A)
-                           result.set_noclamp_rgba(0, 0, 0, 0);
-                        else
-                           result.set_noclamp_rgb(0, 0, 0);
-                        break;
-                     }
-                  }
-               }
-
-               break;
-            }
-            case cAlphaDXT5:
-            {
-               const int comp_index = m_element_component_index[element_index];
-
-               const dxt5_block* pBlock = reinterpret_cast<const dxt5_block*>(&get_element(block_x, block_y, element_index));
-
-               const uint l = pBlock->get_low_alpha();
-               const uint h = pBlock->get_high_alpha();
-
-               const uint s = pBlock->get_selector(x & 3, y & 3);
-
-               if (l > h)
-               {
-                  switch (s)
-                  {
-                     case 0: result[comp_index] = static_cast<uint8>(l); break;
-                     case 1: result[comp_index] = static_cast<uint8>(h); break;
-                     case 2: result[comp_index] = static_cast<uint8>((l * 6 + h    ) / 7); break;
-                     case 3: result[comp_index] = static_cast<uint8>((l * 5 + h * 2) / 7); break;
-                     case 4: result[comp_index] = static_cast<uint8>((l * 4 + h * 3) / 7); break;
-                     case 5: result[comp_index] = static_cast<uint8>((l * 3 + h * 4) / 7); break;
-                     case 6: result[comp_index] = static_cast<uint8>((l * 2 + h * 5) / 7); break;
-                     case 7: result[comp_index] = static_cast<uint8>((l     + h * 6) / 7); break;
-                  }
-               }
-               else
-               {
-                  switch (s)
-                  {
-                     case 0: result[comp_index] = static_cast<uint8>(l); break;
-                     case 1: result[comp_index] = static_cast<uint8>(h); break;
-                     case 2: result[comp_index] = static_cast<uint8>((l * 4 + h    ) / 5); break;
-                     case 3: result[comp_index] = static_cast<uint8>((l * 3 + h * 2) / 5); break;
-                     case 4: result[comp_index] = static_cast<uint8>((l * 2 + h * 3) / 5); break;
-                     case 5: result[comp_index] = static_cast<uint8>((l     + h * 4) / 5); break;
-                     case 6: result[comp_index] = 0; break;
-                     case 7: result[comp_index] = 255; break;
-                  }
-               }
-
-               break;
-            }
-            case cAlphaDXT3:
-            {
-               const int comp_index = m_element_component_index[element_index];
-
-               const dxt3_block* pBlock = reinterpret_cast<const dxt3_block*>(&get_element(block_x, block_y, element_index));
-
-               result[comp_index] = static_cast<uint8>(pBlock->get_alpha(x & 3, y & 3, true));
-
-               break;
-            }
-            default: break;
-         }
-      }
-
-      return result;
-   }
-
-   uint dxt_image::get_pixel_alpha(uint x, uint y, uint element_index) const
-   {
-      CRNLIB_ASSERT((x < m_width) && (y < m_height) && (element_index < m_num_elements_per_block));
-
-      const uint block_x = x >> cDXTBlockShift;
-      const uint block_y = y >> cDXTBlockShift;
-
-      switch (m_element_type[element_index])
-      {
-         case cColorDXT1:
-         {
-            if (m_format <= cDXT1A)
-            {
-               const dxt1_block* pBlock = reinterpret_cast<const dxt1_block*>(&get_element(block_x, block_y, element_index));
-
-               const uint l = pBlock->get_low_color();
-               const uint h = pBlock->get_high_color();
-
-               if (l <= h)
-               {
-                  uint s = pBlock->get_selector(x & 3, y & 3);
-
-                  return (s == 3) ? 0 : 255;
-               }
-               else
-               {
-                  return 255;
-               }
-            }
-
-            break;
-         }
-         case cAlphaDXT5:
-         {
-            const dxt5_block* pBlock = reinterpret_cast<const dxt5_block*>(&get_element(block_x, block_y, element_index));
-
-            const uint l = pBlock->get_low_alpha();
-            const uint h = pBlock->get_high_alpha();
-
-            const uint s = pBlock->get_selector(x & 3, y & 3);
-
-            if (l > h)
-            {
-               switch (s)
-               {
-                  case 0: return l;
-                  case 1: return h;
-                  case 2: return (l * 6 + h    ) / 7;
-                  case 3: return (l * 5 + h * 2) / 7;
-                  case 4: return (l * 4 + h * 3) / 7;
-                  case 5: return (l * 3 + h * 4) / 7;
-                  case 6: return (l * 2 + h * 5) / 7;
-                  case 7: return (l     + h * 6) / 7;
-               }
-            }
-            else
-            {
-               switch (s)
-               {
-                  case 0: return l;
-                  case 1: return h;
-                  case 2: return (l * 4 + h    ) / 5;
-                  case 3: return (l * 3 + h * 2) / 5;
-                  case 4: return (l * 2 + h * 3) / 5;
-                  case 5: return (l     + h * 4) / 5;
-                  case 6: return 0;
-                  case 7: return 255;
-               }
-            }
-         }
-         case cAlphaDXT3:
-         {
-            const dxt3_block* pBlock = reinterpret_cast<const dxt3_block*>(&get_element(block_x, block_y, element_index));
-
-            return pBlock->get_alpha(x & 3, y & 3, true);
-         }
-         default: break;
-      }
-
-      return 255;
-   }
-
-   void dxt_image::set_pixel(uint x, uint y, const color_quad_u8& c, bool perceptual)
-   {
-      CRNLIB_ASSERT((x < m_width) && (y < m_height));
-
-      const uint block_x = x >> cDXTBlockShift;
-      const uint block_y = y >> cDXTBlockShift;
-
-      element* pElement = &get_element(block_x, block_y, 0);
-
-      for (uint element_index = 0; element_index < m_num_elements_per_block; element_index++, pElement++)
-      {
-         switch (m_element_type[element_index])
-         {
-            case cColorETC1:
-            {
-               etc1_block& block = *reinterpret_cast<etc1_block*>(&get_element(block_x, block_y, element_index));
-
-               const bool diff_flag = block.get_diff_bit();
-               const bool flip_flag = block.get_flip_bit();
-               const uint table_index0 = block.get_inten_table(0);
-               const uint table_index1 = block.get_inten_table(1);
-               color_quad_u8 subblock_colors0[4], subblock_colors1[4];
-
-               if (diff_flag)
-               {
-                  const uint16 base_color5 = block.get_base5_color();
-                  const uint16 delta_color3 = block.get_delta3_color();
-                  etc1_block::get_diff_subblock_colors(subblock_colors0, base_color5, table_index0);
-                  etc1_block::get_diff_subblock_colors(subblock_colors1, base_color5, delta_color3, table_index1);
-               }
-               else
-               {
-                  const uint16 base_color4_0 = block.get_base4_color(0);
-                  etc1_block::get_abs_subblock_colors(subblock_colors0, base_color4_0, table_index0);
-                  const uint16 base_color4_1 = block.get_base4_color(1);
-                  etc1_block::get_abs_subblock_colors(subblock_colors1, base_color4_1, table_index1);
-               }
-
-               const uint bx = x & 3;
-               const uint by = y & 3;
-
-               color_quad_u8* pColors = subblock_colors1;
-               if (flip_flag)
-               {
-                  if (by <= 2)
-                     pColors = subblock_colors0;
-               }
-               else
-               {
-                  if (bx <= 2)
-                     pColors = subblock_colors0;
-               }
-
-               uint best_error = UINT_MAX;
-               uint best_selector = 0;
-
-               for (uint i = 0; i < 4; i++)
-               {
-                  uint error = color::color_distance(perceptual, pColors[i], c, false);
-                  if (error < best_error)
-                  {
-                     best_error = error;
-                     best_selector = i;
-                  }
-               }
-
-               block.set_selector(bx, by, best_selector);
-               break;
-            }
-            case cColorDXT1:
-            {
-               dxt1_block* pDXT1_block = reinterpret_cast<dxt1_block*>(pElement);
-
-               color_quad_u8 colors[cDXT1SelectorValues];
-               const uint n = pDXT1_block->get_block_colors(colors, static_cast<uint16>(pDXT1_block->get_low_color()), static_cast<uint16>(pDXT1_block->get_high_color()));
-
-               if ((m_format == cDXT1A) && (c.a < 128))
-                  pDXT1_block->set_selector(x & 3, y & 3, 3);
-               else
-               {
-                  uint best_error = UINT_MAX;
-                  uint best_selector = 0;
-
-                  for (uint i = 0; i < n; i++)
-                  {
-                     uint error = color::color_distance(perceptual, colors[i], c, false);
-                     if (error < best_error)
-                     {
-                        best_error = error;
-                        best_selector = i;
-                     }
-                  }
-
-                  pDXT1_block->set_selector(x & 3, y & 3, best_selector);
-               }
-
-               break;
-            }
-            case cAlphaDXT5:
-            {
-               dxt5_block* pDXT5_block = reinterpret_cast<dxt5_block*>(pElement);
-
-               uint values[cDXT5SelectorValues];
-               dxt5_block::get_block_values(values, pDXT5_block->get_low_alpha(), pDXT5_block->get_high_alpha());
-
-               const int comp_index = m_element_component_index[element_index];
-
-               uint best_error = UINT_MAX;
-               uint best_selector = 0;
-
-               for (uint i = 0; i < cDXT5SelectorValues; i++)
-               {
-                  uint error = labs(values[i] - c[comp_index]); // no need to square
-
-                  if (error < best_error)
-                  {
-                     best_error = error;
-                     best_selector = i;
-                  }
-               }
-
-               pDXT5_block->set_selector(x & 3, y & 3, best_selector);
-
-               break;
-            }
-            case cAlphaDXT3:
-            {
-               const int comp_index = m_element_component_index[element_index];
-
-               dxt3_block* pDXT3_block = reinterpret_cast<dxt3_block*>(pElement);
-
-               pDXT3_block->set_alpha(x & 3, y & 3, c[comp_index], true);
-
-               break;
-            }
-            default: break;
-         }
-      } // element_index
-   }
-
-   bool dxt_image::get_block_pixels(uint block_x, uint block_y, color_quad_u8* pPixels) const
-   {
-      bool success = true;
-      const element* pElement = &get_element(block_x, block_y, 0);
-
-      for (uint element_index = 0; element_index < m_num_elements_per_block; element_index++, pElement++)
-      {
-         switch (m_element_type[element_index])
-         {
-            case cColorETC1:
-            {
-               const etc1_block& block = *reinterpret_cast<const etc1_block*>(&get_element(block_x, block_y, element_index));
-               // Preserve alpha if the format is something weird (like ETC1 for color and DXT5A for alpha) - which isn't currently supported.
-#if CRNLIB_USE_RG_ETC1
-               if (!rg_etc1::unpack_etc1_block(&block, (uint32*)pPixels, m_format != cETC1))
-                  success = false;
-#else
-               if (!unpack_etc1(block, pPixels, m_format != cETC1))
-                  success = false;
-#endif
-
-               break;
-            }
-            case cColorDXT1:
-            {
-               const dxt1_block* pDXT1_block = reinterpret_cast<const dxt1_block*>(pElement);
-
-               color_quad_u8 colors[cDXT1SelectorValues];
-               pDXT1_block->get_block_colors(colors, static_cast<uint16>(pDXT1_block->get_low_color()), static_cast<uint16>(pDXT1_block->get_high_color()));
-
-               for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-               {
-                  uint s = pDXT1_block->get_selector(i & 3, i >> 2);
-
-                  pPixels[i].r = colors[s].r;
-                  pPixels[i].g = colors[s].g;
-                  pPixels[i].b = colors[s].b;
-
-                  if (m_format <= cDXT1A)
-                     pPixels[i].a = colors[s].a;
-               }
-
-               break;
-            }
-            case cAlphaDXT5:
-            {
-               const dxt5_block* pDXT5_block = reinterpret_cast<const dxt5_block*>(pElement);
-
-               uint values[cDXT5SelectorValues];
-               dxt5_block::get_block_values(values, pDXT5_block->get_low_alpha(), pDXT5_block->get_high_alpha());
-
-               const int comp_index = m_element_component_index[element_index];
-
-               for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-               {
-                  uint s = pDXT5_block->get_selector(i & 3, i >> 2);
-
-                  pPixels[i][comp_index] = static_cast<uint8>(values[s]);
-               }
-
-               break;
-            }
-            case cAlphaDXT3:
-            {
-               const dxt3_block* pDXT3_block = reinterpret_cast<const dxt3_block*>(pElement);
-
-               const int comp_index = m_element_component_index[element_index];
-
-               for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-               {
-                  uint a = pDXT3_block->get_alpha(i & 3, i >> 2, true);
-
-                  pPixels[i][comp_index] = static_cast<uint8>(a);
-               }
-
-               break;
-            }
-            default: break;
-         }
-      } // element_index
-      return success;
-   }
-
-   void dxt_image::set_block_pixels(uint block_x, uint block_y, const color_quad_u8* pPixels, const pack_params& p)
-   {
-      set_block_pixels_context context;
-      set_block_pixels(block_x, block_y, pPixels, p, context);
-   }
-
-   void dxt_image::set_block_pixels(
-      uint block_x, uint block_y, const color_quad_u8* pPixels, const pack_params& p,
-      set_block_pixels_context& context)
-   {
-      element* pElement = &get_element(block_x, block_y, 0);
-
-      if (m_format == cETC1)
-      {
-         etc1_block &dst_block = *reinterpret_cast<etc1_block*>(pElement);
-
-#if CRNLIB_USE_RG_ETC1
-         rg_etc1::etc1_quality etc_quality = rg_etc1::cHighQuality;
-         if (p.m_quality <= cCRNDXTQualityFast)
-            etc_quality = rg_etc1::cLowQuality;
-         else if (p.m_quality <= cCRNDXTQualityNormal)
-            etc_quality = rg_etc1::cMediumQuality;
-
-         rg_etc1::etc1_pack_params pack_params;
-         pack_params.m_dithering = p.m_dithering;
-         //pack_params.m_perceptual = p.m_perceptual;
-         pack_params.m_quality = etc_quality;
-         rg_etc1::pack_etc1_block(&dst_block, (uint32*)pPixels, pack_params);
-#else
-         crn_etc_quality etc_quality = cCRNETCQualitySlow;
-         if (p.m_quality <= cCRNDXTQualityFast)
-            etc_quality = cCRNETCQualityFast;
-         else if (p.m_quality <= cCRNDXTQualityNormal)
-            etc_quality = cCRNETCQualityMedium;
-
-         crn_etc1_pack_params pack_params;
-         pack_params.m_perceptual = p.m_perceptual;
-         pack_params.m_quality = etc_quality;
-         pack_params.m_dithering = p.m_dithering;
-
-         pack_etc1_block(dst_block, pPixels, pack_params, context.m_etc1_optimizer);
-#endif
-      }
-      else
-#if CRNLIB_SUPPORT_SQUISH
-      if ((p.m_compressor == cCRNDXTCompressorSquish) && ((m_format == cDXT1) || (m_format == cDXT1A) || (m_format == cDXT3) || (m_format == cDXT5) || (m_format == cDXT5A)))
-      {
-         uint squish_flags = 0;
-         if ((m_format == cDXT1) || (m_format == cDXT1A))
-            squish_flags = squish::kDxt1;
-         else if (m_format == cDXT3)
-            squish_flags = squish::kDxt3;
-         else  if (m_format == cDXT5A)
-            squish_flags = squish::kDxt5A;
-         else
-            squish_flags = squish::kDxt5;
-
-         if (p.m_perceptual)
-            squish_flags |= squish::kColourMetricPerceptual;
-         else
-            squish_flags |= squish::kColourMetricUniform;
-
-         if (p.m_quality >= cCRNDXTQualityBetter)
-            squish_flags |= squish::kColourIterativeClusterFit;
-         else if (p.m_quality == cCRNDXTQualitySuperFast)
-            squish_flags |= squish::kColourRangeFit;
-
-         color_quad_u8 pixels[cDXTBlockSize * cDXTBlockSize];
-
-         memcpy(pixels, pPixels, sizeof(color_quad_u8) * cDXTBlockSize * cDXTBlockSize);
-
-         if (m_format == cDXT1)
-         {
-            for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-               pixels[i].a = 255;
-         }
-         else if (m_format == cDXT1A)
-         {
-            for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-               if (pixels[i].a < p.m_dxt1a_alpha_threshold)
-                  pixels[i].a = 0;
-               else
-                  pixels[i].a = 255;
-         }
-
-         squish::Compress(reinterpret_cast<const squish::u8*>(pixels), pElement, squish_flags);
-      }
-
-      else
-#endif // CRNLIB_SUPPORT_SQUISH
-      // RYG doesn't support DXT1A
-      if ((p.m_compressor == cCRNDXTCompressorRYG) && ((m_format == cDXT1) || (m_format == cDXT5) || (m_format == cDXT5A)))
-      {
-         color_quad_u8 pixels[cDXTBlockSize * cDXTBlockSize];
-
-         for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-         {
-            pixels[i].r = pPixels[i].b;
-            pixels[i].g = pPixels[i].g;
-            pixels[i].b = pPixels[i].r;
-
-            if (m_format == cDXT1)
-               pixels[i].a = 255;
-            else
-               pixels[i].a = pPixels[i].a;
-         }
-
-         if (m_format == cDXT5A)
-            ryg_dxt::sCompressDXT5ABlock((sU8*)pElement, (const sU32*)pixels, 0);
-         else
-            ryg_dxt::sCompressDXTBlock((sU8*)pElement, (const sU32*)pixels, m_format == cDXT5, 0);
-      }
-      else if ((p.m_compressor == cCRNDXTCompressorCRNF) && (m_format != cDXT1A))
-      {
-         for (uint element_index = 0; element_index < m_num_elements_per_block; element_index++, pElement++)
-         {
-            switch (m_element_type[element_index])
-            {
-               case cColorDXT1:
-               {
-                  dxt1_block* pDXT1_block = reinterpret_cast<dxt1_block*>(pElement);
-                  dxt_fast::compress_color_block(pDXT1_block, pPixels, p.m_quality >= cCRNDXTQualityNormal);
-
-                  break;
-               }
-               case cAlphaDXT5:
-               {
-                  dxt5_block* pDXT5_block = reinterpret_cast<dxt5_block*>(pElement);
-                  dxt_fast::compress_alpha_block(pDXT5_block, pPixels, m_element_component_index[element_index]);
-
-                  break;
-               }
-               case cAlphaDXT3:
-               {
-                  const int comp_index = m_element_component_index[element_index];
-
-                  dxt3_block* pDXT3_block = reinterpret_cast<dxt3_block*>(pElement);
-
-                  for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-                     pDXT3_block->set_alpha(i & 3, i >> 2, pPixels[i][comp_index], true);
-
-                  break;
-               }
-               default: break;
-            }
-         }
-      }
-      else
-      {
-         dxt1_endpoint_optimizer& dxt1_optimizer = context.m_dxt1_optimizer;
-         dxt5_endpoint_optimizer& dxt5_optimizer = context.m_dxt5_optimizer;
-
-         for (uint element_index = 0; element_index < m_num_elements_per_block; element_index++, pElement++)
-         {
-            switch (m_element_type[element_index])
-            {
-               case cColorDXT1:
-               {
-                  dxt1_block* pDXT1_block = reinterpret_cast<dxt1_block*>(pElement);
-
-                  bool pixels_have_alpha = false;
-                  if (m_format == cDXT1A)
-                  {
-                     for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-                        if (pPixels[i].a < p.m_dxt1a_alpha_threshold)
-                        {
-                           pixels_have_alpha = true;
-                           break;
-                        }
-                  }
-
-                  dxt1_endpoint_optimizer::results results;
-                  uint8 selectors[cDXTBlockSize * cDXTBlockSize];
-                  results.m_pSelectors = selectors;
-
-                  dxt1_endpoint_optimizer::params params;
-                  params.m_block_index = block_x + block_y * m_blocks_x;
-                  params.m_quality = p.m_quality;
-                  params.m_perceptual = p.m_perceptual;
-                  params.m_grayscale_sampling = p.m_grayscale_sampling;
-                  params.m_pixels_have_alpha = pixels_have_alpha;
-                  params.m_use_alpha_blocks = p.m_use_both_block_types;
-                  params.m_use_transparent_indices_for_black = p.m_use_transparent_indices_for_black;
-                  params.m_dxt1a_alpha_threshold = p.m_dxt1a_alpha_threshold;
-                  params.m_pPixels = pPixels;
-                  params.m_num_pixels = cDXTBlockSize * cDXTBlockSize;
-                  params.m_endpoint_caching = p.m_endpoint_caching;
-                  params.m_color_weights[0] = p.m_color_weights[0];
-                  params.m_color_weights[1] = p.m_color_weights[1];
-                  params.m_color_weights[2] = p.m_color_weights[2];
-
-                  if ((m_format != cDXT1) && (m_format != cDXT1A))
-                     params.m_use_alpha_blocks = false;
-
-                  if (!dxt1_optimizer.compute(params, results))
-                  {
-                     CRNLIB_ASSERT(0);
-                     break;
-                  }
-
-                  pDXT1_block->set_low_color(results.m_low_color);
-                  pDXT1_block->set_high_color(results.m_high_color);
-
-                  for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-                     pDXT1_block->set_selector(i & 3, i >> 2, selectors[i]);
-
-                  break;
-               }
-               case cAlphaDXT5:
-               {
-                  dxt5_block* pDXT5_block = reinterpret_cast<dxt5_block*>(pElement);
-
-                  dxt5_endpoint_optimizer::results results;
-
-                  uint8 selectors[cDXTBlockSize * cDXTBlockSize];
-                  results.m_pSelectors = selectors;
-
-                  dxt5_endpoint_optimizer::params params;
-                  params.m_block_index = block_x + block_y * m_blocks_x;
-                  params.m_pPixels = pPixels;
-                  params.m_num_pixels = cDXTBlockSize * cDXTBlockSize;
-                  params.m_comp_index = m_element_component_index[element_index];
-                  params.m_quality = p.m_quality;
-                  params.m_use_both_block_types = p.m_use_both_block_types;
-
-                  if (!dxt5_optimizer.compute(params, results))
-                  {
-                     CRNLIB_ASSERT(0);
-                     break;
-                  }
-
-                  pDXT5_block->set_low_alpha(results.m_first_endpoint);
-                  pDXT5_block->set_high_alpha(results.m_second_endpoint);
-
-                  for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-                     pDXT5_block->set_selector(i & 3, i >> 2, selectors[i]);
-
-                  break;
-               }
-               case cAlphaDXT3:
-               {
-                  const int comp_index = m_element_component_index[element_index];
-
-                  dxt3_block* pDXT3_block = reinterpret_cast<dxt3_block*>(pElement);
-
-                  for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-                     pDXT3_block->set_alpha(i & 3, i >> 2, pPixels[i][comp_index], true);
-
-                  break;
-               }
-               default: break;
-            }
-         }
-      }
-   }
-
-   void dxt_image::get_block_endpoints(uint block_x, uint block_y, uint element_index, uint& packed_low_endpoint, uint& packed_high_endpoint) const
-   {
-      const element& block = get_element(block_x, block_y, element_index);
-
-      switch (m_element_type[element_index])
-      {
-         case cColorETC1:
-         {
-            const etc1_block& src_block = *reinterpret_cast<const etc1_block*>(&block);
-            if (src_block.get_diff_bit())
-            {
-               packed_low_endpoint = src_block.get_base5_color();
-               packed_high_endpoint = src_block.get_delta3_color();
-            }
-            else
-            {
-               packed_low_endpoint =  src_block.get_base4_color(0);
-               packed_high_endpoint = src_block.get_base4_color(1);
-            }
-
-            break;
-         }
-         case cColorDXT1:
-         {
-            const dxt1_block& block1 = *reinterpret_cast<const dxt1_block*>(&block);
-
-            packed_low_endpoint = block1.get_low_color();
-            packed_high_endpoint = block1.get_high_color();
-
-            break;
-         }
-         case cAlphaDXT5:
-         {
-            const dxt5_block& block5 = *reinterpret_cast<const dxt5_block*>(&block);
-
-            packed_low_endpoint = block5.get_low_alpha();
-            packed_high_endpoint = block5.get_high_alpha();
-
-            break;
-         }
-         case cAlphaDXT3:
-         {
-            packed_low_endpoint = 0;
-            packed_high_endpoint = 255;
-
-            break;
-         }
-         default: break;
-      }
-   }
-
-   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 = 0, h = 0;
-      get_block_endpoints(block_x, block_y, element_index, l, h);
-
-      switch (m_element_type[element_index])
-      {
-         case cColorETC1:
-         {
-            const etc1_block& src_block = *reinterpret_cast<const etc1_block*>(&get_element(block_x, block_y, element_index));
-            if (src_block.get_diff_bit())
-            {
-               low_endpoint = etc1_block::unpack_color5(static_cast<uint16>(l), scaled);
-               etc1_block::unpack_color5(high_endpoint, static_cast<uint16>(l), static_cast<uint16>(h), scaled);
-            }
-            else
-            {
-               low_endpoint = etc1_block::unpack_color4(static_cast<uint16>(l), scaled);
-               high_endpoint = etc1_block::unpack_color4(static_cast<uint16>(h), scaled);
-            }
-
-            return -1;
-         }
-         case cColorDXT1:
-         {
-            uint r, g, b;
-
-            dxt1_block::unpack_color(r, g, b, static_cast<uint16>(l), scaled);
-            low_endpoint.r = static_cast<uint8>(r);
-            low_endpoint.g = static_cast<uint8>(g);
-            low_endpoint.b = static_cast<uint8>(b);
-
-            dxt1_block::unpack_color(r, g, b, static_cast<uint16>(h), scaled);
-            high_endpoint.r = static_cast<uint8>(r);
-            high_endpoint.g = static_cast<uint8>(g);
-            high_endpoint.b = static_cast<uint8>(b);
-
-            return -1;
-         }
-         case cAlphaDXT5:
-         {
-            const int component = m_element_component_index[element_index];
-
-            low_endpoint[component] = static_cast<uint8>(l);
-            high_endpoint[component] = static_cast<uint8>(h);
-
-            return component;
-         }
-         case cAlphaDXT3:
-         {
-            const int component = m_element_component_index[element_index];
-
-            low_endpoint[component] = static_cast<uint8>(l);
-            high_endpoint[component] = static_cast<uint8>(h);
-
-            return component;
-         }
-         default: break;
-      }
-
-      return 0;
-   }
-
-   uint dxt_image::get_block_colors(uint block_x, uint block_y, uint element_index, color_quad_u8* pColors, uint subblock_index)
-   {
-      const element& block = get_element(block_x, block_y, element_index);
-
-      switch (m_element_type[element_index])
-      {
-         case cColorETC1:
-         {
-            const etc1_block& src_block = *reinterpret_cast<const etc1_block*>(&get_element(block_x, block_y, element_index));
-            const uint table_index0 = src_block.get_inten_table(0);
-            const uint table_index1 = src_block.get_inten_table(1);
-            if (src_block.get_diff_bit())
-            {
-               const uint16 base_color5 = src_block.get_base5_color();
-               const uint16 delta_color3 = src_block.get_delta3_color();
-               if (subblock_index)
-                  etc1_block::get_diff_subblock_colors(pColors, base_color5, delta_color3, table_index1);
-               else
-                  etc1_block::get_diff_subblock_colors(pColors, base_color5, table_index0);
-            }
-            else
-            {
-               if (subblock_index)
-               {
-                  const uint16 base_color4_1 = src_block.get_base4_color(1);
-                  etc1_block::get_abs_subblock_colors(pColors, base_color4_1, table_index1);
-               }
-               else
-               {
-                  const uint16 base_color4_0 = src_block.get_base4_color(0);
-                  etc1_block::get_abs_subblock_colors(pColors, base_color4_0, table_index0);
-               }
-            }
-
-            break;
-         }
-         case cColorDXT1:
-         {
-            const dxt1_block& block1 = *reinterpret_cast<const dxt1_block*>(&block);
-            return dxt1_block::get_block_colors(pColors, static_cast<uint16>(block1.get_low_color()), static_cast<uint16>(block1.get_high_color()));
-         }
-         case cAlphaDXT5:
-         {
-            const dxt5_block& block5 = *reinterpret_cast<const dxt5_block*>(&block);
-
-            uint values[cDXT5SelectorValues];
-
-            const uint n = dxt5_block::get_block_values(values, block5.get_low_alpha(), block5.get_high_alpha());
-
-            const int comp_index = m_element_component_index[element_index];
-            for (uint i = 0; i < n; i++)
-               pColors[i][comp_index] = static_cast<uint8>(values[i]);
-
-            return n;
-         }
-         case cAlphaDXT3:
-         {
-            const int comp_index = m_element_component_index[element_index];
-            for (uint i = 0; i < 16; i++)
-               pColors[i][comp_index] = static_cast<uint8>((i << 4) | i);
-
-            return 16;
-         }
-         default: break;
-      }
-
-      return 0;
-   }
-
-   uint dxt_image::get_subblock_index(uint x, uint y, uint element_index) const
-   {
-      if (m_element_type[element_index] != cColorETC1)
-         return 0;
-
-      const uint block_x = x >> cDXTBlockShift;
-      const uint block_y = y >> cDXTBlockShift;
-
-      const element& block = get_element(block_x, block_y, element_index);
-
-      const etc1_block& src_block = *reinterpret_cast<const etc1_block*>(&block);
-      if (src_block.get_flip_bit())
-      {
-         return ((y & 3) >= 2) ? 1 : 0;
-      }
-      else
-      {
-         return ((x & 3) >= 2) ? 1 : 0;
-      }
-   }
-
-   uint dxt_image::get_total_subblocks(uint element_index) const
-   {
-      return (m_element_type[element_index] == cColorETC1) ? 2 : 0;
-   }
-
-   uint dxt_image::get_selector(uint x, uint y, uint element_index) const
-   {
-      CRNLIB_ASSERT((x < m_width) && (y < m_height));
-
-      const uint block_x = x >> cDXTBlockShift;
-      const uint block_y = y >> cDXTBlockShift;
-
-      const element& block = get_element(block_x, block_y, element_index);
-
-      switch (m_element_type[element_index])
-      {
-         case cColorETC1:
-         {
-            const etc1_block& src_block = *reinterpret_cast<const etc1_block*>(&block);
-            return src_block.get_selector(x & 3, y & 3);
-         }
-         case cColorDXT1:
-         {
-            const dxt1_block& block1 = *reinterpret_cast<const dxt1_block*>(&block);
-            return block1.get_selector(x & 3, y & 3);
-         }
-         case cAlphaDXT5:
-         {
-            const dxt5_block& block5 = *reinterpret_cast<const dxt5_block*>(&block);
-            return block5.get_selector(x & 3, y & 3);
-         }
-         case cAlphaDXT3:
-         {
-            const dxt3_block& block3 = *reinterpret_cast<const dxt3_block*>(&block);
-            return block3.get_alpha(x & 3, y & 3, false);
-         }
-         default: break;
-      }
-
-      return 0;
-   }
-
-   void dxt_image::change_dxt1_to_dxt1a()
-   {
-      if (m_format == cDXT1)
-         m_format = cDXT1A;
-   }
-
-   void dxt_image::flip_col(uint x)
-   {
-      const uint other_x = (m_blocks_x - 1) - x;
-      for (uint y = 0; y < m_blocks_y; y++)
-      {
-         for (uint e = 0; e < get_elements_per_block(); e++)
-         {
-            element tmp[2] = { get_element(x, y, e), get_element(other_x, y, e) };
-
-            for (uint i = 0; i < 2; i++)
-            {
-               switch (get_element_type(e))
-               {
-                  case cColorDXT1: reinterpret_cast<dxt1_block*>(&tmp[i])->flip_x(); break;
-                  case cAlphaDXT3: reinterpret_cast<dxt3_block*>(&tmp[i])->flip_x(); break;
-                  case cAlphaDXT5: reinterpret_cast<dxt5_block*>(&tmp[i])->flip_x(); break;
-                  default: CRNLIB_ASSERT(0); break;
-               }
-            }
-
-            get_element(x, y, e) = tmp[1];
-            get_element(other_x, y, e) = tmp[0];
-         }
-      }
-   }
-
-   void dxt_image::flip_row(uint y)
-   {
-      const uint other_y = (m_blocks_y - 1) - y;
-      for (uint x = 0; x < m_blocks_x; x++)
-      {
-         for (uint e = 0; e < get_elements_per_block(); e++)
-         {
-            element tmp[2] = { get_element(x, y, e), get_element(x, other_y, e) };
-
-            for (uint i = 0; i < 2; i++)
-            {
-               switch (get_element_type(e))
-               {
-                  case cColorDXT1: reinterpret_cast<dxt1_block*>(&tmp[i])->flip_y(); break;
-                  case cAlphaDXT3: reinterpret_cast<dxt3_block*>(&tmp[i])->flip_y(); break;
-                  case cAlphaDXT5: reinterpret_cast<dxt5_block*>(&tmp[i])->flip_y(); break;
-                  default: CRNLIB_ASSERT(0); break;
-               }
-            }
-
-            get_element(x, y, e) = tmp[1];
-            get_element(x, other_y, e) = tmp[0];
-         }
-      }
-   }
-
-   bool dxt_image::can_flip(uint axis_index)
-   {
-      if (m_format == cETC1)
-      {
-         // Can't reliably flip ETC1 textures (because of asymmetry in the 555/333 differential coding of subblock colors).
-         return false;
-      }
-
-      uint d;
-      if (axis_index)
-         d = m_height;
-      else
-         d = m_width;
-
-      if (d & 3)
-      {
-         if (d > 4)
-            return false;
-      }
-
-      return true;
-   }
-
-   bool dxt_image::flip_x()
-   {
-      if (m_format == cETC1)
-      {
-         // Can't reliably flip ETC1 textures (because of asymmetry in the 555/333 differential coding of subblock colors).
-         return false;
-      }
-
-      if ((m_width & 3) && (m_width > 4))
-         return false;
-
-      if (m_width == 1)
-         return true;
-
-      const uint mid_x = m_blocks_x / 2;
-
-      for (uint x = 0; x < mid_x; x++)
-         flip_col(x);
-
-      if (m_blocks_x & 1)
-      {
-         const uint w = math::minimum(m_width, 4U);
-         for (uint y = 0; y < m_blocks_y; y++)
-         {
-            for (uint e = 0; e < get_elements_per_block(); e++)
-            {
-               element tmp(get_element(mid_x, y, e));
-               switch (get_element_type(e))
-               {
-                  case cColorDXT1: reinterpret_cast<dxt1_block*>(&tmp)->flip_x(w, 4); break;
-                  case cAlphaDXT3: reinterpret_cast<dxt3_block*>(&tmp)->flip_x(w, 4); break;
-                  case cAlphaDXT5: reinterpret_cast<dxt5_block*>(&tmp)->flip_x(w, 4); break;
-                  default: CRNLIB_ASSERT(0); break;
-               }
-               get_element(mid_x, y, e) = tmp;
-            }
-         }
-      }
-
-      return true;
-   }
-
-   bool dxt_image::flip_y()
-   {
-      if (m_format == cETC1)
-      {
-         // Can't reliably flip ETC1 textures (because of asymmetry in the 555/333 differential coding of subblock colors).
-         return false;
-      }
-
-      if ((m_height & 3) && (m_height > 4))
-         return false;
-
-      if (m_height == 1)
-         return true;
-
-      const uint mid_y = m_blocks_y / 2;
-
-      for (uint y = 0; y < mid_y; y++)
-         flip_row(y);
-
-      if (m_blocks_y & 1)
-      {
-         const uint h = math::minimum(m_height, 4U);
-         for (uint x = 0; x < m_blocks_x; x++)
-         {
-            for (uint e = 0; e < get_elements_per_block(); e++)
-            {
-               element tmp(get_element(x, mid_y, e));
-               switch (get_element_type(e))
-               {
-                  case cColorDXT1: reinterpret_cast<dxt1_block*>(&tmp)->flip_y(4, h); break;
-                  case cAlphaDXT3: reinterpret_cast<dxt3_block*>(&tmp)->flip_y(4, h); break;
-                  case cAlphaDXT5: reinterpret_cast<dxt5_block*>(&tmp)->flip_y(4, h); break;
-                  default: CRNLIB_ASSERT(0); break;
-               }
-               get_element(x, mid_y, e) = tmp;
-            }
-         }
-      }
-
-      return true;
-   }
-
-} // namespace crnlib
-
-
-
-

+ 0 - 248
Source/ThirdParty/crunch/crnlib/crn_dxt_image.h

@@ -1,248 +0,0 @@
-// File: crn_dxt_image.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dxt1.h"
-#include "crn_dxt5a.h"
-#include "crn_etc.h"
-#if CRNLIB_SUPPORT_ETC_A1
-#include "crn_etc_a1.h"
-#endif
-#include "crn_image.h"
-
-#define CRNLIB_SUPPORT_ATI_COMPRESS 0
-
-namespace crnlib
-{
-   class task_pool;
-
-   class dxt_image
-   {
-   public:
-      dxt_image();
-      dxt_image(const dxt_image& other);
-      dxt_image& operator= (const dxt_image& rhs);
-         
-      void clear();
-
-      inline bool is_valid() const { return m_blocks_x > 0; }
-      
-      uint get_width() const { return m_width; }
-      uint get_height() const { return m_height; }
-      
-      uint get_blocks_x() const { return m_blocks_x; }
-      uint get_blocks_y() const { return m_blocks_y; }
-      uint get_total_blocks() const { return m_blocks_x * m_blocks_y; }
-      
-      uint get_elements_per_block() const { return m_num_elements_per_block; }
-      uint get_bytes_per_block() const { return m_bytes_per_block; }
-      
-      dxt_format get_format() const { return m_format; }
-      
-      bool has_color() const { return (m_format == cDXT1) || (m_format == cDXT1A) || (m_format == cDXT3) || (m_format == cDXT5) || (m_format == cETC1); }
-      
-      // Will be pretty slow if the image is DXT1, as this method scans for alpha blocks/selectors.
-      bool has_alpha() const;
-            
-      enum element_type
-      { 
-         cUnused = 0,
-         
-         cColorDXT1,    // DXT1 color block
-         
-         cAlphaDXT3,    // DXT3 alpha block (only)
-         cAlphaDXT5,    // DXT5 alpha block (only)
-
-         cColorETC1,    // ETC1 color block
-      };
-      
-      element_type get_element_type(uint element_index) const { CRNLIB_ASSERT(element_index < m_num_elements_per_block); return m_element_type[element_index]; }
-            
-      //Returns -1 for RGB, or [0,3]
-      int8 get_element_component_index(uint element_index) const { CRNLIB_ASSERT(element_index < m_num_elements_per_block); return m_element_component_index[element_index]; }
-      
-      struct element
-      {
-         uint8 m_bytes[8];
-         
-         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 <= cUINT16_MAX)); m_bytes[index*2] = static_cast<uint8>(val & 0xFF); m_bytes[index * 2 + 1] = static_cast<uint8>((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<uint8>(val & 0xFF); m_bytes[index * 2] = static_cast<uint8>((val >> 8) & 0xFF); }
-         
-         void clear()
-         {
-            memset(this, 0, sizeof(*this));
-         }
-      };
-      
-      typedef crnlib::vector<element> element_vec;
-                  
-      bool init(dxt_format fmt, uint width, uint height, bool clear_elements);
-      bool init(dxt_format fmt, uint width, uint height, uint num_elements, element* pElements, bool create_copy);
-      
-      struct pack_params
-      {
-         pack_params()
-         {
-            clear();
-         }
-
-         void clear()
-         {
-            m_quality = cCRNDXTQualityUber;
-            m_perceptual = true;
-            m_dithering = false;
-            m_grayscale_sampling = false;
-            m_use_both_block_types = true;
-            m_endpoint_caching = true;
-            m_compressor = cCRNDXTCompressorCRN;
-            m_pProgress_callback = NULL;
-            m_pProgress_callback_user_data_ptr = NULL;
-            m_dxt1a_alpha_threshold = 128;
-            m_num_helper_threads = 0;
-            m_progress_start = 0;
-            m_progress_range = 100;
-            m_use_transparent_indices_for_black = false;
-            m_pTask_pool = NULL;
-            m_color_weights[0] = 1;
-            m_color_weights[1] = 1;
-            m_color_weights[2] = 1;
-         }
-
-         void init(const crn_comp_params &params)
-         {
-            m_perceptual = (params.m_flags & cCRNCompFlagPerceptual) != 0;
-            m_num_helper_threads = params.m_num_helper_threads;
-            m_use_both_block_types = (params.m_flags & cCRNCompFlagUseBothBlockTypes) != 0;
-            m_use_transparent_indices_for_black = (params.m_flags & cCRNCompFlagUseTransparentIndicesForBlack) != 0;
-            m_dxt1a_alpha_threshold = params.m_dxt1a_alpha_threshold;
-            m_quality = params.m_dxt_quality;
-            m_endpoint_caching = (params.m_flags & cCRNCompFlagDisableEndpointCaching) == 0;
-            m_grayscale_sampling = (params.m_flags & cCRNCompFlagGrayscaleSampling) != 0;
-            m_compressor = params.m_dxt_compressor_type;
-         }
-         
-         uint                    m_dxt1a_alpha_threshold;
-         
-         uint                    m_num_helper_threads;
-         
-         crn_dxt_quality         m_quality;
-         
-         crn_dxt_compressor_type m_compressor;
-                           
-         bool                    m_perceptual;
-         bool                    m_dithering;
-         bool                    m_grayscale_sampling;
-         bool                    m_use_both_block_types;
-         bool                    m_endpoint_caching;
-         bool                    m_use_transparent_indices_for_black;
-                                    
-         typedef bool (*progress_callback_func)(uint percentage_complete, void* pUser_data_ptr);
-         progress_callback_func  m_pProgress_callback;
-         void*                   m_pProgress_callback_user_data_ptr;
-         
-         uint                    m_progress_start;
-         uint                    m_progress_range;
-
-         task_pool               *m_pTask_pool;
-
-         int                     m_color_weights[3];
-      };
-      
-      bool init(dxt_format fmt, const image_u8& img, const pack_params& p = dxt_image::pack_params());
-      
-      bool unpack(image_u8& img) const;
-      
-      void endian_swap();
-      
-      uint get_total_elements() const { return m_elements.size(); }
-                  
-      const element_vec& get_element_vec() const   { return m_elements; }
-            element_vec& get_element_vec()         { return m_elements; }
-                  
-      const element& get_element(uint block_x, uint block_y, uint element_index) const;
-            element& get_element(uint block_x, uint block_y, uint element_index);      
-            
-      const element* get_element_ptr() const { return m_pElements; } 
-            element* get_element_ptr()       { return m_pElements; } 
-      
-      uint get_size_in_bytes() const { return m_elements.size() * sizeof(element); }
-      uint get_row_pitch_in_bytes() const { return m_blocks_x * m_bytes_per_block; }
-            
-      color_quad_u8 get_pixel(uint x, uint y) const;
-      uint get_pixel_alpha(uint x, uint y, uint element_index) const;
-      
-      void set_pixel(uint x, uint y, const color_quad_u8& c, bool perceptual = true);
-      
-      // get_block_pixels() only sets those components stored in the image!
-      bool get_block_pixels(uint block_x, uint block_y, color_quad_u8* pPixels) const;
-
-      struct set_block_pixels_context
-      {
-         dxt1_endpoint_optimizer m_dxt1_optimizer;
-         dxt5_endpoint_optimizer m_dxt5_optimizer;
-         pack_etc1_block_context m_etc1_optimizer;
-#if CRNLIB_SUPPORT_ETC_A1
-         etc_a1::pack_etc1_block_context m_etc1_a1_optimizer;
-#endif
-      };
-      
-      void set_block_pixels(uint block_x, uint block_y, const color_quad_u8* pPixels, const pack_params& p, set_block_pixels_context& context);
-      void set_block_pixels(uint block_x, uint block_y, const color_quad_u8* pPixels, const pack_params& p);
-      
-      void get_block_endpoints(uint block_x, uint block_y, uint element_index, uint& packed_low_endpoint, uint& packed_high_endpoint) const;
-      
-      // Returns a value representing the component(s) that where actually set, where -1 = RGB.
-      // This method does not always set every component!
-      int get_block_endpoints(uint block_x, uint block_y, uint element_index, color_quad_u8& low_endpoint, color_quad_u8& high_endpoint, bool scaled = true) const;
-      
-      // pColors should point to a 16 entry array, to handle DXT3.
-      // Returns the number of block colors: 3, 4, 6, 8, or 16.
-      uint get_block_colors(uint block_x, uint block_y, uint element_index, color_quad_u8* pColors, uint subblock_index = 0);
-            
-      uint get_subblock_index(uint x, uint y, uint element_index) const;
-      uint get_total_subblocks(uint element_index) const;
-      
-      uint get_selector(uint x, uint y, uint element_index) const;
-      
-      void change_dxt1_to_dxt1a();
-
-      bool can_flip(uint axis_index);
-
-      // Returns true if the texture can actually be flipped.
-      bool flip_x();
-      bool flip_y();
-         
-   private:
-      element_vec       m_elements;
-      element*          m_pElements;
-      
-      uint              m_width;
-      uint              m_height;
-      
-      uint              m_blocks_x;
-      uint              m_blocks_y;
-      uint              m_total_blocks;
-      uint              m_total_elements;
-      
-      uint              m_num_elements_per_block;   // 1 or 2
-      uint              m_bytes_per_block;          // 8 or 16
-      
-      int8              m_element_component_index[2];            
-      element_type      m_element_type[2];
-         
-      dxt_format        m_format;             // DXT1, 1A, 3, 5, N/3DC, or 5A
-      
-      bool init_internal(dxt_format fmt, uint width, uint height);
-      void init_task(uint64 data, void* pData_ptr);
-
-#if CRNLIB_SUPPORT_ATI_COMPRESS   
-      bool init_ati_compress(dxt_format fmt, const image_u8& img, const pack_params& p);
-#endif      
-
-      void flip_col(uint x);
-      void flip_row(uint y);
-   };
-
-} // namespace crnlib

+ 0 - 206
Source/ThirdParty/crunch/crnlib/crn_dynamic_stream.h

@@ -1,206 +0,0 @@
-// File: crn_dynamic_stream.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_data_stream.h"
-
-namespace crnlib
-{
-   class dynamic_stream : public data_stream
-   {
-   public:
-      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 char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) :
-         data_stream(pName, attribs),
-         m_ofs(0)
-      {
-         open(pBuf, size, pName, attribs);
-      }
-
-      dynamic_stream() :
-         data_stream(),
-         m_ofs(0)
-      {
-         open();
-      }
-
-      virtual ~dynamic_stream()
-      {
-      }
-
-      bool open(uint initial_size = 0, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable)
-      {
-         close();
-
-         m_opened = true;
-         m_buf.clear();
-         m_buf.resize(initial_size);
-         m_ofs = 0;
-         m_name.set(pName ? pName : "dynamic_stream");
-         m_attribs = static_cast<attribs_t>(attribs);
-         return true;
-      }
-
-      bool reopen(const char* pName, uint attribs)
-      {
-         if (!m_opened)
-         {
-            return open(0, pName, attribs);
-         }
-
-         m_name.set(pName ? pName : "dynamic_stream");
-         m_attribs = static_cast<attribs_t>(attribs);
-         return true;
-      }
-
-      bool open(const void* pBuf, uint size, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable)
-      {
-         if (!m_opened)
-         {
-            m_opened = true;
-            m_buf.resize(size);
-            if (size)
-            {
-               CRNLIB_ASSERT(pBuf);
-               memcpy(&m_buf[0], pBuf, size);
-            }
-            m_ofs = 0;
-            m_name.set(pName ? pName : "dynamic_stream");
-            m_attribs = static_cast<attribs_t>(attribs);
-            return true;
-         }
-
-         return false;
-      }
-
-      virtual bool close()
-      {
-         if (m_opened)
-         {
-            m_opened = false;
-            m_buf.clear();
-            m_ofs = 0;
-            return true;
-         }
-
-         return false;
-      }
-
-      const crnlib::vector<uint8>& get_buf() const { return m_buf; }
-            crnlib::vector<uint8>& get_buf()       { return m_buf; }
-
-      void reserve(uint size)
-      {
-         if (m_opened)
-         {
-            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<uint>(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()
-      {
-         if (!m_opened)
-            return 0;
-
-         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()
-      {
-         if (!m_opened)
-            return 0;
-
-         return m_ofs;
-      }
-
-      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<uint>(new_ofs);
-
-         post_seek();
-
-         return true;
-      }
-
-   private:
-      crnlib::vector<uint8>    m_buf;
-      uint                    m_ofs;
-   };
-
-} // namespace crnlib
-

+ 0 - 668
Source/ThirdParty/crunch/crnlib/crn_dynamic_string.cpp

@@ -1,668 +0,0 @@
-// File: crn_dynamic_string.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_strutils.h"
-
-namespace crnlib
-{
-   dynamic_string g_empty_dynamic_string;
-
-   dynamic_string::dynamic_string(eVarArg dummy, const char* p, ...) :
-      m_buf_size(0), m_len(0), m_pStr(NULL)
-   {
-      dummy;
-
-      CRNLIB_ASSERT(p);
-
-      va_list args;
-      va_start(args, p);
-      format_args(p, args);
-      va_end(args);
-   }
-
-   dynamic_string::dynamic_string(const char* p) :
-      m_buf_size(0), m_len(0), m_pStr(NULL)
-   {
-      CRNLIB_ASSERT(p);
-      set(p);
-   }
-
-   dynamic_string::dynamic_string(const char* p, uint len) :
-      m_buf_size(0), m_len(0), m_pStr(NULL)
-   {
-      CRNLIB_ASSERT(p);
-      set_from_buf(p, len);
-   }
-
-   dynamic_string::dynamic_string(const dynamic_string& other) :
-      m_buf_size(0), m_len(0), m_pStr(NULL)
-   {
-      set(other);
-   }
-
-   void dynamic_string::clear()
-   {
-      check();
-
-      if (m_pStr)
-      {
-         crnlib_delete_array(m_pStr);
-         m_pStr = NULL;
-
-         m_len = 0;
-         m_buf_size = 0;
-      }
-   }
-
-   void dynamic_string::empty()
-   {
-      truncate(0);
-   }
-
-   void dynamic_string::optimize()
-   {
-      if (!m_len)
-         clear();
-      else
-      {
-         uint min_buf_size = math::next_pow2((uint)m_len + 1);
-         if (m_buf_size > min_buf_size)
-         {
-            char* p = crnlib_new_array<char>(min_buf_size);
-            memcpy(p, m_pStr, m_len + 1);
-
-            crnlib_delete_array(m_pStr);
-            m_pStr = p;
-
-            m_buf_size = static_cast<uint16>(min_buf_size);
-
-            check();
-         }
-      }
-   }
-
-   int dynamic_string::compare(const char* p, bool case_sensitive) const
-   {
-      CRNLIB_ASSERT(p);
-
-      const int result = (case_sensitive ? strcmp : crn_stricmp)(get_ptr_priv(), p);
-
-      if (result < 0)
-         return -1;
-      else if (result > 0)
-         return 1;
-
-      return 0;
-   }
-
-   int dynamic_string::compare(const dynamic_string& rhs, bool case_sensitive) const
-   {
-      return compare(rhs.get_ptr_priv(), case_sensitive);
-   }
-
-   dynamic_string& dynamic_string::set(const char* p, uint max_len)
-   {
-      CRNLIB_ASSERT(p);
-
-      const uint len = math::minimum<uint>(max_len, static_cast<uint>(strlen(p)));
-      CRNLIB_ASSERT(len < cUINT16_MAX);
-
-      if ((!len) || (len >= cUINT16_MAX))
-         clear();
-      else if ((m_pStr) && (p >= m_pStr) && (p < (m_pStr + m_buf_size)))
-      {
-         if (m_pStr != p)
-            memmove(m_pStr, p, len);
-         m_pStr[len] = '\0';
-         m_len = static_cast<uint16>(len);
-      }
-      else if (ensure_buf(len, false))
-      {
-         m_len = static_cast<uint16>(len);
-         memcpy(m_pStr, p, m_len + 1);
-      }
-
-      check();
-
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::set(const dynamic_string& other, uint max_len)
-   {
-      if (this == &other)
-      {
-         if (max_len < m_len)
-         {
-            m_pStr[max_len] = '\0';
-            m_len = static_cast<uint16>(max_len);
-         }
-      }
-      else
-      {
-         const uint len = math::minimum<uint>(max_len, other.m_len);
-
-         if (!len)
-            clear();
-         else if (ensure_buf(len, false))
-         {
-            m_len = static_cast<uint16>(len);
-            memcpy(m_pStr, other.get_ptr_priv(), m_len);
-            m_pStr[len] = '\0';
-         }
-      }
-
-      check();
-
-      return *this;
-   }
-
-   bool dynamic_string::set_len(uint new_len, char fill_char)
-   {
-      if ((new_len >= cUINT16_MAX) || (!fill_char))
-      {
-         CRNLIB_ASSERT(0);
-         return false;
-      }
-
-      uint cur_len = m_len;
-
-      if (ensure_buf(new_len, true))
-      {
-         if (new_len > cur_len)
-            memset(m_pStr + cur_len, fill_char, new_len - cur_len);
-
-         m_pStr[new_len] = 0;
-
-         m_len = static_cast<uint16>(new_len);
-
-         check();
-      }
-
-      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<uint16>(buf_size_in_chars);
-      m_len = static_cast<uint16>(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 >= 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))
-      {
-         if (buf_size)
-            memcpy(m_pStr, pBuf, buf_size);
-
-         m_pStr[buf_size] = 0;
-
-         m_len = static_cast<uint16>(buf_size);
-
-         check();
-      }
-
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::set_char(uint index, char c)
-   {
-      CRNLIB_ASSERT(index <= m_len);
-
-      if (!c)
-         truncate(index);
-      else if (index < m_len)
-      {
-         m_pStr[index] = c;
-
-         check();
-      }
-      else if (index == m_len)
-         append_char(c);
-
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::append_char(char c)
-   {
-      if (ensure_buf(m_len + 1))
-      {
-         m_pStr[m_len] = c;
-         m_pStr[m_len + 1] = '\0';
-         m_len++;
-         check();
-      }
-
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::truncate(uint new_len)
-   {
-      if (new_len < m_len)
-      {
-         m_pStr[new_len] = '\0';
-         m_len = static_cast<uint16>(new_len);
-         check();
-      }
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::tolower()
-   {
-      if (m_len)
-      {
-#ifdef _MSC_VER
-         _strlwr_s(get_ptr_priv(), m_buf_size);
-#else
-         strlwr(get_ptr_priv());
-#endif
-      }
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::toupper()
-   {
-      if (m_len)
-      {
-#ifdef _MSC_VER
-         _strupr_s(get_ptr_priv(), m_buf_size);
-#else
-         strupr(get_ptr_priv());
-#endif
-      }
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::append(const char* p)
-   {
-      CRNLIB_ASSERT(p);
-
-      uint len = static_cast<uint>(strlen(p));
-      uint new_total_len = m_len + len;
-      if ((new_total_len) && ensure_buf(new_total_len))
-      {
-         memcpy(m_pStr + m_len, p, len + 1);
-         m_len = static_cast<uint16>(m_len + len);
-         check();
-      }
-
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::append(const dynamic_string& other)
-   {
-      uint len = other.m_len;
-      uint new_total_len = m_len + len;
-      if ((new_total_len) && ensure_buf(new_total_len))
-      {
-         memcpy(m_pStr + m_len, other.get_ptr_priv(), len + 1);
-         m_len = static_cast<uint16>(m_len + len);
-         check();
-      }
-
-      return *this;
-   }
-
-   dynamic_string operator+ (const char* p, const dynamic_string& a)
-   {
-      return dynamic_string(p).append(a);
-   }
-
-   dynamic_string operator+ (const dynamic_string& a, const char* p)
-   {
-      return dynamic_string(a).append(p);
-   }
-
-   dynamic_string operator+ (const dynamic_string& a, const dynamic_string& b)
-   {
-      return dynamic_string(a).append(b);
-   }
-
-   dynamic_string& dynamic_string::format_args(const char* p, va_list args)
-   {
-      CRNLIB_ASSERT(p);
-
-      const uint cBufSize = 4096;
-      char buf[cBufSize];
-
-#ifdef _MSC_VER
-      int l = vsnprintf_s(buf, cBufSize, _TRUNCATE, p, args);
-#else
-      int l = vsnprintf(buf, cBufSize, p, args);
-#endif
-      if (l <= 0)
-         clear();
-      else if (ensure_buf(l, false))
-      {
-         memcpy(m_pStr, buf, l + 1);
-
-         m_len = static_cast<uint16>(l);
-
-         check();
-      }
-
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::format(const char* p, ...)
-   {
-      CRNLIB_ASSERT(p);
-
-      va_list args;
-      va_start(args, p);
-      format_args(p, args);
-      va_end(args);
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::crop(uint start, uint len)
-   {
-      if (start >= m_len)
-      {
-         clear();
-         return *this;
-      }
-
-      len = math::minimum<uint>(len, m_len - start);
-
-      if (start)
-         memmove(get_ptr_priv(), get_ptr_priv() + start, len);
-
-      m_pStr[len] = '\0';
-
-      m_len = static_cast<uint16>(len);
-
-      check();
-
-      return *this;
-   }
-
-   dynamic_string& dynamic_string::substring(uint start, uint end)
-   {
-      CRNLIB_ASSERT(start <= end);
-      if (start > end)
-         return *this;
-      return crop(start, end - start);
-   }
-
-   dynamic_string& dynamic_string::left(uint len)
-   {
-      return substring(0, len);
-   }
-
-   dynamic_string& dynamic_string::mid(uint start, uint len)
-   {
-      return crop(start, len);
-   }
-
-   dynamic_string& dynamic_string::right(uint start)
-   {
-      return substring(start, get_len());
-   }
-
-   dynamic_string& dynamic_string::tail(uint num)
-   {
-      return substring(math::maximum<int>(static_cast<int>(get_len()) - static_cast<int>(num), 0), get_len());
-   }
-
-   dynamic_string& dynamic_string::unquote()
-   {
-      if (m_len >= 2)
-      {
-         if ( ((*this)[0] == '\"') && ((*this)[m_len - 1] == '\"') )
-         {
-            return mid(1, m_len - 2);
-         }
-      }
-
-      return *this;
-   }
-
-   int dynamic_string::find_left(const char* p, bool case_sensitive) const
-   {
-      CRNLIB_ASSERT(p);
-
-      const int p_len = (int)strlen(p);
-
-      for (int i = 0; i <= (m_len - p_len); i++)
-         if ((case_sensitive ? strncmp : _strnicmp)(p, &m_pStr[i], p_len) == 0)
-            return i;
-
-      return -1;
-   }
-
-   bool dynamic_string::contains(const char* p, bool case_sensitive) const
-   {
-      return find_left(p, case_sensitive) >= 0;
-   }
-
-   uint dynamic_string::count_char(char c) const
-   {
-      uint count = 0;
-      for (uint i = 0; i < m_len; i++)
-         if (m_pStr[i] == c)
-            count++;
-      return count;
-   }
-
-   int dynamic_string::find_left(char c) const
-   {
-      for (uint i = 0; i < m_len; i++)
-         if (m_pStr[i] == c)
-            return i;
-      return -1;
-   }
-
-   int dynamic_string::find_right(char c) const
-   {
-      for (int i = (int)m_len - 1; i >= 0; i--)
-         if (m_pStr[i] == c)
-            return i;
-      return -1;
-   }
-
-   int dynamic_string::find_right(const char* p, bool case_sensitive) const
-   {
-      CRNLIB_ASSERT(p);
-      const int p_len = (int)strlen(p);
-
-      for (int i = m_len - p_len; i >= 0; i--)
-         if ((case_sensitive ? strncmp : _strnicmp)(p, &m_pStr[i], p_len) == 0)
-            return i;
-
-      return -1;
-   }
-
-   dynamic_string& dynamic_string::trim()
-   {
-      int s, e;
-      for (s = 0; s < (int)m_len; s++)
-         if (!isspace(m_pStr[s]))
-            break;
-
-      for (e = m_len - 1; e > s; e--)
-         if (!isspace(m_pStr[e]))
-            break;
-
-      return crop(s, e - s + 1);
-   }
-
-   dynamic_string& dynamic_string::trim_crlf()
-   {
-      int s = 0, e;
-
-      for (e = m_len - 1; e > s; e--)
-         if ((m_pStr[e] != 13) && (m_pStr[e] != 10))
-            break;
-
-      return crop(s, e - s + 1);
-   }
-
-   dynamic_string& dynamic_string::remap(int from_char, int to_char)
-   {
-      for (uint i = 0; i < m_len; i++)
-         if (m_pStr[i] == from_char)
-            m_pStr[i] = (char)to_char;
-      return *this;
-   }
-
-#ifdef CRNLIB_BUILD_DEBUG
-   void dynamic_string::check() const
-   {
-      if (!m_pStr)
-      {
-         CRNLIB_ASSERT(!m_buf_size && !m_len);
-      }
-      else
-      {
-         CRNLIB_ASSERT(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
-
-   bool dynamic_string::ensure_buf(uint len, bool preserve_contents)
-   {
-      uint buf_size_needed = len + 1;
-
-      CRNLIB_ASSERT(buf_size_needed <= cUINT16_MAX);
-
-      if (buf_size_needed <= cUINT16_MAX)
-      {
-         if (buf_size_needed > m_buf_size)
-            expand_buf(buf_size_needed, preserve_contents);
-      }
-
-      return m_buf_size >= buf_size_needed;
-   }
-
-   bool dynamic_string::expand_buf(uint new_buf_size, bool preserve_contents)
-   {
-      new_buf_size = math::minimum<uint>(cUINT16_MAX, math::next_pow2(math::maximum<uint>(m_buf_size, new_buf_size)));
-
-      if (new_buf_size != m_buf_size)
-      {
-         char* p = crnlib_new_array<char>(new_buf_size);
-
-         if (preserve_contents)
-            memcpy(p, get_ptr_priv(), m_len + 1);
-
-         crnlib_delete_array(m_pStr);
-         m_pStr = p;
-
-         m_buf_size = static_cast<uint16>(new_buf_size);
-
-         if (preserve_contents)
-            check();
-      }
-
-      return m_buf_size >= new_buf_size;
-   }
-
-   void dynamic_string::swap(dynamic_string& other)
-   {
-      utils::swap(other.m_buf_size, m_buf_size);
-      utils::swap(other.m_len, m_len);
-      utils::swap(other.m_pStr, m_pStr);
-   }
-
-   int dynamic_string::serialize(void* pBuf, uint buf_size, bool little_endian) const
-   {
-      uint buf_left = buf_size;
-
-      //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;
-
-      if (buf_left < m_len)
-         return -1;
-
-      memcpy(pBuf, get_ptr(), m_len);
-
-      buf_left -= m_len;
-
-      return buf_size - buf_left;
-   }
-
-   int dynamic_string::deserialize(const void* pBuf, uint buf_size, bool little_endian)
-   {
-      uint buf_left = buf_size;
-
-      if (buf_left < sizeof(uint16)) return -1;
-
-      uint16 l;
-      if (!utils::read_obj(l, pBuf, buf_left, little_endian))
-         return -1;
-
-      if (buf_left < l)
-         return -1;
-
-      set_from_buf(pBuf, l);
-
-      buf_left -= l;
-
-      return buf_size - buf_left;
-   }
-
-   void dynamic_string::translate_lf_to_crlf()
-   {
-      if (find_left(0x0A) < 0)
-         return;
-
-      dynamic_string tmp;
-      tmp.ensure_buf(m_len + 2);
-
-      // normal sequence is 0x0D 0x0A (CR LF, \r\n)
-
-      int prev_char = -1;
-      for (uint i = 0; i < get_len(); i++)
-      {
-         const int cur_char = (*this)[i];
-
-         if ((cur_char == 0x0A) && (prev_char != 0x0D))
-            tmp.append_char(0x0D);
-
-         tmp.append_char(cur_char);
-
-         prev_char = cur_char;
-      }
-
-      swap(tmp);
-   }
-
-} // namespace crnlib

+ 0 - 173
Source/ThirdParty/crunch/crnlib/crn_dynamic_string.h

@@ -1,173 +0,0 @@
-// File: crn_dynamic_string.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   enum { cMaxDynamicStringLen = cUINT16_MAX - 1 };
-   class dynamic_string
-   {
-   public:
-      inline dynamic_string() : m_buf_size(0), m_len(0), m_pStr(NULL) { }
-      dynamic_string(eVarArg dummy, const char* p, ...);
-      dynamic_string(const char* p);
-      dynamic_string(const char* p, uint len);
-      dynamic_string(const dynamic_string& other);
-
-      inline ~dynamic_string() { if (m_pStr) crnlib_delete_array(m_pStr); }
-
-      // 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)); }
-
-      int compare(const char* p, bool case_sensitive = false) const;
-      int compare(const dynamic_string& rhs, bool case_sensitive = false) const;
-
-      inline bool operator== (const dynamic_string& rhs) const { return compare(rhs) == 0; }
-      inline bool operator== (const char* p) const { return compare(p) == 0; }
-
-      inline bool operator!= (const dynamic_string& rhs) const { return compare(rhs) != 0; }
-      inline bool operator!= (const char* p) const { return compare(p) != 0; }
-
-      inline bool operator< (const dynamic_string& rhs) const { return compare(rhs) < 0; }
-      inline bool operator< (const char* p) const { return compare(p) < 0; }
-
-      inline bool operator> (const dynamic_string& rhs) const { return compare(rhs) > 0; }
-      inline bool operator> (const char* p) const { return compare(p) > 0; }
-
-      inline bool operator<= (const dynamic_string& rhs) const { return compare(rhs) <= 0; }
-      inline bool operator<= (const char* p) const { return compare(p) <= 0; }
-
-      inline bool operator>= (const dynamic_string& rhs) const { return compare(rhs) >= 0; }
-      inline bool operator>= (const char* p) const { return compare(p) >= 0; }
-
-      friend inline bool operator== (const char* p, const dynamic_string& rhs) { return rhs.compare(p) == 0; }
-
-      dynamic_string& set(const char* p, uint max_len = UINT_MAX);
-      dynamic_string& set(const dynamic_string& other, uint max_len = UINT_MAX);
-
-      bool set_len(uint new_len, char fill_char = ' ');
-
-      // Set from non-zero terminated buffer.
-      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 char* p) { return set(p); }
-
-      dynamic_string& set_char(uint index, char c);
-      dynamic_string& append_char(char c);
-      dynamic_string& append_char(int c) { CRNLIB_ASSERT((c >= 0) && (c <= 255)); return append_char(static_cast<char>(c)); }
-      dynamic_string& truncate(uint new_len);
-      dynamic_string& tolower();
-      dynamic_string& toupper();
-
-      dynamic_string& append(const char* p);
-      dynamic_string& append(const dynamic_string& other);
-      dynamic_string& operator += (const char* p) { return append(p); }
-      dynamic_string& operator += (const dynamic_string& other) { return append(other); }
-
-      friend dynamic_string operator+ (const char* p, const dynamic_string& a);
-      friend dynamic_string operator+ (const dynamic_string& a, const char* p);
-      friend dynamic_string operator+ (const dynamic_string& a, const dynamic_string& b);
-
-      dynamic_string& format_args(const char* p, va_list args);
-      dynamic_string& format(const char* p, ...);
-
-      dynamic_string& crop(uint start, uint len);
-      dynamic_string& substring(uint start, uint end);
-      dynamic_string& left(uint len);
-      dynamic_string& mid(uint start, uint len);
-      dynamic_string& right(uint start);
-      dynamic_string& tail(uint num);
-
-      dynamic_string& unquote();
-
-      uint count_char(char c) const;
-
-      int find_left(const char* p, bool case_sensitive = false) const;
-      int find_left(char c) const;
-
-      int find_right(char c) const;
-      int find_right(const char* p, bool case_sensitive = false) const;
-
-      bool contains(const char* p, bool case_sensitive = false) const;
-
-      dynamic_string& trim();
-      dynamic_string& trim_crlf();
-
-      dynamic_string& remap(int from_char, int to_char);
-
-      void swap(dynamic_string& other);
-
-      // Returns -1 on failure, or the number of bytes written.
-      int serialize(void* pBuf, uint buf_size, bool little_endian) const;
-
-      // Returns -1 on failure, or the number of bytes read.
-      int deserialize(const void* pBuf, uint buf_size, bool little_endian);
-
-      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;
-      char*       m_pStr;
-
-#ifdef CRNLIB_BUILD_DEBUG
-      void check() const;
-#else
-      inline void check() const { }
-#endif
-
-      bool expand_buf(uint new_buf_size, bool preserve_contents);
-
-      const char* get_ptr_priv() const { return m_pStr ? m_pStr : ""; }
-      char* get_ptr_priv() { return (char*)(m_pStr ? m_pStr : ""); }
-
-      bool ensure_buf(uint len, bool preserve_contents = true);
-   };
-
-   typedef crnlib::vector<dynamic_string> dynamic_string_array;
-
-   extern dynamic_string g_empty_dynamic_string;
-
-   CRNLIB_DEFINE_BITWISE_MOVABLE(dynamic_string);
-
-   inline void swap (dynamic_string& a, dynamic_string& b)
-   {
-      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<uint>(cUINT16_MAX, math::next_pow2(buf_size_in_chars));
-      return crnlib_new_array<char>(buf_size_in_chars);
-   }
-} // namespace crnlib

+ 0 - 1481
Source/ThirdParty/crunch/crnlib/crn_etc.cpp

@@ -1,1481 +0,0 @@
-// File: crn_etc.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_etc.h"
-#include "crn_radix_sort.h"
-#include "crn_ryg_dxt.hpp"
-
-namespace crnlib
-{
-   const int g_etc1_inten_tables[cETC1IntenModifierValues][cETC1SelectorValues] = 
-   { 
-      { -8,  -2,   2,   8 }, { -17,  -5,  5,  17 }, { -29,  -9,   9,  29 }, {  -42, -13, 13,  42 }, 
-      { -60, -18, 18,  60 }, { -80, -24, 24,  80 }, { -106, -33, 33, 106 }, { -183, -47, 47, 183 } 
-   };
-
-   const uint8 g_etc1_to_selector_index[cETC1SelectorValues] = { 2, 3, 1, 0 };
-   const uint8 g_selector_index_to_etc1[cETC1SelectorValues] = { 3, 2, 0, 1 };
-
-   // [flip][subblock][pixel_index]
-   const etc1_coord2 g_etc1_pixel_coords[2][2][8] = 
-   {
-      {
-         {
-            { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 },
-            { 1, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 }
-         },
-         {
-            { 2, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 },
-            { 3, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 }
-         }
-      },
-      {
-         { 
-            { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 },               
-            { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 } 
-         },
-         { 
-            { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 },
-            { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 }
-         },
-      }
-   };
-
-   // Given an ETC1 diff/inten_table/selector, and an 8-bit desired color, this table encodes the best packed_color in the low byte, and the abs error in the high byte.
-   static uint16 g_etc1_inverse_lookup[2*8*4][256];      // [diff/inten_table/selector][desired_color]
-
-   // g_color8_to_etc_block_config[color][table_index] = Supplies for each 8-bit color value a list of packed ETC1 diff/intensity table/selectors/packed_colors that map to that color.
-   // To pack: diff | (inten << 1) | (selector << 4) | (packed_c << 8)
-   static const uint16 g_color8_to_etc_block_config_0_255[2][33] =
-   {
-      { 0x0000,  0x0010,  0x0002,  0x0012,  0x0004,  0x0014,  0x0006,  0x0016,  0x0008,  0x0018,  0x000A,  0x001A,  0x000C,  0x001C,  0x000E,  0x001E,
-        0x0001,  0x0011,  0x0003,  0x0013,  0x0005,  0x0015,  0x0007,  0x0017,  0x0009,  0x0019,  0x000B,  0x001B,  0x000D,  0x001D,  0x000F,  0x001F, 0xFFFF },
-      { 0x0F20,  0x0F30,  0x0E32,  0x0F22,  0x0E34,  0x0F24,  0x0D36,  0x0F26,  0x0C38,  0x0E28,  0x0B3A,  0x0E2A,  0x093C,  0x0E2C,  0x053E,  0x0D2E,
-        0x1E31,  0x1F21,  0x1D33,  0x1F23,  0x1C35,  0x1E25,  0x1A37,  0x1E27,  0x1839,  0x1D29,  0x163B,  0x1C2B,  0x133D,  0x1B2D,  0x093F,  0x1A2F, 0xFFFF },
-   };
-
-   // Really only [254][11].
-   static const uint16 g_color8_to_etc_block_config_1_to_254[254][12] = 
-   {
-      { 0x021C, 0x0D0D, 0xFFFF }, { 0x0020, 0x0021, 0x0A0B, 0x061F, 0xFFFF }, { 0x0113, 0x0217, 0xFFFF }, { 0x0116, 0x031E,
-      0x0B0E, 0x0405, 0xFFFF }, { 0x0022, 0x0204, 0x050A, 0x0023, 0xFFFF }, { 0x0111, 0x0319, 0x0809, 0x170F, 0xFFFF }, {
-      0x0303, 0x0215, 0x0607, 0xFFFF }, { 0x0030, 0x0114, 0x0408, 0x0031, 0x0201, 0x051D, 0xFFFF }, { 0x0100, 0x0024, 0x0306,
-      0x0025, 0x041B, 0x0E0D, 0xFFFF }, { 0x021A, 0x0121, 0x0B0B, 0x071F, 0xFFFF }, { 0x0213, 0x0317, 0xFFFF }, { 0x0112,
-      0x0505, 0xFFFF }, { 0x0026, 0x070C, 0x0123, 0x0027, 0xFFFF }, { 0x0211, 0x0909, 0xFFFF }, { 0x0110, 0x0315, 0x0707,
-      0x0419, 0x180F, 0xFFFF }, { 0x0218, 0x0131, 0x0301, 0x0403, 0x061D, 0xFFFF }, { 0x0032, 0x0202, 0x0033, 0x0125, 0x051B,
-      0x0F0D, 0xFFFF }, { 0x0028, 0x031C, 0x0221, 0x0029, 0xFFFF }, { 0x0120, 0x0313, 0x0C0B, 0x081F, 0xFFFF }, { 0x0605,
-      0x0417, 0xFFFF }, { 0x0216, 0x041E, 0x0C0E, 0x0223, 0x0127, 0xFFFF }, { 0x0122, 0x0304, 0x060A, 0x0311, 0x0A09, 0xFFFF
-      }, { 0x0519, 0x190F, 0xFFFF }, { 0x002A, 0x0231, 0x0503, 0x0415, 0x0807, 0x002B, 0x071D, 0xFFFF }, { 0x0130, 0x0214,
-      0x0508, 0x0401, 0x0133, 0x0225, 0x061B, 0xFFFF }, { 0x0200, 0x0124, 0x0406, 0x0321, 0x0129, 0x100D, 0xFFFF }, { 0x031A,
-      0x0D0B, 0x091F, 0xFFFF }, { 0x0413, 0x0705, 0x0517, 0xFFFF }, { 0x0212, 0x0034, 0x0323, 0x0035, 0x0227, 0xFFFF }, {
-      0x0126, 0x080C, 0x0B09, 0xFFFF }, { 0x0411, 0x0619, 0x1A0F, 0xFFFF }, { 0x0210, 0x0331, 0x0603, 0x0515, 0x0907, 0x012B,
-      0xFFFF }, { 0x0318, 0x002C, 0x0501, 0x0233, 0x0325, 0x071B, 0x002D, 0x081D, 0xFFFF }, { 0x0132, 0x0302, 0x0229, 0x110D,
-      0xFFFF }, { 0x0128, 0x041C, 0x0421, 0x0E0B, 0x0A1F, 0xFFFF }, { 0x0220, 0x0513, 0x0617, 0xFFFF }, { 0x0135, 0x0805,
-      0x0327, 0xFFFF }, { 0x0316, 0x051E, 0x0D0E, 0x0423, 0xFFFF }, { 0x0222, 0x0404, 0x070A, 0x0511, 0x0719, 0x0C09, 0x1B0F,
-      0xFFFF }, { 0x0703, 0x0615, 0x0A07, 0x022B, 0xFFFF }, { 0x012A, 0x0431, 0x0601, 0x0333, 0x012D, 0x091D, 0xFFFF }, {
-      0x0230, 0x0314, 0x0036, 0x0608, 0x0425, 0x0037, 0x0329, 0x081B, 0x120D, 0xFFFF }, { 0x0300, 0x0224, 0x0506, 0x0521,
-      0x0F0B, 0x0B1F, 0xFFFF }, { 0x041A, 0x0613, 0x0717, 0xFFFF }, { 0x0235, 0x0905, 0xFFFF }, { 0x0312, 0x0134, 0x0523,
-      0x0427, 0xFFFF }, { 0x0226, 0x090C, 0x002E, 0x0611, 0x0D09, 0x002F, 0xFFFF }, { 0x0715, 0x0B07, 0x0819, 0x032B, 0x1C0F,
-      0xFFFF }, { 0x0310, 0x0531, 0x0701, 0x0803, 0x022D, 0x0A1D, 0xFFFF }, { 0x0418, 0x012C, 0x0433, 0x0525, 0x0137, 0x091B,
-      0x130D, 0xFFFF }, { 0x0232, 0x0402, 0x0621, 0x0429, 0xFFFF }, { 0x0228, 0x051C, 0x0713, 0x100B, 0x0C1F, 0xFFFF }, {
-      0x0320, 0x0335, 0x0A05, 0x0817, 0xFFFF }, { 0x0623, 0x0527, 0xFFFF }, { 0x0416, 0x061E, 0x0E0E, 0x0711, 0x0E09, 0x012F,
-      0xFFFF }, { 0x0322, 0x0504, 0x080A, 0x0919, 0x1D0F, 0xFFFF }, { 0x0631, 0x0903, 0x0815, 0x0C07, 0x042B, 0x032D, 0x0B1D,
-      0xFFFF }, { 0x022A, 0x0801, 0x0533, 0x0625, 0x0237, 0x0A1B, 0xFFFF }, { 0x0330, 0x0414, 0x0136, 0x0708, 0x0721, 0x0529,
-      0x140D, 0xFFFF }, { 0x0400, 0x0324, 0x0606, 0x0038, 0x0039, 0x110B, 0x0D1F, 0xFFFF }, { 0x051A, 0x0813, 0x0B05, 0x0917,
-      0xFFFF }, { 0x0723, 0x0435, 0x0627, 0xFFFF }, { 0x0412, 0x0234, 0x0F09, 0x022F, 0xFFFF }, { 0x0326, 0x0A0C, 0x012E,
-      0x0811, 0x0A19, 0x1E0F, 0xFFFF }, { 0x0731, 0x0A03, 0x0915, 0x0D07, 0x052B, 0xFFFF }, { 0x0410, 0x0901, 0x0633, 0x0725,
-      0x0337, 0x0B1B, 0x042D, 0x0C1D, 0xFFFF }, { 0x0518, 0x022C, 0x0629, 0x150D, 0xFFFF }, { 0x0332, 0x0502, 0x0821, 0x0139,
-      0x120B, 0x0E1F, 0xFFFF }, { 0x0328, 0x061C, 0x0913, 0x0A17, 0xFFFF }, { 0x0420, 0x0535, 0x0C05, 0x0727, 0xFFFF }, {
-      0x0823, 0x032F, 0xFFFF }, { 0x0516, 0x071E, 0x0F0E, 0x0911, 0x0B19, 0x1009, 0x1F0F, 0xFFFF }, { 0x0422, 0x0604, 0x090A,
-      0x0B03, 0x0A15, 0x0E07, 0x062B, 0xFFFF }, { 0x0831, 0x0A01, 0x0733, 0x052D, 0x0D1D, 0xFFFF }, { 0x032A, 0x0825, 0x0437,
-      0x0729, 0x0C1B, 0x160D, 0xFFFF }, { 0x0430, 0x0514, 0x0236, 0x0808, 0x0921, 0x0239, 0x130B, 0x0F1F, 0xFFFF }, { 0x0500,
-      0x0424, 0x0706, 0x0138, 0x0A13, 0x0B17, 0xFFFF }, { 0x061A, 0x0635, 0x0D05, 0xFFFF }, { 0x0923, 0x0827, 0xFFFF }, {
-      0x0512, 0x0334, 0x003A, 0x0A11, 0x1109, 0x003B, 0x042F, 0xFFFF }, { 0x0426, 0x0B0C, 0x022E, 0x0B15, 0x0F07, 0x0C19,
-      0x072B, 0xFFFF }, { 0x0931, 0x0B01, 0x0C03, 0x062D, 0x0E1D, 0xFFFF }, { 0x0510, 0x0833, 0x0925, 0x0537, 0x0D1B, 0x170D,
-      0xFFFF }, { 0x0618, 0x032C, 0x0A21, 0x0339, 0x0829, 0xFFFF }, { 0x0432, 0x0602, 0x0B13, 0x140B, 0x101F, 0xFFFF }, {
-      0x0428, 0x071C, 0x0735, 0x0E05, 0x0C17, 0xFFFF }, { 0x0520, 0x0A23, 0x0927, 0xFFFF }, { 0x0B11, 0x1209, 0x013B, 0x052F,
-      0xFFFF }, { 0x0616, 0x081E, 0x0D19, 0xFFFF }, { 0x0522, 0x0704, 0x0A0A, 0x0A31, 0x0D03, 0x0C15, 0x1007, 0x082B, 0x072D,
-      0x0F1D, 0xFFFF }, { 0x0C01, 0x0933, 0x0A25, 0x0637, 0x0E1B, 0xFFFF }, { 0x042A, 0x0B21, 0x0929, 0x180D, 0xFFFF }, {
-      0x0530, 0x0614, 0x0336, 0x0908, 0x0439, 0x150B, 0x111F, 0xFFFF }, { 0x0600, 0x0524, 0x0806, 0x0238, 0x0C13, 0x0F05,
-      0x0D17, 0xFFFF }, { 0x071A, 0x0B23, 0x0835, 0x0A27, 0xFFFF }, { 0x1309, 0x023B, 0x062F, 0xFFFF }, { 0x0612, 0x0434,
-      0x013A, 0x0C11, 0x0E19, 0xFFFF }, { 0x0526, 0x0C0C, 0x032E, 0x0B31, 0x0E03, 0x0D15, 0x1107, 0x092B, 0xFFFF }, { 0x0D01,
-      0x0A33, 0x0B25, 0x0737, 0x0F1B, 0x082D, 0x101D, 0xFFFF }, { 0x0610, 0x0A29, 0x190D, 0xFFFF }, { 0x0718, 0x042C, 0x0C21,
-      0x0539, 0x160B, 0x121F, 0xFFFF }, { 0x0532, 0x0702, 0x0D13, 0x0E17, 0xFFFF }, { 0x0528, 0x081C, 0x0935, 0x1005, 0x0B27,
-      0xFFFF }, { 0x0620, 0x0C23, 0x033B, 0x072F, 0xFFFF }, { 0x0D11, 0x0F19, 0x1409, 0xFFFF }, { 0x0716, 0x003C, 0x091E,
-      0x0F03, 0x0E15, 0x1207, 0x0A2B, 0x003D, 0xFFFF }, { 0x0622, 0x0804, 0x0B0A, 0x0C31, 0x0E01, 0x0B33, 0x092D, 0x111D,
-      0xFFFF }, { 0x0C25, 0x0837, 0x0B29, 0x101B, 0x1A0D, 0xFFFF }, { 0x052A, 0x0D21, 0x0639, 0x170B, 0x131F, 0xFFFF }, {
-      0x0630, 0x0714, 0x0436, 0x0A08, 0x0E13, 0x0F17, 0xFFFF }, { 0x0700, 0x0624, 0x0906, 0x0338, 0x0A35, 0x1105, 0xFFFF }, {
-      0x081A, 0x0D23, 0x0C27, 0xFFFF }, { 0x0E11, 0x1509, 0x043B, 0x082F, 0xFFFF }, { 0x0712, 0x0534, 0x023A, 0x0F15, 0x1307,
-      0x1019, 0x0B2B, 0x013D, 0xFFFF }, { 0x0626, 0x0D0C, 0x042E, 0x0D31, 0x0F01, 0x1003, 0x0A2D, 0x121D, 0xFFFF }, { 0x0C33,
-      0x0D25, 0x0937, 0x111B, 0x1B0D, 0xFFFF }, { 0x0710, 0x0E21, 0x0739, 0x0C29, 0xFFFF }, { 0x0818, 0x052C, 0x0F13, 0x180B,
-      0x141F, 0xFFFF }, { 0x0632, 0x0802, 0x0B35, 0x1205, 0x1017, 0xFFFF }, { 0x0628, 0x091C, 0x0E23, 0x0D27, 0xFFFF }, {
-      0x0720, 0x0F11, 0x1609, 0x053B, 0x092F, 0xFFFF }, { 0x1119, 0x023D, 0xFFFF }, { 0x0816, 0x013C, 0x0A1E, 0x0E31, 0x1103,
-      0x1015, 0x1407, 0x0C2B, 0x0B2D, 0x131D, 0xFFFF }, { 0x0722, 0x0904, 0x0C0A, 0x1001, 0x0D33, 0x0E25, 0x0A37, 0x121B,
-      0xFFFF }, { 0x0F21, 0x0D29, 0x1C0D, 0xFFFF }, { 0x062A, 0x0839, 0x190B, 0x151F, 0xFFFF }, { 0x0730, 0x0814, 0x0536,
-      0x0B08, 0x1013, 0x1305, 0x1117, 0xFFFF }, { 0x0800, 0x0724, 0x0A06, 0x0438, 0x0F23, 0x0C35, 0x0E27, 0xFFFF }, { 0x091A,
-      0x1709, 0x063B, 0x0A2F, 0xFFFF }, { 0x1011, 0x1219, 0x033D, 0xFFFF }, { 0x0812, 0x0634, 0x033A, 0x0F31, 0x1203, 0x1115,
-      0x1507, 0x0D2B, 0xFFFF }, { 0x0726, 0x0E0C, 0x052E, 0x1101, 0x0E33, 0x0F25, 0x0B37, 0x131B, 0x0C2D, 0x141D, 0xFFFF }, {
-      0x0E29, 0x1D0D, 0xFFFF }, { 0x0810, 0x1021, 0x0939, 0x1A0B, 0x161F, 0xFFFF }, { 0x0918, 0x062C, 0x1113, 0x1217, 0xFFFF
-      }, { 0x0732, 0x0902, 0x0D35, 0x1405, 0x0F27, 0xFFFF }, { 0x0728, 0x0A1C, 0x1023, 0x073B, 0x0B2F, 0xFFFF }, { 0x0820,
-      0x1111, 0x1319, 0x1809, 0xFFFF }, { 0x1303, 0x1215, 0x1607, 0x0E2B, 0x043D, 0xFFFF }, { 0x0916, 0x023C, 0x0B1E, 0x1031,
-      0x1201, 0x0F33, 0x0D2D, 0x151D, 0xFFFF }, { 0x0822, 0x0A04, 0x0D0A, 0x1025, 0x0C37, 0x0F29, 0x141B, 0x1E0D, 0xFFFF }, {
-      0x1121, 0x0A39, 0x1B0B, 0x171F, 0xFFFF }, { 0x072A, 0x1213, 0x1317, 0xFFFF }, { 0x0830, 0x0914, 0x0636, 0x0C08, 0x0E35,
-      0x1505, 0xFFFF }, { 0x0900, 0x0824, 0x0B06, 0x0538, 0x1123, 0x1027, 0xFFFF }, { 0x0A1A, 0x1211, 0x1909, 0x083B, 0x0C2F,
-      0xFFFF }, { 0x1315, 0x1707, 0x1419, 0x0F2B, 0x053D, 0xFFFF }, { 0x0912, 0x0734, 0x043A, 0x1131, 0x1301, 0x1403, 0x0E2D,
-      0x161D, 0xFFFF }, { 0x0826, 0x0F0C, 0x062E, 0x1033, 0x1125, 0x0D37, 0x151B, 0x1F0D, 0xFFFF }, { 0x1221, 0x0B39, 0x1029,
-      0xFFFF }, { 0x0910, 0x1313, 0x1C0B, 0x181F, 0xFFFF }, { 0x0A18, 0x072C, 0x0F35, 0x1605, 0x1417, 0xFFFF }, { 0x0832,
-      0x0A02, 0x1223, 0x1127, 0xFFFF }, { 0x0828, 0x0B1C, 0x1311, 0x1A09, 0x093B, 0x0D2F, 0xFFFF }, { 0x0920, 0x1519, 0x063D,
-      0xFFFF }, { 0x1231, 0x1503, 0x1415, 0x1807, 0x102B, 0x0F2D, 0x171D, 0xFFFF }, { 0x0A16, 0x033C, 0x0C1E, 0x1401, 0x1133,
-      0x1225, 0x0E37, 0x161B, 0xFFFF }, { 0x0922, 0x0B04, 0x0E0A, 0x1321, 0x1129, 0xFFFF }, { 0x0C39, 0x1D0B, 0x191F, 0xFFFF
-      }, { 0x082A, 0x1413, 0x1705, 0x1517, 0xFFFF }, { 0x0930, 0x0A14, 0x0736, 0x0D08, 0x1323, 0x1035, 0x1227, 0xFFFF }, {
-      0x0A00, 0x0924, 0x0C06, 0x0638, 0x1B09, 0x0A3B, 0x0E2F, 0xFFFF }, { 0x0B1A, 0x1411, 0x1619, 0x073D, 0xFFFF }, { 0x1331,
-      0x1603, 0x1515, 0x1907, 0x112B, 0xFFFF }, { 0x0A12, 0x0834, 0x053A, 0x1501, 0x1233, 0x1325, 0x0F37, 0x171B, 0x102D,
-      0x181D, 0xFFFF }, { 0x0926, 0x072E, 0x1229, 0xFFFF }, { 0x1421, 0x0D39, 0x1E0B, 0x1A1F, 0xFFFF }, { 0x0A10, 0x1513,
-      0x1617, 0xFFFF }, { 0x0B18, 0x082C, 0x1135, 0x1805, 0x1327, 0xFFFF }, { 0x0932, 0x0B02, 0x1423, 0x0B3B, 0x0F2F, 0xFFFF
-      }, { 0x0928, 0x0C1C, 0x1511, 0x1719, 0x1C09, 0xFFFF }, { 0x0A20, 0x1703, 0x1615, 0x1A07, 0x122B, 0x083D, 0xFFFF }, {
-      0x1431, 0x1601, 0x1333, 0x112D, 0x191D, 0xFFFF }, { 0x0B16, 0x043C, 0x0D1E, 0x1425, 0x1037, 0x1329, 0x181B, 0xFFFF }, {
-      0x0A22, 0x0C04, 0x0F0A, 0x1521, 0x0E39, 0x1F0B, 0x1B1F, 0xFFFF }, { 0x1613, 0x1717, 0xFFFF }, { 0x092A, 0x1235, 0x1905,
-      0xFFFF }, { 0x0A30, 0x0B14, 0x0836, 0x0E08, 0x1523, 0x1427, 0xFFFF }, { 0x0B00, 0x0A24, 0x0D06, 0x0738, 0x1611, 0x1D09,
-      0x0C3B, 0x102F, 0xFFFF }, { 0x0C1A, 0x1715, 0x1B07, 0x1819, 0x132B, 0x093D, 0xFFFF }, { 0x1531, 0x1701, 0x1803, 0x122D,
-      0x1A1D, 0xFFFF }, { 0x0B12, 0x0934, 0x063A, 0x1433, 0x1525, 0x1137, 0x191B, 0xFFFF }, { 0x0A26, 0x003E, 0x082E, 0x1621,
-      0x0F39, 0x1429, 0x003F, 0xFFFF }, { 0x1713, 0x1C1F, 0xFFFF }, { 0x0B10, 0x1335, 0x1A05, 0x1817, 0xFFFF }, { 0x0C18,
-      0x092C, 0x1623, 0x1527, 0xFFFF }, { 0x0A32, 0x0C02, 0x1711, 0x1E09, 0x0D3B, 0x112F, 0xFFFF }, { 0x0A28, 0x0D1C, 0x1919,
-      0x0A3D, 0xFFFF }, { 0x0B20, 0x1631, 0x1903, 0x1815, 0x1C07, 0x142B, 0x132D, 0x1B1D, 0xFFFF }, { 0x1801, 0x1533, 0x1625,
-      0x1237, 0x1A1B, 0xFFFF }, { 0x0C16, 0x053C, 0x0E1E, 0x1721, 0x1529, 0x013F, 0xFFFF }, { 0x0B22, 0x0D04, 0x1039, 0x1D1F,
-      0xFFFF }, { 0x1813, 0x1B05, 0x1917, 0xFFFF }, { 0x0A2A, 0x1723, 0x1435, 0x1627, 0xFFFF }, { 0x0B30, 0x0C14, 0x0936,
-      0x0F08, 0x1F09, 0x0E3B, 0x122F, 0xFFFF }, { 0x0C00, 0x0B24, 0x0E06, 0x0838, 0x1811, 0x1A19, 0x0B3D, 0xFFFF }, { 0x0D1A,
-      0x1731, 0x1A03, 0x1915, 0x1D07, 0x152B, 0xFFFF }, { 0x1901, 0x1633, 0x1725, 0x1337, 0x1B1B, 0x142D, 0x1C1D, 0xFFFF }, {
-      0x0C12, 0x0A34, 0x073A, 0x1629, 0x023F, 0xFFFF }, { 0x0B26, 0x013E, 0x092E, 0x1821, 0x1139, 0x1E1F, 0xFFFF }, { 0x1913,
-      0x1A17, 0xFFFF }, { 0x0C10, 0x1535, 0x1C05, 0x1727, 0xFFFF }, { 0x0D18, 0x0A2C, 0x1823, 0x0F3B, 0x132F, 0xFFFF }, {
-      0x0B32, 0x0D02, 0x1911, 0x1B19, 0xFFFF }, { 0x0B28, 0x0E1C, 0x1B03, 0x1A15, 0x1E07, 0x162B, 0x0C3D, 0xFFFF }, { 0x0C20,
-      0x1831, 0x1A01, 0x1733, 0x152D, 0x1D1D, 0xFFFF }, { 0x1825, 0x1437, 0x1729, 0x1C1B, 0x033F, 0xFFFF }, { 0x0D16, 0x063C,
-      0x0F1E, 0x1921, 0x1239, 0x1F1F, 0xFFFF }, { 0x0C22, 0x0E04, 0x1A13, 0x1B17, 0xFFFF }, { 0x1635, 0x1D05, 0xFFFF }, {
-      0x0B2A, 0x1923, 0x1827, 0xFFFF }, { 0x0C30, 0x0D14, 0x0A36, 0x1A11, 0x103B, 0x142F, 0xFFFF }, { 0x0D00, 0x0C24, 0x0F06,
-      0x0938, 0x1B15, 0x1F07, 0x1C19, 0x172B, 0x0D3D, 0xFFFF }, { 0x0E1A, 0x1931, 0x1B01, 0x1C03, 0x162D, 0x1E1D, 0xFFFF }, {
-      0x1833, 0x1925, 0x1537, 0x1D1B, 0xFFFF }, { 0x0D12, 0x0B34, 0x083A, 0x1A21, 0x1339, 0x1829, 0x043F, 0xFFFF }, { 0x0C26,
-      0x023E, 0x0A2E, 0x1B13, 0xFFFF }, { 0x1735, 0x1E05, 0x1C17, 0xFFFF }, { 0x0D10, 0x1A23, 0x1927, 0xFFFF }, { 0x0E18,
-      0x0B2C, 0x1B11, 0x113B, 0x152F, 0xFFFF }, { 0x0C32, 0x0E02, 0x1D19, 0x0E3D, 0xFFFF }, { 0x0C28, 0x0F1C, 0x1A31, 0x1D03,
-      0x1C15, 0x182B, 0x172D, 0x1F1D, 0xFFFF }, { 0x0D20, 0x1C01, 0x1933, 0x1A25, 0x1637, 0x1E1B, 0xFFFF }, { 0x1B21, 0x1929,
-      0x053F, 0xFFFF }, { 0x0E16, 0x073C, 0x1439, 0xFFFF }, { 0x0D22, 0x0F04, 0x1C13, 0x1F05, 0x1D17, 0xFFFF }, { 0x1B23,
-      0x1835, 0x1A27, 0xFFFF }, { 0x0C2A, 0x123B, 0x162F, 0xFFFF }, { 0x0D30, 0x0E14, 0x0B36, 0x1C11, 0x1E19, 0x0F3D, 0xFFFF
-      }, { 0x0E00, 0x0D24, 0x0A38, 0x1B31, 0x1E03, 0x1D15, 0x192B, 0xFFFF }, { 0x0F1A, 0x1D01, 0x1A33, 0x1B25, 0x1737, 0x1F1B,
-      0x182D, 0xFFFF }, { 0x1A29, 0x063F, 0xFFFF }, { 0x0E12, 0x0C34, 0x093A, 0x1C21, 0x1539, 0xFFFF }, { 0x0D26, 0x033E,
-      0x0B2E, 0x1D13, 0x1E17, 0xFFFF }, { 0x1935, 0x1B27, 0xFFFF }, { 0x0E10, 0x1C23, 0x133B, 0x172F, 0xFFFF }, { 0x0F18,
-      0x0C2C, 0x1D11, 0x1F19, 0xFFFF }, { 0x0D32, 0x0F02, 0x1F03, 0x1E15, 0x1A2B, 0x103D, 0xFFFF }, { 0x0D28, 0x1C31, 0x1E01,
-      0x1B33, 0x192D, 0xFFFF }, { 0x0E20, 0x1C25, 0x1837, 0x1B29, 0x073F, 0xFFFF }, { 0x1D21, 0x1639, 0xFFFF }, { 0x0F16,
-      0x083C, 0x1E13, 0x1F17, 0xFFFF }, { 0x0E22, 0x1A35, 0xFFFF }, { 0x1D23, 0x1C27, 0xFFFF }, { 0x0D2A, 0x1E11, 0x143B,
-      0x182F, 0xFFFF }, { 0x0E30, 0x0F14, 0x0C36, 0x1F15, 0x1B2B, 0x113D, 0xFFFF }, { 0x0F00, 0x0E24, 0x0B38, 0x1D31, 0x1F01,
-      0x1A2D, 0xFFFF }, { 0x1C33, 0x1D25, 0x1937, 0xFFFF }, { 0x1E21, 0x1739, 0x1C29, 0x083F, 0xFFFF }, { 0x0F12, 0x0D34,
-      0x0A3A, 0x1F13, 0xFFFF }, { 0x0E26, 0x043E, 0x0C2E, 0x1B35, 0xFFFF }, { 0x1E23, 0x1D27, 0xFFFF }, { 0x0F10, 0x1F11,
-      0x153B, 0x192F, 0xFFFF }, { 0x0D2C, 0x123D, 0xFFFF },
-   };
-
-   uint16 etc1_block::pack_color5(const color_quad_u8& color, bool scaled, uint bias)
-   {
-      return pack_color5(color.r, color.g, color.b, scaled, bias);
-   }
-   
-   uint16 etc1_block::pack_color5(uint r, uint g, uint b, bool scaled, uint bias)
-   {
-      if (scaled)
-      {
-         r = (r * 31U + bias) / 255U;
-         g = (g * 31U + bias) / 255U;
-         b = (b * 31U + bias) / 255U;
-      }
-
-      r = math::minimum(r, 31U);
-      g = math::minimum(g, 31U);
-      b = math::minimum(b, 31U);
-
-      return static_cast<uint16>(b | (g << 5U) | (r << 10U));
-   }
-
-   color_quad_u8 etc1_block::unpack_color5(uint16 packed_color5, bool scaled, uint alpha)
-   {
-      uint b = packed_color5 & 31U;
-      uint g = (packed_color5 >> 5U) & 31U;
-      uint r = (packed_color5 >> 10U) & 31U;
-
-      if (scaled)
-      {
-         b = (b << 3U) | (b >> 2U);
-         g = (g << 3U) | (g >> 2U);
-         r = (r << 3U) | (r >> 2U);
-      }
-
-      return color_quad_u8(cNoClamp, r, g, b, math::minimum(alpha, 255U));
-   }
-
-   void etc1_block::unpack_color5(uint& r, uint& g, uint& b, uint16 packed_color5, bool scaled)
-   {
-      color_quad_u8 c(unpack_color5(packed_color5, scaled, 0));
-      r = c.r;
-      g = c.g;
-      b = c.b;
-   }
-
-   bool etc1_block::unpack_color5(color_quad_u8& result, uint16 packed_color5, uint16 packed_delta3, bool scaled, uint alpha)
-   {
-      color_quad_i16 dc(unpack_delta3(packed_delta3));
-      
-      int b = (packed_color5 & 31U) + dc.b;
-      int g = ((packed_color5 >> 5U) & 31U) + dc.g;
-      int r = ((packed_color5 >> 10U) & 31U) + dc.r;
-
-      bool success = true;
-      if (static_cast<uint>(r | g | b) > 31U)
-      {
-         success = false;
-         r = math::clamp<int>(r, 0, 31);
-         g = math::clamp<int>(g, 0, 31);
-         b = math::clamp<int>(b, 0, 31);
-      }
-
-      if (scaled)
-      {
-         b = (b << 3U) | (b >> 2U);
-         g = (g << 3U) | (g >> 2U);
-         r = (r << 3U) | (r >> 2U);
-      }
-
-      result.set_noclamp_rgba(r, g, b, math::minimum(alpha, 255U));
-      return success;
-   }
-
-   bool etc1_block::unpack_color5(uint& r, uint& g, uint& b, uint16 packed_color5, uint16 packed_delta3, bool scaled, uint alpha)
-   {
-      color_quad_u8 result;
-      const bool success = unpack_color5(result, packed_color5, packed_delta3, scaled, alpha);
-      r = result.r;
-      g = result.g;
-      b = result.b;
-      return success;
-   }
-  
-   uint16 etc1_block::pack_delta3(const color_quad_i16& color)
-   {
-      return pack_delta3(color.r, color.g, color.b);
-   }
-
-   uint16 etc1_block::pack_delta3(int r, int g, int b)
-   {
-      CRNLIB_ASSERT((r >= cETC1ColorDeltaMin) && (r <= cETC1ColorDeltaMax));
-      CRNLIB_ASSERT((g >= cETC1ColorDeltaMin) && (g <= cETC1ColorDeltaMax));
-      CRNLIB_ASSERT((b >= cETC1ColorDeltaMin) && (b <= cETC1ColorDeltaMax));
-      if (r < 0) r += 8;
-      if (g < 0) g += 8;
-      if (b < 0) b += 8;
-      return static_cast<uint16>(b | (g << 3) | (r << 6));
-   }
-
-   color_quad_i16 etc1_block::unpack_delta3(uint16 packed_delta3)
-   {
-      int r = (packed_delta3 >> 6) & 7;
-      int g = (packed_delta3 >> 3) & 7;
-      int b = packed_delta3 & 7;
-      if (r >= 4) r -= 8;
-      if (g >= 4) g -= 8;
-      if (b >= 4) b -= 8;
-      return color_quad_i16(r, g, b, 0);
-   }
-
-   void etc1_block::unpack_delta3(int& r, int& g, int& b, uint16 packed_delta3)
-   {
-      r = (packed_delta3 >> 6) & 7;
-      g = (packed_delta3 >> 3) & 7;
-      b = packed_delta3 & 7;
-      if (r >= 4) r -= 8;
-      if (g >= 4) g -= 8;
-      if (b >= 4) b -= 8;
-   }
-
-   uint16 etc1_block::pack_color4(const color_quad_u8& color, bool scaled, uint bias)
-   {
-      return pack_color4(color.r, color.g, color.b, scaled, bias);
-   }
-   
-   uint16 etc1_block::pack_color4(uint r, uint g, uint b, bool scaled, uint bias)
-   {
-      if (scaled)
-      {
-         r = (r * 15U + bias) / 255U;
-         g = (g * 15U + bias) / 255U;
-         b = (b * 15U + bias) / 255U;
-      }
-
-      r = math::minimum(r, 15U);
-      g = math::minimum(g, 15U);
-      b = math::minimum(b, 15U);
-
-      return static_cast<uint16>(b | (g << 4U) | (r << 8U));
-   }
-
-   color_quad_u8 etc1_block::unpack_color4(uint16 packed_color4, bool scaled, uint alpha)
-   {
-      uint b = packed_color4 & 15U;
-      uint g = (packed_color4 >> 4U) & 15U;
-      uint r = (packed_color4 >> 8U) & 15U;
-
-      if (scaled)
-      {
-         b = (b << 4U) | b;
-         g = (g << 4U) | g;
-         r = (r << 4U) | r;
-      }
-
-      return color_quad_u8(cNoClamp, r, g, b, math::minimum(alpha, 255U));
-   }
-   
-   void etc1_block::unpack_color4(uint& r, uint& g, uint& b, uint16 packed_color4, bool scaled)
-   {
-      color_quad_u8 c(unpack_color4(packed_color4, scaled, 0));
-      r = c.r;
-      g = c.g;
-      b = c.b;
-   }
-
-   void etc1_block::get_diff_subblock_colors(color_quad_u8* pDst, uint16 packed_color5, uint table_idx)
-   {
-      CRNLIB_ASSERT(table_idx < cETC1IntenModifierValues);
-      const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0];
-
-      uint r, g, b;
-      unpack_color5(r, g, b, packed_color5, true);
-
-      const int ir = static_cast<int>(r), ig = static_cast<int>(g), ib = static_cast<int>(b);
-
-      const int y0 = pInten_modifer_table[0];
-      pDst[0].set(ir + y0, ig + y0, ib + y0);
-
-      const int y1 = pInten_modifer_table[1];
-      pDst[1].set(ir + y1, ig + y1, ib + y1);
-
-      const int y2 = pInten_modifer_table[2];
-      pDst[2].set(ir + y2, ig + y2, ib + y2);
-
-      const int y3 = pInten_modifer_table[3];
-      pDst[3].set(ir + y3, ig + y3, ib + y3);
-   }
-   
-   bool etc1_block::get_diff_subblock_colors(color_quad_u8* pDst, uint16 packed_color5, uint16 packed_delta3, uint table_idx)
-   {
-      CRNLIB_ASSERT(table_idx < cETC1IntenModifierValues);
-      const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0];
-
-      uint r, g, b;
-      bool success = unpack_color5(r, g, b, packed_color5, packed_delta3, true);
-
-      const int ir = static_cast<int>(r), ig = static_cast<int>(g), ib = static_cast<int>(b);
-
-      const int y0 = pInten_modifer_table[0];
-      pDst[0].set(ir + y0, ig + y0, ib + y0);
-
-      const int y1 = pInten_modifer_table[1];
-      pDst[1].set(ir + y1, ig + y1, ib + y1);
-
-      const int y2 = pInten_modifer_table[2];
-      pDst[2].set(ir + y2, ig + y2, ib + y2);
-
-      const int y3 = pInten_modifer_table[3];
-      pDst[3].set(ir + y3, ig + y3, ib + y3);
-
-      return success;
-   }
-   
-   void etc1_block::get_abs_subblock_colors(color_quad_u8* pDst, uint16 packed_color4, uint table_idx)
-   {
-      CRNLIB_ASSERT(table_idx < cETC1IntenModifierValues);
-      const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0];
-
-      uint r, g, b;
-      unpack_color4(r, g, b, packed_color4, true);
-      
-      const int ir = static_cast<int>(r), ig = static_cast<int>(g), ib = static_cast<int>(b);
-
-      const int y0 = pInten_modifer_table[0];
-      pDst[0].set(ir + y0, ig + y0, ib + y0);
-      
-      const int y1 = pInten_modifer_table[1];
-      pDst[1].set(ir + y1, ig + y1, ib + y1);
-
-      const int y2 = pInten_modifer_table[2];
-      pDst[2].set(ir + y2, ig + y2, ib + y2);
-
-      const int y3 = pInten_modifer_table[3];
-      pDst[3].set(ir + y3, ig + y3, ib + y3);
-   }
-      
-   bool unpack_etc1(const etc1_block& block, color_quad_u8 *pDst, bool preserve_alpha)
-   {
-      const bool diff_flag = block.get_diff_bit();
-      const bool flip_flag = block.get_flip_bit();
-      const uint table_index0 = block.get_inten_table(0);
-      const uint table_index1 = block.get_inten_table(1);
-
-      color_quad_u8 subblock_colors0[4];
-      color_quad_u8 subblock_colors1[4];
-      bool success = true;
-
-      if (diff_flag)
-      {
-         const uint16 base_color5 = block.get_base5_color();
-         const uint16 delta_color3 = block.get_delta3_color();
-         etc1_block::get_diff_subblock_colors(subblock_colors0, base_color5, table_index0);
-            
-         if (!etc1_block::get_diff_subblock_colors(subblock_colors1, base_color5, delta_color3, table_index1))
-            success = false;
-      }
-      else
-      {
-         const uint16 base_color4_0 = block.get_base4_color(0);
-         etc1_block::get_abs_subblock_colors(subblock_colors0, base_color4_0, table_index0);
-
-         const uint16 base_color4_1 = block.get_base4_color(1);
-         etc1_block::get_abs_subblock_colors(subblock_colors1, base_color4_1, table_index1);
-      }
-
-      if (preserve_alpha)
-      {
-         if (flip_flag)
-         {
-            for (uint y = 0; y < 2; y++)
-            {
-               pDst[0].set_rgb(subblock_colors0[block.get_selector(0, y)]);
-               pDst[1].set_rgb(subblock_colors0[block.get_selector(1, y)]);
-               pDst[2].set_rgb(subblock_colors0[block.get_selector(2, y)]);
-               pDst[3].set_rgb(subblock_colors0[block.get_selector(3, y)]);
-               pDst += 4;
-            }
-
-            for (uint y = 2; y < 4; y++)
-            {
-               pDst[0].set_rgb(subblock_colors1[block.get_selector(0, y)]);
-               pDst[1].set_rgb(subblock_colors1[block.get_selector(1, y)]);
-               pDst[2].set_rgb(subblock_colors1[block.get_selector(2, y)]);
-               pDst[3].set_rgb(subblock_colors1[block.get_selector(3, y)]);
-               pDst += 4;
-            }
-         }
-         else
-         {
-            for (uint y = 0; y < 4; y++)
-            {
-               pDst[0].set_rgb(subblock_colors0[block.get_selector(0, y)]);
-               pDst[1].set_rgb(subblock_colors0[block.get_selector(1, y)]);
-               pDst[2].set_rgb(subblock_colors1[block.get_selector(2, y)]);
-               pDst[3].set_rgb(subblock_colors1[block.get_selector(3, y)]);
-               pDst += 4;
-            }
-         }
-      }
-      else 
-      {
-         if (flip_flag)
-         {
-            // 0000
-            // 0000
-            // 1111
-            // 1111
-            for (uint y = 0; y < 2; y++)
-            {
-               pDst[0] = subblock_colors0[block.get_selector(0, y)];
-               pDst[1] = subblock_colors0[block.get_selector(1, y)];
-               pDst[2] = subblock_colors0[block.get_selector(2, y)];
-               pDst[3] = subblock_colors0[block.get_selector(3, y)];
-               pDst += 4;
-            }
-
-            for (uint y = 2; y < 4; y++)
-            {
-               pDst[0] = subblock_colors1[block.get_selector(0, y)];
-               pDst[1] = subblock_colors1[block.get_selector(1, y)];
-               pDst[2] = subblock_colors1[block.get_selector(2, y)];
-               pDst[3] = subblock_colors1[block.get_selector(3, y)];
-               pDst += 4;
-            }
-         }
-         else
-         {
-            // 0011
-            // 0011
-            // 0011
-            // 0011
-            for (uint y = 0; y < 4; y++)
-            {
-               pDst[0] = subblock_colors0[block.get_selector(0, y)];
-               pDst[1] = subblock_colors0[block.get_selector(1, y)];
-               pDst[2] = subblock_colors1[block.get_selector(2, y)];
-               pDst[3] = subblock_colors1[block.get_selector(3, y)];
-               pDst += 4;
-            }
-         }
-      }
-      
-      return success;
-   }
-      
-   bool etc1_optimizer::compute()
-   {
-      const uint n = m_pParams->m_num_src_pixels;
-      const int scan_delta_size = m_pParams->m_scan_delta_size;
-      
-      // Scan through a subset of the 3D lattice centered around the avg block color trying each 3D (555 or 444) lattice point as a potential block color.
-      // Each time a better solution is found try to refine the current solution's block color based of the current selectors and intensity table index.
-      for (int zdi = 0; zdi < scan_delta_size; zdi++)
-      {
-         const int zd = m_pParams->m_pScan_deltas[zdi];
-         const int mbb = m_bb + zd;
-         if (mbb < 0) continue; else if (mbb > m_limit) break;
-         
-         for (int ydi = 0; ydi < scan_delta_size; ydi++)
-         {
-            const int yd = m_pParams->m_pScan_deltas[ydi];
-            const int mbg = m_bg + yd;
-            if (mbg < 0) continue; else if (mbg > m_limit) break;
-
-            for (int xdi = 0; xdi < scan_delta_size; xdi++)
-            {
-               const int xd = m_pParams->m_pScan_deltas[xdi];
-               const int mbr = m_br + xd;
-               if (mbr < 0) continue; else if (mbr > m_limit) break;
-      
-               etc1_solution_coordinates coords(mbr, mbg, mbb, 0, m_pParams->m_use_color4);
-               if (m_pParams->m_quality == cCRNETCQualitySlow)
-               {
-                  if (!evaluate_solution(coords, m_trial_solution, &m_best_solution))
-                     continue;
-               }
-               else
-               {
-                  if (!evaluate_solution_fast(coords, m_trial_solution, &m_best_solution))
-                     continue;
-               }
-               
-               // Now we have the input block, the avg. color of the input pixels, a set of trial selector indices, and the block color+intensity index.
-               // Now, for each component, attempt to refine the current solution by solving a simple linear equation. For example, for 4 colors:
-               // The goal is:
-               // pixel0 - (block_color+inten_table[selector0]) + pixel1 - (block_color+inten_table[selector1]) + pixel2 - (block_color+inten_table[selector2]) + pixel3 - (block_color+inten_table[selector3]) = 0
-               // Rearranging this:
-               // (pixel0 + pixel1 + pixel2 + pixel3) - (block_color+inten_table[selector0]) - (block_color+inten_table[selector1]) - (block_color+inten_table[selector2]) - (block_color+inten_table[selector3]) = 0
-               // (pixel0 + pixel1 + pixel2 + pixel3) - block_color - inten_table[selector0] - block_color-inten_table[selector1] - block_color-inten_table[selector2] - block_color-inten_table[selector3] = 0
-               // (pixel0 + pixel1 + pixel2 + pixel3) - 4*block_color - inten_table[selector0] - inten_table[selector1] - inten_table[selector2] - inten_table[selector3] = 0
-               // (pixel0 + pixel1 + pixel2 + pixel3) - 4*block_color - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3]) = 0
-               // (pixel0 + pixel1 + pixel2 + pixel3)/4 - block_color - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3])/4 = 0
-               // block_color = (pixel0 + pixel1 + pixel2 + pixel3)/4 - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3])/4
-               // So what this means:
-               // optimal_block_color = avg_input - avg_inten_delta
-               // So the optimal block color can be computed by taking the average block color and subtracting the current average of the intensity delta.
-               // Unfortunately, optimal_block_color must then be quantized to 555 or 444 so it's not always possible to improve matters using this formula.
-               // Also, the above formula is for unclamped intensity deltas. The actual implementation takes into account clamping.
-
-               const uint max_refinement_trials = (m_pParams->m_quality == cCRNETCQualityFast) ? 2 : (((xd | yd | zd) == 0) ? 4 : 2);
-               for (uint refinement_trial = 0; refinement_trial < max_refinement_trials; refinement_trial++)
-               {
-                  const uint8* pSelectors = m_best_solution.m_selectors.get_ptr();
-                  const int* pInten_table = g_etc1_inten_tables[m_best_solution.m_coords.m_inten_table];
-
-                  int delta_sum_r = 0, delta_sum_g = 0, delta_sum_b = 0;
-                  const color_quad_u8 base_color(m_best_solution.m_coords.get_scaled_color());
-                  for (uint r = 0; r < n; r++)
-                  {
-                     const uint s = *pSelectors++;
-                     const int yd = pInten_table[s];
-                     // Compute actual delta being applied to each pixel, taking into account clamping.
-                     delta_sum_r += math::clamp<int>(base_color.r + yd, 0, 255) - base_color.r;
-                     delta_sum_g += math::clamp<int>(base_color.g + yd, 0, 255) - base_color.g;
-                     delta_sum_b += math::clamp<int>(base_color.b + yd, 0, 255) - base_color.b;
-                  }
-                  if ((!delta_sum_r) && (!delta_sum_g) && (!delta_sum_b))
-                     break;
-                  const float avg_delta_r_f = static_cast<float>(delta_sum_r) / n;
-                  const float avg_delta_g_f = static_cast<float>(delta_sum_g) / n;
-                  const float avg_delta_b_f = static_cast<float>(delta_sum_b) / n;
-                  const int br1 = math::clamp<int>(static_cast<uint>((m_avg_color[0] - avg_delta_r_f) * m_limit / 255.0f + .5f), 0, m_limit);
-                  const int bg1 = math::clamp<int>(static_cast<uint>((m_avg_color[1] - avg_delta_g_f) * m_limit / 255.0f + .5f), 0, m_limit);
-                  const int bb1 = math::clamp<int>(static_cast<uint>((m_avg_color[2] - avg_delta_b_f) * m_limit / 255.0f + .5f), 0, m_limit);
-                  
-                  bool skip = false;
-                  
-                  if ((mbr == br1) && (mbg == bg1) && (mbb == bb1))
-                     skip = true;
-                  else if ((br1 == m_best_solution.m_coords.m_unscaled_color.r) && (bg1 == m_best_solution.m_coords.m_unscaled_color.g) && (bb1 == m_best_solution.m_coords.m_unscaled_color.b))
-                     skip = true;
-                  else if ((m_br == br1) && (m_bg == bg1) && (m_bb == bb1))
-                     skip = true;
-
-                  if (skip)
-                     break;
-
-                  etc1_solution_coordinates coords1(br1, bg1, bb1, 0, m_pParams->m_use_color4);
-                  if (m_pParams->m_quality == cCRNETCQualitySlow)
-                  {
-                     if (!evaluate_solution(coords1, m_trial_solution, &m_best_solution)) 
-                        break;
-                  }
-                  else
-                  {
-                     if (!evaluate_solution_fast(coords1, m_trial_solution, &m_best_solution))
-                        break;
-                  }
-
-               }  // refinement_trial
-
-            } // xdi
-         } // ydi
-      } // zdi
-
-      if (!m_best_solution.m_valid)
-      {
-         m_pResult->m_error = cUINT32_MAX;
-         return false;
-      }
-      
-      const uint8* pSelectors = m_best_solution.m_selectors.get_ptr();
-
-#ifdef CRNLIB_BUILD_DEBUG
-      {
-         color_quad_u8 block_colors[4];
-         m_best_solution.m_coords.get_block_colors(block_colors);
-
-         const color_quad_u8* pSrc_pixels = m_pParams->m_pSrc_pixels;
-         uint64 actual_error = 0;
-         for (uint i = 0; i < n; i++)
-            actual_error += color::elucidian_distance(pSrc_pixels[i], block_colors[pSelectors[i]], false);
-         
-         CRNLIB_ASSERT(actual_error == m_best_solution.m_error);
-      }
-#endif      
-      
-      m_pResult->m_error = m_best_solution.m_error;
-
-      m_pResult->m_block_color_unscaled = m_best_solution.m_coords.m_unscaled_color;
-      m_pResult->m_block_color4 = m_best_solution.m_coords.m_color4;
-      
-      m_pResult->m_block_inten_table = m_best_solution.m_coords.m_inten_table;
-      memcpy(m_pResult->m_pSelectors, pSelectors, n);
-      m_pResult->m_n = n;
-
-      return true;
-   }
-
-   void etc1_optimizer::init(const params& params, results& result)
-   {
-      m_pParams = &params;
-      m_pResult = &result;
-                  
-      const uint n = m_pParams->m_num_src_pixels;
-
-      m_selectors.resize(n);
-      m_best_selectors.resize(n);
-      m_temp_selectors.resize(n);
-      m_trial_solution.m_selectors.resize(n);
-      m_best_solution.m_selectors.resize(n);
-
-      m_limit = m_pParams->m_use_color4 ? 15 : 31;
-
-      vec3F avg_color(0.0f);
-
-      m_luma.resize(n);
-      m_sorted_luma[0].resize(n);
-      m_sorted_luma[1].resize(n);
-
-      for (uint i = 0; i < n; i++)
-      {
-         const color_quad_u8& c = m_pParams->m_pSrc_pixels[i];
-         const vec3F fc(c.r, c.g, c.b);
-
-         avg_color += fc;
-
-         m_luma[i] = static_cast<uint16>(c.r + c.g + c.b);
-         m_sorted_luma[0][i] = i;
-      }
-      avg_color /= static_cast<float>(n);
-      m_avg_color = avg_color;
-
-      m_br = math::clamp<int>(static_cast<uint>(m_avg_color[0] * m_limit / 255.0f + .5f), 0, m_limit);
-      m_bg = math::clamp<int>(static_cast<uint>(m_avg_color[1] * m_limit / 255.0f + .5f), 0, m_limit);
-      m_bb = math::clamp<int>(static_cast<uint>(m_avg_color[2] * m_limit / 255.0f + .5f), 0, m_limit);
-
-      if (m_pParams->m_quality <= cCRNETCQualityMedium)
-      {
-         m_pSorted_luma_indices = indirect_radix_sort(n, m_sorted_luma[0].get_ptr(), m_sorted_luma[1].get_ptr(), m_luma.get_ptr(), 0, sizeof(m_luma[0]), false);
-         m_pSorted_luma = m_sorted_luma[0].get_ptr();
-         if (m_pSorted_luma_indices == m_sorted_luma[0].get_ptr())
-            m_pSorted_luma = m_sorted_luma[1].get_ptr();
-      
-         for (uint i = 0; i < n; i++)
-            m_pSorted_luma[i] = m_luma[m_pSorted_luma_indices[i]];
-      }
-      
-      m_best_solution.m_coords.clear();
-      m_best_solution.m_valid = false;
-      m_best_solution.m_error = cUINT64_MAX;
-   }
-
-   bool etc1_optimizer::evaluate_solution(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution)
-   {
-      trial_solution.m_valid = false;
-
-      if (m_pParams->m_constrain_against_base_color5)
-      {
-         const int dr = coords.m_unscaled_color.r - m_pParams->m_base_color5.r;
-         const int dg = coords.m_unscaled_color.g - m_pParams->m_base_color5.g;
-         const int db = coords.m_unscaled_color.b - m_pParams->m_base_color5.b;
-
-         if ((math::minimum(dr, dg, db) < cETC1ColorDeltaMin) || (math::maximum(dr, dg, db) > cETC1ColorDeltaMax))
-            return false;
-      }
-
-      const color_quad_u8 base_color(coords.get_scaled_color());
-      
-      const uint n = m_pParams->m_num_src_pixels;
-      CRNLIB_ASSERT(trial_solution.m_selectors.size() == n);
-      
-      trial_solution.m_error = cUINT64_MAX;
-            
-      for (uint inten_table = 0; inten_table < cETC1IntenModifierValues; inten_table++)
-      {
-         const int* pInten_table = g_etc1_inten_tables[inten_table];
-
-         color_quad_u8 block_colors[4];
-         for (uint s = 0; s < 4; s++)
-         {
-            const int yd = pInten_table[s];
-            block_colors[s].set(base_color.r + yd, base_color.g + yd, base_color.b + yd, 0);
-         }
-         
-         uint64 total_error = 0;
-         
-         const color_quad_u8* pSrc_pixels = m_pParams->m_pSrc_pixels;
-         for (uint c = 0; c < n; c++)
-         {
-            const color_quad_u8& src_pixel = *pSrc_pixels++;
-            
-            uint best_selector_index = 0;
-            uint best_error = math::square(src_pixel.r - block_colors[0].r) + math::square(src_pixel.g - block_colors[0].g) + math::square(src_pixel.b - block_colors[0].b);
-
-            uint trial_error = math::square(src_pixel.r - block_colors[1].r) + math::square(src_pixel.g - block_colors[1].g) + math::square(src_pixel.b - block_colors[1].b);
-            if (trial_error < best_error)
-            {
-               best_error = trial_error;
-               best_selector_index = 1;
-            }
-
-            trial_error = math::square(src_pixel.r - block_colors[2].r) + math::square(src_pixel.g - block_colors[2].g) + math::square(src_pixel.b - block_colors[2].b);
-            if (trial_error < best_error)
-            {
-               best_error = trial_error;
-               best_selector_index = 2;
-            }
-
-            trial_error = math::square(src_pixel.r - block_colors[3].r) + math::square(src_pixel.g - block_colors[3].g) + math::square(src_pixel.b - block_colors[3].b);
-            if (trial_error < best_error)
-            {
-               best_error = trial_error;
-               best_selector_index = 3;
-            }
-
-            m_temp_selectors[c] = static_cast<uint8>(best_selector_index);
-
-            total_error += best_error;
-            if (total_error >= trial_solution.m_error)
-               break;
-         }
-         
-         if (total_error < trial_solution.m_error)
-         {
-            trial_solution.m_error = total_error;
-            trial_solution.m_coords.m_inten_table = inten_table;
-            trial_solution.m_selectors.swap(m_temp_selectors);
-            trial_solution.m_valid = true;
-         }
-      }
-      trial_solution.m_coords.m_unscaled_color = coords.m_unscaled_color;
-      trial_solution.m_coords.m_color4 = m_pParams->m_use_color4;
-
-      bool success = false;
-      if (pBest_solution)
-      {
-         if (trial_solution.m_error < pBest_solution->m_error)
-         {
-            *pBest_solution = trial_solution;
-            success = true;
-         }
-      }
-
-      return success;
-   }
-
-   bool etc1_optimizer::evaluate_solution_fast(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution)
-   {
-      if (m_pParams->m_constrain_against_base_color5)
-      {
-         const int dr = coords.m_unscaled_color.r - m_pParams->m_base_color5.r;
-         const int dg = coords.m_unscaled_color.g - m_pParams->m_base_color5.g;
-         const int db = coords.m_unscaled_color.b - m_pParams->m_base_color5.b;
-
-         if ((math::minimum(dr, dg, db) < cETC1ColorDeltaMin) || (math::maximum(dr, dg, db) > cETC1ColorDeltaMax))
-         {
-            trial_solution.m_valid = false;
-            return false;
-         }
-      }
-
-      const color_quad_u8 base_color(coords.get_scaled_color());
-
-      const uint n = m_pParams->m_num_src_pixels;
-      CRNLIB_ASSERT(trial_solution.m_selectors.size() == n);
-
-      trial_solution.m_error = cUINT64_MAX;
-
-      for (int inten_table = cETC1IntenModifierValues - 1; inten_table >= 0; --inten_table)
-      {
-         const int* pInten_table = g_etc1_inten_tables[inten_table];
-
-         uint block_inten[4];
-         color_quad_u8 block_colors[4];
-         for (uint s = 0; s < 4; s++)
-         {
-            const int yd = pInten_table[s];
-            color_quad_u8 block_color(base_color.r + yd, base_color.g + yd, base_color.b + yd, 0);
-            block_colors[s] = block_color;
-            block_inten[s] = block_color.r + block_color.g + block_color.b;
-         }
-
-         // evaluate_solution_fast() enforces/assumesd a total ordering of the input colors along the intensity (1,1,1) axis to more quickly classify the inputs to selectors.
-         // The inputs colors have been presorted along the projection onto this axis, and ETC1 block colors are always ordered along the intensity axis, so this classification is fast.
-         // 0   1   2   3
-         //   01  12  23
-         const uint block_inten_midpoints[3] = { block_inten[0] + block_inten[1], block_inten[1] + block_inten[2], block_inten[2] + block_inten[3] };
-
-         uint64 total_error = 0;
-         const color_quad_u8* pSrc_pixels = m_pParams->m_pSrc_pixels;
-         if ((m_pSorted_luma[n - 1] * 2) < block_inten_midpoints[0])
-         {
-            if (block_inten[0] > m_pSorted_luma[n - 1])
-            {
-               const uint min_error = labs(block_inten[0] - m_pSorted_luma[n - 1]);
-               if (min_error >= trial_solution.m_error)
-                  continue;
-            }
-
-            memset(&m_temp_selectors[0], 0, n);
-
-            for (uint c = 0; c < n; c++)
-               total_error += color::elucidian_distance(block_colors[0], pSrc_pixels[c], false);
-         }
-         else if ((m_pSorted_luma[0] * 2) >= block_inten_midpoints[2])
-         {
-            if (m_pSorted_luma[0] > block_inten[3])
-            {
-               const uint min_error = labs(m_pSorted_luma[0] - block_inten[3]);
-               if (min_error >= trial_solution.m_error)
-                  continue;
-            }
-
-            memset(&m_temp_selectors[0], 3, n);
-
-            for (uint c = 0; c < n; c++)
-               total_error += color::elucidian_distance(block_colors[3], pSrc_pixels[c], false);
-         }
-         else
-         {
-            uint cur_selector = 0, c;
-            for (c = 0; c < n; c++)
-            {
-               const uint y = m_pSorted_luma[c];
-               while ((y * 2) >= block_inten_midpoints[cur_selector])
-                  if (++cur_selector > 2)
-                     goto done;
-               const uint sorted_pixel_index = m_pSorted_luma_indices[c];
-               m_temp_selectors[sorted_pixel_index] = static_cast<uint8>(cur_selector);
-               total_error += color::elucidian_distance(block_colors[cur_selector], pSrc_pixels[sorted_pixel_index], false);
-            }
-done:
-            while (c < n)
-            {
-               const uint sorted_pixel_index = m_pSorted_luma_indices[c];
-               m_temp_selectors[sorted_pixel_index] = 3;
-               total_error += color::elucidian_distance(block_colors[3], pSrc_pixels[sorted_pixel_index], false);
-               ++c;
-            }
-         }
-
-         if (total_error < trial_solution.m_error)
-         {
-            trial_solution.m_error = total_error;
-            trial_solution.m_coords.m_inten_table = inten_table;
-            trial_solution.m_selectors.swap(m_temp_selectors);
-            trial_solution.m_valid = true;
-            if (!total_error)
-               break;
-         }
-      }
-      trial_solution.m_coords.m_unscaled_color = coords.m_unscaled_color;
-      trial_solution.m_coords.m_color4 = m_pParams->m_use_color4;
-      
-      bool success = false;
-      if (pBest_solution)
-      {
-         if (trial_solution.m_error < pBest_solution->m_error)
-         {
-            *pBest_solution = trial_solution;
-            success = true;
-         }
-      }
-
-      return success;
-   }
-
-   // Dither function from RYG's public domain real-time DXT1 compressor, modified for 555.
-   static void DitherBlock(color_quad_u8 *dest, const color_quad_u8 *block)
-   {
-      int err[8],*ep1 = err,*ep2 = err+4;
-      uint8 *quant = ryg_dxt::QuantRBTab+8;
-
-      // process channels seperately
-      for(int ch=0;ch<3;ch++)
-      {
-         uint8 *bp = (uint8 *) block;
-         uint8 *dp = (uint8 *) dest;
-         
-         bp += ch;
-         dp += ch;
-         memset(err,0,sizeof(err));
-
-         for(int y=0;y<4;y++)
-         {
-            // pixel 0
-            dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)];
-            ep1[0] = bp[ 0] - dp[ 0];
-
-            // pixel 1
-            dp[ 4] = quant[bp[ 4] + ((7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]) >> 4)];
-            ep1[1] = bp[ 4] - dp[ 4];
-
-            // pixel 2
-            dp[ 8] = quant[bp[ 8] + ((7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]) >> 4)];
-            ep1[2] = bp[ 8] - dp[ 8];
-
-            // pixel 3
-            dp[12] = quant[bp[12] + ((7*ep1[2] + 5*ep2[3] + ep2[2]) >> 4)];
-            ep1[3] = bp[12] - dp[12];
-
-            // advance to next line
-            std::swap(ep1,ep2);
-            bp += 16;
-            dp += 16;
-         }
-      }
-   }
-      
-   static uint etc1_decode_value(uint diff, uint inten, uint selector, uint packed_c)
-   {
-      const uint limit = diff ? 32 : 16; limit;
-      CRNLIB_ASSERT((diff < 2) && (inten < 8) && (selector < 4) && (packed_c < limit));
-      int c;
-      if (diff)
-         c = (packed_c >> 2) | (packed_c << 3);
-      else 
-         c = packed_c | (packed_c << 4);
-      c += g_etc1_inten_tables[inten][selector];
-      c = math::clamp<int>(c, 0, 255);
-      return c;
-   }
-
-   void pack_etc1_block_init()
-   {
-      for (uint diff = 0; diff < 2; diff++)
-      {
-         const uint limit = diff ? 32 : 16;
-
-         for (uint inten = 0; inten < 8; inten++)
-         {
-            for (uint selector = 0; selector < 4; selector++)
-            {
-               const uint inverse_table_index = diff + (inten << 1) + (selector << 4);
-               for (uint color = 0; color < 256; color++)
-               {
-                  uint best_error = cUINT32_MAX, best_packed_c = 0;
-                  for (uint packed_c = 0; packed_c < limit; packed_c++)
-                  {
-                     int v = etc1_decode_value(diff, inten, selector, packed_c);
-                     uint err = labs(v - color);
-                     if (err < best_error)
-                     {
-                        best_error = err;
-                        best_packed_c = packed_c;
-                        if (!best_error) 
-                           break;
-                     }
-                  }
-                  CRNLIB_ASSERT(best_error <= 255);
-                  g_etc1_inverse_lookup[inverse_table_index][color] = static_cast<uint16>(best_packed_c | (best_error << 8));
-               }
-            }
-         }
-      }
-   }
-
-   // Packs solid color blocks efficiently using a set of small precomputed tables.
-   // For random 888 inputs, MSE results are better than Erricson's ETC1 packer in "slow" mode ~9.5% of the time, is slightly worse only ~.01% of the time, and is equal the rest of the time.
-   static uint64 pack_etc1_block_solid_color(etc1_block& block, const uint8* pColor, crn_etc1_pack_params& pack_params, pack_etc1_block_context& context)
-   {
-      CRNLIB_ASSERT(g_etc1_inverse_lookup[0][255]);
-
-      context, pack_params;
-      static uint s_next_comp[4] = { 1, 2, 0, 1 };
-            
-      uint best_error = cUINT32_MAX, best_i = 0;
-      int best_x = 0, best_packed_c1 = 0, best_packed_c2 = 0;
-
-      // For each possible 8-bit value, there is a precomputed list of diff/inten/selector configurations that allow that 8-bit value to be encoded with no error.
-      for (uint i = 0; i < 3; i++)
-      {
-         const uint c1 = pColor[s_next_comp[i]], c2 = pColor[s_next_comp[i + 1]];
-
-         const int delta_range = 1;
-         for (int delta = -delta_range; delta <= delta_range; delta++)
-         {
-            const int c_plus_delta = math::clamp<int>(pColor[i] + delta, 0, 255);
-
-            const uint16* pTable;
-            if (!c_plus_delta)
-               pTable = g_color8_to_etc_block_config_0_255[0];
-            else if (c_plus_delta == 255)
-               pTable = g_color8_to_etc_block_config_0_255[1];
-            else
-               pTable = g_color8_to_etc_block_config_1_to_254[c_plus_delta - 1];
-
-            do
-            {
-               const uint x = *pTable++;
-
-#ifdef CRNLIB_BUILD_DEBUG
-               const uint diff = x & 1;
-               const uint inten = (x >> 1) & 7;
-               const uint selector = (x >> 4) & 3;
-               const uint p0 = (x >> 8) & 255;
-               CRNLIB_ASSERT(etc1_decode_value(diff, inten, selector, p0) == (uint)c_plus_delta);
-#endif
-
-               const uint16* pInverse_table = g_etc1_inverse_lookup[x & 0xFF];
-               uint16 p1 = pInverse_table[c1];
-               uint16 p2 = pInverse_table[c2];
-               const uint trial_error = math::square(c_plus_delta - pColor[i]) + math::square(p1 >> 8) + math::square(p2 >> 8);
-               if (trial_error < best_error)
-               {
-                  best_error = trial_error;
-                  best_x = x;
-                  best_packed_c1 = p1 & 0xFF;
-                  best_packed_c2 = p2 & 0xFF;
-                  best_i = i;
-                  if (!best_error)
-                     goto found_perfect_match;
-               }
-            } while (*pTable != 0xFFFF);
-         }
-      }
-found_perfect_match:
-
-      const uint diff = best_x & 1;
-      const uint inten = (best_x >> 1) & 7;
-
-      block.m_bytes[3] = static_cast<uint8>(((inten | (inten << 3)) << 2) | (diff << 1));
-                        
-      const uint etc1_selector = g_selector_index_to_etc1[(best_x >> 4) & 3];
-      *reinterpret_cast<uint16*>(&block.m_bytes[4]) = (etc1_selector & 2) ? 0xFFFF : 0;
-      *reinterpret_cast<uint16*>(&block.m_bytes[6]) = (etc1_selector & 1) ? 0xFFFF : 0;
-
-      const uint best_packed_c0 = (best_x >> 8) & 255;
-      if (diff)
-      {
-         block.m_bytes[best_i] = static_cast<uint8>(best_packed_c0 << 3);
-         block.m_bytes[s_next_comp[best_i]] = static_cast<uint8>(best_packed_c1 << 3);
-         block.m_bytes[s_next_comp[best_i+1]] = static_cast<uint8>(best_packed_c2 << 3);
-      }
-      else
-      {
-         block.m_bytes[best_i] = static_cast<uint8>(best_packed_c0 | (best_packed_c0 << 4));
-         block.m_bytes[s_next_comp[best_i]] = static_cast<uint8>(best_packed_c1 | (best_packed_c1 << 4));
-         block.m_bytes[s_next_comp[best_i+1]] = static_cast<uint8>(best_packed_c2 | (best_packed_c2 << 4));
-      }
-
-      return best_error;
-   }
-      
-   static uint pack_etc1_block_solid_color_constrained(
-      etc1_optimizer::results& results, 
-      uint num_colors, const uint8 *pColor, 
-      crn_etc1_pack_params& pack_params, 
-      pack_etc1_block_context& context,
-      bool use_diff,
-      const color_quad_u8* pBase_color5_unscaled)
-   {
-      CRNLIB_ASSERT(g_etc1_inverse_lookup[0][255]);
-
-      context, pack_params;
-      static uint s_next_comp[4] = { 1, 2, 0, 1 };
-
-      uint best_error = cUINT32_MAX, best_i = 0;
-      int best_x = 0, best_packed_c1 = 0, best_packed_c2 = 0;
-
-      // For each possible 8-bit value, there is a precomputed list of diff/inten/selector configurations that allow that 8-bit value to be encoded with no error.
-      for (uint i = 0; i < 3; i++)
-      {
-         const uint c1 = pColor[s_next_comp[i]], c2 = pColor[s_next_comp[i + 1]];
-
-         const int delta_range = 1;
-         for (int delta = -delta_range; delta <= delta_range; delta++)
-         {
-            const int c_plus_delta = math::clamp<int>(pColor[i] + delta, 0, 255);
-
-            const uint16* pTable;
-            if (!c_plus_delta)
-               pTable = g_color8_to_etc_block_config_0_255[0];
-            else if (c_plus_delta == 255)
-               pTable = g_color8_to_etc_block_config_0_255[1];
-            else
-               pTable = g_color8_to_etc_block_config_1_to_254[c_plus_delta - 1];
-
-            do
-            {
-               const uint x = *pTable++;
-               const uint diff = x & 1;
-               if (static_cast<uint>(use_diff) != diff)
-               {
-                  if (*pTable == 0xFFFF)
-                     break;
-                  continue;
-               }
-
-               if ((diff) && (pBase_color5_unscaled))
-               {
-                  const int p0 = (x >> 8) & 255;
-                  int delta = p0 - static_cast<int>(pBase_color5_unscaled->c[i]);
-                  if ((delta < cETC1ColorDeltaMin) || (delta > cETC1ColorDeltaMax))
-                  {
-                     if (*pTable == 0xFFFF)
-                        break;
-                     continue;
-                  }
-               }
-
-#ifdef CRNLIB_BUILD_DEBUG
-               {
-                  const uint inten = (x >> 1) & 7;
-                  const uint selector = (x >> 4) & 3;
-                  const uint p0 = (x >> 8) & 255;
-                  CRNLIB_ASSERT(etc1_decode_value(diff, inten, selector, p0) == (uint)c_plus_delta);
-               }
-#endif
-
-               const uint16* pInverse_table = g_etc1_inverse_lookup[x & 0xFF];
-               uint16 p1 = pInverse_table[c1];
-               uint16 p2 = pInverse_table[c2];
-
-               if ((diff) && (pBase_color5_unscaled))
-               {
-                  int delta1 = (p1 & 0xFF) - static_cast<int>(pBase_color5_unscaled->c[s_next_comp[i]]);
-                  int delta2 = (p2 & 0xFF) - static_cast<int>(pBase_color5_unscaled->c[s_next_comp[i + 1]]);
-                  if ((delta1 < cETC1ColorDeltaMin) || (delta1 > cETC1ColorDeltaMax) || (delta2 < cETC1ColorDeltaMin) || (delta2 > cETC1ColorDeltaMax))
-                  {
-                     if (*pTable == 0xFFFF)
-                        break;
-                     continue;
-                  }
-               }
-
-               const uint trial_error = math::square(c_plus_delta - pColor[i]) + math::square(p1 >> 8) + math::square(p2 >> 8);
-               if (trial_error < best_error)
-               {
-                  best_error = trial_error;
-                  best_x = x;
-                  best_packed_c1 = p1 & 0xFF;
-                  best_packed_c2 = p2 & 0xFF;
-                  best_i = i;
-                  if (!best_error)
-                     goto found_perfect_match;
-               }
-            } while (*pTable != 0xFFFF);
-         }
-      }
-found_perfect_match:
-
-      if (best_error == cUINT32_MAX)
-         return best_error;
-
-      best_error *= num_colors;
-
-      results.m_n = num_colors;
-      results.m_block_color4 = !(best_x & 1);
-      results.m_block_inten_table = (best_x >> 1) & 7;
-      memset(results.m_pSelectors, (best_x >> 4) & 3, num_colors);
-
-      const uint best_packed_c0 = (best_x >> 8) & 255;
-      results.m_block_color_unscaled[best_i] = static_cast<uint8>(best_packed_c0);
-      results.m_block_color_unscaled[s_next_comp[best_i]] = static_cast<uint8>(best_packed_c1);
-      results.m_block_color_unscaled[s_next_comp[best_i + 1]] = static_cast<uint8>(best_packed_c2);
-      results.m_error = best_error;
-      
-      return best_error;
-   }
-
-   uint64 pack_etc1_block(etc1_block& dst_block, const color_quad_u8* pSrc_pixels, crn_etc1_pack_params& pack_params, pack_etc1_block_context& context)
-   {
-      color_quad_u8 src_pixel0(pSrc_pixels[0]);
-
-      int r;
-      for (r = 15; r >= 1; --r)
-         if ((pSrc_pixels[r].r != src_pixel0.r) || (pSrc_pixels[r].g != src_pixel0.g) || (pSrc_pixels[r].b != src_pixel0.b))
-            break;
-      if (!r)
-         return 16 * pack_etc1_block_solid_color(dst_block, &pSrc_pixels[0].r, pack_params, context);
-      
-      color_quad_u8 dithered_pixels[16];
-      if (pack_params.m_dithering)
-      {
-         DitherBlock(dithered_pixels, pSrc_pixels);
-         pSrc_pixels = dithered_pixels;
-      }
-
-      uint64 best_error = cUINT64_MAX;
-      uint best_flip = false, best_use_color4 = false;
-      
-      uint8 best_selectors[2][8];
-      etc1_optimizer::results best_results[2];
-      for (uint i = 0; i < 2; i++)
-      {
-         best_results[i].m_n = 8;
-         best_results[i].m_pSelectors = best_selectors[i];
-      }
-      
-      uint8 selectors[3][8];
-      etc1_optimizer::results results[3];
-      
-      for (uint i = 0; i < 3; i++)
-      {
-         results[i].m_n = 8;
-         results[i].m_pSelectors = selectors[i];
-      }
-            
-      color_quad_u8 subblock_pixels[8];
-
-      etc1_optimizer::params params(pack_params);
-      params.m_num_src_pixels = 8;
-      params.m_pSrc_pixels = subblock_pixels;
-
-      for (uint flip = 0; flip < 2; flip++)
-      {
-         for (uint use_color4 = 0; use_color4 < 2; use_color4++)
-         {
-            uint64 trial_error = 0;
-
-            uint subblock;
-            for (subblock = 0; subblock < 2; subblock++)
-            {
-               if (flip)
-                  memcpy(subblock_pixels, pSrc_pixels + subblock * 8, sizeof(color_quad_u8) * 8);
-               else
-               {
-                  const color_quad_u8* pSrc_col = pSrc_pixels + subblock * 2;
-                  subblock_pixels[0] = pSrc_col[0]; subblock_pixels[1] = pSrc_col[4]; subblock_pixels[2] = pSrc_col[8]; subblock_pixels[3] = pSrc_col[12];
-                  subblock_pixels[4] = pSrc_col[1]; subblock_pixels[5] = pSrc_col[5]; subblock_pixels[6] = pSrc_col[9]; subblock_pixels[7] = pSrc_col[13];
-               }
-
-               results[2].m_error = cUINT64_MAX;
-               if ((params.m_quality >= cCRNETCQualityMedium) && ((subblock) || (use_color4)))
-               {
-                  color_quad_u8 subblock_pixel0(subblock_pixels[0]);
-                  for (r = 7; r >= 1; --r)
-                     if ((subblock_pixels[r].r != subblock_pixel0.r) || (subblock_pixels[r].g != subblock_pixel0.g) || (subblock_pixels[r].b != subblock_pixel0.b))
-                        break;
-                  if (!r)
-                  {
-                     pack_etc1_block_solid_color_constrained(results[2], 8, &subblock_pixel0.r, pack_params, context, !use_color4, (subblock && !use_color4) ? &results[0].m_block_color_unscaled : NULL);
-                  }
-               }
-
-               params.m_use_color4 = (use_color4 != 0);
-               params.m_constrain_against_base_color5 = false;
-
-               if ((!use_color4) && (subblock))
-               {
-                  params.m_constrain_against_base_color5 = true;
-                  params.m_base_color5 = results[0].m_block_color_unscaled;
-               }
-                              
-               if (params.m_quality == cCRNETCQualitySlow)
-               {
-                  static const int s_scan_delta_0_to_4[] = { -4, -3, -2, -1, 0, 1, 2, 3, 4 };
-                  params.m_scan_delta_size = CRNLIB_ARRAY_SIZE(s_scan_delta_0_to_4);
-                  params.m_pScan_deltas = s_scan_delta_0_to_4;
-               }
-               else if (params.m_quality == cCRNETCQualityMedium)
-               {
-                  static const int s_scan_delta_0_to_1[] = { -1, 0, 1 };
-                  params.m_scan_delta_size = CRNLIB_ARRAY_SIZE(s_scan_delta_0_to_1);
-                  params.m_pScan_deltas = s_scan_delta_0_to_1;
-               }
-               else
-               {
-                  static const int s_scan_delta_0[] = { 0 };
-                  params.m_scan_delta_size = CRNLIB_ARRAY_SIZE(s_scan_delta_0);
-                  params.m_pScan_deltas = s_scan_delta_0;
-               }
-               
-               context.m_optimizer.init(params, results[subblock]);
-
-               if (!context.m_optimizer.compute())
-                  break;
-                             
-               // Fairly arbitrary/unrefined thresholds that control how far away to scan for potentially better solutions.
-               const uint refinement_error_thresh0 = 3000;
-               const uint refinement_error_thresh1 = 6000;
-               if ((params.m_quality >= cCRNETCQualityMedium) && (results[subblock].m_error > refinement_error_thresh0))
-               {
-                  if (params.m_quality == cCRNETCQualityMedium)
-                  {
-                     static const int s_scan_delta_2_to_3[] = { -3, -2, 2, 3 };
-                     params.m_scan_delta_size = CRNLIB_ARRAY_SIZE(s_scan_delta_2_to_3);
-                     params.m_pScan_deltas = s_scan_delta_2_to_3;
-                  }
-                  else
-                  {
-                     static const int s_scan_delta_5_to_5[] = { -5, 5 };
-                     static const int s_scan_delta_5_to_8[] = { -8, -7, -6, -5, 5, 6, 7, 8 };
-                     if (results[subblock].m_error > refinement_error_thresh1)
-                     {
-                        params.m_scan_delta_size = CRNLIB_ARRAY_SIZE(s_scan_delta_5_to_8);
-                        params.m_pScan_deltas = s_scan_delta_5_to_8;
-                     }
-                     else
-                     {
-                        params.m_scan_delta_size = CRNLIB_ARRAY_SIZE(s_scan_delta_5_to_5);
-                        params.m_pScan_deltas = s_scan_delta_5_to_5;
-                     }
-                  }
-
-                  if (!context.m_optimizer.compute())
-                     break;
-               }
-               
-               if (results[2].m_error < results[subblock].m_error)
-                  results[subblock] = results[2];
-
-               trial_error += results[subblock].m_error;
-               if (trial_error >= best_error)
-                  break;
-            }
-
-            if (subblock < 2)
-               continue;
-
-            best_error = trial_error;
-            best_results[0] = results[0];
-            best_results[1] = results[1];
-            best_flip = flip;
-            best_use_color4 = use_color4;
-            
-         } // use_color4
-
-      } // flip
-
-      int dr = best_results[1].m_block_color_unscaled.r - best_results[0].m_block_color_unscaled.r;
-      int dg = best_results[1].m_block_color_unscaled.g - best_results[0].m_block_color_unscaled.g;
-      int db = best_results[1].m_block_color_unscaled.b - best_results[0].m_block_color_unscaled.b;
-      if (!best_use_color4)
-      {
-         if ((math::minimum(dr, dg, db) < cETC1ColorDeltaMin) || (math::maximum(dr, dg, db) > cETC1ColorDeltaMax))
-         {
-            // Shouldn't ever happen
-            CRNLIB_VERIFY(0);
-         }
-      }
-           
-      if (best_use_color4)
-      {
-         dst_block.m_bytes[0] = static_cast<uint8>(best_results[1].m_block_color_unscaled.r | (best_results[0].m_block_color_unscaled.r << 4));
-         dst_block.m_bytes[1] = static_cast<uint8>(best_results[1].m_block_color_unscaled.g | (best_results[0].m_block_color_unscaled.g << 4));
-         dst_block.m_bytes[2] = static_cast<uint8>(best_results[1].m_block_color_unscaled.b | (best_results[0].m_block_color_unscaled.b << 4));
-      }
-      else
-      {
-         if (dr < 0) dr += 8;
-         if (dg < 0) dg += 8;
-         if (db < 0) db += 8;
-         dst_block.m_bytes[0] = static_cast<uint8>((best_results[0].m_block_color_unscaled.r << 3) | dr);
-         dst_block.m_bytes[1] = static_cast<uint8>((best_results[0].m_block_color_unscaled.g << 3) | dg);
-         dst_block.m_bytes[2] = static_cast<uint8>((best_results[0].m_block_color_unscaled.b << 3) | db);
-      }
-      
-      dst_block.m_bytes[3] = static_cast<uint8>( (best_results[1].m_block_inten_table << 2) | (best_results[0].m_block_inten_table << 5) | ((~best_use_color4 & 1) << 1) | best_flip );
-      
-      uint selector0 = 0, selector1 = 0;
-      if (best_flip)
-      {
-         // flipped:
-         // { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 },               
-         // { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 } 
-         //
-         // { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 },
-         // { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 }
-         const uint8* pSelectors0 = best_results[0].m_pSelectors;
-         const uint8* pSelectors1 = best_results[1].m_pSelectors;
-         for (int x = 3; x >= 0; --x)
-         {
-            uint b;
-            b = g_selector_index_to_etc1[pSelectors1[4 + x]];
-            selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1);
-
-            b = g_selector_index_to_etc1[pSelectors1[x]];
-            selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1);
-
-            b = g_selector_index_to_etc1[pSelectors0[4 + x]];
-            selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1);
-
-            b = g_selector_index_to_etc1[pSelectors0[x]];
-            selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1);
-         }
-      }
-      else
-      {
-         // non-flipped:
-         // { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 },
-         // { 1, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 }
-         //
-         // { 2, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 },
-         // { 3, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 }
-         for (int subblock = 1; subblock >= 0; --subblock)
-         {
-            const uint8* pSelectors = best_results[subblock].m_pSelectors + 4;
-            for (uint i = 0; i < 2; i++)
-            {
-               uint b;
-               b = g_selector_index_to_etc1[pSelectors[3]];
-               selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1);
-
-               b = g_selector_index_to_etc1[pSelectors[2]];
-               selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1);
-
-               b = g_selector_index_to_etc1[pSelectors[1]];
-               selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1);
-
-               b = g_selector_index_to_etc1[pSelectors[0]];
-               selector0 = (selector0 << 1) | (b & 1);selector1 = (selector1 << 1) | (b >> 1);
-
-               pSelectors -= 4;
-            }
-         }
-      }
-                  
-      dst_block.m_bytes[4] = static_cast<uint8>(selector1 >> 8);
-      dst_block.m_bytes[5] = static_cast<uint8>(selector1 & 0xFF);
-      dst_block.m_bytes[6] = static_cast<uint8>(selector0 >> 8);
-      dst_block.m_bytes[7] = static_cast<uint8>(selector0 & 0xFF);
-
-      return best_error;
-   }
-
-} // namespace crnlib

+ 0 - 609
Source/ThirdParty/crunch/crnlib/crn_etc.h

@@ -1,609 +0,0 @@
-// File: crn_etc.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "../inc/crnlib.h"
-#include "crn_dxt.h"
-
-namespace crnlib
-{
-   enum etc_constants
-   {
-      cETC1BytesPerBlock = 8U,
-
-      cETC1SelectorBits = 2U,
-      cETC1SelectorValues = 1U << cETC1SelectorBits,
-      cETC1SelectorMask = cETC1SelectorValues - 1U,
-
-      cETC1BlockShift = 2U,
-      cETC1BlockSize = 1U << cETC1BlockShift,
-
-      cETC1LSBSelectorIndicesBitOffset = 0,
-      cETC1MSBSelectorIndicesBitOffset = 16,
-      
-      cETC1FlipBitOffset = 32,
-      cETC1DiffBitOffset = 33,
-      
-      cETC1IntenModifierNumBits = 3,
-      cETC1IntenModifierValues = 1 << cETC1IntenModifierNumBits,
-      cETC1RightIntenModifierTableBitOffset = 34,
-      cETC1LeftIntenModifierTableBitOffset = 37,
-
-      // Base+Delta encoding (5 bit bases, 3 bit delta)
-      cETC1BaseColorCompNumBits = 5,
-      cETC1BaseColorCompMax = 1 << cETC1BaseColorCompNumBits,
-
-      cETC1DeltaColorCompNumBits = 3,
-      cETC1DeltaColorComp = 1 << cETC1DeltaColorCompNumBits,
-      cETC1DeltaColorCompMax = 1 << cETC1DeltaColorCompNumBits,
-
-      cETC1BaseColor5RBitOffset = 59,
-      cETC1BaseColor5GBitOffset = 51,
-      cETC1BaseColor5BBitOffset = 43,
-
-      cETC1DeltaColor3RBitOffset = 56,
-      cETC1DeltaColor3GBitOffset = 48,
-      cETC1DeltaColor3BBitOffset = 40,
-      
-      // Absolute (non-delta) encoding (two 4-bit per component bases)
-      cETC1AbsColorCompNumBits = 4,
-      cETC1AbsColorCompMax = 1 << cETC1AbsColorCompNumBits,
-
-      cETC1AbsColor4R1BitOffset = 60,
-      cETC1AbsColor4G1BitOffset = 52,
-      cETC1AbsColor4B1BitOffset = 44,
-
-      cETC1AbsColor4R2BitOffset = 56,
-      cETC1AbsColor4G2BitOffset = 48,
-      cETC1AbsColor4B2BitOffset = 40,
-
-      cETC1ColorDeltaMin = -4,
-      cETC1ColorDeltaMax = 3,
-
-      // Delta3:
-      // 0   1   2   3   4   5   6   7
-      // 000 001 010 011 100 101 110 111
-      // 0   1   2   3   -4  -3  -2  -1
-   };
-
-   extern const int g_etc1_inten_tables[cETC1IntenModifierValues][cETC1SelectorValues];
-   extern const uint8 g_etc1_to_selector_index[cETC1SelectorValues];
-   extern const uint8 g_selector_index_to_etc1[cETC1SelectorValues];
-
-   struct etc1_coord2
-   { 
-      uint8 m_x, m_y; 
-   };
-   extern const etc1_coord2 g_etc1_pixel_coords[2][2][8]; // [flipped][subblock][subblock_pixel]
-
-   struct etc1_block
-   {
-      // big endian uint64:
-      // bit ofs:  56  48  40  32  24  16   8   0
-      // byte ofs: b0, b1, b2, b3, b4, b5, b6, b7 
-      union 
-      {
-         uint64 m_uint64;
-         uint8 m_bytes[8];
-      };
-
-      uint8 m_low_color[2];
-      uint8 m_high_color[2];
-
-      enum { cNumSelectorBytes = 4 };
-      uint8 m_selectors[cNumSelectorBytes];
-
-      inline void clear()
-      {
-         utils::zero_this(this);
-      }
-
-      inline uint get_general_bits(uint ofs, uint num) const
-      {
-         CRNLIB_ASSERT((ofs + num) <= 64U);
-         CRNLIB_ASSERT(num && (num < 32U));
-         return (utils::read_be64(&m_uint64) >> ofs) & ((1UL << num) - 1UL);
-      }
-
-      inline void set_general_bits(uint ofs, uint num, uint bits)
-      {
-         CRNLIB_ASSERT((ofs + num) <= 64U);
-         CRNLIB_ASSERT(num && (num < 32U));
-         
-         uint64 x = utils::read_be64(&m_uint64);
-         uint64 msk = ((1ULL << static_cast<uint64>(num)) - 1ULL) << static_cast<uint64>(ofs);
-         x &= ~msk;
-         x |= (static_cast<uint64>(bits) << static_cast<uint64>(ofs));
-         utils::write_be64(&m_uint64, x);
-      }
-
-      inline uint get_byte_bits(uint ofs, uint num) const
-      {
-         CRNLIB_ASSERT((ofs + num) <= 64U);
-         CRNLIB_ASSERT(num && (num <= 8U));
-         CRNLIB_ASSERT((ofs >> 3) == ((ofs + num - 1) >> 3));
-         const uint byte_ofs = 7 - (ofs >> 3);
-         const uint byte_bit_ofs = ofs & 7;
-         return (m_bytes[byte_ofs] >> byte_bit_ofs) & ((1 << num) - 1);
-      }
-
-      inline void set_byte_bits(uint ofs, uint num, uint bits)
-      {
-         CRNLIB_ASSERT((ofs + num) <= 64U);
-         CRNLIB_ASSERT(num && (num < 32U));
-         CRNLIB_ASSERT((ofs >> 3) == ((ofs + num - 1) >> 3));
-         CRNLIB_ASSERT(bits < (1U << num));
-         const uint byte_ofs = 7 - (ofs >> 3);
-         const uint byte_bit_ofs = ofs & 7;
-         const uint mask = (1 << num) - 1;
-         m_bytes[byte_ofs] &= ~(mask << byte_bit_ofs);
-         m_bytes[byte_ofs] |= (bits << byte_bit_ofs);
-      }
-
-      // false = left/right subblocks
-      // true = upper/lower subblocks
-      inline bool get_flip_bit() const 
-      {
-         return (m_bytes[3] & 1) != 0;
-      }   
-
-      inline void set_flip_bit(bool flip)
-      {
-         m_bytes[3] &= ~1;
-         m_bytes[3] |= static_cast<uint8>(flip);
-      }
-
-      inline bool get_diff_bit() const
-      {
-         return (m_bytes[3] & 2) != 0;
-      }
-
-      inline void set_diff_bit(bool diff)
-      {
-         m_bytes[3] &= ~2;
-         m_bytes[3] |= (static_cast<uint>(diff) << 1);
-      }
-
-      // Returns intensity modifier table (0-7) used by subblock subblock_id.
-      // subblock_id=0 left/top (CW 1), 1=right/bottom (CW 2)
-      inline uint get_inten_table(uint subblock_id) const
-      {
-         CRNLIB_ASSERT(subblock_id < 2);
-         const uint ofs = subblock_id ? 2 : 5;
-         return (m_bytes[3] >> ofs) & 7;
-      }
-
-      // Sets intensity modifier table (0-7) used by subblock subblock_id (0 or 1)
-      inline void set_inten_table(uint subblock_id, uint t)
-      {
-         CRNLIB_ASSERT(subblock_id < 2);
-         CRNLIB_ASSERT(t < 8);
-         const uint ofs = subblock_id ? 2 : 5;
-         m_bytes[3] &= ~(7 << ofs);
-         m_bytes[3] |= (t << ofs);
-      }
-
-      // Returned selector value ranges from 0-3 and is a direct index into g_etc1_inten_tables.
-      inline uint get_selector(uint x, uint y) const
-      {
-         CRNLIB_ASSERT((x | y) < 4);
-                  
-         const uint bit_index = x * 4 + y;
-         const uint byte_bit_ofs = bit_index & 7;
-         const uint8 *p = &m_bytes[7 - (bit_index >> 3)];
-         const uint lsb = (p[0] >> byte_bit_ofs) & 1;
-         const uint msb = (p[-2] >> byte_bit_ofs) & 1;
-         const uint val = lsb | (msb << 1);
-         
-         return g_etc1_to_selector_index[val];
-      }
-
-      // Selector "val" ranges from 0-3 and is a direct index into g_etc1_inten_tables.
-      inline void set_selector(uint x, uint y, uint val)
-      {
-         CRNLIB_ASSERT((x | y | val) < 4);
-         const uint bit_index = x * 4 + y;
-         
-         uint8 *p = &m_bytes[7 - (bit_index >> 3)];
-         
-         const uint byte_bit_ofs = bit_index & 7;
-         const uint mask = 1 << byte_bit_ofs;
-         
-         const uint etc1_val = g_selector_index_to_etc1[val];
-
-         const uint lsb = etc1_val & 1;
-         const uint msb = etc1_val >> 1;
-
-         p[0] &= ~mask;
-         p[0] |= (lsb << byte_bit_ofs);
-
-         p[-2] &= ~mask;
-         p[-2] |= (msb << byte_bit_ofs);
-      }
-
-      inline void set_base4_color(uint idx, uint16 c)
-      {
-         if (idx)
-         {
-            set_byte_bits(cETC1AbsColor4R2BitOffset, 4, (c >> 8) & 15);
-            set_byte_bits(cETC1AbsColor4G2BitOffset, 4, (c >> 4) & 15);
-            set_byte_bits(cETC1AbsColor4B2BitOffset, 4, c & 15);
-         }
-         else
-         {
-            set_byte_bits(cETC1AbsColor4R1BitOffset, 4, (c >> 8) & 15);
-            set_byte_bits(cETC1AbsColor4G1BitOffset, 4, (c >> 4) & 15);
-            set_byte_bits(cETC1AbsColor4B1BitOffset, 4, c & 15);
-         }
-      }
-
-      inline uint16 get_base4_color(uint idx) const
-      {
-         uint r, g, b;
-         if (idx)
-         {
-            r = get_byte_bits(cETC1AbsColor4R2BitOffset, 4);
-            g = get_byte_bits(cETC1AbsColor4G2BitOffset, 4);
-            b = get_byte_bits(cETC1AbsColor4B2BitOffset, 4);
-         }
-         else
-         {
-            r = get_byte_bits(cETC1AbsColor4R1BitOffset, 4);
-            g = get_byte_bits(cETC1AbsColor4G1BitOffset, 4);
-            b = get_byte_bits(cETC1AbsColor4B1BitOffset, 4);
-         }
-         return static_cast<uint16>(b | (g << 4U) | (r << 8U));
-      }
-
-      inline void set_base5_color(uint16 c)
-      {
-         set_byte_bits(cETC1BaseColor5RBitOffset, 5, (c >> 10) & 31);
-         set_byte_bits(cETC1BaseColor5GBitOffset, 5, (c >> 5) & 31);
-         set_byte_bits(cETC1BaseColor5BBitOffset, 5, c & 31);
-      }
-
-      inline uint16 get_base5_color() const
-      {
-         const uint r = get_byte_bits(cETC1BaseColor5RBitOffset, 5);
-         const uint g = get_byte_bits(cETC1BaseColor5GBitOffset, 5);
-         const uint b = get_byte_bits(cETC1BaseColor5BBitOffset, 5);
-         return static_cast<uint16>(b | (g << 5U) | (r << 10U));
-      }
-
-      void set_delta3_color(uint16 c)
-      {
-         set_byte_bits(cETC1DeltaColor3RBitOffset, 3, (c >> 6) & 7);
-         set_byte_bits(cETC1DeltaColor3GBitOffset, 3, (c >> 3) & 7);
-         set_byte_bits(cETC1DeltaColor3BBitOffset, 3, c & 7);
-      }
-
-      inline uint16 get_delta3_color() const
-      {
-         const uint r = get_byte_bits(cETC1DeltaColor3RBitOffset, 3);
-         const uint g = get_byte_bits(cETC1DeltaColor3GBitOffset, 3);
-         const uint b = get_byte_bits(cETC1DeltaColor3BBitOffset, 3);
-         return static_cast<uint16>(b | (g << 3U) | (r << 6U));
-      }
-      
-      // Base color 5
-      static uint16 pack_color5(const color_quad_u8& color, bool scaled, uint bias = 127U);
-      static uint16 pack_color5(uint r, uint g, uint b, bool scaled, uint bias = 127U);
-
-      static color_quad_u8 unpack_color5(uint16 packed_color5, bool scaled, uint alpha = 255U);
-      static void unpack_color5(uint& r, uint& g, uint& b, uint16 packed_color, bool scaled);
-      
-      static bool unpack_color5(color_quad_u8& result, uint16 packed_color5, uint16 packed_delta3, bool scaled, uint alpha = 255U);
-      static bool unpack_color5(uint& r, uint& g, uint& b, uint16 packed_color5, uint16 packed_delta3, bool scaled, uint alpha = 255U);
-
-      // Delta color 3
-      // Inputs range from -4 to 3 (cETC1ColorDeltaMin to cETC1ColorDeltaMax)
-      static uint16 pack_delta3(const color_quad_i16& color);
-      static uint16 pack_delta3(int r, int g, int b);
-
-      // Results range from -4 to 3 (cETC1ColorDeltaMin to cETC1ColorDeltaMax)
-      static color_quad_i16 unpack_delta3(uint16 packed_delta3);
-      static void unpack_delta3(int& r, int& g, int& b, uint16 packed_delta3);
-
-      // Abs color 4
-      static uint16 pack_color4(const color_quad_u8& color, bool scaled, uint bias = 127U);
-      static uint16 pack_color4(uint r, uint g, uint b, bool scaled, uint bias = 127U);
-
-      static color_quad_u8 unpack_color4(uint16 packed_color4, bool scaled, uint alpha = 255U);
-      static void unpack_color4(uint& r, uint& g, uint& b, uint16 packed_color4, bool scaled);
-
-      // subblock colors
-      static void get_diff_subblock_colors(color_quad_u8* pDst, uint16 packed_color5, uint table_idx);
-      static bool get_diff_subblock_colors(color_quad_u8* pDst, uint16 packed_color5, uint16 packed_delta3, uint table_idx);
-      static void get_abs_subblock_colors(color_quad_u8* pDst, uint16 packed_color4, uint table_idx);
-
-      static inline void unscaled_to_scaled_color(color_quad_u8& dst, const color_quad_u8& src, bool color4)
-      {
-         if (color4)
-         {
-            dst.r = src.r | (src.r << 4);
-            dst.g = src.g | (src.g << 4);
-            dst.b = src.b | (src.b << 4);
-         }
-         else
-         {
-            dst.r = (src.r >> 2) | (src.r << 3);
-            dst.g = (src.g >> 2) | (src.g << 3);
-            dst.b = (src.b >> 2) | (src.b << 3);
-         }
-         dst.a = src.a;
-      }
-   };
-
-   CRNLIB_DEFINE_BITWISE_COPYABLE(etc1_block);
-
-   // Returns false if the block is invalid (it will still be unpacked with clamping).
-   bool unpack_etc1(const etc1_block& block, color_quad_u8 *pDst, bool preserve_alpha = false);
-
-   enum crn_etc_quality
-   { 
-      cCRNETCQualityFast,
-      cCRNETCQualityMedium,
-      cCRNETCQualitySlow,
-
-      cCRNETCQualityTotal,
-
-      cCRNETCQualityForceDWORD = 0xFFFFFFFF
-   };
-
-   struct crn_etc1_pack_params
-   {
-      crn_etc_quality m_quality;
-      bool m_perceptual;
-      bool m_dithering;
-                              
-      inline crn_etc1_pack_params() 
-      {
-         clear();
-      }
-
-      void clear()
-      {
-         m_quality = cCRNETCQualitySlow;
-         m_perceptual = true;
-         m_dithering = false;
-      }
-   };
-
-   struct etc1_solution_coordinates
-   {
-      inline etc1_solution_coordinates() :
-         m_unscaled_color(0, 0, 0, 0),
-         m_inten_table(0),
-         m_color4(false)
-      {
-      }
-
-      inline etc1_solution_coordinates(uint r, uint g, uint b, uint inten_table, bool color4) : 
-         m_unscaled_color(r, g, b, 255),
-         m_inten_table(inten_table),
-         m_color4(color4)
-      {
-      }
-
-      inline etc1_solution_coordinates(const color_quad_u8& c, uint inten_table, bool color4) : 
-         m_unscaled_color(c),
-         m_inten_table(inten_table),
-         m_color4(color4)
-      {
-      }
-
-      inline etc1_solution_coordinates(const etc1_solution_coordinates& other)
-      {
-         *this = other;
-      }
-
-      inline etc1_solution_coordinates& operator= (const etc1_solution_coordinates& rhs)
-      {
-         m_unscaled_color = rhs.m_unscaled_color;
-         m_inten_table = rhs.m_inten_table;
-         m_color4 = rhs.m_color4;
-         return *this;
-      }
-
-      inline void clear()
-      {
-         m_unscaled_color.clear();
-         m_inten_table = 0;
-         m_color4 = false;
-      }
-
-      inline color_quad_u8 get_scaled_color() const
-      {
-         int br, bg, bb;
-         if (m_color4)
-         {
-            br = m_unscaled_color.r | (m_unscaled_color.r << 4);
-            bg = m_unscaled_color.g | (m_unscaled_color.g << 4);
-            bb = m_unscaled_color.b | (m_unscaled_color.b << 4);
-         }
-         else
-         {
-            br = (m_unscaled_color.r >> 2) | (m_unscaled_color.r << 3);
-            bg = (m_unscaled_color.g >> 2) | (m_unscaled_color.g << 3);
-            bb = (m_unscaled_color.b >> 2) | (m_unscaled_color.b << 3);
-         }
-         return color_quad_u8(br, bg, bb);
-      }
-      
-      inline void get_block_colors(color_quad_u8* pBlock_colors)
-      {
-         int br, bg, bb;
-         if (m_color4)
-         {
-            br = m_unscaled_color.r | (m_unscaled_color.r << 4);
-            bg = m_unscaled_color.g | (m_unscaled_color.g << 4);
-            bb = m_unscaled_color.b | (m_unscaled_color.b << 4);
-         }
-         else
-         {
-            br = (m_unscaled_color.r >> 2) | (m_unscaled_color.r << 3);
-            bg = (m_unscaled_color.g >> 2) | (m_unscaled_color.g << 3);
-            bb = (m_unscaled_color.b >> 2) | (m_unscaled_color.b << 3);
-         }
-         const int* pInten_table = g_etc1_inten_tables[m_inten_table];
-         pBlock_colors[0].set(br + pInten_table[0], bg + pInten_table[0], bb + pInten_table[0]);
-         pBlock_colors[1].set(br + pInten_table[1], bg + pInten_table[1], bb + pInten_table[1]);
-         pBlock_colors[2].set(br + pInten_table[2], bg + pInten_table[2], bb + pInten_table[2]);
-         pBlock_colors[3].set(br + pInten_table[3], bg + pInten_table[3], bb + pInten_table[3]);
-      }
-
-      color_quad_u8 m_unscaled_color;
-      uint m_inten_table;
-      bool m_color4;
-   };
-  
-   class etc1_optimizer
-   {
-      CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(etc1_optimizer);
-   
-   public:
-      etc1_optimizer()
-      {
-         clear();
-      }
-      
-      void clear()
-      {
-         m_pParams = NULL;
-         m_pResult = NULL;
-         m_pSorted_luma = NULL;
-         m_pSorted_luma_indices = NULL;
-      }
-
-      struct params : crn_etc1_pack_params
-      {
-         params()
-         {
-            clear();
-         }
-
-         params(const crn_etc1_pack_params& base_params) : 
-           crn_etc1_pack_params(base_params)
-         {
-            clear_optimizer_params();
-         }
-
-         void clear()
-         {
-            crn_etc1_pack_params::clear();
-            clear_optimizer_params();
-         }
-
-         void clear_optimizer_params()
-         {
-            m_num_src_pixels = 0;
-            m_pSrc_pixels = 0;
-
-            m_use_color4 = false;
-            static const int s_default_scan_delta[] = { 0 };
-            m_pScan_deltas = s_default_scan_delta;
-            m_scan_delta_size = 1;
-
-            m_base_color5.clear();
-            m_constrain_against_base_color5 = false;
-         }
-                  
-         uint m_num_src_pixels;
-         const color_quad_u8* m_pSrc_pixels;
-
-         bool m_use_color4;
-         const int* m_pScan_deltas;
-         uint m_scan_delta_size;
-                           
-         color_quad_u8 m_base_color5;
-         bool m_constrain_against_base_color5;
-      };
-
-      struct results
-      {
-         uint64 m_error;
-         color_quad_u8 m_block_color_unscaled;
-         uint m_block_inten_table;
-         uint m_n;
-         uint8* m_pSelectors;
-         bool m_block_color4;
-
-         inline results& operator= (const results& rhs)
-         {
-            m_block_color_unscaled = rhs.m_block_color_unscaled;
-            m_block_color4 = rhs.m_block_color4;
-            m_block_inten_table = rhs.m_block_inten_table;
-            m_error = rhs.m_error;
-            CRNLIB_ASSERT(m_n == rhs.m_n);
-            memcpy(m_pSelectors, rhs.m_pSelectors, rhs.m_n);
-            return *this;
-         }
-      };
-
-      void init(const params& params, results& result);
-      bool compute();
-            
-   private:      
-      struct potential_solution
-      {
-         potential_solution() : m_coords(), m_error(cUINT64_MAX), m_valid(false)
-         {
-         }
-
-         etc1_solution_coordinates  m_coords;
-         crnlib::vector<uint8>      m_selectors;
-         uint64                     m_error;
-         bool                       m_valid;
-
-         void clear()
-         {
-            m_coords.clear();
-            m_selectors.resize(0);
-            m_error = cUINT64_MAX;
-            m_valid = false;
-         }
-
-         bool are_selectors_all_equal() const
-         {
-            if (m_selectors.empty())
-               return false;
-            const uint s = m_selectors[0];
-            for (uint i = 1; i < m_selectors.size(); i++)
-               if (m_selectors[i] != s)
-                  return false;
-            return true;
-         }
-      };
-
-      const params* m_pParams;
-      results* m_pResult;
-
-      int m_limit;
-
-      vec3F m_avg_color;
-      int m_br, m_bg, m_bb;
-      crnlib::vector<uint16> m_luma;
-      crnlib::vector<uint32> m_sorted_luma[2];
-      const uint32* m_pSorted_luma_indices;
-      uint32* m_pSorted_luma;
-
-      crnlib::vector<uint8> m_selectors;
-      crnlib::vector<uint8> m_best_selectors;
-
-      potential_solution m_best_solution;
-      potential_solution m_trial_solution;
-      crnlib::vector<uint8> m_temp_selectors;
-      
-      bool evaluate_solution(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution);
-      bool evaluate_solution_fast(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution);
-   };
-
-   struct pack_etc1_block_context
-   {
-      etc1_optimizer m_optimizer;
-   };
-   
-   void pack_etc1_block_init();
-
-   uint64 pack_etc1_block(etc1_block& block, const color_quad_u8* pSrc_pixels, crn_etc1_pack_params& pack_params, pack_etc1_block_context& context);
-         
-} // namespace crnlib

+ 0 - 578
Source/ThirdParty/crunch/crnlib/crn_file_utils.cpp

@@ -1,578 +0,0 @@
-// File: crn_file_utils.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_file_utils.h"
-#include "crn_strutils.h"
-
-#if CRNLIB_USE_WIN32_API
-#include "crn_winhdr.h"
-#endif
-
-#ifdef WIN32
-#include <direct.h>
-#endif
-
-#ifdef __GNUC__
-#include <sys/stat.h>
-#include <sys/stat.h>
-#include <libgen.h>
-#endif
-
-namespace crnlib
-{
-#if CRNLIB_USE_WIN32_API
-   bool file_utils::is_read_only(const char* pFilename)
-   {
-      uint32 dst_file_attribs = GetFileAttributesA(pFilename);
-      if (dst_file_attribs == INVALID_FILE_ATTRIBUTES)
-         return false;
-      if (dst_file_attribs & FILE_ATTRIBUTE_READONLY)
-         return true;
-      return false;
-   }
-
-   bool file_utils::disable_read_only(const char* pFilename)
-   {
-      uint32 dst_file_attribs = GetFileAttributesA(pFilename);
-      if (dst_file_attribs == INVALID_FILE_ATTRIBUTES)
-         return false;
-      if (dst_file_attribs & FILE_ATTRIBUTE_READONLY)
-      {
-         dst_file_attribs &= ~FILE_ATTRIBUTE_READONLY;
-         if (SetFileAttributesA(pFilename, dst_file_attribs))
-            return true;
-      }
-      return false;
-   }
-
-   bool file_utils::is_older_than(const char* pSrcFilename, const char* pDstFilename)
-   {
-      WIN32_FILE_ATTRIBUTE_DATA src_file_attribs;
-      const BOOL src_file_exists = GetFileAttributesExA(pSrcFilename, GetFileExInfoStandard, &src_file_attribs);
-
-      WIN32_FILE_ATTRIBUTE_DATA dst_file_attribs;
-      const BOOL dest_file_exists = GetFileAttributesExA(pDstFilename, GetFileExInfoStandard, &dst_file_attribs);
-
-      if ((dest_file_exists) && (src_file_exists))
-      {
-         LONG timeComp = CompareFileTime(&src_file_attribs.ftLastWriteTime, &dst_file_attribs.ftLastWriteTime);
-         if (timeComp < 0)
-            return true;
-      }
-      return false;
-   }
-
-   bool file_utils::does_file_exist(const char* pFilename)
-   {
-      const DWORD fullAttributes = GetFileAttributesA(pFilename);
-
-      if (fullAttributes == INVALID_FILE_ATTRIBUTES)
-         return false;
-
-      if (fullAttributes & FILE_ATTRIBUTE_DIRECTORY)
-         return false;
-
-      return true;
-   }
-
-   bool file_utils::does_dir_exist(const char* pDir)
-   {
-      //-- Get the file attributes.
-      DWORD fullAttributes = GetFileAttributesA(pDir);
-
-      if (fullAttributes == INVALID_FILE_ATTRIBUTES)
-         return false;
-
-      if (fullAttributes & FILE_ATTRIBUTE_DIRECTORY)
-         return true;
-
-      return false;
-   }
-
-   bool file_utils::get_file_size(const char* pFilename, uint64& file_size)
-   {
-      file_size = 0;
-
-      WIN32_FILE_ATTRIBUTE_DATA attr;
-
-      if (0 == GetFileAttributesExA(pFilename, GetFileExInfoStandard, &attr))
-         return false;
-
-      if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-         return false;
-
-      file_size = static_cast<uint64>(attr.nFileSizeLow) | (static_cast<uint64>(attr.nFileSizeHigh) << 32U);
-
-      return true;
-   }
-#elif defined( __GNUC__ )
-   bool file_utils::is_read_only(const char* pFilename)
-   {
-      pFilename;
-      // TODO
-      return false;
-   }
-
-   bool file_utils::disable_read_only(const char* pFilename)
-   {
-      pFilename;
-      // TODO
-      return false;
-   }
-
-   bool file_utils::is_older_than(const char *pSrcFilename, const char* pDstFilename)
-   {
-      pSrcFilename, pDstFilename;
-      // TODO
-      return false;
-   }
-
-   bool file_utils::does_file_exist(const char* pFilename)
-   {
-      struct stat stat_buf;
-      int result = stat(pFilename, &stat_buf);
-      if (result)
-         return false;
-      if (S_ISREG(stat_buf.st_mode))
-         return true;
-      return false;
-   }
-
-   bool file_utils::does_dir_exist(const char* pDir)
-   {
-      struct stat stat_buf;
-      int result = stat(pDir, &stat_buf);
-      if (result)
-         return false;
-      if (S_ISDIR(stat_buf.st_mode) || S_ISLNK(stat_buf.st_mode))
-         return true;
-      return false;
-   }
-
-   bool file_utils::get_file_size(const char* pFilename, uint64& file_size)
-   {
-      file_size = 0;
-      struct stat stat_buf;
-      int result = stat(pFilename, &stat_buf);
-      if (result)
-         return false;
-      if (!S_ISREG(stat_buf.st_mode))
-         return false;
-      file_size = stat_buf.st_size;
-      return true;
-   }
-#else
-   bool file_utils::is_read_only(const char* pFilename)
-   {
-      return false;
-   }
-
-   bool file_utils::disable_read_only(const char* pFilename)
-   {
-      pFilename;
-      // TODO
-      return false;
-   }
-
-   bool file_utils::is_older_than(const char *pSrcFilename, const char* pDstFilename)
-   {
-      return false;
-   }
-
-   bool file_utils::does_file_exist(const char* pFilename)
-   {
-      FILE* pFile;
-      crn_fopen(&pFile, pFilename, "rb");
-      if (!pFile)
-         return false;
-      fclose(pFile);
-      return true;
-   }
-
-   bool file_utils::does_dir_exist(const char* pDir)
-   {
-      return false;
-   }
-
-   bool file_utils::get_file_size(const char* pFilename, uint64& file_size)
-   {
-      FILE* pFile;
-      crn_fopen(&pFile, pFilename, "rb");
-      if (!pFile)
-         return false;
-      crn_fseek(pFile, 0, SEEK_END);
-      file_size = crn_ftell(pFile);
-      fclose(pFile);
-      return true;
-   }
-#endif
-
-   bool file_utils::get_file_size(const char* pFilename, uint32& file_size)
-   {
-      uint64 file_size64;
-      if (!get_file_size(pFilename, file_size64))
-      {
-         file_size = 0;
-         return false;
-      }
-
-      if (file_size64 > cUINT32_MAX)
-         file_size64 = cUINT32_MAX;
-
-      file_size = static_cast<uint32>(file_size64);
-      return true;
-   }
-
-   bool file_utils::is_path_separator(char c)
-   {
-#ifdef WIN32
-      return (c == '/') || (c == '\\');
-#else
-      return (c == '/');
-#endif
-   }
-
-   bool file_utils::is_path_or_drive_separator(char c)
-   {
-#ifdef WIN32
-      return (c == '/') || (c == '\\') || (c == ':');
-#else
-      return (c == '/');
-#endif
-   }
-
-   bool file_utils::is_drive_separator(char c)
-   {
-#ifdef WIN32
-      return (c == ':');
-#else
-      c;
-      return false;
-#endif
-   }
-
-   bool file_utils::split_path(const char* p, dynamic_string* pDrive, dynamic_string* pDir, dynamic_string* pFilename, dynamic_string* pExt)
-   {
-      CRNLIB_ASSERT(p);
-
-#ifdef WIN32
-      char drive_buf[_MAX_DRIVE];
-      char dir_buf[_MAX_DIR];
-      char fname_buf[_MAX_FNAME];
-      char ext_buf[_MAX_EXT];
-
-#ifdef _MSC_VER
-      // Compiling with MSVC
-      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
-      // Compiling with MinGW
-      _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;
-#else
-      char dirtmp[1024];
-      char nametmp[1024];
-      strcpy_safe(dirtmp, sizeof(dirtmp), p);
-      strcpy_safe(nametmp, sizeof(nametmp), p);
-
-      if (pDrive) pDrive->clear();
-
-      const char *pDirName = dirname(dirtmp);
-      if (!pDirName)
-         return false;
-
-      if (pDir)
-      {
-         pDir->set(pDirName);
-         if ((!pDir->is_empty()) && (pDir->back() != '/'))
-            pDir->append_char('/');
-      }
-
-      const char *pBaseName = basename(nametmp);
-      if (!pBaseName)
-         return false;
-
-      if (pFilename)
-      {
-         pFilename->set(pBaseName);
-         remove_extension(*pFilename);
-      }
-
-      if (pExt)
-      {
-         pExt->set(pBaseName);
-         get_extension(*pExt);
-         *pExt = "." + *pExt;
-      }
-#endif // #ifdef WIN32
-
-      return true;
-   }
-
-   bool file_utils::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 file_utils::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 file_utils::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;
-   }
-
-   void file_utils::combine_path(dynamic_string& dst, const char* pA, const char* pB)
-   {
-      dynamic_string temp(pA);
-      if ((!temp.is_empty()) && (!is_path_separator(pB[0])))
-      {
-         char c = temp[temp.get_len() - 1];
-         if (!is_path_separator(c))
-            temp.append_char(CRNLIB_PATH_SEPERATOR_CHAR);
-      }
-      temp += pB;
-      dst.swap(temp);
-   }
-
-   void file_utils::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);
-   }
-
-   bool file_utils::full_path(dynamic_string& path)
-   {
-#ifdef WIN32
-      char buf[1024];
-      char* p = _fullpath(buf, path.get_ptr(), sizeof(buf));
-      if (!p)
-         return false;
-#else
-      char buf[PATH_MAX];
-      char* p;
-      dynamic_string pn, fn;
-      split_path(path.get_ptr(), pn, fn);
-      if ((fn == ".") || (fn == ".."))
-      {
-         p = realpath(path.get_ptr(), buf);
-         if (!p)
-            return false;
-         path.set(buf);
-      }
-      else
-      {
-         if (pn.is_empty())
-            pn = "./";
-         p = realpath(pn.get_ptr(), buf);
-         if (!p)
-            return false;
-         combine_path(path, buf, fn.get_ptr());
-      }
-#endif
-
-      return true;
-   }
-
-   bool file_utils::get_extension(dynamic_string& filename)
-   {
-      int sep = -1;
-#ifdef WIN32
-      sep = filename.find_right('\\');
-#endif
-      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 file_utils::remove_extension(dynamic_string& filename)
-   {
-      int sep = -1;
-#ifdef WIN32
-      sep = filename.find_right('\\');
-#endif
-      if (sep < 0)
-         sep = filename.find_right('/');
-
-      int dot = filename.find_right('.');
-      if (dot < sep)
-         return false;
-
-      filename.left(dot);
-
-      return true;
-   }
-
-   bool file_utils::create_path(const dynamic_string& fullpath)
-   {
-      bool got_unc = false; got_unc;
-      dynamic_string cur_path;
-
-      const int l = fullpath.get_len();
-
-      int n = 0;
-      while (n < l)
-      {
-         const char c = fullpath.get_ptr()[n];
-
-         const bool sep = is_path_separator(c);
-         const bool back_sep = is_path_separator(cur_path.back());
-         const bool is_last_char = (n == (l - 1));
-
-         if ( ((sep) && (!back_sep)) || (is_last_char) )
-         {
-            if ((is_last_char) && (!sep))
-               cur_path.append_char(c);
-
-            bool valid = !cur_path.is_empty();
-
-#ifdef WIN32
-            // reject obvious stuff (drives, beginning of UNC paths):
-            // c:\b\cool
-            // \\machine\blah
-            // \cool\blah
-            if ((cur_path.get_len() == 2) && (cur_path[1] == ':'))
-               valid = false;
-            else if ((cur_path.get_len() >= 2) && (cur_path[0] == '\\') && (cur_path[1] == '\\'))
-            {
-               if (!got_unc)
-                  valid = false;
-               got_unc = true;
-            }
-            else if (cur_path == "\\")
-               valid = false;
-#endif
-            if (cur_path == "/")
-               valid = false;
-
-            if ((valid) && (cur_path.get_len()))
-            {
-#ifdef WIN32
-               _mkdir(cur_path.get_ptr());
-#else
-               mkdir(cur_path.get_ptr(), S_IRWXU | S_IRWXG | S_IRWXO );
-#endif
-            }
-         }
-
-         cur_path.append_char(c);
-
-         n++;
-      }
-
-      return true;
-   }
-
-   void file_utils::trim_trailing_seperator(dynamic_string& path)
-   {
-      if ((path.get_len()) && (is_path_separator(path.back())))
-         path.truncate(path.get_len() - 1);
-   }
-
-   // See http://www.codeproject.com/KB/string/wildcmp.aspx
-   int file_utils::wildcmp(const char* pWild, const char* pString)
-   {
-      const char* cp = NULL, *mp = NULL;
-
-      while ((*pString) && (*pWild != '*'))
-      {
-         if ((*pWild != *pString) && (*pWild != '?'))
-            return 0;
-         pWild++;
-         pString++;
-      }
-
-      // Either *pString=='\0' or *pWild='*' here.
-
-      while (*pString)
-      {
-         if (*pWild == '*')
-         {
-            if (!*++pWild)
-               return 1;
-            mp = pWild;
-            cp = pString+1;
-         }
-         else if ((*pWild == *pString) || (*pWild == '?'))
-         {
-            pWild++;
-            pString++;
-         }
-         else
-         {
-            pWild = mp;
-            pString = cp++;
-         }
-      }
-
-      while (*pWild == '*')
-         pWild++;
-
-      return !*pWild;
-   }
-
-   bool file_utils::write_buf_to_file(const char* pPath, const void* pData, size_t data_size)
-   {
-      FILE *pFile = NULL;
-
-#ifdef _MSC_VER
-      // Compiling with MSVC
-      if (fopen_s(&pFile, pPath, "wb"))
-         return false;
-#else
-      pFile = fopen(pPath, "wb");
-#endif
-      if (!pFile)
-         return false;
-
-      bool success = fwrite(pData, 1, data_size, pFile) == data_size;
-
-      fclose(pFile);
-
-      return success;
-   }
-
-} // namespace crnlib

+ 0 - 43
Source/ThirdParty/crunch/crnlib/crn_file_utils.h

@@ -1,43 +0,0 @@
-// File: crn_file_utils.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   struct file_utils
-   {
-      // Returns true if pSrcFilename is older than pDstFilename
-      static bool is_read_only(const char* pFilename);
-      static bool disable_read_only(const char* pFilename);
-      static bool is_older_than(const char *pSrcFilename, const char* pDstFilename);
-      static bool does_file_exist(const char* pFilename);
-      static bool does_dir_exist(const char* pDir);
-      static bool get_file_size(const char* pFilename, uint64& file_size);
-      static bool get_file_size(const char* pFilename, uint32& file_size);
-
-      static bool is_path_separator(char c);
-      static bool is_path_or_drive_separator(char c);
-      static bool is_drive_separator(char c);
-
-      static bool split_path(const char* p, dynamic_string* pDrive, dynamic_string* pDir, dynamic_string* pFilename, dynamic_string* pExt);
-      static bool split_path(const char* p, dynamic_string& path, dynamic_string& filename);
-
-      static bool get_pathname(const char* p, dynamic_string& path);
-      static bool get_filename(const char* p, dynamic_string& filename);
-
-      static void combine_path(dynamic_string& dst, const char* pA, const char* pB);
-      static void combine_path(dynamic_string& dst, const char* pA, const char* pB, const char* pC);
-
-      static bool full_path(dynamic_string& path);
-      static bool get_extension(dynamic_string& filename);
-      static bool remove_extension(dynamic_string& filename);
-      static bool create_path(const dynamic_string& path);
-      static void trim_trailing_seperator(dynamic_string& path);
-
-      static int wildcmp(const char* pWild, const char* pString);
-
-      static bool write_buf_to_file(const char* pPath, const void* pData, size_t data_size);
-
-   }; // struct file_utils
-
-} // namespace crnlib

+ 0 - 287
Source/ThirdParty/crunch/crnlib/crn_find_files.cpp

@@ -1,287 +0,0 @@
-// File: crn_win32_find_files.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_find_files.h"
-#include "crn_file_utils.h"
-#include "crn_strutils.h"
-
-#ifdef CRNLIB_USE_WIN32_API
-#include "crn_winhdr.h"
-
-#elif defined(__GNUC__)
-#include <fnmatch.h>
-#include <dirent.h>
-#endif
-
-namespace crnlib
-{
-#ifdef CRNLIB_USE_WIN32_API
-   bool find_files::find(const char* pBasepath, const char* pFilespec, uint flags)
-   {
-      m_last_error = S_OK;
-      m_files.resize(0);
-
-      return find_internal(pBasepath, "", pFilespec, flags, 0);
-   }
-
-   bool find_files::find(const char* pSpec, uint flags)
-   {
-      dynamic_string find_name(pSpec);
-
-      if (!file_utils::full_path(find_name))
-         return false;
-
-      dynamic_string find_pathname, find_filename;
-      if (!file_utils::split_path(find_name.get_ptr(), find_pathname, find_filename))
-         return false;
-
-      return find(find_pathname.get_ptr(), find_filename.get_ptr(), flags);
-   }
-
-   bool find_files::find_internal(const char* pBasepath, const char* pRelpath, const char* pFilespec, uint flags, int level)
-   {
-      WIN32_FIND_DATAA find_data;
-
-      dynamic_string filename;
-
-      dynamic_string_array child_paths;
-      if (flags & cFlagRecursive)
-      {
-         if (strlen(pRelpath))
-            file_utils::combine_path(filename, pBasepath, pRelpath, "*");
-         else
-            file_utils::combine_path(filename, pBasepath, "*");
-
-         HANDLE handle = FindFirstFileA(filename.get_ptr(), &find_data);
-         if (handle == INVALID_HANDLE_VALUE)
-         {
-            HRESULT hres = GetLastError();
-            if ((level == 0) && (hres != NO_ERROR) && (hres != ERROR_FILE_NOT_FOUND))
-            {
-               m_last_error = hres;
-               return false;
-            }
-         }
-         else
-         {
-            do
-            {
-               const bool is_dir = (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
-
-               bool skip = !is_dir;
-               if (is_dir)
-                  skip = (strcmp(find_data.cFileName, ".") == 0) || (strcmp(find_data.cFileName, "..") == 0);
-
-               if (find_data.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_TEMPORARY))
-                  skip = true;
-
-               if (find_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
-               {
-                  if ((flags & cFlagAllowHidden) == 0)
-                     skip = true;
-               }
-
-               if (!skip)
-               {
-                  dynamic_string child_path(find_data.cFileName);
-                  if ((!child_path.count_char('?')) && (!child_path.count_char('*')))
-                     child_paths.push_back(child_path);
-               }
-
-            } while (FindNextFileA(handle, &find_data) != 0);
-
-            HRESULT hres = GetLastError();
-
-            FindClose(handle);
-            handle = INVALID_HANDLE_VALUE;
-
-            if (hres != ERROR_NO_MORE_FILES)
-            {
-               m_last_error = hres;
-               return false;
-            }
-         }
-      }
-
-      if (strlen(pRelpath))
-         file_utils::combine_path(filename, pBasepath, pRelpath, pFilespec);
-      else
-         file_utils::combine_path(filename, pBasepath, pFilespec);
-
-      HANDLE handle = FindFirstFileA(filename.get_ptr(), &find_data);
-      if (handle == INVALID_HANDLE_VALUE)
-      {
-         HRESULT hres = GetLastError();
-         if ((level == 0) && (hres != NO_ERROR) && (hres != ERROR_FILE_NOT_FOUND))
-         {
-            m_last_error = hres;
-            return false;
-         }
-      }
-      else
-      {
-         do
-         {
-            const bool is_dir = (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
-
-            bool skip = false;
-            if (is_dir)
-               skip = (strcmp(find_data.cFileName, ".") == 0) || (strcmp(find_data.cFileName, "..") == 0);
-
-            if (find_data.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_TEMPORARY))
-               skip = true;
-
-            if (find_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
-            {
-               if ((flags & cFlagAllowHidden) == 0)
-                  skip = true;
-            }
-
-            if (!skip)
-            {
-               if (((is_dir) && (flags & cFlagAllowDirs)) || ((!is_dir) && (flags & cFlagAllowFiles)))
-               {
-                  m_files.resize(m_files.size() + 1);
-                  file_desc& file = m_files.back();
-                  file.m_is_dir = is_dir;
-                  file.m_base = pBasepath;
-                  file.m_name = find_data.cFileName;
-                  file.m_rel = pRelpath;
-                  if (strlen(pRelpath))
-                     file_utils::combine_path(file.m_fullname, pBasepath, pRelpath, find_data.cFileName);
-                  else
-                     file_utils::combine_path(file.m_fullname, pBasepath, find_data.cFileName);
-               }
-            }
-
-         } while (FindNextFileA(handle, &find_data) != 0);
-
-         HRESULT hres = GetLastError();
-
-         FindClose(handle);
-
-         if (hres != ERROR_NO_MORE_FILES)
-         {
-            m_last_error = hres;
-            return false;
-         }
-      }
-
-      for (uint i = 0; i < child_paths.size(); i++)
-      {
-         dynamic_string child_path;
-         if (strlen(pRelpath))
-            file_utils::combine_path(child_path, pRelpath, child_paths[i].get_ptr());
-         else
-            child_path = child_paths[i];
-
-         if (!find_internal(pBasepath, child_path.get_ptr(), pFilespec, flags, level + 1))
-            return false;
-      }
-
-      return true;
-   }
-#elif defined(__GNUC__)
-   bool find_files::find(const char* pBasepath, const char* pFilespec, uint flags)
-   {
-      m_files.resize(0);
-      return find_internal(pBasepath, "", pFilespec, flags, 0);
-   }
-
-   bool find_files::find(const char* pSpec, uint flags)
-   {
-      dynamic_string find_name(pSpec);
-
-      if (!file_utils::full_path(find_name))
-         return false;
-
-      dynamic_string find_pathname, find_filename;
-      if (!file_utils::split_path(find_name.get_ptr(), find_pathname, find_filename))
-         return false;
-
-      return find(find_pathname.get_ptr(), find_filename.get_ptr(), flags);
-   }
-
-   bool find_files::find_internal(const char* pBasepath, const char* pRelpath, const char* pFilespec, uint flags, int level)
-   {
-      dynamic_string pathname;
-      if (strlen(pRelpath))
-         file_utils::combine_path(pathname, pBasepath, pRelpath);
-      else
-         pathname = pBasepath;
-
-      if (!pathname.is_empty())
-      {
-         char c = pathname.back();
-         if (c != '/')
-            pathname += "/";
-      }
-
-      DIR *dp = opendir(pathname.get_ptr());
-
-      if (!dp)
-         return level ? true : false;
-
-      dynamic_string_array paths;
-
-      for ( ; ; )
-      {
-         struct dirent *ep = readdir(dp);
-         if (!ep)
-            break;
-         if ((strcmp(ep->d_name, ".") == 0) || (strcmp(ep->d_name, "..") == 0))
-            continue;
-
-         const bool is_directory = (ep->d_type & DT_DIR) != 0;
-         const bool is_file =  (ep->d_type & DT_REG) != 0;
-
-         dynamic_string filename(ep->d_name);
-
-         if (is_directory)
-         {
-            if (flags & cFlagRecursive)
-            {
-               paths.push_back(filename);
-            }
-         }
-
-         if (((is_file) && (flags & cFlagAllowFiles)) || ((is_directory) && (flags & cFlagAllowDirs)))
-         {
-            if (0 == fnmatch(pFilespec, filename.get_ptr(), 0))
-            {
-               m_files.resize(m_files.size() + 1);
-               file_desc& file = m_files.back();
-               file.m_is_dir = is_directory;
-               file.m_base = pBasepath;
-               file.m_rel = pRelpath;
-               file.m_name = filename;
-               file.m_fullname = pathname + filename;
-            }
-         }
-      }
-
-      closedir(dp);
-      dp = NULL;
-
-      if (flags & cFlagRecursive)
-      {
-         for (uint i = 0; i < paths.size(); i++)
-         {
-            dynamic_string childpath;
-            if (strlen(pRelpath))
-               file_utils::combine_path(childpath, pRelpath, paths[i].get_ptr());
-            else
-               childpath = paths[i];
-
-            if (!find_internal(pBasepath, childpath.get_ptr(), pFilespec, flags, level + 1))
-               return false;
-         }
-      }
-
-      return true;
-   }
-#else
-   #error Unimplemented
-#endif
-
-} // namespace crnlib

+ 0 - 60
Source/ThirdParty/crunch/crnlib/crn_find_files.h

@@ -1,60 +0,0 @@
-// File: crn_win32_find_files.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   class find_files
-   {
-   public:
-      struct file_desc
-      {
-         inline file_desc() : m_is_dir(false) { }
-
-         dynamic_string  m_fullname;
-         dynamic_string  m_base;
-         dynamic_string  m_rel;
-         dynamic_string  m_name;
-         bool            m_is_dir;
-
-         inline bool operator== (const file_desc& other) const { return m_fullname == other.m_fullname; }
-         inline bool operator< (const file_desc& other) const { return m_fullname < other.m_fullname; }
-
-         inline operator size_t() const { return static_cast<size_t>(m_fullname); }
-      };
-
-      typedef crnlib::vector<file_desc> file_desc_vec;
-
-      inline find_files()
-      {
-         m_last_error = 0; // S_OK;
-      }
-
-      enum flags
-      {
-         cFlagRecursive = 1,
-         cFlagAllowDirs = 2,
-         cFlagAllowFiles = 4,
-         cFlagAllowHidden = 8
-      };
-
-      bool find(const char* pBasepath, const char* pFilespec, uint flags = cFlagAllowFiles);
-
-      bool find(const char* pSpec, uint flags = cFlagAllowFiles);
-
-      // An HRESULT under Win32. FIXME: Abstract this better?
-      inline int64 get_last_error() const { return m_last_error; }
-
-      const file_desc_vec& get_files() const { return m_files; }
-
-   private:
-      file_desc_vec m_files;
-
-      // A HRESULT under Win32
-      int64 m_last_error;
-
-      bool find_internal(const char* pBasepath, const char* pRelpath, const char* pFilespec, uint flags, int level);
-
-   }; // class find_files
-
-} // namespace crnlib

+ 0 - 158
Source/ThirdParty/crunch/crnlib/crn_freeimage_image_utils.h

@@ -1,158 +0,0 @@
-// File: crn_freeimage_image_utils.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-// Note: This header file requires FreeImage/FreeImagePlus.
-
-#include "crn_image_utils.h"
-
-#include "freeImagePlus.h"
-
-namespace crnlib
-{
-   namespace freeimage_image_utils
-   {
-      inline bool load_from_file(image_u8& dest, const wchar_t* pFilename, int fi_flag)
-      {
-         fipImage src_image;
-
-         if (!src_image.loadU(pFilename, fi_flag))
-            return false;
-         
-         const uint orig_bits_per_pixel = src_image.getBitsPerPixel();
-
-         const FREE_IMAGE_COLOR_TYPE orig_color_type = src_image.getColorType();
-         
-         if (!src_image.convertTo32Bits())
-            return false;
-
-         if (src_image.getBitsPerPixel() != 32)
-            return false;
-
-         uint width = src_image.getWidth();
-         uint height = src_image.getHeight();
-
-         dest.resize(src_image.getWidth(), src_image.getHeight(), src_image.getWidth());
-
-         color_quad_u8* pDst = dest.get_ptr();
-
-         bool grayscale = true;
-         bool has_alpha = false;
-         for (uint y = 0; y < height; y++)
-         {
-            const BYTE* pSrc = src_image.getScanLine((WORD)(height - 1 - y));
-            color_quad_u8* pD = pDst;
-
-            for (uint x = width; x; x--)
-            {
-               color_quad_u8 c;
-               c.r = pSrc[FI_RGBA_RED];
-               c.g = pSrc[FI_RGBA_GREEN];
-               c.b = pSrc[FI_RGBA_BLUE];
-               c.a = pSrc[FI_RGBA_ALPHA];
-               
-               if (!c.is_grayscale())
-                  grayscale = false;
-               has_alpha |= (c.a < 255);
-
-               pSrc += 4;
-               *pD++ = c;
-            }
-
-            pDst += width;
-         }
-
-         dest.reset_comp_flags();
-         
-         if (grayscale)
-            dest.set_grayscale(true);
-         
-         dest.set_component_valid(3, has_alpha || (orig_color_type == FIC_RGBALPHA) || (orig_bits_per_pixel == 32));
-
-         return true;
-      }
-            
-      const int cSaveLuma = -1;
-      
-      inline bool save_to_grayscale_file(const wchar_t* pFilename, const image_u8& src, int component, int fi_flag)
-      {
-         fipImage dst_image(FIT_BITMAP, (WORD)src.get_width(), (WORD)src.get_height(), 8);
-
-         RGBQUAD* p = dst_image.getPalette();
-         for (uint i = 0; i < dst_image.getPaletteSize(); i++)
-         {
-            p[i].rgbRed = (BYTE)i;
-            p[i].rgbGreen = (BYTE)i;
-            p[i].rgbBlue = (BYTE)i;
-            p[i].rgbReserved = 255;
-         }
-
-         for (uint y = 0; y < src.get_height(); y++)
-         {
-            const color_quad_u8* pSrc = src.get_scanline(y);
-
-            for (uint x = 0; x < src.get_width(); x++)
-            {
-               BYTE v;
-               if (component == cSaveLuma)
-                  v = (BYTE)(*pSrc).get_luma();
-               else
-                  v = (*pSrc)[component];
-               dst_image.setPixelIndex(x, src.get_height() - 1 - y, &v);
-
-               pSrc++;
-            } 
-         }
-
-         if (!dst_image.saveU(pFilename, fi_flag))
-            return false; 
-
-         return true;
-      }
-
-      inline bool save_to_file(const wchar_t* pFilename, const image_u8& src, int fi_flag, bool ignore_alpha = false)
-      {
-         const bool save_alpha = src.is_component_valid(3);
-         uint bpp = (save_alpha && !ignore_alpha) ? 32 : 24;
-         
-         if (bpp == 32)
-         {
-            dynamic_wstring ext(pFilename);
-            get_extension(ext);
-
-            if ((ext == L"jpg") || (ext == L"jpeg") || (ext == L"gif") || (ext == L"jp2"))
-               bpp = 24;
-         }
-         
-         if ((bpp == 24) && (src.is_grayscale()))
-            return save_to_grayscale_file(pFilename, src, cSaveLuma, fi_flag);
-                  
-         fipImage dst_image(FIT_BITMAP, (WORD)src.get_width(), (WORD)src.get_height(), (WORD)bpp);
-
-         for (uint y = 0; y < src.get_height(); y++)
-         {
-            for (uint x = 0; x < src.get_width(); x++)
-            {
-               color_quad_u8 c(src(x, y));
-
-               RGBQUAD quad;
-               quad.rgbRed = c.r;
-               quad.rgbGreen = c.g;
-               quad.rgbBlue = c.b;
-               if (bpp == 32)
-                  quad.rgbReserved = c.a;
-               else
-                  quad.rgbReserved = 255;
-
-               dst_image.setPixelColor(x, src.get_height() - 1 - y, &quad);
-            } 
-         }
-
-         if (!dst_image.saveU(pFilename, fi_flag))
-            return false; 
-
-         return true;
-      }
-   
-   } // namespace freeimage_image_utils
-   
-} // namespace crnlib
-

+ 0 - 68
Source/ThirdParty/crunch/crnlib/crn_hash.cpp

@@ -1,68 +0,0 @@
-// File: crn_hash.cpp
-// See Paul Hsieh's page at: http://www.azillionmonkeys.com/qed/hash.html
-// Also see http://www.concentric.net/~Ttwang/tech/inthash.htm,
-// http://burtleburtle.net/bob/hash/integer.html
-#include "crn_core.h"
-
-#undef get16bits
-#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
-   || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
-#define get16bits(d) (*((const uint16 *) (d)))
-#endif
-
-#if !defined (get16bits)
-#define get16bits(d) ((((uint32)(((const uint8 *)(d))[1])) << 8)\
-   +(uint32)(((const uint8 *)(d))[0]) )
-#endif
-
-namespace crnlib
-{
-   uint32 fast_hash (const void* p, int len) 
-   {
-      const char * data = static_cast<const char *>(p);
-      
-      uint32 hash = len, tmp;
-      int rem;
-
-      if (len <= 0 || data == NULL) return 0;
-
-      rem = len & 3;
-      len >>= 2;
-
-      /* Main loop */
-      for (;len > 0; len--) {
-         hash  += get16bits (data);
-         tmp    = (get16bits (data+2) << 11) ^ hash;
-         hash   = (hash << 16) ^ tmp;
-         data  += 2*sizeof (uint16);
-         hash  += hash >> 11;
-      }
-
-      /* Handle end cases */
-      switch (rem) {
-           case 3: hash += get16bits (data);
-              hash ^= hash << 16;
-              hash ^= data[sizeof (uint16)] << 18;
-              hash += hash >> 11;
-              break;
-           case 2: hash += get16bits (data);
-              hash ^= hash << 11;
-              hash += hash >> 17;
-              break;
-           case 1: hash += *data;
-              hash ^= hash << 10;
-              hash += hash >> 1;
-      }
-
-      /* Force "avalanching" of final 127 bits */
-      hash ^= hash << 3;
-      hash += hash >> 5;
-      hash ^= hash << 4;
-      hash += hash >> 17;
-      hash ^= hash << 25;
-      hash += hash >> 6;
-
-      return hash;
-   }
-
-}  // namespace crnlib

+ 0 - 34
Source/ThirdParty/crunch/crnlib/crn_hash.h

@@ -1,34 +0,0 @@
-// File: crn_hash.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   uint32 fast_hash (const void* p, int len);
-   
-   // 4-byte integer hash, full avalanche
-   inline uint32 bitmix32c(uint32 a)
-   {
-      a = (a+0x7ed55d16) + (a<<12);
-      a = (a^0xc761c23c) ^ (a>>19);
-      a = (a+0x165667b1) + (a<<5);
-      a = (a+0xd3a2646c) ^ (a<<9);
-      a = (a+0xfd7046c5) + (a<<3);
-      a = (a^0xb55a4f09) ^ (a>>16);
-      return a;
-   }
-   
-   // 4-byte integer hash, full avalanche, no constants
-   inline uint32 bitmix32(uint32 a)
-   {
-      a -= (a<<6);
-      a ^= (a>>17);
-      a -= (a<<9);
-      a ^= (a<<4);
-      a -= (a<<3);
-      a ^= (a<<10);
-      a ^= (a>>15);
-      return a;
-   }
-      
-}  // namespace crnlib

+ 0 - 155
Source/ThirdParty/crunch/crnlib/crn_hash_map.cpp

@@ -1,155 +0,0 @@
-// File: crn_hash_map.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_hash_map.h"
-#include "crn_rand.h"
-
-namespace crnlib
-{
-#if 0
-   class counted_obj
-   {
-   public:
-      counted_obj(uint v = 0) :
-         m_val(v)
-      {
-         m_count++;
-      }
-
-      counted_obj(const counted_obj& obj) :
-         m_val(obj.m_val)
-      {
-         m_count++;
-      }
-
-      ~counted_obj()
-      {
-         CRNLIB_ASSERT(m_count > 0);
-         m_count--;
-      }
-
-      static uint m_count;
-
-      uint m_val;
-
-      operator size_t() const { return m_val; }
-
-      bool operator== (const counted_obj& rhs) const { return m_val == rhs.m_val; }
-      bool operator== (const uint rhs) const { return m_val == rhs; }
-
-   };
-
-   uint counted_obj::m_count;
-
-   void hash_map_test()
-   {
-      random r0, r1;
-
-      uint seed = 0;
-      for ( ; ; )
-      {
-         seed++;
-
-         typedef crnlib::hash_map<counted_obj, counted_obj> my_hash_map;
-         my_hash_map m;
-
-         const uint n = r0.irand(1, 100000);
-
-         printf("%u\n", n);
-
-         r1.seed(seed);
-
-         crnlib::vector<int> q;
-
-         uint count = 0;
-         for (uint i = 0; i < n; i++)
-         {
-            uint v = r1.urand32() & 0x7FFFFFFF;
-            my_hash_map::insert_result res = m.insert(counted_obj(v), counted_obj(v ^ 0xdeadbeef));
-            if (res.second)
-            {
-               count++;
-               q.push_back(v);
-            }
-         }
-
-         CRNLIB_VERIFY(m.size() == count);
-
-         r1.seed(seed);
-
-         my_hash_map cm(m);
-         m.clear();
-         m = cm;
-         cm.reset();
-
-         for (uint i = 0; i < n; i++)
-         {
-            uint v = r1.urand32() & 0x7FFFFFFF;
-            my_hash_map::const_iterator it = m.find(counted_obj(v));
-            CRNLIB_VERIFY(it != m.end());
-            CRNLIB_VERIFY(it->first == v);
-            CRNLIB_VERIFY(it->second == (v ^ 0xdeadbeef));
-         }
-
-         for (uint t = 0; t < 2; t++)
-         {
-            const uint nd = r0.irand(1, q.size() + 1);
-            for (uint i = 0; i < nd; i++)
-            {
-               uint p = r0.irand(0, q.size());
-
-               int k = q[p];
-               if (k >= 0)
-               {
-                  q[p] = -k - 1;
-
-                  bool s = m.erase(counted_obj(k));
-                  CRNLIB_VERIFY(s);
-               }
-            }
-
-            typedef crnlib::hash_map<uint, empty_type> uint_hash_set;
-            uint_hash_set s;
-
-            for (uint i = 0; i < q.size(); i++)
-            {
-               int v = q[i];
-
-               if (v >= 0)
-               {
-                  my_hash_map::const_iterator it = m.find(counted_obj(v));
-                  CRNLIB_VERIFY(it != m.end());
-                  CRNLIB_VERIFY(it->first == (uint)v);
-                  CRNLIB_VERIFY(it->second == ((uint)v ^ 0xdeadbeef));
-
-                  s.insert(v);
-               }
-               else
-               {
-                  my_hash_map::const_iterator it = m.find(counted_obj(-v - 1));
-                  CRNLIB_VERIFY(it == m.end());
-               }
-            }
-
-            uint found_count = 0;
-            for (my_hash_map::const_iterator it = m.begin(); it != m.end(); ++it)
-            {
-               CRNLIB_VERIFY(it->second == ((uint)it->first ^ 0xdeadbeef));
-
-               uint_hash_set::const_iterator fit(s.find((uint)it->first));
-               CRNLIB_VERIFY(fit != s.end());
-
-               CRNLIB_VERIFY(fit->first == it->first);
-
-               found_count++;
-            }
-
-            CRNLIB_VERIFY(found_count == s.size());
-         }
-
-         CRNLIB_VERIFY(counted_obj::m_count == m.size() * 2);
-      }
-   }
-#endif
-
-} // namespace crnlib

+ 0 - 876
Source/ThirdParty/crunch/crnlib/crn_hash_map.h

@@ -1,876 +0,0 @@
-// File: crn_hash_map.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-//
-// Notes:
-// stl-like hash map/hash set, with predictable performance across platforms/compilers/C run times/etc.
-// Hash function ref: http://www.brpreiss.com/books/opus4/html/page215.html
-// Compared for performance against VC9's std::hash_map.
-// Linear probing, auto resizes on ~50% load factor.
-// Uses Knuth's multiplicative method (Fibonacci hashing).
-#pragma once
-#include "crn_sparse_array.h"
-#include "crn_sparse_bit_array.h"
-#include "crn_hash.h"
-
-namespace crnlib
-{
-   template <typename T>
-   struct hasher
-   {
-      inline size_t operator() (const T& key) const { return static_cast<size_t>(key); }
-   };
-
-   template <typename T>
-   struct bit_hasher
-   {
-      inline size_t operator() (const T& key) const { return static_cast<size_t>(fast_hash(&key, sizeof(key))); }
-   };
-
-   template <typename T>
-   struct equal_to
-   {
-      inline bool operator()(const T& a, const T& b) const { return a == b;  }
-   };
-
-   // Important: The Hasher and Equals objects must be bitwise movable!
-   template<typename Key, typename Value = empty_type, typename Hasher = hasher<Key>, typename Equals = equal_to<Key> >
-   class hash_map
-   {
-      friend class iterator;
-      friend class const_iterator;
-
-      enum state
-      {
-         cStateInvalid = 0,
-         cStateValid = 1
-      };
-
-      enum
-      {
-         cMinHashSize = 4U
-      };
-
-   public:
-      typedef hash_map<Key, Value, Hasher, Equals> hash_map_type;
-      typedef std::pair<Key, Value> value_type;
-      typedef Key                   key_type;
-      typedef Value                 referent_type;
-      typedef Hasher                hasher_type;
-      typedef Equals                equals_type;
-
-      hash_map() :
-         m_hash_shift(32), m_num_valid(0), m_grow_threshold(0)
-      {
-      }
-
-      hash_map(const hash_map& other) :
-         m_values(other.m_values),
-         m_hash_shift(other.m_hash_shift),
-         m_hasher(other.m_hasher),
-         m_equals(other.m_equals),
-         m_num_valid(other.m_num_valid),
-         m_grow_threshold(other.m_grow_threshold)
-      {
-      }
-
-      hash_map& operator= (const hash_map& other)
-      {
-         if (this == &other)
-            return *this;
-
-         clear();
-
-         m_values = other.m_values;
-         m_hash_shift = other.m_hash_shift;
-         m_num_valid = other.m_num_valid;
-         m_grow_threshold = other.m_grow_threshold;
-         m_hasher = other.m_hasher;
-         m_equals = other.m_equals;
-
-         return *this;
-      }
-
-      inline ~hash_map()
-      {
-         clear();
-      }
-
-      const Equals& get_equals() const { return m_equals; }
-            Equals& get_equals()       { return m_equals; }
-
-      void set_equals(const Equals& equals) { m_equals = equals; }
-
-      const Hasher& get_hasher() const { return m_hasher; }
-            Hasher& get_hasher()       { return m_hasher; }
-
-      void set_hasher(const Hasher& hasher) { m_hasher = hasher; }
-
-      inline void clear()
-      {
-         if (!m_values.empty())
-         {
-            if (CRNLIB_HAS_DESTRUCTOR(Key) || CRNLIB_HAS_DESTRUCTOR(Value))
-            {
-               node* p = &get_node(0);
-               node* p_end = p + m_values.size();
-
-               uint num_remaining = m_num_valid;
-               while (p != p_end)
-               {
-                  if (p->state)
-                  {
-                     destruct_value_type(p);
-                     num_remaining--;
-                     if (!num_remaining)
-                        break;
-                  }
-
-                  p++;
-               }
-            }
-
-            m_values.clear_no_destruction();
-
-            m_hash_shift = 32;
-            m_num_valid = 0;
-            m_grow_threshold = 0;
-         }
-      }
-
-      inline void reset()
-      {
-         if (!m_num_valid)
-            return;
-
-         if (CRNLIB_HAS_DESTRUCTOR(Key) || CRNLIB_HAS_DESTRUCTOR(Value))
-         {
-            node* p = &get_node(0);
-            node* p_end = p + m_values.size();
-
-            uint num_remaining = m_num_valid;
-            while (p != p_end)
-            {
-               if (p->state)
-               {
-                  destruct_value_type(p);
-                  p->state = cStateInvalid;
-
-                  num_remaining--;
-                  if (!num_remaining)
-                     break;
-               }
-
-               p++;
-            }
-         }
-         else if (sizeof(node) <= 32)
-         {
-            memset(&m_values[0], 0, m_values.size_in_bytes());
-         }
-         else
-         {
-            node* p = &get_node(0);
-            node* p_end = p + m_values.size();
-
-            uint num_remaining = m_num_valid;
-            while (p != p_end)
-            {
-               if (p->state)
-               {
-                  p->state = cStateInvalid;
-
-                  num_remaining--;
-                  if (!num_remaining)
-                     break;
-               }
-
-               p++;
-            }
-         }
-
-         m_num_valid = 0;
-      }
-
-      inline uint size()
-      {
-         return m_num_valid;
-      }
-
-      inline uint get_table_size()
-      {
-         return m_values.size();
-      }
-
-      inline bool empty()
-      {
-         return !m_num_valid;
-      }
-
-      inline void reserve(uint new_capacity)
-      {
-         uint new_hash_size = math::maximum(1U, new_capacity);
-
-         new_hash_size = new_hash_size * 2U;
-
-         if (!math::is_power_of_2(new_hash_size))
-            new_hash_size = math::next_pow2(new_hash_size);
-
-         new_hash_size = math::maximum<uint>(cMinHashSize, new_hash_size);
-
-         if (new_hash_size > m_values.size())
-            rehash(new_hash_size);
-      }
-
-      class const_iterator;
-
-      class iterator
-      {
-         friend class hash_map<Key, Value, Hasher, Equals>;
-         friend class hash_map<Key, Value, Hasher, Equals>::const_iterator;
-
-      public:
-         inline iterator() : m_pTable(NULL), m_index(0) { }
-         inline iterator(hash_map_type& table, uint index) : m_pTable(&table), m_index(index) { }
-         inline iterator(const iterator& other) : m_pTable(other.m_pTable), m_index(other.m_index) { }
-
-         inline iterator& operator= (const iterator& other)
-         {
-            m_pTable = other.m_pTable;
-            m_index = other.m_index;
-            return *this;
-         }
-
-          // post-increment
-         inline iterator operator++(int)
-         {
-            iterator result(*this);
-            ++*this;
-            return result;
-         }
-
-         // pre-increment
-         inline iterator& operator++()
-         {
-            probe();
-            return *this;
-         }
-
-         inline value_type& operator*() const { return *get_cur(); }
-         inline value_type* operator->() const { return get_cur(); }
-
-         inline bool operator == (const iterator& b) const { return (m_pTable == b.m_pTable) && (m_index == b.m_index); }
-         inline bool operator != (const iterator& b) const { return !(*this == b); }
-         inline bool operator == (const const_iterator& b) const { return (m_pTable == b.m_pTable) && (m_index == b.m_index); }
-         inline bool operator != (const const_iterator& b) const { return !(*this == b); }
-
-      private:
-         hash_map_type* m_pTable;
-         uint m_index;
-
-         inline value_type* get_cur() const
-         {
-            CRNLIB_ASSERT(m_pTable && (m_index < m_pTable->m_values.size()));
-            CRNLIB_ASSERT(m_pTable->get_node_state(m_index) == cStateValid);
-
-            return &m_pTable->get_node(m_index);
-         }
-
-         inline void probe()
-         {
-            CRNLIB_ASSERT(m_pTable);
-            m_index = m_pTable->find_next(m_index);
-         }
-      };
-
-      class const_iterator
-      {
-         friend class hash_map<Key, Value, Hasher, Equals>;
-         friend class hash_map<Key, Value, Hasher, Equals>::iterator;
-
-      public:
-         inline const_iterator() : m_pTable(NULL), m_index(0) { }
-         inline const_iterator(const hash_map_type& table, uint index) : m_pTable(&table), m_index(index) { }
-         inline const_iterator(const iterator& other) : m_pTable(other.m_pTable), m_index(other.m_index) { }
-         inline const_iterator(const const_iterator& other) : m_pTable(other.m_pTable), m_index(other.m_index) { }
-
-         inline const_iterator& operator= (const const_iterator& other)
-         {
-            m_pTable = other.m_pTable;
-            m_index = other.m_index;
-            return *this;
-         }
-
-         inline const_iterator& operator= (const iterator& other)
-         {
-            m_pTable = other.m_pTable;
-            m_index = other.m_index;
-            return *this;
-         }
-
-         // post-increment
-         inline const_iterator operator++(int)
-         {
-            const_iterator result(*this);
-            ++*this;
-            return result;
-         }
-
-         // pre-increment
-         inline const_iterator& operator++()
-         {
-            probe();
-            return *this;
-         }
-
-         inline const value_type& operator*() const { return *get_cur(); }
-         inline const value_type* operator->() const { return get_cur(); }
-
-         inline bool operator == (const const_iterator& b) const { return (m_pTable == b.m_pTable) && (m_index == b.m_index); }
-         inline bool operator != (const const_iterator& b) const { return !(*this == b); }
-         inline bool operator == (const iterator& b) const { return (m_pTable == b.m_pTable) && (m_index == b.m_index); }
-         inline bool operator != (const iterator& b) const { return !(*this == b); }
-
-      private:
-         const hash_map_type* m_pTable;
-         uint m_index;
-
-         inline const value_type* get_cur() const
-         {
-            CRNLIB_ASSERT(m_pTable && (m_index < m_pTable->m_values.size()));
-            CRNLIB_ASSERT(m_pTable->get_node_state(m_index) == cStateValid);
-
-            return &m_pTable->get_node(m_index);
-         }
-
-         inline void probe()
-         {
-            CRNLIB_ASSERT(m_pTable);
-            m_index = m_pTable->find_next(m_index);
-         }
-      };
-
-      inline const_iterator begin() const
-      {
-         if (!m_num_valid)
-            return end();
-
-         return const_iterator(*this, find_next(-1));
-      }
-
-      inline const_iterator end() const
-      {
-         return const_iterator(*this, m_values.size());
-      }
-
-      inline iterator begin()
-      {
-         if (!m_num_valid)
-            return end();
-
-         return iterator(*this, find_next(-1));
-      }
-
-      inline iterator end()
-      {
-         return iterator(*this, m_values.size());
-      }
-
-      // insert_result.first will always point to inserted key/value (or the already existing key/value).
-      // insert_resutt.second will be true if a new key/value was inserted, or false if the key already existed (in which case first will point to the already existing value).
-      typedef std::pair<iterator, bool> insert_result;
-
-      inline insert_result insert(const Key& k, const Value& v = Value())
-      {
-         insert_result result;
-         if (!insert_no_grow(result, k, v))
-         {
-            grow();
-
-            // This must succeed.
-            if (!insert_no_grow(result, k, v))
-            {
-               CRNLIB_FAIL("insert() failed");
-            }
-         }
-
-         return result;
-      }
-
-      inline insert_result insert(const value_type& v)
-      {
-         return insert(v.first, v.second);
-      }
-
-      inline const_iterator find(const Key& k) const
-      {
-         return const_iterator(*this, find_index(k));
-      }
-
-      inline iterator find(const Key& k)
-      {
-         return iterator(*this, find_index(k));
-      }
-
-      inline bool erase(const Key& k)
-      {
-         int i = find_index(k);
-
-         if (i >= static_cast<int>(m_values.size()))
-            return false;
-
-         node* pDst = &get_node(i);
-         destruct_value_type(pDst);
-         pDst->state = cStateInvalid;
-
-         m_num_valid--;
-
-         for ( ; ; )
-         {
-            int r, j = i;
-
-            node* pSrc = pDst;
-
-            do
-            {
-               if (!i)
-               {
-                  i = m_values.size() - 1;
-                  pSrc = &get_node(i);
-               }
-               else
-               {
-                  i--;
-                  pSrc--;
-               }
-
-               if (!pSrc->state)
-                  return true;
-
-               r = hash_key(pSrc->first);
-
-            } while ((i <= r && r < j) || (r < j && j < i) || (j < i && i <= r));
-
-            move_node(pDst, pSrc);
-
-            pDst = pSrc;
-         }
-      }
-
-      inline void swap(hash_map_type& other)
-      {
-         m_values.swap(other.m_values);
-         utils::swap(m_hash_shift,     other.m_hash_shift);
-         utils::swap(m_num_valid,      other.m_num_valid);
-         utils::swap(m_grow_threshold, other.m_grow_threshold);
-         utils::swap(m_hasher,         other.m_hasher);
-         utils::swap(m_equals,         other.m_equals);
-      }
-
-   private:
-      struct node : public value_type
-      {
-         uint8 state;
-      };
-
-      static inline void construct_value_type(value_type* pDst, const Key& k, const Value& v)
-      {
-         if (CRNLIB_IS_BITWISE_COPYABLE(Key))
-            memcpy(&pDst->first, &k, sizeof(Key));
-         else
-            scalar_type<Key>::construct(&pDst->first, k);
-
-         if (CRNLIB_IS_BITWISE_COPYABLE(Value))
-            memcpy(&pDst->second, &v, sizeof(Value));
-         else
-            scalar_type<Value>::construct(&pDst->second, v);
-      }
-
-      static inline void construct_value_type(value_type* pDst, const value_type* pSrc)
-      {
-         if ((CRNLIB_IS_BITWISE_COPYABLE(Key)) && (CRNLIB_IS_BITWISE_COPYABLE(Value)))
-         {
-            memcpy(pDst, pSrc, sizeof(value_type));
-         }
-         else
-         {
-            if (CRNLIB_IS_BITWISE_COPYABLE(Key))
-               memcpy(&pDst->first, &pSrc->first, sizeof(Key));
-            else
-               scalar_type<Key>::construct(&pDst->first, pSrc->first);
-
-            if (CRNLIB_IS_BITWISE_COPYABLE(Value))
-               memcpy(&pDst->second, &pSrc->second, sizeof(Value));
-            else
-               scalar_type<Value>::construct(&pDst->second, pSrc->second);
-         }
-      }
-
-      static inline void destruct_value_type(value_type* p)
-      {
-         scalar_type<Key>::destruct(&p->first);
-         scalar_type<Value>::destruct(&p->second);
-      }
-
-      // Moves *pSrc to *pDst efficiently.
-      // pDst should NOT be constructed on entry.
-      static inline void move_node(node* pDst, node* pSrc)
-      {
-         CRNLIB_ASSERT(!pDst->state);
-
-         if (CRNLIB_IS_BITWISE_COPYABLE_OR_MOVABLE(Key) && CRNLIB_IS_BITWISE_COPYABLE_OR_MOVABLE(Value))
-         {
-            memcpy(pDst, pSrc, sizeof(node));
-         }
-         else
-         {
-            if (CRNLIB_IS_BITWISE_COPYABLE_OR_MOVABLE(Key))
-               memcpy(&pDst->first, &pSrc->first, sizeof(Key));
-            else
-            {
-               scalar_type<Key>::construct(&pDst->first, pSrc->first);
-               scalar_type<Key>::destruct(&pSrc->first);
-            }
-
-            if (CRNLIB_IS_BITWISE_COPYABLE_OR_MOVABLE(Value))
-               memcpy(&pDst->second, &pSrc->second, sizeof(Value));
-            else
-            {
-               scalar_type<Value>::construct(&pDst->second, pSrc->second);
-               scalar_type<Value>::destruct(&pSrc->second);
-            }
-
-            pDst->state = cStateValid;
-         }
-
-         pSrc->state = cStateInvalid;
-      }
-
-      struct raw_node
-      {
-         inline raw_node()
-         {
-            node* p = reinterpret_cast<node*>(this);
-            p->state = cStateInvalid;
-         }
-
-         inline ~raw_node()
-         {
-            node* p = reinterpret_cast<node*>(this);
-            if (p->state)
-               hash_map_type::destruct_value_type(p);
-         }
-
-         inline raw_node(const raw_node& other)
-         {
-            node* pDst = reinterpret_cast<node*>(this);
-            const node* pSrc = reinterpret_cast<const node*>(&other);
-
-            if (pSrc->state)
-            {
-               hash_map_type::construct_value_type(pDst, pSrc);
-               pDst->state = cStateValid;
-            }
-            else
-               pDst->state = cStateInvalid;
-         }
-
-         inline raw_node& operator= (const raw_node& rhs)
-         {
-            if (this == &rhs)
-               return *this;
-
-            node* pDst = reinterpret_cast<node*>(this);
-            const node* pSrc = reinterpret_cast<const node*>(&rhs);
-
-            if (pSrc->state)
-            {
-               if (pDst->state)
-               {
-                  pDst->first = pSrc->first;
-                  pDst->second = pSrc->second;
-               }
-               else
-               {
-                  hash_map_type::construct_value_type(pDst, pSrc);
-                  pDst->state = cStateValid;
-               }
-            }
-            else if (pDst->state)
-            {
-               hash_map_type::destruct_value_type(pDst);
-               pDst->state = cStateInvalid;
-            }
-
-            return *this;
-         }
-
-         uint8 m_bits[sizeof(node)];
-      };
-
-      typedef crnlib::vector<raw_node> node_vector;
-
-      node_vector       m_values;
-      uint              m_hash_shift;
-
-      Hasher            m_hasher;
-      Equals            m_equals;
-
-      uint              m_num_valid;
-
-      uint              m_grow_threshold;
-
-      inline int hash_key(const Key& k) const
-      {
-         CRNLIB_ASSERT((1U << (32U - m_hash_shift)) == m_values.size());
-
-         uint hash = static_cast<uint>(m_hasher(k));
-
-         // Fibonacci hashing
-         hash = (2654435769U * hash) >> m_hash_shift;
-
-         CRNLIB_ASSERT(hash < m_values.size());
-         return hash;
-      }
-
-      inline const node& get_node(uint index) const
-      {
-         return *reinterpret_cast<const node*>(&m_values[index]);
-      }
-
-      inline node& get_node(uint index)
-      {
-         return *reinterpret_cast<node*>(&m_values[index]);
-      }
-
-      inline state get_node_state(uint index) const
-      {
-         return static_cast<state>(get_node(index).state);
-      }
-
-      inline void set_node_state(uint index, bool valid)
-      {
-         get_node(index).state = valid;
-      }
-
-      inline void grow()
-      {
-         rehash(math::maximum<uint>(cMinHashSize, m_values.size() * 2U));
-      }
-
-      inline void rehash(uint new_hash_size)
-      {
-         CRNLIB_ASSERT(new_hash_size >= m_num_valid);
-         CRNLIB_ASSERT(math::is_power_of_2(new_hash_size));
-
-         if ((new_hash_size < m_num_valid) || (new_hash_size == m_values.size()))
-            return;
-
-         hash_map new_map;
-         new_map.m_values.resize(new_hash_size);
-         new_map.m_hash_shift = 32U - math::floor_log2i(new_hash_size);
-         CRNLIB_ASSERT(new_hash_size == (1U << (32U - new_map.m_hash_shift)));
-         new_map.m_grow_threshold = UINT_MAX;
-
-         node* pNode = reinterpret_cast<node*>(m_values.begin());
-         node* pNode_end = pNode + m_values.size();
-
-         while (pNode != pNode_end)
-         {
-            if (pNode->state)
-            {
-               new_map.move_into(pNode);
-
-               if (new_map.m_num_valid == m_num_valid)
-                  break;
-            }
-
-            pNode++;
-         }
-
-         new_map.m_grow_threshold = (new_hash_size + 1U) >> 1U;
-
-         m_values.clear_no_destruction();
-         m_hash_shift = 32;
-
-         swap(new_map);
-      }
-
-      inline uint find_next(int index) const
-      {
-         index++;
-
-         if (index >= static_cast<int>(m_values.size()))
-            return index;
-
-         const node* pNode = &get_node(index);
-
-         for ( ; ; )
-         {
-            if (pNode->state)
-               break;
-
-            if (++index >= static_cast<int>(m_values.size()))
-               break;
-
-            pNode++;
-         }
-
-         return index;
-      }
-
-      inline uint find_index(const Key& k) const
-      {
-         if (m_num_valid)
-         {
-            int index = hash_key(k);
-            const node* pNode = &get_node(index);
-
-            if (pNode->state)
-            {
-               if (m_equals(pNode->first, k))
-                  return index;
-
-               const int orig_index = index;
-
-               for ( ; ; )
-               {
-                  if (!index)
-                  {
-                     index = m_values.size() - 1;
-                     pNode = &get_node(index);
-                  }
-                  else
-                  {
-                     index--;
-                     pNode--;
-                  }
-
-                  if (index == orig_index)
-                     break;
-
-                  if (!pNode->state)
-                     break;
-
-                  if (m_equals(pNode->first, k))
-                     return index;
-               }
-            }
-         }
-
-         return m_values.size();
-      }
-
-      inline bool insert_no_grow(insert_result& result, const Key& k, const Value& v = Value())
-      {
-         if (!m_values.size())
-            return false;
-
-         int index = hash_key(k);
-         node* pNode = &get_node(index);
-
-         if (pNode->state)
-         {
-            if (m_equals(pNode->first, k))
-            {
-               result.first = iterator(*this, index);
-               result.second = false;
-               return true;
-            }
-
-            const int orig_index = index;
-
-            for ( ; ; )
-            {
-               if (!index)
-               {
-                  index = m_values.size() - 1;
-                  pNode = &get_node(index);
-               }
-               else
-               {
-                  index--;
-                  pNode--;
-               }
-
-               if (orig_index == index)
-                  return false;
-
-               if (!pNode->state)
-                  break;
-
-               if (m_equals(pNode->first, k))
-               {
-                  result.first = iterator(*this, index);
-                  result.second = false;
-                  return true;
-               }
-            }
-         }
-
-         if (m_num_valid >= m_grow_threshold)
-            return false;
-
-         construct_value_type(pNode, k, v);
-
-         pNode->state = cStateValid;
-
-         m_num_valid++;
-         CRNLIB_ASSERT(m_num_valid <= m_values.size());
-
-         result.first = iterator(*this, index);
-         result.second = true;
-
-         return true;
-      }
-
-      inline void move_into(node* pNode)
-      {
-         int index = hash_key(pNode->first);
-         node* pDst_node = &get_node(index);
-
-         if (pDst_node->state)
-         {
-            const int orig_index = index;
-
-            for ( ; ; )
-            {
-               if (!index)
-               {
-                  index = m_values.size() - 1;
-                  pDst_node = &get_node(index);
-               }
-               else
-               {
-                  index--;
-                  pDst_node--;
-               }
-
-               if (index == orig_index)
-               {
-                  CRNLIB_ASSERT(false);
-                  return;
-               }
-
-               if (!pDst_node->state)
-                  break;
-            }
-         }
-
-         move_node(pDst_node, pNode);
-
-         m_num_valid++;
-      }
-   };
-
-   template<typename Key, typename Value, typename Hasher, typename Equals>
-   struct bitwise_movable< hash_map<Key, Value, Hasher, Equals> > { enum { cFlag = true }; };
-
-   template<typename Key, typename Value, typename Hasher, typename Equals>
-   inline void swap(hash_map<Key, Value, Hasher, Equals>& a, hash_map<Key, Value, Hasher, Equals>& b)
-   {
-      a.swap(b);
-   }
-
-   extern void hash_map_test();
-
-} // namespace crnlib

+ 0 - 64
Source/ThirdParty/crunch/crnlib/crn_helpers.h

@@ -1,64 +0,0 @@
-// File: crn_helpers.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-#define CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(c) c(const c&); c& operator= (const c&);
-#define CRNLIB_NO_HEAP_ALLOC() private: static void* operator new(size_t); static void* operator new[](size_t);
-
-namespace crnlib
-{
-   namespace helpers
-   {
-      template<typename T> struct rel_ops 
-      {
-         friend bool operator!=(const T& x, const T& y) { return (!(x == y)); }
-         friend bool operator> (const T& x, const T& y) { return (y < x); }
-         friend bool operator<=(const T& x, const T& y) { return (!(y < x)); }
-         friend bool operator>=(const T& x, const T& y) { return (!(x < y)); }
-      };
-      
-      template <typename T> 
-      inline T* construct(T* p) 
-      { 
-         return new (static_cast<void*>(p)) T; 
-      }
-
-      template <typename T, typename U> 
-      inline T* construct(T* p, const U& init) 
-      { 
-         return new (static_cast<void*>(p)) T(init); 
-      }
-
-      template <typename T> 
-      inline void construct_array(T* p, uint n) 
-      { 
-         T* q = p + n;
-         for ( ; p != q; ++p)
-            new (static_cast<void*>(p)) T; 
-      }
-      
-      template <typename T, typename U> 
-      inline void construct_array(T* p, uint n, const U& init) 
-      { 
-         T* q = p + n;
-         for ( ; p != q; ++p)
-            new (static_cast<void*>(p)) T(init); 
-      }
-
-      template <typename T> 
-      inline void destruct(T* p) 
-      {	   
-         p;
-         p->~T(); 
-      } 
-      
-      template <typename T> inline void destruct_array(T* p, uint n) 
-      {	
-         T* q = p + n;
-         for ( ; p != q; ++p)
-            p->~T();
-      } 
-                  
-   }  // namespace helpers    
-   
-}  // namespace crnlib

+ 0 - 387
Source/ThirdParty/crunch/crnlib/crn_huffman_codes.cpp

@@ -1,387 +0,0 @@
-// File: crn_huffman_codes.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_huffman_codes.h"
-
-namespace crnlib
-{
-   struct sym_freq
-   {
-      uint m_freq;
-      uint16 m_left;
-      uint16 m_right;
-
-      inline bool operator< (const sym_freq& other) const
-      {
-         return m_freq > other.m_freq;
-      }
-   };
-   
-   static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* syms0, sym_freq* syms1)
-   {  
-      const uint cMaxPasses = 2;
-      uint hist[256 * cMaxPasses];
-            
-      memset(hist, 0, sizeof(hist[0]) * 256 * cMaxPasses);
-
-      sym_freq* p = syms0;
-      sym_freq* q = syms0 + (num_syms >> 1) * 2;
-
-      for ( ; p != q; p += 2)
-      {
-         const uint freq0 = p[0].m_freq;
-         const uint freq1 = p[1].m_freq;
-
-         hist[        freq0         & 0xFF]++;
-         hist[256 + ((freq0 >>  8) & 0xFF)]++;
-
-         hist[        freq1        & 0xFF]++;
-         hist[256 + ((freq1 >>  8) & 0xFF)]++;
-      }
-
-      if (num_syms & 1)
-      {
-         const uint freq = p->m_freq;
-
-         hist[        freq        & 0xFF]++;
-         hist[256 + ((freq >>  8) & 0xFF)]++;
-      }
-      
-      sym_freq* pCur_syms = syms0;
-      sym_freq* pNew_syms = syms1;
-
-      for (uint pass = 0; pass < cMaxPasses; pass++)
-      {
-         const uint* pHist = &hist[pass << 8];
-
-         uint offsets[256];
-
-         uint cur_ofs = 0;
-         for (uint i = 0; i < 256; i += 2)
-         {
-            offsets[i] = cur_ofs;
-            cur_ofs += pHist[i];
-
-            offsets[i+1] = cur_ofs;
-            cur_ofs += pHist[i+1];
-         }
-
-         const uint pass_shift = pass << 3;
-
-         sym_freq* p = pCur_syms;
-         sym_freq* q = pCur_syms + (num_syms >> 1) * 2;
-
-         for ( ; p != q; p += 2)
-         {
-            uint c0 = p[0].m_freq;
-            uint c1 = p[1].m_freq;
-            
-            if (pass)
-            {
-               c0 >>= 8;
-               c1 >>= 8;
-            }
-            
-            c0 &= 0xFF;
-            c1 &= 0xFF;
-
-            if (c0 == c1)
-            {
-               uint dst_offset0 = offsets[c0];
-
-               offsets[c0] = dst_offset0 + 2;
-
-               pNew_syms[dst_offset0] = p[0];
-               pNew_syms[dst_offset0 + 1] = p[1];
-            }
-            else
-            {
-               uint dst_offset0 = offsets[c0]++;
-               uint dst_offset1 = offsets[c1]++;
-
-               pNew_syms[dst_offset0] = p[0];
-               pNew_syms[dst_offset1] = p[1];
-            }
-         }
-
-         if (num_syms & 1)
-         {
-            uint c = ((p->m_freq) >> pass_shift) & 0xFF;
-
-            uint dst_offset = offsets[c];
-            offsets[c] = dst_offset + 1;
-
-            pNew_syms[dst_offset] = *p;
-         }
-
-         sym_freq* t = pCur_syms;
-         pCur_syms = pNew_syms;
-         pNew_syms = t;
-      }            
-
-#ifdef CRNLIB_ASSERTS_ENABLED
-      uint prev_freq = 0;
-      for (uint i = 0; i < num_syms; i++)
-      {
-         CRNLIB_ASSERT(!(pCur_syms[i].m_freq < prev_freq));
-         prev_freq = pCur_syms[i].m_freq;
-      }
-#endif
-      
-      return pCur_syms;
-   }
-   
-   struct huffman_work_tables
-   {
-      enum { cMaxInternalNodes = cHuffmanMaxSupportedSyms };
-      
-      sym_freq syms0[cHuffmanMaxSupportedSyms + 1 + cMaxInternalNodes];
-      sym_freq syms1[cHuffmanMaxSupportedSyms + 1 + cMaxInternalNodes];
-                  
-      uint16 queue[cMaxInternalNodes];
-   };
-   
-   void* create_generate_huffman_codes_tables()
-   {
-      return crnlib_new<huffman_work_tables>();
-   }
-   
-   void free_generate_huffman_codes_tables(void* p)
-   {
-      crnlib_delete(static_cast<huffman_work_tables*>(p)); 
-   }
-
-#if USE_CALCULATE_MINIMUM_REDUNDANCY      
-   /* calculate_minimum_redundancy() written by
-      Alistair Moffat, [email protected],
-      Jyrki Katajainen, [email protected]
-      November 1996.
-   */
-   static void calculate_minimum_redundancy(int A[], int n) {
-         int root;                  /* next root node to be used */
-         int leaf;                  /* next leaf to be used */
-         int next;                  /* next value to be assigned */
-         int avbl;                  /* number of available nodes */
-         int used;                  /* number of internal nodes */
-         int dpth;                  /* current depth of leaves */
-
-         /* check for pathological cases */
-         if (n==0) { return; }
-         if (n==1) { A[0] = 0; return; }
-
-         /* first pass, left to right, setting parent pointers */
-         A[0] += A[1]; root = 0; leaf = 2;
-         for (next=1; next < n-1; next++) {
-            /* select first item for a pairing */
-            if (leaf>=n || A[root]<A[leaf]) {
-               A[next] = A[root]; A[root++] = next;
-            } else
-               A[next] = A[leaf++];
-
-            /* add on the second item */
-            if (leaf>=n || (root<next && A[root]<A[leaf])) {
-               A[next] += A[root]; A[root++] = next;
-            } else
-               A[next] += A[leaf++];
-         }
-
-         /* second pass, right to left, setting internal depths */
-         A[n-2] = 0;
-         for (next=n-3; next>=0; next--)
-            A[next] = A[A[next]]+1;
-
-         /* third pass, right to left, setting leaf depths */
-         avbl = 1; used = dpth = 0; root = n-2; next = n-1;
-         while (avbl>0) {
-            while (root>=0 && A[root]==dpth) {
-               used++; root--;
-            }
-            while (avbl>used) {
-               A[next--] = dpth; avbl--;
-            }
-            avbl = 2*used; dpth++; used = 0;
-         }
-   }
-#endif
-     
-   bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret)
-   {
-      if ((!num_syms) || (num_syms > cHuffmanMaxSupportedSyms))
-         return false;
-                  
-      huffman_work_tables& state = *static_cast<huffman_work_tables*>(pContext);;
-            
-      uint max_freq = 0;
-      uint total_freq = 0;
-      
-      uint num_used_syms = 0;
-      for (uint i = 0; i < num_syms; i++)
-      {
-         uint freq = pFreq[i];
-         
-         if (!freq)
-            pCodesizes[i] = 0;
-         else
-         {
-            total_freq += freq;
-            max_freq = math::maximum(max_freq, freq);
-            
-            sym_freq& sf = state.syms0[num_used_syms];
-            sf.m_left = (uint16)i;
-            sf.m_right = cUINT16_MAX;
-            sf.m_freq = freq;
-            num_used_syms++;
-         }            
-      }
-      
-      total_freq_ret = total_freq;
-
-      if (num_used_syms == 1)
-      {
-         pCodesizes[state.syms0[0].m_left] = 1;
-         return true;
-      }
-
-      sym_freq* syms = radix_sort_syms(num_used_syms, state.syms0, state.syms1);
-
-#if USE_CALCULATE_MINIMUM_REDUNDANCY
-      int x[cHuffmanMaxSupportedSyms];
-      for (uint i = 0; i < num_used_syms; i++)
-         x[i] = state.syms0[i].m_freq;
-      
-      calculate_minimum_redundancy(x, num_used_syms);
-      
-      uint max_len = 0;
-      for (uint i = 0; i < num_used_syms; i++)
-      {
-         uint len = x[i];
-         max_len = math::maximum(len, max_len);
-         pCodesizes[state.syms0[i].m_left] = static_cast<uint8>(len);
-      }
-      
-      return true;
-#else    
-      // Dummy node
-      sym_freq& sf = state.syms0[num_used_syms];
-      sf.m_left = cUINT16_MAX;
-      sf.m_right = cUINT16_MAX;
-      sf.m_freq = UINT_MAX;
-      
-      uint next_internal_node = num_used_syms + 1;
-            
-      uint queue_front = 0;
-      uint queue_end = 0;
-            
-      uint next_lowest_sym = 0;
-      
-      uint num_nodes_remaining = num_used_syms;
-      do
-      {
-         uint left_freq = syms[next_lowest_sym].m_freq;
-         uint left_child = next_lowest_sym;
-         
-         if ((queue_end > queue_front) && (syms[state.queue[queue_front]].m_freq < left_freq))
-         {
-            left_child = state.queue[queue_front];
-            left_freq = syms[left_child].m_freq;
-            
-            queue_front++;
-         }
-         else
-            next_lowest_sym++;
-         
-         uint right_freq = syms[next_lowest_sym].m_freq;
-         uint right_child = next_lowest_sym;
-
-         if ((queue_end > queue_front) && (syms[state.queue[queue_front]].m_freq < right_freq))
-         {
-            right_child = state.queue[queue_front];
-            right_freq = syms[right_child].m_freq;
-            
-            queue_front++;
-         }
-         else
-            next_lowest_sym++;
-                        
-         const uint internal_node_index = next_internal_node;
-         next_internal_node++;
-
-         CRNLIB_ASSERT(next_internal_node < CRNLIB_ARRAYSIZE(state.syms0));
-         
-         syms[internal_node_index].m_freq = left_freq + right_freq;
-         syms[internal_node_index].m_left = static_cast<uint16>(left_child);
-         syms[internal_node_index].m_right = static_cast<uint16>(right_child);
-         
-         CRNLIB_ASSERT(queue_end < huffman_work_tables::cMaxInternalNodes);
-         state.queue[queue_end] = static_cast<uint16>(internal_node_index);
-         queue_end++;
-                  
-         num_nodes_remaining--;
-         
-      } while (num_nodes_remaining > 1);
-      
-      CRNLIB_ASSERT(next_lowest_sym == num_used_syms);
-      CRNLIB_ASSERT((queue_end - queue_front) == 1);
-      
-      uint cur_node_index = state.queue[queue_front];
-      
-      uint32* pStack = (syms == state.syms0) ? (uint32*)state.syms1 : (uint32*)state.syms0;
-      uint32* pStack_top = pStack;
-
-      uint max_level = 0;
-      
-      for ( ; ; ) 
-      {
-         uint level = cur_node_index >> 16;
-         uint node_index = cur_node_index & 0xFFFF;
-         
-         uint left_child = syms[node_index].m_left;
-         uint right_child = syms[node_index].m_right;
-         
-         uint next_level = (cur_node_index + 0x10000) & 0xFFFF0000;
-                           
-         if (left_child < num_used_syms)
-         {
-            max_level = math::maximum(max_level, level);
-            
-            pCodesizes[syms[left_child].m_left] = static_cast<uint8>(level + 1);
-            
-            if (right_child < num_used_syms)
-            {
-               pCodesizes[syms[right_child].m_left] = static_cast<uint8>(level + 1);
-               
-               if (pStack == pStack_top) break;
-               cur_node_index = *--pStack;
-            }
-            else
-            {
-               cur_node_index = next_level | right_child;
-            }
-         }
-         else
-         {
-            if (right_child < num_used_syms)
-            {
-               max_level = math::maximum(max_level, level);
-               
-               pCodesizes[syms[right_child].m_left] = static_cast<uint8>(level + 1);
-                              
-               cur_node_index = next_level | left_child;
-            }
-            else
-            {
-               *pStack++ = next_level | left_child;
-                              
-               cur_node_index = next_level | right_child;
-            }
-         }
-      }
-      
-      max_code_size = max_level + 1;
-#endif
-                  
-      return true;
-   }
-
-} // namespace crnlib
-

+ 0 - 14
Source/ThirdParty/crunch/crnlib/crn_huffman_codes.h

@@ -1,14 +0,0 @@
-// File: crn_huffman_codes.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   const uint cHuffmanMaxSupportedSyms = 8192;
-
-   void* create_generate_huffman_codes_tables();
-   void free_generate_huffman_codes_tables(void* p);
-   
-   bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret);
-
-} // namespace crnlib

+ 0 - 723
Source/ThirdParty/crunch/crnlib/crn_image.h

@@ -1,723 +0,0 @@
-// File: crn_image.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_color.h"
-#include "crn_vec.h"
-#include "crn_pixel_format.h"
-#include "crn_rect.h"
-
-namespace crnlib
-{
-   template<typename color_type>
-   class image
-   {
-   public:
-      typedef color_type color_t;
-
-      typedef crnlib::vector<color_type> pixel_buf_t;
-
-      image() :
-         m_width(0),
-         m_height(0),
-         m_pitch(0),
-         m_total(0),
-         m_comp_flags(pixel_format_helpers::cDefaultCompFlags),
-         m_pPixels(NULL)
-      {
-      }
-
-      // pitch is in PIXELS, not bytes.
-      image(uint width, uint height, uint pitch = UINT_MAX, const color_type& background = color_type::make_black(), uint flags = pixel_format_helpers::cDefaultCompFlags) :
-         m_comp_flags(flags)
-      {
-         CRNLIB_ASSERT((width > 0) && (height > 0));
-         if (pitch == UINT_MAX)
-            pitch = width;
-
-         m_pixel_buf.resize(pitch * height);
-
-         m_width = width;
-         m_height = height;
-         m_pitch = pitch;
-         m_total = m_pitch * m_height;
-
-         m_pPixels = &m_pixel_buf.front();
-
-         set_all(background);
-      }
-
-      // pitch is in PIXELS, not bytes.
-      image(color_type* pPixels, uint width, uint height, uint pitch = UINT_MAX, uint flags = pixel_format_helpers::cDefaultCompFlags)
-      {
-         alias(pPixels, width, height, pitch, flags);
-      }
-
-      image& operator= (const image& other)
-      {
-         if (this == &other)
-            return *this;
-
-         if (other.m_pixel_buf.empty())
-         {
-            // This doesn't look very safe - let's make a new instance.
-            //m_pixel_buf.clear();
-            //m_pPixels = other.m_pPixels;
-
-            const uint total_pixels = other.m_pitch * other.m_height;
-            if ((total_pixels) && (other.m_pPixels))
-            {
-               m_pixel_buf.resize(total_pixels);
-               m_pixel_buf.insert(0, other.m_pPixels, m_pixel_buf.size());
-               m_pPixels = &m_pixel_buf.front();
-            }
-            else
-            {
-               m_pixel_buf.clear();
-               m_pPixels = NULL;
-            }
-         }
-         else
-         {
-            m_pixel_buf = other.m_pixel_buf;
-            m_pPixels = &m_pixel_buf.front();
-         }
-
-         m_width = other.m_width;
-         m_height = other.m_height;
-         m_pitch = other.m_pitch;
-         m_total = other.m_total;
-         m_comp_flags = other.m_comp_flags;
-
-         return *this;
-      }
-
-      image(const image& other) :
-         m_width(0), m_height(0), m_pitch(0), m_total(0), m_comp_flags(pixel_format_helpers::cDefaultCompFlags), m_pPixels(NULL)
-      {
-         *this = other;
-      }
-
-      // pitch is in PIXELS, not bytes.
-      void alias(color_type* pPixels, uint width, uint height, uint pitch = UINT_MAX, uint flags = pixel_format_helpers::cDefaultCompFlags)
-      {
-         m_pixel_buf.clear();
-
-         m_pPixels = pPixels;
-
-         m_width = width;
-         m_height = height;
-         m_pitch = (pitch == UINT_MAX) ? width : pitch;
-         m_total = m_pitch * m_height;
-         m_comp_flags = flags;
-      }
-
-      // pitch is in PIXELS, not bytes.
-      bool grant_ownership(color_type* pPixels, uint width, uint height, uint pitch = UINT_MAX, uint flags = pixel_format_helpers::cDefaultCompFlags)
-      {
-         if (pitch == UINT_MAX)
-            pitch = width;
-
-         if ((!pPixels) || (!width) || (!height) || (pitch < width))
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         if (pPixels == get_ptr())
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-         
-         clear();
-
-         if (!m_pixel_buf.grant_ownership(pPixels, height * pitch, height * pitch))
-            return false;
-         
-         m_pPixels = pPixels;
-
-         m_width = width;
-         m_height = height;
-         m_pitch = pitch;
-         m_total = pitch * height;
-         m_comp_flags = flags;
-         
-         return true;
-      }
-
-      void clear()
-      {
-         m_pPixels = NULL;
-         m_pixel_buf.clear();
-         m_width = 0;
-         m_height = 0;
-         m_pitch = 0;
-         m_total = 0;
-         m_comp_flags = pixel_format_helpers::cDefaultCompFlags;
-      }
-
-      inline bool is_valid() const { return m_total > 0; }
-
-      inline pixel_format_helpers::component_flags get_comp_flags() const { return static_cast<pixel_format_helpers::component_flags>(m_comp_flags); }
-      inline void set_comp_flags(pixel_format_helpers::component_flags new_flags) { m_comp_flags = new_flags; }
-      inline void reset_comp_flags() { m_comp_flags = pixel_format_helpers::cDefaultCompFlags; }
-
-      inline bool is_component_valid(uint index) const { CRNLIB_ASSERT(index < 4U); return utils::is_flag_set(m_comp_flags, index); }
-      inline void set_component_valid(uint index, bool state) { CRNLIB_ASSERT(index < 4U); utils::set_flag(m_comp_flags, index, state); }
-
-      inline bool has_rgb() const { return is_component_valid(0) || is_component_valid(1) || is_component_valid(2); }
-      inline bool has_alpha() const { return is_component_valid(3); }
-
-      inline bool is_grayscale() const { return utils::is_bit_set(m_comp_flags, pixel_format_helpers::cCompFlagGrayscale); }
-      inline void set_grayscale(bool state) { utils::set_bit(m_comp_flags, pixel_format_helpers::cCompFlagGrayscale, state); }
-
-      void set_all(const color_type& c)
-      {
-         for (uint i = 0; i < m_total; i++)
-            m_pPixels[i] = c;
-      }
-
-      void flip_x()
-      {
-         const uint half_width = m_width / 2;
-         for (uint y = 0; y < m_height; y++)
-         {
-            for (uint x = 0; x < half_width; x++)
-            {
-               color_type c((*this)(x, y));
-               (*this)(x, y) = (*this)(m_width - 1 - x, y);
-               (*this)(m_width - 1 - x, y) = c;
-            }
-         }
-      }
-
-      void flip_y()
-      {
-         const uint half_height = m_height / 2;
-         for (uint y = 0; y < half_height; y++)
-         {
-            for (uint x = 0; x < m_width; x++)
-            {
-               color_type c((*this)(x, y));
-               (*this)(x, y) = (*this)(x, m_height - 1 - y);
-               (*this)(x, m_height - 1 - y) = c;
-            }
-         }
-      }
-
-      void convert_to_grayscale()
-      {
-         for (uint y = 0; y < m_height; y++)
-            for (uint x = 0; x < m_width; x++)
-            {
-               color_type c((*this)(x, y));
-               typename color_type::component_t l = static_cast< typename color_type::component_t >(c.get_luma());
-               c.r = l;
-               c.g = l;
-               c.b = l;
-               (*this)(x, y) = c;
-            }
-
-         set_grayscale(true);
-      }
-
-      void swizzle(uint r, uint g, uint b, uint a)
-      {
-         for (uint y = 0; y < m_height; y++)
-            for (uint x = 0; x < m_width; x++)
-            {
-               const color_type& c = (*this)(x, y);
-
-               (*this)(x, y) = color_type(c[r], c[g], c[b], c[a]);
-            }
-      }
-
-      void set_alpha_to_luma()
-      {
-         for (uint y = 0; y < m_height; y++)
-            for (uint x = 0; x < m_width; x++)
-            {
-               color_type c((*this)(x, y));
-               typename color_type::component_t l = static_cast< typename color_type::component_t >(c.get_luma());
-               c.a = l;
-               (*this)(x, y) = c;
-            }
-
-         set_component_valid(3, true);
-      }
-
-      bool extract_block(color_type* pDst, uint x, uint y, uint w, uint h, bool flip_xy = false) const
-      {
-         if ((x >= m_width) || (y >= m_height))
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         if (flip_xy)
-         {
-            for (uint y_ofs = 0; y_ofs < h; y_ofs++)
-               for (uint x_ofs = 0; x_ofs < w; x_ofs++)
-                  pDst[x_ofs * h + y_ofs] = get_clamped(x_ofs + x, y_ofs + y);      // 5/4/12 - this was incorrectly x_ofs * 4
-         }
-         else if (((x + w) > m_width) || ((y + h) > m_height))
-         {
-            for (uint y_ofs = 0; y_ofs < h; y_ofs++)
-               for (uint x_ofs = 0; x_ofs < w; x_ofs++)
-                  *pDst++ = get_clamped(x_ofs + x, y_ofs + y);
-         }
-         else
-         {
-            const color_type* pSrc = get_scanline(y) + x;
-
-            for (uint i = h; i; i--)
-            {
-               memcpy(pDst, pSrc, w * sizeof(color_type));
-               pDst += w;
-
-               pSrc += m_pitch;
-            }
-         }
-
-         return true;
-      }
-
-      // No clipping!
-      void unclipped_fill_box(uint x, uint y, uint w, uint h, const color_type& c)
-      {
-         if (((x + w) > m_width) || ((y + h) > m_height))
-         {
-            CRNLIB_ASSERT(0);
-            return;
-         }
-
-         color_type* p = get_scanline(y) + x;
-
-         for (uint i = h; i; i--)
-         {
-            color_type* q = p;
-            for (uint j = w; j; j--)
-               *q++ = c;
-            p += m_pitch;
-         }
-      }
-
-      void draw_rect(int x, int y, uint width, uint height, const color_type& c)
-      {
-         draw_line(x, y, x + width - 1, y, c);
-         draw_line(x, y, x, y + height - 1, c);
-         draw_line(x + width - 1, y, x + width - 1, y + height - 1, c);
-         draw_line(x, y + height - 1, x + width - 1, y + height - 1, c);
-      }
-
-      // No clipping!
-      bool unclipped_blit(uint src_x, uint src_y, uint src_w, uint src_h, uint dst_x, uint dst_y, const image& src)
-      {
-         if ((!is_valid()) || (!src.is_valid()))
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         if ( ((src_x + src_w) > src.get_width()) || ((src_y + src_h) > src.get_height()) )
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         if ( ((dst_x + src_w) > get_width()) || ((dst_y + src_h) > get_height()) )
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         const color_type* pS = &src(src_x, src_y);
-         color_type* pD = &(*this)(dst_x, dst_y);
-
-         const uint bytes_to_copy = src_w * sizeof(color_type);
-         for (uint i = src_h; i; i--)
-         {
-            memcpy(pD, pS, bytes_to_copy);
-
-            pS += src.get_pitch();
-            pD += get_pitch();
-         }
-
-         return true;
-      }
-
-      // With clipping.
-      bool blit(int dst_x, int dst_y, const image& src)
-      {
-         if ((!is_valid()) || (!src.is_valid()))
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         int src_x = 0;
-         int src_y = 0;
-
-         if (dst_x < 0)
-         {
-            src_x = -dst_x;
-            if (src_x >= static_cast<int>(src.get_width()))
-               return false;
-            dst_x = 0;
-         }
-
-         if (dst_y < 0)
-         {
-            src_y = -dst_y;
-            if (src_y >= static_cast<int>(src.get_height()))
-               return false;
-            dst_y = 0;
-         }
-
-         if ((dst_x >= (int)m_width) || (dst_y >= (int)m_height))
-            return false;
-
-         uint width = math::minimum(m_width - dst_x, src.get_width() - src_x);
-         uint height = math::minimum(m_height - dst_y, src.get_height() - src_y);
-
-         bool success = unclipped_blit(src_x, src_y, width, height, dst_x, dst_y, src);
-         success;
-         CRNLIB_ASSERT(success);
-
-         return true;
-      }
-
-      // With clipping.
-      bool blit(int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, const image& src)
-      {
-         if ((!is_valid()) || (!src.is_valid()))
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         rect src_rect(src_x, src_y, src_x + src_w, src_y + src_h);
-         if (!src_rect.intersect(src.get_bounds()))
-            return false;
-
-         rect dst_rect(dst_x, dst_y, dst_x + src_rect.get_width(), dst_y + src_rect.get_height());
-         if (!dst_rect.intersect(get_bounds()))
-            return false;
-         
-         bool success = unclipped_blit(
-            src_rect.get_left(), src_rect.get_top(), 
-            math::minimum(src_rect.get_width(), dst_rect.get_width()), math::minimum(src_rect.get_height(), dst_rect.get_height()),
-            dst_rect.get_left(), dst_rect.get_top(), src);
-         success;
-         CRNLIB_ASSERT(success);
-
-         return true;
-      }
-
-      // In-place resize of image dimensions (cropping).
-      bool resize(uint new_width, uint new_height, uint new_pitch = UINT_MAX, const color_type background = color_type::make_black())
-      {
-         if (new_pitch == UINT_MAX)
-            new_pitch = new_width;
-
-         if ((new_width == m_width) && (new_height == m_height) && (new_pitch == m_pitch))
-            return true;
-
-         if ((!new_width) || (!new_height) || (!new_pitch))
-         {
-            clear();
-            return false;
-         }
-
-         pixel_buf_t existing_pixels;
-         existing_pixels.swap(m_pixel_buf);
-
-         if (!m_pixel_buf.try_resize(new_height * new_pitch))
-         {
-            clear();
-            return false;
-         }
-
-         for (uint y = 0; y < new_height; y++)
-         {
-            for (uint x = 0; x < new_width; x++)
-            {
-               if ((x < m_width) && (y < m_height))
-                  m_pixel_buf[x + y * new_pitch] = existing_pixels[x + y * m_pitch];
-               else
-                  m_pixel_buf[x + y * new_pitch] = background;
-            }
-         }
-
-         m_width = new_width;
-         m_height = new_height;
-         m_pitch = new_pitch;
-         m_total = new_pitch * new_height;
-         m_pPixels = &m_pixel_buf.front();
-
-         return true;
-      }
-
-      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 rect get_bounds() const { return rect(0, 0, m_width, m_height); }
-
-      inline uint get_pitch() const { return m_pitch; }
-      inline uint get_pitch_in_bytes() const { return m_pitch * sizeof(color_type); }
-
-      // Returns pitch * height, NOT width * height!
-      inline uint get_total() const { return m_total; }
-
-      inline uint get_block_width(uint block_size) const { return (m_width + block_size - 1) / block_size; }
-      inline uint get_block_height(uint block_size) const { return (m_height + block_size - 1) / block_size; }
-      inline uint get_total_blocks(uint block_size) const { return get_block_width(block_size) * get_block_height(block_size); }
-
-      inline uint get_size_in_bytes() const { return sizeof(color_type) * m_total; }
-
-      inline const color_type* get_pixels() const  { return m_pPixels; }
-      inline       color_type* get_pixels()        { return m_pPixels; }
-
-      inline const color_type& operator() (uint x, uint y) const
-      {
-         CRNLIB_ASSERT((x < m_width) && (y < m_height));
-         return m_pPixels[x + y * m_pitch];
-      }
-
-      inline color_type& operator() (uint x, uint y)
-      {
-         CRNLIB_ASSERT((x < m_width) && (y < m_height));
-         return m_pPixels[x + y * m_pitch];
-      }
-
-      inline const color_type& get_unclamped(uint x, uint y) const
-      {
-         CRNLIB_ASSERT((x < m_width) && (y < m_height));
-         return m_pPixels[x + y * m_pitch];
-      }
-
-      inline const color_type& get_clamped(int x, int y) const
-      {
-         x = math::clamp<int>(x, 0, m_width - 1);
-         y = math::clamp<int>(y, 0, m_height - 1);
-         return m_pPixels[x + y * m_pitch];
-      }
-
-      // Sample image with bilinear filtering.
-      // (x,y) - Continuous coordinates, where pixel centers are at (.5,.5), valid image coords are [0,width] and [0,height].
-      void get_filtered(float x, float y, color_type& result) const
-      {
-         x -= .5f;
-         y -= .5f;
-
-         int ix = (int)floor(x);
-         int iy = (int)floor(y);
-         float wx = x - ix;
-         float wy = y - iy;
-
-         color_type a(get_clamped(ix, iy));
-         color_type b(get_clamped(ix + 1, iy));
-         color_type c(get_clamped(ix, iy + 1));
-         color_type d(get_clamped(ix + 1, iy + 1));
-
-         for (uint i = 0; i < 4; i++)
-         {
-            double top = math::lerp<double>(a[i], b[i], wx);
-            double bot = math::lerp<double>(c[i], d[i], wx);
-            double m = math::lerp<double>(top, bot, wy);
-
-            if (!color_type::component_traits::cFloat)
-               m += .5f;
-
-            result.set_component(i, static_cast< typename color_type::parameter_t >(m));
-         }
-      }
-
-      void get_filtered(float x, float y, vec4F& result) const
-      {
-         x -= .5f;
-         y -= .5f;
-
-         int ix = (int)floor(x);
-         int iy = (int)floor(y);
-         float wx = x - ix;
-         float wy = y - iy;
-
-         color_type a(get_clamped(ix, iy));
-         color_type b(get_clamped(ix + 1, iy));
-         color_type c(get_clamped(ix, iy + 1));
-         color_type d(get_clamped(ix + 1, iy + 1));
-
-         for (uint i = 0; i < 4; i++)
-         {
-            float top = math::lerp<float>(a[i], b[i], wx);
-            float bot = math::lerp<float>(c[i], d[i], wx);
-            float m = math::lerp<float>(top, bot, wy);
-
-            result[i] = m;
-         }
-      }
-
-      inline void set_pixel_unclipped(uint x, uint y, const color_type& c)
-      {
-         CRNLIB_ASSERT((x < m_width) && (y < m_height));
-         m_pPixels[x + y * m_pitch] = c;
-      }
-
-      inline void set_pixel_clipped(int x, int y, const color_type& c)
-      {
-         if ((static_cast<uint>(x) >= m_width) || (static_cast<uint>(y) >= m_height))
-            return;
-
-         m_pPixels[x + y * m_pitch] = c;
-      }
-
-      inline const color_type* get_scanline(uint y) const
-      {
-         CRNLIB_ASSERT(y < m_height);
-         return &m_pPixels[y * m_pitch];
-      }
-
-      inline color_type* get_scanline(uint y)
-      {
-         CRNLIB_ASSERT(y < m_height);
-         return &m_pPixels[y * m_pitch];
-      }
-
-      inline const color_type* get_ptr() const
-      {
-         return m_pPixels;
-      }
-
-      inline color_type* get_ptr()
-      {
-         return m_pPixels;
-      }
-
-      inline void swap(image& other)
-      {
-         utils::swap(m_width, other.m_width);
-         utils::swap(m_height, other.m_height);
-         utils::swap(m_pitch, other.m_pitch);
-         utils::swap(m_total, other.m_total);
-         utils::swap(m_comp_flags, other.m_comp_flags);
-         utils::swap(m_pPixels, other.m_pPixels);
-         m_pixel_buf.swap(other.m_pixel_buf);
-      }
-
-      void draw_line(int xs, int ys, int xe, int ye, const color_type& color)
-      {
-         if (xs > xe)
-         {
-            utils::swap(xs, xe);
-            utils::swap(ys, ye);
-         }
-
-         int dx = xe - xs, dy = ye - ys;
-         if (!dx)
-         {
-            if (ys > ye)
-               utils::swap(ys, ye);
-            for (int i = ys ; i <= ye ; i++)
-               set_pixel_clipped(xs, i, color);
-         }
-         else if (!dy)
-         {
-            for (int i = xs ; i < xe ; i++)
-               set_pixel_clipped(i, ys, color);
-         }
-         else if (dy > 0)
-         {
-            if (dy <= dx)
-            {
-               int e = 2 * dy - dx, e_no_inc = 2 * dy, e_inc = 2 * (dy - dx);
-               rasterize_line(xs, ys, xe, ye, 0, 1, e, e_inc, e_no_inc, color);
-            }
-            else
-            {
-               int e = 2 * dx - dy, e_no_inc = 2 * dx, e_inc = 2 * (dx - dy);
-               rasterize_line(xs, ys, xe, ye, 1, 1, e, e_inc, e_no_inc, color);
-            }
-         }
-         else
-         {
-            dy = -dy;
-            if (dy <= dx)
-            {
-               int e = 2 * dy - dx, e_no_inc = 2 * dy, e_inc = 2 * (dy - dx);
-               rasterize_line(xs, ys, xe, ye, 0, -1, e, e_inc, e_no_inc, color);
-            }
-            else
-            {
-               int e = 2 * dx - dy, e_no_inc = (2 * dx), e_inc = 2 * (dx - dy);
-               rasterize_line(xe, ye, xs, ys, 1, -1, e, e_inc, e_no_inc, color);
-            }
-         }
-      }
-
-      const pixel_buf_t& get_pixel_buf() const  { return m_pixel_buf; }
-            pixel_buf_t& get_pixel_buf()        { return m_pixel_buf; }
-
-   private:
-      uint                    m_width;
-      uint                    m_height;
-      uint                    m_pitch;
-      uint                    m_total;
-      uint                    m_comp_flags;
-
-      color_type*             m_pPixels;
-
-      pixel_buf_t             m_pixel_buf;
-
-      void rasterize_line(int xs, int ys, int xe, int ye, int pred, int inc_dec, int e, int e_inc, int e_no_inc, const color_type& color)
-      {
-         int start, end, var;
-
-         if (pred)
-         {
-            start = ys; end = ye; var = xs;
-            for (int i = start; i <= end; i++)
-            {
-               set_pixel_clipped(var, i, color);
-               if (e < 0)
-                  e += e_no_inc;
-               else
-               {
-                  var += inc_dec;
-                  e += e_inc;
-               }
-            }
-         }
-         else
-         {
-            start = xs; end = xe; var = ys;
-            for (int i = start; i <= end; i++)
-            {
-               set_pixel_clipped(i, var, color);
-               if (e < 0)
-                  e += e_no_inc;
-               else
-               {
-                  var += inc_dec;
-                  e += e_inc;
-               }
-            }
-         }
-      }
-   };
-
-   typedef image<color_quad_u8>  image_u8;
-   typedef image<color_quad_i16> image_i16;
-   typedef image<color_quad_u16> image_u16;
-   typedef image<color_quad_i32> image_i32;
-   typedef image<color_quad_u32> image_u32;
-   typedef image<color_quad_f>   image_f;
-
-   template<typename color_type>
-   inline void swap(image<color_type>& a, image<color_type>& b)
-   {
-      a.swap(b);
-   }
-
-} // namespace crnlib

+ 0 - 1367
Source/ThirdParty/crunch/crnlib/crn_image_utils.cpp

@@ -1,1367 +0,0 @@
-// File: crn_image_utils.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_image_utils.h"
-#include "crn_console.h"
-#include "crn_resampler.h"
-#include "crn_threaded_resampler.h"
-#include "crn_strutils.h"
-#include "crn_file_utils.h"
-#include "crn_threading.h"
-#include "crn_miniz.h"
-#include "crn_jpge.h"
-#include "crn_cfile_stream.h"
-#include "crn_mipmapped_texture.h"
-#include "crn_buffer_stream.h"
-
-#define STBI_HEADER_FILE_ONLY
-#include "crn_stb_image.cpp"
-
-#include "crn_jpgd.h"
-
-#include "crn_pixel_format.h"
-
-namespace crnlib
-{
-   const float cInfinitePSNR = 999999.0f;
-   const uint CRNLIB_LARGEST_SUPPORTED_IMAGE_DIMENSION = 16384;
-
-   namespace image_utils
-   {
-      bool read_from_stream_stb(data_stream_serializer &serializer, image_u8& img)
-      {
-         uint8_vec buf;
-         if (!serializer.read_entire_file(buf))
-            return false;
-
-         int x = 0, y = 0, n = 0;
-         unsigned char* pData = stbi_load_from_memory(buf.get_ptr(), buf.size_in_bytes(), &x, &y, &n, 4);
-
-         if (!pData)
-            return false;
-
-         if ((x > (int)CRNLIB_LARGEST_SUPPORTED_IMAGE_DIMENSION) || (y > (int)CRNLIB_LARGEST_SUPPORTED_IMAGE_DIMENSION))
-         {
-            stbi_image_free(pData);
-            return false;
-         }
-
-         const bool has_alpha = ((n == 2) || (n == 4));
-
-         img.resize(x, y);
-
-         bool grayscale = true;
-
-         for (int py = 0; py < y; py++)
-         {
-            const color_quad_u8* pSrc = reinterpret_cast<const color_quad_u8*>(pData) + (py * x);
-            color_quad_u8* pDst = img.get_scanline(py);
-            color_quad_u8* pDst_end = pDst + x;
-
-            while (pDst != pDst_end)
-            {
-               color_quad_u8 c(*pSrc++);
-               if (!has_alpha)
-                  c.a = 255;
-
-               if (!c.is_grayscale())
-                  grayscale = false;
-
-               *pDst++ = c;
-            }
-         }
-
-         stbi_image_free(pData);
-
-         img.reset_comp_flags();
-         img.set_grayscale(grayscale);
-         img.set_component_valid(3, has_alpha);
-
-         return true;
-      }
-
-      bool read_from_stream_jpgd(data_stream_serializer &serializer, image_u8& img)
-      {
-         uint8_vec buf;
-         if (!serializer.read_entire_file(buf))
-            return false;
-
-         int width = 0, height = 0, actual_comps = 0;
-         unsigned char *pSrc_img = jpgd::decompress_jpeg_image_from_memory(buf.get_ptr(), buf.size_in_bytes(), &width, &height, &actual_comps, 4);
-         if (!pSrc_img)
-            return false;
-
-         if (math::maximum(width, height) > (int)CRNLIB_LARGEST_SUPPORTED_IMAGE_DIMENSION)
-         {
-            crnlib_free(pSrc_img);
-            return false;
-         }
-
-         if (!img.grant_ownership(reinterpret_cast<color_quad_u8*>(pSrc_img), width, height))
-         {
-            crnlib_free(pSrc_img);
-            return false;
-         }
-
-         img.reset_comp_flags();
-         img.set_grayscale(actual_comps == 1);
-         img.set_component_valid(3, false);
-
-         return true;
-      }
-
-      bool read_from_stream(image_u8& dest, data_stream_serializer& serializer, uint read_flags)
-      {
-         if (read_flags > cReadFlagsAllFlags)
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         if (!serializer.get_stream())
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         dynamic_string ext(serializer.get_name());
-         file_utils::get_extension(ext);
-
-         if ((ext == "jpg") || (ext == "jpeg"))
-         {
-            // Use my jpeg decoder by default because it supports progressive jpeg's.
-            if ((read_flags & cReadFlagForceSTB) == 0)
-            {
-               return image_utils::read_from_stream_jpgd(serializer, dest);
-            }
-         }
-
-         return image_utils::read_from_stream_stb(serializer, dest);
-      }
-
-      bool read_from_file(image_u8& dest, const char* pFilename, uint read_flags)
-      {
-         if (read_flags > cReadFlagsAllFlags)
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         cfile_stream file_stream;
-         if (!file_stream.open(pFilename))
-            return false;
-
-         data_stream_serializer serializer(file_stream);
-         return read_from_stream(dest, serializer, read_flags);
-      }
-
-      bool write_to_file(const char* pFilename, const image_u8& img, uint write_flags, int grayscale_comp_index)
-      {
-         if ((grayscale_comp_index < -1) || (grayscale_comp_index > 3))
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         if (!img.get_width())
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-
-         dynamic_string ext(pFilename);
-         bool is_jpeg = false;
-         if (file_utils::get_extension(ext))
-         {
-            is_jpeg = ((ext == "jpg") || (ext == "jpeg"));
-
-            if ((ext != "png") && (ext != "bmp") && (ext != "tga") && (!is_jpeg))
-            {
-               console::error("crnlib::image_utils::write_to_file: Can only write .BMP, .TGA, .PNG, or .JPG files!\n");
-               return false;
-            }
-         }
-
-         crnlib::vector<uint8> temp;
-         uint num_src_chans = 0;
-         const void *pSrc_img = NULL;
-
-         if (is_jpeg)
-         {
-            write_flags |= cWriteFlagIgnoreAlpha;
-         }
-
-         if ((img.get_comp_flags() & pixel_format_helpers::cCompFlagGrayscale) || (write_flags & image_utils::cWriteFlagGrayscale))
-         {
-            CRNLIB_ASSERT(grayscale_comp_index < 4);
-            if (grayscale_comp_index > 3) grayscale_comp_index = 3;
-
-            temp.resize(img.get_total_pixels());
-
-            for (uint y = 0; y < img.get_height(); y++)
-            {
-               const color_quad_u8* pSrc = img.get_scanline(y);
-               const color_quad_u8* pSrc_end = pSrc + img.get_width();
-               uint8* pDst = &temp[y * img.get_width()];
-
-               if (img.get_comp_flags() & pixel_format_helpers::cCompFlagGrayscale)
-               {
-                  while (pSrc != pSrc_end)
-                     *pDst++ = (*pSrc++)[1];
-               }
-               else if (grayscale_comp_index < 0)
-               {
-                  while (pSrc != pSrc_end)
-                     *pDst++ = static_cast<uint8>((*pSrc++).get_luma());
-               }
-               else
-               {
-                  while (pSrc != pSrc_end)
-                     *pDst++ = (*pSrc++)[grayscale_comp_index];
-               }
-            }
-
-            pSrc_img = &temp[0];
-            num_src_chans = 1;
-         }
-         else if ((!img.is_component_valid(3)) || (write_flags & cWriteFlagIgnoreAlpha))
-         {
-            temp.resize(img.get_total_pixels() * 3);
-
-            for (uint y = 0; y < img.get_height(); y++)
-            {
-               const color_quad_u8* pSrc = img.get_scanline(y);
-               const color_quad_u8* pSrc_end = pSrc + img.get_width();
-               uint8* pDst = &temp[y * img.get_width() * 3];
-
-               while (pSrc != pSrc_end)
-               {
-                  const color_quad_u8 c(*pSrc++);
-
-                  pDst[0] = c.r;
-                  pDst[1] = c.g;
-                  pDst[2] = c.b;
-
-                  pDst += 3;
-               }
-            }
-
-            num_src_chans = 3;
-            pSrc_img = &temp[0];
-         }
-         else
-         {
-            num_src_chans = 4;
-            pSrc_img = img.get_ptr();
-         }
-
-         bool success = false;
-         if (ext == "png")
-         {
-            size_t png_image_size = 0;
-            void *pPNG_image_data = tdefl_write_image_to_png_file_in_memory(pSrc_img, img.get_width(), img.get_height(), num_src_chans, &png_image_size);
-            if (!pPNG_image_data)
-               return false;
-            success = file_utils::write_buf_to_file(pFilename, pPNG_image_data, png_image_size);
-            mz_free(pPNG_image_data);
-         }
-         else if (is_jpeg)
-         {
-            jpge::params params;
-            if (write_flags & cWriteFlagJPEGQualityLevelMask)
-               params.m_quality = math::clamp<uint>((write_flags & cWriteFlagJPEGQualityLevelMask) >> cWriteFlagJPEGQualityLevelShift, 1U, 100U);
-            params.m_two_pass_flag = (write_flags & cWriteFlagJPEGTwoPass) != 0;
-            params.m_no_chroma_discrim_flag = (write_flags & cWriteFlagJPEGNoChromaDiscrim) != 0;
-
-            if (write_flags & cWriteFlagJPEGH1V1)
-               params.m_subsampling = jpge::H1V1;
-            else if (write_flags & cWriteFlagJPEGH2V1)
-               params.m_subsampling = jpge::H2V1;
-            else if (write_flags & cWriteFlagJPEGH2V2)
-               params.m_subsampling = jpge::H2V2;
-
-            success = jpge::compress_image_to_jpeg_file(pFilename, img.get_width(), img.get_height(), num_src_chans, (const jpge::uint8*)pSrc_img, params);
-         }
-         else
-         {
-            success = ((ext == "bmp" ? stbi_write_bmp : stbi_write_tga)(pFilename, img.get_width(), img.get_height(), num_src_chans, pSrc_img) == CRNLIB_TRUE);
-         }
-         return success;
-      }
-
-      bool has_alpha(const image_u8& img)
-      {
-         for (uint y = 0; y < img.get_height(); y++)
-            for (uint x = 0; x < img.get_width(); x++)
-               if (img(x, y).a < 255)
-                  return true;
-
-         return false;
-      }
-
-      void renorm_normal_map(image_u8& img)
-      {
-         for (uint y = 0; y < img.get_height(); y++)
-         {
-            for (uint x = 0; x < img.get_width(); x++)
-            {
-               color_quad_u8& c = img(x, y);
-               if ((c.r == 128) && (c.g == 128) && (c.b == 128))
-                  continue;
-
-               vec3F v(c.r, c.g, c.b);
-               v *= 1.0f/255.0f;
-               v *= 2.0f;
-               v -= vec3F(1.0f);
-               v.clamp(-1.0f, 1.0f);
-
-               float length = v.length();
-               if (length < .077f)
-                  c.set(128, 128, 128, c.a);
-               else if (fabs(length - 1.0f) > .077f)
-               {
-                  if (length)
-                     v /= length;
-
-                  for (uint i = 0; i < 3; i++)
-                     c[i] = static_cast<uint8>(math::clamp<float>(floor((v[i] + 1.0f) * .5f * 255.0f + .5f), 0.0f, 255.0f));
-
-                  if ((c.r == 128) && (c.g == 128))
-                  {
-                     if (c.b < 128)
-                        c.b = 0;
-                     else
-                        c.b = 255;
-                  }
-               }
-            }
-         }
-      }
-
-      bool is_normal_map(const image_u8& img, const char* pFilename)
-      {
-         float score = 0.0f;
-
-         uint num_invalid_pixels = 0;
-
-         // TODO: Derive better score from pixel mean, eigenvecs/vals
-         //crnlib::vector<vec3F> pixels;
-
-         for (uint y = 0; y < img.get_height(); y++)
-         {
-            for (uint x = 0; x < img.get_width(); x++)
-            {
-               const color_quad_u8& c = img(x, y);
-
-               if (c.b < 123)
-               {
-                  num_invalid_pixels++;
-                  continue;
-               }
-               else if ((c.r != 128) || (c.g != 128) || (c.b != 128))
-               {
-                  vec3F v(c.r, c.g, c.b);
-                  v -= vec3F(128.0f);
-                  v /= vec3F(127.0f);
-                  //pixels.push_back(v);
-                  v.clamp(-1.0f, 1.0f);
-
-                  float norm = v.norm();
-                  if ((norm < 0.83f) || (norm > 1.29f))
-                     num_invalid_pixels++;
-               }
-            }
-         }
-
-         score -= math::clamp(float(num_invalid_pixels) / (img.get_width() * img.get_height()) - .026f, 0.0f, 1.0f) * 5.0f;
-
-         if (pFilename)
-         {
-            dynamic_string str(pFilename);
-            str.tolower();
-
-            if (str.contains("normal")  || str.contains("local") || str.contains("nmap"))
-               score += 1.0f;
-
-            if (str.contains("diffuse") || str.contains("spec") || str.contains("gloss"))
-               score -= 1.0f;
-         }
-
-         return score >= 0.0f;
-      }
-
-      bool resample_single_thread(const image_u8& src, image_u8& dst, const resample_params& params)
-      {
-         const uint src_width = src.get_width();
-         const uint src_height = src.get_height();
-
-         if (math::maximum(src_width, src_height) > CRNLIB_RESAMPLER_MAX_DIMENSION)
-         {
-            printf("Image is too large!\n");
-            return EXIT_FAILURE;
-         }
-
-         const int cMaxComponents = 4;
-         if (((int)params.m_num_comps < 1) || ((int)params.m_num_comps > (int)cMaxComponents))
-            return false;
-
-         const uint dst_width = params.m_dst_width;
-         const uint dst_height = params.m_dst_height;
-
-         if ((math::minimum(dst_width, dst_height) < 1) || (math::maximum(dst_width, dst_height) > CRNLIB_RESAMPLER_MAX_DIMENSION))
-         {
-            printf("Image is too large!\n");
-            return EXIT_FAILURE;
-         }
-
-         if ((src_width == dst_width) && (src_height == dst_height))
-         {
-            dst = src;
-            return true;
-         }
-
-         dst.clear();
-         dst.resize(params.m_dst_width, params.m_dst_height);
-
-         // Partial gamma correction looks better on mips. Set to 1.0 to disable gamma correction.
-         const float source_gamma = params.m_source_gamma;//1.75f;
-
-         float srgb_to_linear[256];
-         if (params.m_srgb)
-         {
-            for (int i = 0; i < 256; ++i)
-               srgb_to_linear[i] = (float)pow(i * 1.0f/255.0f, source_gamma);
-         }
-
-         const int linear_to_srgb_table_size = 8192;
-         unsigned char linear_to_srgb[linear_to_srgb_table_size];
-
-         const float inv_linear_to_srgb_table_size = 1.0f / linear_to_srgb_table_size;
-         const float inv_source_gamma = 1.0f / source_gamma;
-
-         if (params.m_srgb)
-         {
-            for (int i = 0; i < linear_to_srgb_table_size; ++i)
-            {
-               int k = (int)(255.0f * pow(i * inv_linear_to_srgb_table_size, inv_source_gamma) + .5f);
-               if (k < 0) k = 0; else if (k > 255) k = 255;
-               linear_to_srgb[i] = (unsigned char)k;
-            }
-         }
-
-         Resampler* resamplers[cMaxComponents];
-         crnlib::vector<float> samples[cMaxComponents];
-
-         resamplers[0] = crnlib_new<Resampler>(src_width, src_height, dst_width, dst_height,
-            params.m_wrapping ? Resampler::BOUNDARY_WRAP : Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f,
-            params.m_pFilter, (Resampler::Contrib_List*)NULL, (Resampler::Contrib_List*)NULL, params.m_filter_scale, params.m_filter_scale);
-         samples[0].resize(src_width);
-
-         for (uint i = 1; i < params.m_num_comps; i++)
-         {
-            resamplers[i] = crnlib_new<Resampler>(src_width, src_height, dst_width, dst_height,
-               params.m_wrapping ? Resampler::BOUNDARY_WRAP : Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f,
-               params.m_pFilter, resamplers[0]->get_clist_x(), resamplers[0]->get_clist_y(), params.m_filter_scale, params.m_filter_scale);
-            samples[i].resize(src_width);
-         }
-
-         uint dst_y = 0;
-
-         for (uint src_y = 0; src_y < src_height; src_y++)
-         {
-            const color_quad_u8* pSrc = src.get_scanline(src_y);
-
-            for (uint x = 0; x < src_width; x++)
-            {
-               for (uint c = 0; c < params.m_num_comps; c++)
-               {
-                  const uint comp_index = params.m_first_comp + c;
-                  const uint8 v = (*pSrc)[comp_index];
-
-                  if (!params.m_srgb || (comp_index == 3))
-                     samples[c][x] = v * (1.0f/255.0f);
-                  else
-                     samples[c][x] = srgb_to_linear[v];
-               }
-
-               pSrc++;
-            }
-
-            for (uint c = 0; c < params.m_num_comps; c++)
-            {
-               if (!resamplers[c]->put_line(&samples[c][0]))
-               {
-                  for (uint i = 0; i < params.m_num_comps; i++)
-                     crnlib_delete(resamplers[i]);
-                  return false;
-               }
-            }
-
-            for ( ; ; )
-            {
-               uint c;
-               for (c = 0; c < params.m_num_comps; c++)
-               {
-                  const uint comp_index = params.m_first_comp + c;
-
-                  const float* pOutput_samples = resamplers[c]->get_line();
-                  if (!pOutput_samples)
-                     break;
-
-                  const bool linear = !params.m_srgb || (comp_index == 3);
-                  CRNLIB_ASSERT(dst_y < dst_height);
-                  color_quad_u8* pDst = dst.get_scanline(dst_y);
-
-                  for (uint x = 0; x < dst_width; x++)
-                  {
-                     if (linear)
-                     {
-                        int c = (int)(255.0f * pOutput_samples[x] + .5f);
-                        if (c < 0) c = 0; else if (c > 255) c = 255;
-                        (*pDst)[comp_index] = (unsigned char)c;
-                     }
-                     else
-                     {
-                        int j = (int)(linear_to_srgb_table_size * pOutput_samples[x] + .5f);
-                        if (j < 0) j = 0; else if (j >= linear_to_srgb_table_size) j = linear_to_srgb_table_size - 1;
-                        (*pDst)[comp_index] = linear_to_srgb[j];
-                     }
-
-                     pDst++;
-                  }
-               }
-               if (c < params.m_num_comps)
-                  break;
-
-               dst_y++;
-            }
-         }
-
-         for (uint i = 0; i < params.m_num_comps; i++)
-            crnlib_delete(resamplers[i]);
-
-         return true;
-      }
-
-      bool resample_multithreaded(const image_u8& src, image_u8& dst, const resample_params& params)
-      {
-         const uint src_width = src.get_width();
-         const uint src_height = src.get_height();
-
-         if (math::maximum(src_width, src_height) > CRNLIB_RESAMPLER_MAX_DIMENSION)
-         {
-            printf("Image is too large!\n");
-            return EXIT_FAILURE;
-         }
-
-         const int cMaxComponents = 4;
-         if (((int)params.m_num_comps < 1) || ((int)params.m_num_comps > (int)cMaxComponents))
-            return false;
-
-         const uint dst_width = params.m_dst_width;
-         const uint dst_height = params.m_dst_height;
-
-         if ((math::minimum(dst_width, dst_height) < 1) || (math::maximum(dst_width, dst_height) > CRNLIB_RESAMPLER_MAX_DIMENSION))
-         {
-            printf("Image is too large!\n");
-            return EXIT_FAILURE;
-         }
-
-         if ((src_width == dst_width) && (src_height == dst_height))
-         {
-            dst = src;
-            return true;
-         }
-
-         dst.clear();
-
-         // Partial gamma correction looks better on mips. Set to 1.0 to disable gamma correction.
-         const float source_gamma = params.m_source_gamma;//1.75f;
-
-         float srgb_to_linear[256];
-         if (params.m_srgb)
-         {
-            for (int i = 0; i < 256; ++i)
-               srgb_to_linear[i] = (float)pow(i * 1.0f/255.0f, source_gamma);
-         }
-
-         const int linear_to_srgb_table_size = 8192;
-         unsigned char linear_to_srgb[linear_to_srgb_table_size];
-
-         const float inv_linear_to_srgb_table_size = 1.0f / linear_to_srgb_table_size;
-         const float inv_source_gamma = 1.0f / source_gamma;
-
-         if (params.m_srgb)
-         {
-            for (int i = 0; i < linear_to_srgb_table_size; ++i)
-            {
-               int k = (int)(255.0f * pow(i * inv_linear_to_srgb_table_size, inv_source_gamma) + .5f);
-               if (k < 0) k = 0; else if (k > 255) k = 255;
-               linear_to_srgb[i] = (unsigned char)k;
-            }
-         }
-
-         task_pool tp;
-         tp.init(g_number_of_processors - 1);
-
-         threaded_resampler resampler(tp);
-         threaded_resampler::params p;
-         p.m_src_width = src_width;
-         p.m_src_height = src_height;
-         p.m_dst_width = dst_width;
-         p.m_dst_height = dst_height;
-         p.m_sample_low = 0.0f;
-         p.m_sample_high = 1.0f;
-         p.m_boundary_op = params.m_wrapping ? Resampler::BOUNDARY_WRAP : Resampler::BOUNDARY_CLAMP;
-         p.m_Pfilter_name = params.m_pFilter;
-         p.m_filter_x_scale = params.m_filter_scale;
-         p.m_filter_y_scale = params.m_filter_scale;
-
-         uint resampler_comps = 4;
-         if (params.m_num_comps == 1)
-         {
-            p.m_fmt = threaded_resampler::cPF_Y_F32;
-            resampler_comps = 1;
-         }
-         else if (params.m_num_comps <= 3)
-            p.m_fmt = threaded_resampler::cPF_RGBX_F32;
-         else
-            p.m_fmt = threaded_resampler::cPF_RGBA_F32;
-
-         crnlib::vector<float> src_samples;
-         crnlib::vector<float> dst_samples;
-
-         if (!src_samples.try_resize(src_width * src_height * resampler_comps))
-            return false;
-
-         if (!dst_samples.try_resize(dst_width * dst_height * resampler_comps))
-            return false;
-
-         p.m_pSrc_pixels = src_samples.get_ptr();
-         p.m_src_pitch = src_width * resampler_comps * sizeof(float);
-         p.m_pDst_pixels = dst_samples.get_ptr();
-         p.m_dst_pitch = dst_width * resampler_comps * sizeof(float);
-
-         for (uint src_y = 0; src_y < src_height; src_y++)
-         {
-            const color_quad_u8* pSrc = src.get_scanline(src_y);
-            float* pDst = src_samples.get_ptr() + src_width * resampler_comps * src_y;
-
-            for (uint x = 0; x < src_width; x++)
-            {
-               for (uint c = 0; c < params.m_num_comps; c++)
-               {
-                  const uint comp_index = params.m_first_comp + c;
-                  const uint8 v = (*pSrc)[comp_index];
-
-                  if (!params.m_srgb || (comp_index == 3))
-                     pDst[c] = v * (1.0f/255.0f);
-                  else
-                     pDst[c] = srgb_to_linear[v];
-               }
-
-               pSrc++;
-               pDst += resampler_comps;
-            }
-         }
-
-         if (!resampler.resample(p))
-            return false;
-
-         src_samples.clear();
-
-         if (!dst.resize(params.m_dst_width, params.m_dst_height))
-            return false;
-
-         for (uint dst_y = 0; dst_y < dst_height; dst_y++)
-         {
-            const float* pSrc = dst_samples.get_ptr() + dst_width * resampler_comps * dst_y;
-            color_quad_u8* pDst = dst.get_scanline(dst_y);
-
-            for (uint x = 0; x < dst_width; x++)
-            {
-               color_quad_u8 dst(0, 0, 0, 255);
-
-               for (uint c = 0; c < params.m_num_comps; c++)
-               {
-                  const uint comp_index = params.m_first_comp + c;
-                  const float v = pSrc[c];
-
-                  if ((!params.m_srgb) || (comp_index == 3))
-                  {
-                     int c = static_cast<int>(255.0f * v + .5f);
-                     if (c < 0) c = 0; else if (c > 255) c = 255;
-                     dst[comp_index] = (unsigned char)c;
-                  }
-                  else
-                  {
-                     int j = static_cast<int>(linear_to_srgb_table_size * v + .5f);
-                     if (j < 0) j = 0; else if (j >= linear_to_srgb_table_size) j = linear_to_srgb_table_size - 1;
-                     dst[comp_index] = linear_to_srgb[j];
-                  }
-               }
-
-               *pDst++ = dst;
-
-               pSrc += resampler_comps;
-            }
-         }
-
-         return true;
-      }
-
-      bool resample(const image_u8& src, image_u8& dst, const resample_params& params)
-      {
-         if ((params.m_multithreaded) && (g_number_of_processors > 1))
-            return resample_multithreaded(src, dst, params);
-         else
-            return resample_single_thread(src, dst, params);
-      }
-
-      bool compute_delta(image_u8& dest, image_u8& a, image_u8& b, uint scale)
-      {
-         if ( (a.get_width() != b.get_width()) || (a.get_height() != b.get_height()) )
-            return false;
-
-         dest.resize(a.get_width(), b.get_height());
-
-         for (uint y = 0; y < a.get_height(); y++)
-         {
-            for (uint x = 0; x < a.get_width(); x++)
-            {
-               const color_quad_u8& ca = a(x, y);
-               const color_quad_u8& cb = b(x, y);
-
-               color_quad_u8 cd;
-               for (uint c = 0; c < 4; c++)
-               {
-                  int d = (ca[c] - cb[c]) * scale + 128;
-                  d = math::clamp(d, 0, 255);
-                  cd[c] = static_cast<uint8>(d);
-               }
-
-               dest(x, y) = cd;
-            }
-         }
-
-         return true;
-      }
-
-      // FIXME: Totally hack-ass computation.
-      // Perhaps port http://www.lomont.org/Software/Misc/SSIM/SSIM.html?
-      double compute_block_ssim(uint t, const uint8* pX, const uint8* pY)
-      {
-         double ave_x = 0.0f;
-         double ave_y = 0.0f;
-         for (uint i = 0; i < t; i++)
-         {
-            ave_x += pX[i];
-            ave_y += pY[i];
-         }
-
-         ave_x /= t;
-         ave_y /= t;
-
-         double var_x = 0.0f;
-         double var_y = 0.0f;
-         for (uint i = 0; i < t; i++)
-         {
-            var_x += math::square(pX[i] - ave_x);
-            var_y += math::square(pY[i] - ave_y);
-         }
-
-         var_x = sqrt(var_x / (t - 1));
-         var_y = sqrt(var_y / (t - 1));
-
-         double covar_xy = 0.0f;
-         for (uint i = 0; i < t; i++)
-            covar_xy += (pX[i] - ave_x) * (pY[i] - ave_y);
-
-         covar_xy /= (t - 1);
-
-         const double c1 = 6.5025; //(255*.01)^2
-         const double c2 = 58.5225; //(255*.03)^2
-
-         double n = (2.0f * ave_x * ave_y + c1) * (2.0f * covar_xy + c2);
-         double d = (ave_x * ave_x + ave_y * ave_y + c1) * (var_x * var_x + var_y * var_y + c2);
-
-         return n / d;
-      }
-
-      double compute_ssim(const image_u8& a, const image_u8& b, int channel_index)
-      {
-         const uint N = 6;
-         uint8 sx[N*N], sy[N*N];
-
-         double total_ssim = 0.0f;
-         uint total_blocks = 0;
-
-         //image_u8 yimg((a.get_width() + N - 1) / N, (a.get_height() + N - 1) / N);
-
-         for (uint y = 0; y < a.get_height(); y += N)
-         {
-            for (uint x = 0; x < a.get_width(); x += N)
-            {
-               for (uint iy = 0; iy < N; iy++)
-               {
-                  for (uint ix = 0; ix < N; ix++)
-                  {
-                     if (channel_index < 0)
-                        sx[ix+iy*N] = (uint8)a.get_clamped(x+ix, y+iy).get_luma();
-                     else
-                        sx[ix+iy*N] = (uint8)a.get_clamped(x+ix, y+iy)[channel_index];
-
-                     if (channel_index < 0)
-                        sy[ix+iy*N] = (uint8)b.get_clamped(x+ix, y+iy).get_luma();
-                     else
-                        sy[ix+iy*N] = (uint8)b.get_clamped(x+ix, y+iy)[channel_index];
-                  }
-               }
-
-               double ssim = compute_block_ssim(N*N, sx, sy);
-               total_ssim += ssim;
-               total_blocks++;
-
-               //uint ssim_c = (uint)math::clamp<double>(ssim * 127.0f + 128.0f, 0, 255);
-               //yimg(x / N, y / N).set(ssim_c, ssim_c, ssim_c, 255);
-            }
-         }
-
-         if (!total_blocks)
-            return 0.0f;
-
-         //save_to_file_stb_or_miniz("ssim.tga", yimg, cWriteFlagGrayscale);
-
-         return total_ssim / total_blocks;
-      }
-
-      void print_ssim(const image_u8& src_img, const image_u8& dst_img)
-      {
-         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("   R MSSIM: %f", r_ssim);
-
-         //double g_ssim = compute_ssim(src_img, dst_img, 1);
-         //console::printf("   G MSSIM: %f", g_ssim);
-
-         //double b_ssim = compute_ssim(src_img, dst_img, 2);
-         //console::printf("   B MSSIM: %f", b_ssim);
-      }
-
-      void error_metrics::print(const char* pName) const
-      {
-         if (mPeakSNR >= cInfinitePSNR)
-            console::printf("%s Error: Max: %3u, Mean: %3.3f, MSE: %3.3f, RMSE: %3.3f, PSNR: Infinite", pName, mMax, mMean, mMeanSquared, mRootMeanSquared);
-         else
-            console::printf("%s Error: Max: %3u, Mean: %3.3f, MSE: %3.3f, RMSE: %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)
-      {
-         //if ( (!a.get_width()) || (!b.get_height()) || (a.get_width() != b.get_width()) || (a.get_height() != b.get_height()) )
-         //   return false;
-
-         const uint width = math::minimum(a.get_width(), b.get_width());
-         const uint height = math::minimum(a.get_height(), b.get_height());
-
-         CRNLIB_ASSERT((first_channel < 4U) && (first_channel + num_channels <= 4U));
-
-         // Histogram approach due to Charles Bloom.
-         double hist[256];
-         utils::zero_object(hist);
-
-         for (uint y = 0; y < height; y++)
-         {
-            for (uint x = 0; x < width; x++)
-            {
-               const color_quad_u8& ca = a(x, y);
-               const color_quad_u8& cb = b(x, y);
-
-               if (!num_channels)
-                  hist[labs(ca.get_luma() - cb.get_luma())]++;
-               else
-               {
-                  for (uint c = 0; c < num_channels; c++)
-                     hist[labs(ca[first_channel + c] - cb[first_channel + c])]++;
-               }
-            }
-         }
-
-         mMax = 0;
-         double sum = 0.0f, sum2 = 0.0f;
-         for (uint i = 0; i < 256; i++)
-         {
-            if (!hist[i])
-               continue;
-
-            mMax = math::maximum(mMax, i);
-
-            double x = i * hist[i];
-
-            sum += x;
-            sum2 += i * x;
-         }
-
-         // See http://bmrc.berkeley.edu/courseware/cs294/fall97/assignment/psnr.html
-         double total_values = width * height;
-
-         if (average_component_error)
-            total_values *= math::clamp<uint>(num_channels, 1, 4);
-
-         mMean = math::clamp<double>(sum / total_values, 0.0f, 255.0f);
-         mMeanSquared = math::clamp<double>(sum2 / total_values, 0.0f, 255.0f*255.0f);
-
-         mRootMeanSquared = sqrt(mMeanSquared);
-
-         if (!mRootMeanSquared)
-            mPeakSNR = cInfinitePSNR;
-         else
-            mPeakSNR = math::clamp<double>(log10(255.0f / mRootMeanSquared) * 20.0f, 0.0f, 500.0f);
-
-         return true;
-      }
-
-      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("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("RGB Total  ");
-
-            error_metrics.compute(src_img, dst_img, 0, 3, true);
-            error_metrics.print("RGB Average");
-
-            error_metrics.compute(src_img, dst_img, 0, 0);
-            error_metrics.print("Luma       ");
-
-            error_metrics.compute(src_img, dst_img, 0, 1);
-            error_metrics.print("Red        ");
-
-            error_metrics.compute(src_img, dst_img, 1, 1);
-            error_metrics.print("Green      ");
-
-            error_metrics.compute(src_img, dst_img, 2, 1);
-            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("Alpha      ");
-         }
-      }
-
-      static uint8 regen_z(uint x, uint y)
-      {
-         float vx = math::clamp((x - 128.0f) * 1.0f/127.0f, -1.0f, 1.0f);
-         float vy = math::clamp((y - 128.0f) * 1.0f/127.0f, -1.0f, 1.0f);
-         float vz = sqrt(math::clamp(1.0f - vx * vx - vy * vy, 0.0f, 1.0f));
-
-         vz = vz * 127.0f + 128.0f;
-
-         if (vz < 128.0f)
-            vz -= .5f;
-         else
-            vz += .5f;
-
-         int ib = math::float_to_int(vz);
-
-         return static_cast<uint8>(math::clamp(ib, 0, 255));
-      }
-
-      void convert_image(image_u8& img, image_utils::conversion_type conv_type)
-      {
-         switch (conv_type)
-         {
-            case image_utils::cConversion_To_CCxY:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagAValid | pixel_format_helpers::cCompFlagLumaChroma));
-               break;
-            }
-            case image_utils::cConversion_From_CCxY:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid));
-               break;
-            }
-            case image_utils::cConversion_To_xGxR:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagAValid | pixel_format_helpers::cCompFlagNormalMap));
-               break;
-            }
-            case image_utils::cConversion_From_xGxR:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid | pixel_format_helpers::cCompFlagNormalMap));
-               break;
-            }
-            case image_utils::cConversion_To_xGBR:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid | pixel_format_helpers::cCompFlagAValid | pixel_format_helpers::cCompFlagNormalMap));
-               break;
-            }
-            case image_utils::cConversion_To_AGBR:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid | pixel_format_helpers::cCompFlagAValid | pixel_format_helpers::cCompFlagNormalMap));
-               break;
-            }
-            case image_utils::cConversion_From_xGBR:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid | pixel_format_helpers::cCompFlagNormalMap));
-               break;
-            }
-            case image_utils::cConversion_From_AGBR:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid | pixel_format_helpers::cCompFlagAValid | pixel_format_helpers::cCompFlagNormalMap));
-               break;
-            }
-            case image_utils::cConversion_XY_to_XYZ:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid | pixel_format_helpers::cCompFlagNormalMap));
-               break;
-            }
-            case cConversion_Y_To_A:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(img.get_comp_flags() | pixel_format_helpers::cCompFlagAValid));
-               break;
-            }
-            case cConversion_A_To_RGBA:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid | pixel_format_helpers::cCompFlagAValid));
-               break;
-            }
-            case cConversion_Y_To_RGB:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(pixel_format_helpers::cCompFlagRValid | pixel_format_helpers::cCompFlagGValid | pixel_format_helpers::cCompFlagBValid | pixel_format_helpers::cCompFlagGrayscale | (img.has_alpha() ? pixel_format_helpers::cCompFlagAValid : 0)));
-               break;
-            }
-            case cConversion_To_Y:
-            {
-               img.set_comp_flags(static_cast<pixel_format_helpers::component_flags>(img.get_comp_flags() | pixel_format_helpers::cCompFlagGrayscale));
-               break;
-            }
-            default:
-            {
-               CRNLIB_ASSERT(false);
-               return;
-            }
-         }
-
-         for (uint y = 0; y < img.get_height(); y++)
-         {
-            for (uint x = 0; x < img.get_width(); x++)
-            {
-               color_quad_u8 src(img(x, y));
-               color_quad_u8 dst;
-
-               switch (conv_type)
-               {
-                  case image_utils::cConversion_To_CCxY:
-                  {
-                     color::RGB_to_YCC(dst, src);
-                     break;
-                  }
-                  case image_utils::cConversion_From_CCxY:
-                  {
-                     color::YCC_to_RGB(dst, src);
-                     break;
-                  }
-                  case image_utils::cConversion_To_xGxR:
-                  {
-                     dst.r = 0;
-                     dst.g = src.g;
-                     dst.b = 0;
-                     dst.a = src.r;
-                     break;
-                  }
-                  case image_utils::cConversion_From_xGxR:
-                  {
-                     dst.r = src.a;
-                     dst.g = src.g;
-                     // This is kinda iffy, we're assuming the image is a normal map here.
-                     dst.b = regen_z(src.a, src.g);
-                     dst.a = 255;
-                     break;
-                  }
-                  case image_utils::cConversion_To_xGBR:
-                  {
-                     dst.r = 0;
-                     dst.g = src.g;
-                     dst.b = src.b;
-                     dst.a = src.r;
-                     break;
-                  }
-                  case image_utils::cConversion_To_AGBR:
-                  {
-                     dst.r = src.a;
-                     dst.g = src.g;
-                     dst.b = src.b;
-                     dst.a = src.r;
-                     break;
-                  }
-                  case image_utils::cConversion_From_xGBR:
-                  {
-                     dst.r = src.a;
-                     dst.g = src.g;
-                     dst.b = src.b;
-                     dst.a = 255;
-                     break;
-                  }
-                  case image_utils::cConversion_From_AGBR:
-                  {
-                     dst.r = src.a;
-                     dst.g = src.g;
-                     dst.b = src.b;
-                     dst.a = src.r;
-                     break;
-                  }
-                  case image_utils::cConversion_XY_to_XYZ:
-                  {
-                     dst.r = src.r;
-                     dst.g = src.g;
-                     // This is kinda iffy, we're assuming the image is a normal map here.
-                     dst.b = regen_z(src.r, src.g);
-                     dst.a = 255;
-                     break;
-                  }
-                  case image_utils::cConversion_Y_To_A:
-                  {
-                     dst.r = src.r;
-                     dst.g = src.g;
-                     dst.b = src.b;
-                     dst.a = static_cast<uint8>(src.get_luma());
-                     break;
-                  }
-                  case image_utils::cConversion_Y_To_RGB:
-                  {
-                     uint8 y = static_cast<uint8>(src.get_luma());
-                     dst.r = y;
-                     dst.g = y;
-                     dst.b = y;
-                     dst.a = src.a;
-                     break;
-                  }
-                  case image_utils::cConversion_A_To_RGBA:
-                  {
-                     dst.r = src.a;
-                     dst.g = src.a;
-                     dst.b = src.a;
-                     dst.a = src.a;
-                     break;
-                  }
-                  case image_utils::cConversion_To_Y:
-                  {
-                     uint8 y = static_cast<uint8>(src.get_luma());
-                     dst.r = y;
-                     dst.g = y;
-                     dst.b = y;
-                     dst.a = src.a;
-                     break;
-                  }
-                  default:
-                  {
-                     CRNLIB_ASSERT(false);
-                     dst = src;
-                     break;
-                  }
-               }
-
-               img(x, y) = dst;
-            }
-         }
-      }
-
-      image_utils::conversion_type get_conversion_type(bool cooking, pixel_format fmt)
-      {
-         image_utils::conversion_type conv_type = image_utils::cConversion_Invalid;
-
-         if (cooking)
-         {
-            switch (fmt)
-            {
-               case PIXEL_FMT_DXT5_CCxY:
-               {
-                  conv_type = image_utils::cConversion_To_CCxY;
-                  break;
-               }
-               case PIXEL_FMT_DXT5_xGxR:
-               {
-                  conv_type = image_utils::cConversion_To_xGxR;
-                  break;
-               }
-               case PIXEL_FMT_DXT5_xGBR:
-               {
-                  conv_type = image_utils::cConversion_To_xGBR;
-                  break;
-               }
-               case PIXEL_FMT_DXT5_AGBR:
-               {
-                  conv_type = image_utils::cConversion_To_AGBR;
-                  break;
-               }
-               default: break;
-            }
-         }
-         else
-         {
-            switch (fmt)
-            {
-               case PIXEL_FMT_3DC:
-               case PIXEL_FMT_DXN:
-               {
-                  conv_type = image_utils::cConversion_XY_to_XYZ;
-                  break;
-               }
-               case PIXEL_FMT_DXT5_CCxY:
-               {
-                  conv_type = image_utils::cConversion_From_CCxY;
-                  break;
-               }
-               case PIXEL_FMT_DXT5_xGxR:
-               {
-                  conv_type = image_utils::cConversion_From_xGxR;
-                  break;
-               }
-               case PIXEL_FMT_DXT5_xGBR:
-               {
-                  conv_type = image_utils::cConversion_From_xGBR;
-                  break;
-               }
-               case PIXEL_FMT_DXT5_AGBR:
-               {
-                  conv_type = image_utils::cConversion_From_AGBR;
-                  break;
-               }
-               default: break;
-            }
-         }
-
-         return conv_type;
-      }
-
-      image_utils::conversion_type get_image_conversion_type_from_crn_format(crn_format fmt)
-      {
-         switch (fmt)
-         {
-            case cCRNFmtDXT5_CCxY: return image_utils::cConversion_To_CCxY;
-            case cCRNFmtDXT5_xGxR: return image_utils::cConversion_To_xGxR;
-            case cCRNFmtDXT5_xGBR: return image_utils::cConversion_To_xGBR;
-            case cCRNFmtDXT5_AGBR: return image_utils::cConversion_To_AGBR;
-            default: break;
-         }
-         return image_utils::cConversion_Invalid;
-      }
-
-      double compute_std_dev(uint n, const color_quad_u8* pPixels, uint first_channel, uint num_channels)
-      {
-         if (!n)
-            return 0.0f;
-
-         double sum = 0.0f;
-         double sum2 = 0.0f;
-
-         for (uint i = 0; i < n; i++)
-         {
-            const color_quad_u8& cp = pPixels[i];
-
-            if (!num_channels)
-            {
-               uint l = cp.get_luma();
-               sum += l;
-               sum2 += l*l;
-            }
-            else
-            {
-               for (uint c = 0; c < num_channels; c++)
-               {
-                  uint l = cp[first_channel + c];
-                  sum += l;
-                  sum2 += l*l;
-               }
-            }
-         }
-
-         double w = math::maximum(1U, num_channels) * n;
-         sum /= w;
-         sum2 /= w;
-
-         double var = sum2 - sum * sum;
-         var = math::maximum<double>(var, 0.0f);
-
-         return sqrt(var);
-      }
-
-      uint8* read_image_from_memory(const uint8* pImage, int nSize, int* pWidth, int* pHeight, int* pActualComps, int req_comps, const char* pFilename)
-      {
-         *pWidth = 0;
-         *pHeight = 0;
-         *pActualComps = 0;
-
-         if ((req_comps < 1) || (req_comps > 4))
-            return false;
-
-         mipmapped_texture tex;
-
-         buffer_stream buf_stream(pImage, nSize);
-         buf_stream.set_name(pFilename);
-         data_stream_serializer serializer(buf_stream);
-
-         if (!tex.read_from_stream(serializer))
-            return NULL;
-
-         if (tex.is_packed())
-         {
-            if (!tex.unpack_from_dxt(true))
-               return NULL;
-         }
-
-         image_u8 img;
-         image_u8* pImg = tex.get_level_image(0, 0, img);
-         if (!pImg)
-            return NULL;
-
-         *pWidth = tex.get_width();
-         *pHeight = tex.get_height();
-
-         if (pImg->has_alpha())
-            *pActualComps = 4;
-         else if (pImg->is_grayscale())
-            *pActualComps = 1;
-         else
-            *pActualComps = 3;
-
-         uint8 *pDst = NULL;
-         if (req_comps == 4)
-         {
-            pDst = (uint8*)malloc(tex.get_total_pixels() * sizeof(uint32));
-            uint8 *pSrc = (uint8*)pImg->get_ptr();
-            memcpy(pDst, pSrc, tex.get_total_pixels() * sizeof(uint32));
-         }
-         else
-         {
-            image_u8 luma_img;
-            if (req_comps == 1)
-            {
-               luma_img = *pImg;
-               luma_img.convert_to_grayscale();
-               pImg = &luma_img;
-            }
-
-            pixel_packer packer(req_comps, 8);
-            uint32 n;
-            pDst = image_utils::pack_image(*pImg, packer, n);
-         }
-
-         return pDst;
-      }
-
-   } // namespace image_utils
-
-} // namespace crnlib

+ 0 - 193
Source/ThirdParty/crunch/crnlib/crn_image_utils.h

@@ -1,193 +0,0 @@
-// File: crn_image_utils.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_image.h"
-#include "crn_data_stream_serializer.h"
-
-namespace crnlib
-{
-   enum pixel_format;
-
-   namespace image_utils
-   {
-      enum read_flags_t
-      {
-         cReadFlagForceSTB = 1,
-
-         cReadFlagsAllFlags = 1
-      };
-
-      bool read_from_stream_stb(data_stream_serializer& serializer, image_u8& img);
-      bool read_from_stream_jpgd(data_stream_serializer& serializer, image_u8& img);
-      bool read_from_stream(image_u8& dest, data_stream_serializer& serializer, uint read_flags = 0);
-      bool read_from_file(image_u8& dest, const char* pFilename, uint read_flags = 0);
-
-      // Reads texture from memory, results returned stb_image.c style.
-      // *pActual_comps is set to 1, 3, or 4. req_comps must range from 1-4.
-      uint8* read_from_memory(const uint8* pImage, int nSize, int* pWidth, int* pHeight, int* pActualComps, int req_comps, const char* pFilename);
-
-      enum
-      {
-         cWriteFlagIgnoreAlpha            = 0x00000001,
-         cWriteFlagGrayscale              = 0x00000002,
-
-         cWriteFlagJPEGH1V1               = 0x00010000,
-         cWriteFlagJPEGH2V1               = 0x00020000,
-         cWriteFlagJPEGH2V2               = 0x00040000,
-         cWriteFlagJPEGTwoPass            = 0x00080000,
-         cWriteFlagJPEGNoChromaDiscrim    = 0x00100000,
-         cWriteFlagJPEGQualityLevelMask   = 0xFF000000,
-         cWriteFlagJPEGQualityLevelShift  = 24,
-      };
-
-      const int cLumaComponentIndex = -1;
-
-      inline uint create_jpeg_write_flags(uint base_flags, uint quality_level) { CRNLIB_ASSERT(quality_level <= 100); return base_flags | ((quality_level << cWriteFlagJPEGQualityLevelShift) & cWriteFlagJPEGQualityLevelMask); }
-
-      bool write_to_file(const char* pFilename, const image_u8& img, uint write_flags = 0, int grayscale_comp_index = cLumaComponentIndex);
-
-      bool has_alpha(const image_u8& img);
-      bool is_normal_map(const image_u8& img, const char* pFilename = NULL);
-      void renorm_normal_map(image_u8& img);
-
-      struct resample_params
-      {
-         resample_params() :
-            m_dst_width(0),
-            m_dst_height(0),
-            m_pFilter("lanczos4"),
-            m_filter_scale(1.0f),
-            m_srgb(true),
-            m_wrapping(false),
-            m_first_comp(0),
-            m_num_comps(4),
-            m_source_gamma(2.2f), // 1.75f
-            m_multithreaded(true)
-         {
-         }
-
-         uint        m_dst_width;
-         uint        m_dst_height;
-         const char* m_pFilter;
-         float       m_filter_scale;
-         bool        m_srgb;
-         bool        m_wrapping;
-         uint        m_first_comp;
-         uint        m_num_comps;
-         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 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;
-         }
-      };
-
-      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,
-
-         cConversion_To_Y,
-
-         cConversionTotal
-      };
-
-      void convert_image(image_u8& img, conversion_type conv_type);
-
-      template<typename image_type>
-      inline uint8* pack_image(const image_type& img, const pixel_packer& packer, uint& n)
-      {
-         n = 0;
-
-         if (!packer.is_valid())
-            return NULL;
-
-         const uint width = img.get_width(), height = img.get_height();
-         uint dst_pixel_stride = packer.get_pixel_stride();
-         uint dst_pitch = width * dst_pixel_stride;
-
-         n = dst_pitch * height;
-
-         uint8* pImage = static_cast<uint8*>(crnlib_malloc(n));
-
-         uint8* pDst = pImage;
-         for (uint y = 0; y < height; y++)
-         {
-            const typename image_type::color_t* pSrc = img.get_scanline(y);
-            for (uint x = 0; x < width; x++)
-               pDst = (uint8*)packer.pack(*pSrc++, pDst);
-         }
-
-         return pImage;
-      }
-
-      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);
-
-      uint8* read_image_from_memory(const uint8* pImage, int nSize, int* pWidth, int* pHeight, int* pActualComps, int req_comps, const char* pFilename);
-
-   } // namespace image_utils
-
-} // namespace crnlib

+ 0 - 123
Source/ThirdParty/crunch/crnlib/crn_intersect.h

@@ -1,123 +0,0 @@
-// File: crn_intersect.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_ray.h"
-
-namespace crnlib
-{
-   namespace intersection
-   {
-      enum result 
-      {
-         cBackfacing = -1,
-         cFailure = 0,
-         cSuccess,
-         cParallel,
-         cInside,
-      };
-      
-      // Returns cInside, cSuccess, or cFailure.
-      // Algorithm: Graphics Gems 1
-      template<typename vector_type, typename scalar_type, typename ray_type, typename aabb_type>
-      result ray_aabb(vector_type& coord, scalar_type& t, const ray_type& ray, const aabb_type& box)
-      {
-         enum 
-         { 
-            cNumDim = vector_type::num_elements, 
-            cRight = 0, 
-            cLeft = 1, 
-            cMiddle = 2 
-         };
-
-         bool inside = true;
-         int quadrant[cNumDim];
-         scalar_type candidate_plane[cNumDim];
-
-         for (int i = 0; i < cNumDim; i++)
-         {
-            if (ray.get_origin()[i] < box[0][i])
-            {
-               quadrant[i] = cLeft;
-               candidate_plane[i] = box[0][i];
-               inside = false;
-            }
-            else if (ray.get_origin()[i] > box[1][i])
-            {
-               quadrant[i] = cRight;
-               candidate_plane[i] = box[1][i];
-               inside = false;
-            }
-            else
-            {
-               quadrant[i] = cMiddle;
-            }
-         }
-
-         if (inside)
-         {
-            coord = ray.get_origin();
-            t = 0.0f;
-            return cInside;
-         }
-
-         scalar_type max_t[cNumDim];
-         for (int i = 0; i < cNumDim; i++)
-         {
-            if ((quadrant[i] != cMiddle) && (ray.get_direction()[i] != 0.0f))
-               max_t[i] = (candidate_plane[i] - ray.get_origin()[i]) / ray.get_direction()[i];
-            else
-               max_t[i] = -1.0f;
-         }         
-
-         int which_plane = 0;
-         for (int i = 1; i < cNumDim; i++)
-            if (max_t[which_plane] < max_t[i])
-               which_plane = i;
-
-         if (max_t[which_plane] < 0.0f)
-            return cFailure;               
-
-         for (int i = 0; i < cNumDim; i++)
-         {
-            if (i != which_plane)
-            {
-               coord[i] = ray.get_origin()[i] + max_t[which_plane] * ray.get_direction()[i];
-
-               if ( (coord[i] < box[0][i]) || (coord[i] > box[1][i]) )
-                  return cFailure;
-            }
-            else
-            {
-               coord[i] = candidate_plane[i];
-            }
-
-            CRNLIB_ASSERT(coord[i] >= box[0][i] && coord[i] <= box[1][i]); 
-         }               
-
-         t = max_t[which_plane];
-         return cSuccess;
-      }
-      
-      template<typename vector_type, typename scalar_type, typename ray_type, typename aabb_type>
-      result ray_aabb(bool& started_within, vector_type& coord, scalar_type& t, const ray_type& ray, const aabb_type& box)
-      {
-         if (!box.contains(ray.get_origin()))
-         {
-            started_within = false;
-            return ray_aabb(coord, t, ray, box);
-         }
-         
-         started_within = true;
-         
-         float diag_dist = box.diagonal_length() * 1.5f;
-         ray_type outside_ray(ray.eval(diag_dist), -ray.get_direction());
-         
-         result res(ray_aabb(coord, t, outside_ray, box));
-         if (res != cSuccess)
-            return res;
-         
-         t = math::maximum(0.0f, diag_dist - t);
-         return cSuccess;
-      }
-   }
-}

+ 0 - 3172
Source/ThirdParty/crunch/crnlib/crn_jpgd.cpp

@@ -1,3172 +0,0 @@
-// jpgd.cpp - C++ class for JPEG decompression.
-// Public domain, Rich Geldreich <[email protected]>
-// Alex Evans: Linear memory allocator (taken from jpge.h).
-// v1.04, May. 19, 2012: Code tweaks to fix VS2008 static code analysis warnings (all looked harmless)
-//
-// Supports progressive and baseline sequential JPEG image files, and the most common chroma subsampling factors: Y, H1V1, H2V1, H1V2, and H2V2.
-//
-// Chroma upsampling quality: H2V2 is upsampled in the frequency domain, H2V1 and H1V2 are upsampled using point sampling.
-// Chroma upsampling reference: "Fast Scheme for Image Size Change in the Compressed Domain"
-// http://vision.ai.uiuc.edu/~dugad/research/dct/index.html
-
-#include "crn_jpgd.h"
-#include <string.h>
-
-#include <assert.h>
-#define JPGD_ASSERT(x) assert(x)
-
-#include "crn_core.h"
-
-#ifdef _MSC_VER
-#pragma warning (disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
-#endif
-
-// Set to 1 to enable freq. domain chroma upsampling on images using H2V2 subsampling (0=faster nearest neighbor sampling).
-// This is slower, but results in higher quality on images with highly saturated colors.
-#define JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING 1
-
-#define JPGD_TRUE (1)
-#define JPGD_FALSE (0)
-
-#define JPGD_MAX(a,b) (((a)>(b)) ? (a) : (b))
-#define JPGD_MIN(a,b) (((a)<(b)) ? (a) : (b))
-
-namespace jpgd {
-
-static inline void *jpgd_malloc(size_t nSize) { return crnlib::crnlib_malloc(nSize); }
-static inline void jpgd_free(void *p) { crnlib::crnlib_free(p); }
-
-// DCT coefficients are stored in this sequence.
-static int g_ZAG[64] = {  0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 };
-
-enum JPEG_MARKER
-{
-  M_SOF0  = 0xC0, M_SOF1  = 0xC1, M_SOF2  = 0xC2, M_SOF3  = 0xC3, M_SOF5  = 0xC5, M_SOF6  = 0xC6, M_SOF7  = 0xC7, M_JPG   = 0xC8,
-  M_SOF9  = 0xC9, M_SOF10 = 0xCA, M_SOF11 = 0xCB, M_SOF13 = 0xCD, M_SOF14 = 0xCE, M_SOF15 = 0xCF, M_DHT   = 0xC4, M_DAC   = 0xCC,
-  M_RST0  = 0xD0, M_RST1  = 0xD1, M_RST2  = 0xD2, M_RST3  = 0xD3, M_RST4  = 0xD4, M_RST5  = 0xD5, M_RST6  = 0xD6, M_RST7  = 0xD7,
-  M_SOI   = 0xD8, M_EOI   = 0xD9, M_SOS   = 0xDA, M_DQT   = 0xDB, M_DNL   = 0xDC, M_DRI   = 0xDD, M_DHP   = 0xDE, M_EXP   = 0xDF,
-  M_APP0  = 0xE0, M_APP15 = 0xEF, M_JPG0  = 0xF0, M_JPG13 = 0xFD, M_COM   = 0xFE, M_TEM   = 0x01, M_ERROR = 0x100, RST0   = 0xD0
-};
-
-enum JPEG_SUBSAMPLING { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2, JPGD_YH2V2 };
-
-#define CONST_BITS  13
-#define PASS1_BITS  2
-#define SCALEDONE ((int32)1)
-
-#define FIX_0_298631336  ((int32)2446)        /* FIX(0.298631336) */
-#define FIX_0_390180644  ((int32)3196)        /* FIX(0.390180644) */
-#define FIX_0_541196100  ((int32)4433)        /* FIX(0.541196100) */
-#define FIX_0_765366865  ((int32)6270)        /* FIX(0.765366865) */
-#define FIX_0_899976223  ((int32)7373)        /* FIX(0.899976223) */
-#define FIX_1_175875602  ((int32)9633)        /* FIX(1.175875602) */
-#define FIX_1_501321110  ((int32)12299)       /* FIX(1.501321110) */
-#define FIX_1_847759065  ((int32)15137)       /* FIX(1.847759065) */
-#define FIX_1_961570560  ((int32)16069)       /* FIX(1.961570560) */
-#define FIX_2_053119869  ((int32)16819)       /* FIX(2.053119869) */
-#define FIX_2_562915447  ((int32)20995)       /* FIX(2.562915447) */
-#define FIX_3_072711026  ((int32)25172)       /* FIX(3.072711026) */
-
-#define DESCALE(x,n)  (((x) + (SCALEDONE << ((n)-1))) >> (n))
-#define DESCALE_ZEROSHIFT(x,n)  (((x) + (128 << (n)) + (SCALEDONE << ((n)-1))) >> (n))
-
-#define MULTIPLY(var, cnst)  ((var) * (cnst))
-
-#define CLAMP(i) ((static_cast<uint>(i) > 255) ? (((~i) >> 31) & 0xFF) : (i))
-
-// Compiler creates a fast path 1D IDCT for X non-zero columns
-template <int NONZERO_COLS>
-struct Row
-{
-  static void idct(int* pTemp, const jpgd_block_t* pSrc)
-  {
-    // ACCESS_COL() will be optimized at compile time to either an array access, or 0.
-    #define ACCESS_COL(x) (((x) < NONZERO_COLS) ? (int)pSrc[x] : 0)
-
-    const int z2 = ACCESS_COL(2), z3 = ACCESS_COL(6);
-
-    const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
-    const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
-    const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
-
-    const int tmp0 = (ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS;
-    const int tmp1 = (ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS;
-
-    const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
-
-    const int atmp0 = ACCESS_COL(7), atmp1 = ACCESS_COL(5), atmp2 = ACCESS_COL(3), atmp3 = ACCESS_COL(1);
-
-    const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
-    const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
-
-    const int az1 = MULTIPLY(bz1, - FIX_0_899976223);
-    const int az2 = MULTIPLY(bz2, - FIX_2_562915447);
-    const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5;
-    const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5;
-
-    const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
-    const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
-    const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
-    const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
-
-    pTemp[0] = DESCALE(tmp10 + btmp3, CONST_BITS-PASS1_BITS);
-    pTemp[7] = DESCALE(tmp10 - btmp3, CONST_BITS-PASS1_BITS);
-    pTemp[1] = DESCALE(tmp11 + btmp2, CONST_BITS-PASS1_BITS);
-    pTemp[6] = DESCALE(tmp11 - btmp2, CONST_BITS-PASS1_BITS);
-    pTemp[2] = DESCALE(tmp12 + btmp1, CONST_BITS-PASS1_BITS);
-    pTemp[5] = DESCALE(tmp12 - btmp1, CONST_BITS-PASS1_BITS);
-    pTemp[3] = DESCALE(tmp13 + btmp0, CONST_BITS-PASS1_BITS);
-    pTemp[4] = DESCALE(tmp13 - btmp0, CONST_BITS-PASS1_BITS);
-  }
-};
-
-template <>
-struct Row<0>
-{
-  static void idct(int* pTemp, const jpgd_block_t* pSrc)
-  {
-    (void)pTemp; (void)pSrc;
-  }
-};
-
-template <>
-struct Row<1>
-{
-  static void idct(int* pTemp, const jpgd_block_t* pSrc)
-  {
-    const int dcval = (pSrc[0] << PASS1_BITS);
-
-    pTemp[0] = dcval;
-    pTemp[1] = dcval;
-    pTemp[2] = dcval;
-    pTemp[3] = dcval;
-    pTemp[4] = dcval;
-    pTemp[5] = dcval;
-    pTemp[6] = dcval;
-    pTemp[7] = dcval;
-  }
-};
-
-// Compiler creates a fast path 1D IDCT for X non-zero rows
-template <int NONZERO_ROWS>
-struct Col
-{
-  static void idct(uint8* pDst_ptr, const int* pTemp)
-  {
-    // ACCESS_ROW() will be optimized at compile time to either an array access, or 0.
-    #define ACCESS_ROW(x) (((x) < NONZERO_ROWS) ? pTemp[x * 8] : 0)
-
-    const int z2 = ACCESS_ROW(2);
-    const int z3 = ACCESS_ROW(6);
-
-    const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
-    const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
-    const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
-
-    const int tmp0 = (ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS;
-    const int tmp1 = (ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS;
-
-    const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
-
-    const int atmp0 = ACCESS_ROW(7), atmp1 = ACCESS_ROW(5), atmp2 = ACCESS_ROW(3), atmp3 = ACCESS_ROW(1);
-
-    const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
-    const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
-
-    const int az1 = MULTIPLY(bz1, - FIX_0_899976223);
-    const int az2 = MULTIPLY(bz2, - FIX_2_562915447);
-    const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5;
-    const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5;
-
-    const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
-    const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
-    const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
-    const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
-
-    int i = DESCALE_ZEROSHIFT(tmp10 + btmp3, CONST_BITS+PASS1_BITS+3);
-    pDst_ptr[8*0] = (uint8)CLAMP(i);
-
-    i = DESCALE_ZEROSHIFT(tmp10 - btmp3, CONST_BITS+PASS1_BITS+3);
-    pDst_ptr[8*7] = (uint8)CLAMP(i);
-
-    i = DESCALE_ZEROSHIFT(tmp11 + btmp2, CONST_BITS+PASS1_BITS+3);
-    pDst_ptr[8*1] = (uint8)CLAMP(i);
-
-    i = DESCALE_ZEROSHIFT(tmp11 - btmp2, CONST_BITS+PASS1_BITS+3);
-    pDst_ptr[8*6] = (uint8)CLAMP(i);
-
-    i = DESCALE_ZEROSHIFT(tmp12 + btmp1, CONST_BITS+PASS1_BITS+3);
-    pDst_ptr[8*2] = (uint8)CLAMP(i);
-
-    i = DESCALE_ZEROSHIFT(tmp12 - btmp1, CONST_BITS+PASS1_BITS+3);
-    pDst_ptr[8*5] = (uint8)CLAMP(i);
-
-    i = DESCALE_ZEROSHIFT(tmp13 + btmp0, CONST_BITS+PASS1_BITS+3);
-    pDst_ptr[8*3] = (uint8)CLAMP(i);
-
-    i = DESCALE_ZEROSHIFT(tmp13 - btmp0, CONST_BITS+PASS1_BITS+3);
-    pDst_ptr[8*4] = (uint8)CLAMP(i);
-  }
-};
-
-template <>
-struct Col<1>
-{
-  static void idct(uint8* pDst_ptr, const int* pTemp)
-  {
-    int dcval = DESCALE_ZEROSHIFT(pTemp[0], PASS1_BITS+3);
-    const uint8 dcval_clamped = (uint8)CLAMP(dcval);
-    pDst_ptr[0*8] = dcval_clamped;
-    pDst_ptr[1*8] = dcval_clamped;
-    pDst_ptr[2*8] = dcval_clamped;
-    pDst_ptr[3*8] = dcval_clamped;
-    pDst_ptr[4*8] = dcval_clamped;
-    pDst_ptr[5*8] = dcval_clamped;
-    pDst_ptr[6*8] = dcval_clamped;
-    pDst_ptr[7*8] = dcval_clamped;
-  }
-};
-
-static const uint8 s_idct_row_table[] =
-{
-  1,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 2,1,0,0,0,0,0,0, 2,1,1,0,0,0,0,0, 2,2,1,0,0,0,0,0, 3,2,1,0,0,0,0,0, 4,2,1,0,0,0,0,0, 4,3,1,0,0,0,0,0,
-  4,3,2,0,0,0,0,0, 4,3,2,1,0,0,0,0, 4,3,2,1,1,0,0,0, 4,3,2,2,1,0,0,0, 4,3,3,2,1,0,0,0, 4,4,3,2,1,0,0,0, 5,4,3,2,1,0,0,0, 6,4,3,2,1,0,0,0,
-  6,5,3,2,1,0,0,0, 6,5,4,2,1,0,0,0, 6,5,4,3,1,0,0,0, 6,5,4,3,2,0,0,0, 6,5,4,3,2,1,0,0, 6,5,4,3,2,1,1,0, 6,5,4,3,2,2,1,0, 6,5,4,3,3,2,1,0,
-  6,5,4,4,3,2,1,0, 6,5,5,4,3,2,1,0, 6,6,5,4,3,2,1,0, 7,6,5,4,3,2,1,0, 8,6,5,4,3,2,1,0, 8,7,5,4,3,2,1,0, 8,7,6,4,3,2,1,0, 8,7,6,5,3,2,1,0,
-  8,7,6,5,4,2,1,0, 8,7,6,5,4,3,1,0, 8,7,6,5,4,3,2,0, 8,7,6,5,4,3,2,1, 8,7,6,5,4,3,2,2, 8,7,6,5,4,3,3,2, 8,7,6,5,4,4,3,2, 8,7,6,5,5,4,3,2,
-  8,7,6,6,5,4,3,2, 8,7,7,6,5,4,3,2, 8,8,7,6,5,4,3,2, 8,8,8,6,5,4,3,2, 8,8,8,7,5,4,3,2, 8,8,8,7,6,4,3,2, 8,8,8,7,6,5,3,2, 8,8,8,7,6,5,4,2,
-  8,8,8,7,6,5,4,3, 8,8,8,7,6,5,4,4, 8,8,8,7,6,5,5,4, 8,8,8,7,6,6,5,4, 8,8,8,7,7,6,5,4, 8,8,8,8,7,6,5,4, 8,8,8,8,8,6,5,4, 8,8,8,8,8,7,5,4,
-  8,8,8,8,8,7,6,4, 8,8,8,8,8,7,6,5, 8,8,8,8,8,7,6,6, 8,8,8,8,8,7,7,6, 8,8,8,8,8,8,7,6, 8,8,8,8,8,8,8,6, 8,8,8,8,8,8,8,7, 8,8,8,8,8,8,8,8,
-};
-
-static const uint8 s_idct_col_table[] = { 1, 1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 };
-
-void idct(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr, int block_max_zag)
-{
-  JPGD_ASSERT(block_max_zag >= 1);
-  JPGD_ASSERT(block_max_zag <= 64);
-
-  if (block_max_zag <= 1)
-  {
-    int k = ((pSrc_ptr[0] + 4) >> 3) + 128;
-    k = CLAMP(k);
-    k = k | (k<<8);
-    k = k | (k<<16);
-
-    for (int i = 8; i > 0; i--)
-    {
-      *(int*)&pDst_ptr[0] = k;
-      *(int*)&pDst_ptr[4] = k;
-      pDst_ptr += 8;
-    }
-    return;
-  }
-
-  int temp[64];
-
-  const jpgd_block_t* pSrc = pSrc_ptr;
-  int* pTemp = temp;
-
-  const uint8* pRow_tab = &s_idct_row_table[(block_max_zag - 1) * 8];
-  int i;
-  for (i = 8; i > 0; i--, pRow_tab++)
-  {
-    switch (*pRow_tab)
-    {
-      case 0: Row<0>::idct(pTemp, pSrc); break;
-      case 1: Row<1>::idct(pTemp, pSrc); break;
-      case 2: Row<2>::idct(pTemp, pSrc); break;
-      case 3: Row<3>::idct(pTemp, pSrc); break;
-      case 4: Row<4>::idct(pTemp, pSrc); break;
-      case 5: Row<5>::idct(pTemp, pSrc); break;
-      case 6: Row<6>::idct(pTemp, pSrc); break;
-      case 7: Row<7>::idct(pTemp, pSrc); break;
-      case 8: Row<8>::idct(pTemp, pSrc); break;
-    }
-
-    pSrc += 8;
-    pTemp += 8;
-  }
-
-  pTemp = temp;
-
-  const int nonzero_rows = s_idct_col_table[block_max_zag - 1];
-  for (i = 8; i > 0; i--)
-  {
-    switch (nonzero_rows)
-    {
-      case 1: Col<1>::idct(pDst_ptr, pTemp); break;
-      case 2: Col<2>::idct(pDst_ptr, pTemp); break;
-      case 3: Col<3>::idct(pDst_ptr, pTemp); break;
-      case 4: Col<4>::idct(pDst_ptr, pTemp); break;
-      case 5: Col<5>::idct(pDst_ptr, pTemp); break;
-      case 6: Col<6>::idct(pDst_ptr, pTemp); break;
-      case 7: Col<7>::idct(pDst_ptr, pTemp); break;
-      case 8: Col<8>::idct(pDst_ptr, pTemp); break;
-    }
-
-    pTemp++;
-    pDst_ptr++;
-  }
-}
-
-void idct_4x4(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr)
-{
-  int temp[64];
-  int* pTemp = temp;
-  const jpgd_block_t* pSrc = pSrc_ptr;
-
-  for (int i = 4; i > 0; i--)
-  {
-    Row<4>::idct(pTemp, pSrc);
-    pSrc += 8;
-    pTemp += 8;
-  }
-
-  pTemp = temp;
-  for (int i = 8; i > 0; i--)
-  {
-    Col<4>::idct(pDst_ptr, pTemp);
-    pTemp++;
-    pDst_ptr++;
-  }
-}
-
-// Retrieve one character from the input stream.
-inline uint jpeg_decoder::get_char()
-{
-  // Any bytes remaining in buffer?
-  if (!m_in_buf_left)
-  {
-    // Try to get more bytes.
-    prep_in_buffer();
-    // Still nothing to get?
-    if (!m_in_buf_left)
-    {
-      // Pad the end of the stream with 0xFF 0xD9 (EOI marker)
-      int t = m_tem_flag;
-      m_tem_flag ^= 1;
-      if (t)
-        return 0xD9;
-      else
-        return 0xFF;
-    }
-  }
-
-  uint c = *m_pIn_buf_ofs++;
-  m_in_buf_left--;
-
-  return c;
-}
-
-// Same as previous method, except can indicate if the character is a pad character or not.
-inline uint jpeg_decoder::get_char(bool *pPadding_flag)
-{
-  if (!m_in_buf_left)
-  {
-    prep_in_buffer();
-    if (!m_in_buf_left)
-    {
-      *pPadding_flag = true;
-      int t = m_tem_flag;
-      m_tem_flag ^= 1;
-      if (t)
-        return 0xD9;
-      else
-        return 0xFF;
-    }
-  }
-
-  *pPadding_flag = false;
-
-  uint c = *m_pIn_buf_ofs++;
-  m_in_buf_left--;
-
-  return c;
-}
-
-// Inserts a previously retrieved character back into the input buffer.
-inline void jpeg_decoder::stuff_char(uint8 q)
-{
-  *(--m_pIn_buf_ofs) = q;
-  m_in_buf_left++;
-}
-
-// Retrieves one character from the input stream, but does not read past markers. Will continue to return 0xFF when a marker is encountered.
-inline uint8 jpeg_decoder::get_octet()
-{
-  bool padding_flag;
-  int c = get_char(&padding_flag);
-
-  if (c == 0xFF)
-  {
-    if (padding_flag)
-      return 0xFF;
-
-    c = get_char(&padding_flag);
-    if (padding_flag)
-    {
-      stuff_char(0xFF);
-      return 0xFF;
-    }
-
-    if (c == 0x00)
-      return 0xFF;
-    else
-    {
-      stuff_char(static_cast<uint8>(c));
-      stuff_char(0xFF);
-      return 0xFF;
-    }
-  }
-
-  return static_cast<uint8>(c);
-}
-
-// Retrieves a variable number of bits from the input stream. Does not recognize markers.
-inline uint jpeg_decoder::get_bits(int num_bits)
-{
-  if (!num_bits)
-    return 0;
-
-  uint i = m_bit_buf >> (32 - num_bits);
-
-  if ((m_bits_left -= num_bits) <= 0)
-  {
-    m_bit_buf <<= (num_bits += m_bits_left);
-
-    uint c1 = get_char();
-    uint c2 = get_char();
-    m_bit_buf = (m_bit_buf & 0xFFFF0000) | (c1 << 8) | c2;
-
-    m_bit_buf <<= -m_bits_left;
-
-    m_bits_left += 16;
-
-    JPGD_ASSERT(m_bits_left >= 0);
-  }
-  else
-    m_bit_buf <<= num_bits;
-
-  return i;
-}
-
-// Retrieves a variable number of bits from the input stream. Markers will not be read into the input bit buffer. Instead, an infinite number of all 1's will be returned when a marker is encountered.
-inline uint jpeg_decoder::get_bits_no_markers(int num_bits)
-{
-  if (!num_bits)
-    return 0;
-
-  uint i = m_bit_buf >> (32 - num_bits);
-
-  if ((m_bits_left -= num_bits) <= 0)
-  {
-    m_bit_buf <<= (num_bits += m_bits_left);
-
-    if ((m_in_buf_left < 2) || (m_pIn_buf_ofs[0] == 0xFF) || (m_pIn_buf_ofs[1] == 0xFF))
-    {
-      uint c1 = get_octet();
-      uint c2 = get_octet();
-      m_bit_buf |= (c1 << 8) | c2;
-    }
-    else
-    {
-      m_bit_buf |= ((uint)m_pIn_buf_ofs[0] << 8) | m_pIn_buf_ofs[1];
-      m_in_buf_left -= 2;
-      m_pIn_buf_ofs += 2;
-    }
-
-    m_bit_buf <<= -m_bits_left;
-
-    m_bits_left += 16;
-
-    JPGD_ASSERT(m_bits_left >= 0);
-  }
-  else
-    m_bit_buf <<= num_bits;
-
-  return i;
-}
-
-// Decodes a Huffman encoded symbol.
-inline int jpeg_decoder::huff_decode(huff_tables *pH)
-{
-  int symbol;
-
-  // Check first 8-bits: do we have a complete symbol?
-  if ((symbol = pH->look_up[m_bit_buf >> 24]) < 0)
-  {
-    // Decode more bits, use a tree traversal to find symbol.
-    int ofs = 23;
-    do
-    {
-      symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))];
-      ofs--;
-    } while (symbol < 0);
-
-    get_bits_no_markers(8 + (23 - ofs));
-  }
-  else
-    get_bits_no_markers(pH->code_size[symbol]);
-
-  return symbol;
-}
-
-// Decodes a Huffman encoded symbol.
-inline int jpeg_decoder::huff_decode(huff_tables *pH, int& extra_bits)
-{
-  int symbol;
-
-  // Check first 8-bits: do we have a complete symbol?
-  if ((symbol = pH->look_up2[m_bit_buf >> 24]) < 0)
-  {
-    // Use a tree traversal to find symbol.
-    int ofs = 23;
-    do
-    {
-      symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))];
-      ofs--;
-    } while (symbol < 0);
-
-    get_bits_no_markers(8 + (23 - ofs));
-
-    extra_bits = get_bits_no_markers(symbol & 0xF);
-  }
-  else
-  {
-    JPGD_ASSERT(((symbol >> 8) & 31) == pH->code_size[symbol & 255] + ((symbol & 0x8000) ? (symbol & 15) : 0));
-
-    if (symbol & 0x8000)
-    {
-      get_bits_no_markers((symbol >> 8) & 31);
-      extra_bits = symbol >> 16;
-    }
-    else
-    {
-      int code_size = (symbol >> 8) & 31;
-      int num_extra_bits = symbol & 0xF;
-      int bits = code_size + num_extra_bits;
-      if (bits <= (m_bits_left + 16))
-        extra_bits = get_bits_no_markers(bits) & ((1 << num_extra_bits) - 1);
-      else
-      {
-        get_bits_no_markers(code_size);
-        extra_bits = get_bits_no_markers(num_extra_bits);
-      }
-    }
-
-    symbol &= 0xFF;
-  }
-
-  return symbol;
-}
-
-// Tables and macro used to fully decode the DPCM differences.
-static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
-static const int s_extend_offset[16] = { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
-static const int s_extend_mask[] = { 0, (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16) };
-// The logical AND's in this macro are to shut up static code analysis (aren't really necessary - couldn't find another way to do this)
-#define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x))
-
-// Clamps a value between 0-255.
-inline uint8 jpeg_decoder::clamp(int i)
-{
-  if (static_cast<uint>(i) > 255)
-    i = (((~i) >> 31) & 0xFF);
-
-  return static_cast<uint8>(i);
-}
-
-namespace DCT_Upsample
-{
-  struct Matrix44
-  {
-    typedef int Element_Type;
-    enum { NUM_ROWS = 4, NUM_COLS = 4 };
-
-    Element_Type v[NUM_ROWS][NUM_COLS];
-
-    inline int rows() const { return NUM_ROWS; }
-    inline int cols() const { return NUM_COLS; }
-
-    inline const Element_Type & at(int r, int c) const { return v[r][c]; }
-    inline       Element_Type & at(int r, int c)       { return v[r][c]; }
-
-    inline Matrix44() { }
-
-    inline Matrix44& operator += (const Matrix44& a)
-    {
-      for (int r = 0; r < NUM_ROWS; r++)
-      {
-        at(r, 0) += a.at(r, 0);
-        at(r, 1) += a.at(r, 1);
-        at(r, 2) += a.at(r, 2);
-        at(r, 3) += a.at(r, 3);
-      }
-      return *this;
-    }
-
-    inline Matrix44& operator -= (const Matrix44& a)
-    {
-      for (int r = 0; r < NUM_ROWS; r++)
-      {
-        at(r, 0) -= a.at(r, 0);
-        at(r, 1) -= a.at(r, 1);
-        at(r, 2) -= a.at(r, 2);
-        at(r, 3) -= a.at(r, 3);
-      }
-      return *this;
-    }
-
-    friend inline Matrix44 operator + (const Matrix44& a, const Matrix44& b)
-    {
-      Matrix44 ret;
-      for (int r = 0; r < NUM_ROWS; r++)
-      {
-        ret.at(r, 0) = a.at(r, 0) + b.at(r, 0);
-        ret.at(r, 1) = a.at(r, 1) + b.at(r, 1);
-        ret.at(r, 2) = a.at(r, 2) + b.at(r, 2);
-        ret.at(r, 3) = a.at(r, 3) + b.at(r, 3);
-      }
-      return ret;
-    }
-
-    friend inline Matrix44 operator - (const Matrix44& a, const Matrix44& b)
-    {
-      Matrix44 ret;
-      for (int r = 0; r < NUM_ROWS; r++)
-      {
-        ret.at(r, 0) = a.at(r, 0) - b.at(r, 0);
-        ret.at(r, 1) = a.at(r, 1) - b.at(r, 1);
-        ret.at(r, 2) = a.at(r, 2) - b.at(r, 2);
-        ret.at(r, 3) = a.at(r, 3) - b.at(r, 3);
-      }
-      return ret;
-    }
-
-    static inline void add_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b)
-    {
-      for (int r = 0; r < 4; r++)
-      {
-        pDst[0*8 + r] = static_cast<jpgd_block_t>(a.at(r, 0) + b.at(r, 0));
-        pDst[1*8 + r] = static_cast<jpgd_block_t>(a.at(r, 1) + b.at(r, 1));
-        pDst[2*8 + r] = static_cast<jpgd_block_t>(a.at(r, 2) + b.at(r, 2));
-        pDst[3*8 + r] = static_cast<jpgd_block_t>(a.at(r, 3) + b.at(r, 3));
-      }
-    }
-
-    static inline void sub_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b)
-    {
-      for (int r = 0; r < 4; r++)
-      {
-        pDst[0*8 + r] = static_cast<jpgd_block_t>(a.at(r, 0) - b.at(r, 0));
-        pDst[1*8 + r] = static_cast<jpgd_block_t>(a.at(r, 1) - b.at(r, 1));
-        pDst[2*8 + r] = static_cast<jpgd_block_t>(a.at(r, 2) - b.at(r, 2));
-        pDst[3*8 + r] = static_cast<jpgd_block_t>(a.at(r, 3) - b.at(r, 3));
-      }
-    }
-  };
-
-  const int FRACT_BITS = 10;
-  const int SCALE = 1 << FRACT_BITS;
-
-  typedef int Temp_Type;
-  #define D(i) (((i) + (SCALE >> 1)) >> FRACT_BITS)
-  #define F(i) ((int)((i) * SCALE + .5f))
-
-  // Any decent C++ compiler will optimize this at compile time to a 0, or an array access.
-  #define AT(c, r) ((((c)>=NUM_COLS)||((r)>=NUM_ROWS)) ? 0 : pSrc[(c)+(r)*8])
-
-  // NUM_ROWS/NUM_COLS = # of non-zero rows/cols in input matrix
-  template<int NUM_ROWS, int NUM_COLS>
-  struct P_Q
-  {
-    static void calc(Matrix44& P, Matrix44& Q, const jpgd_block_t* pSrc)
-    {
-      // 4x8 = 4x8 times 8x8, matrix 0 is constant
-      const Temp_Type X000 = AT(0, 0);
-      const Temp_Type X001 = AT(0, 1);
-      const Temp_Type X002 = AT(0, 2);
-      const Temp_Type X003 = AT(0, 3);
-      const Temp_Type X004 = AT(0, 4);
-      const Temp_Type X005 = AT(0, 5);
-      const Temp_Type X006 = AT(0, 6);
-      const Temp_Type X007 = AT(0, 7);
-      const Temp_Type X010 = D(F(0.415735f) * AT(1, 0) + F(0.791065f) * AT(3, 0) + F(-0.352443f) * AT(5, 0) + F(0.277785f) * AT(7, 0));
-      const Temp_Type X011 = D(F(0.415735f) * AT(1, 1) + F(0.791065f) * AT(3, 1) + F(-0.352443f) * AT(5, 1) + F(0.277785f) * AT(7, 1));
-      const Temp_Type X012 = D(F(0.415735f) * AT(1, 2) + F(0.791065f) * AT(3, 2) + F(-0.352443f) * AT(5, 2) + F(0.277785f) * AT(7, 2));
-      const Temp_Type X013 = D(F(0.415735f) * AT(1, 3) + F(0.791065f) * AT(3, 3) + F(-0.352443f) * AT(5, 3) + F(0.277785f) * AT(7, 3));
-      const Temp_Type X014 = D(F(0.415735f) * AT(1, 4) + F(0.791065f) * AT(3, 4) + F(-0.352443f) * AT(5, 4) + F(0.277785f) * AT(7, 4));
-      const Temp_Type X015 = D(F(0.415735f) * AT(1, 5) + F(0.791065f) * AT(3, 5) + F(-0.352443f) * AT(5, 5) + F(0.277785f) * AT(7, 5));
-      const Temp_Type X016 = D(F(0.415735f) * AT(1, 6) + F(0.791065f) * AT(3, 6) + F(-0.352443f) * AT(5, 6) + F(0.277785f) * AT(7, 6));
-      const Temp_Type X017 = D(F(0.415735f) * AT(1, 7) + F(0.791065f) * AT(3, 7) + F(-0.352443f) * AT(5, 7) + F(0.277785f) * AT(7, 7));
-      const Temp_Type X020 = AT(4, 0);
-      const Temp_Type X021 = AT(4, 1);
-      const Temp_Type X022 = AT(4, 2);
-      const Temp_Type X023 = AT(4, 3);
-      const Temp_Type X024 = AT(4, 4);
-      const Temp_Type X025 = AT(4, 5);
-      const Temp_Type X026 = AT(4, 6);
-      const Temp_Type X027 = AT(4, 7);
-      const Temp_Type X030 = D(F(0.022887f) * AT(1, 0) + F(-0.097545f) * AT(3, 0) + F(0.490393f) * AT(5, 0) + F(0.865723f) * AT(7, 0));
-      const Temp_Type X031 = D(F(0.022887f) * AT(1, 1) + F(-0.097545f) * AT(3, 1) + F(0.490393f) * AT(5, 1) + F(0.865723f) * AT(7, 1));
-      const Temp_Type X032 = D(F(0.022887f) * AT(1, 2) + F(-0.097545f) * AT(3, 2) + F(0.490393f) * AT(5, 2) + F(0.865723f) * AT(7, 2));
-      const Temp_Type X033 = D(F(0.022887f) * AT(1, 3) + F(-0.097545f) * AT(3, 3) + F(0.490393f) * AT(5, 3) + F(0.865723f) * AT(7, 3));
-      const Temp_Type X034 = D(F(0.022887f) * AT(1, 4) + F(-0.097545f) * AT(3, 4) + F(0.490393f) * AT(5, 4) + F(0.865723f) * AT(7, 4));
-      const Temp_Type X035 = D(F(0.022887f) * AT(1, 5) + F(-0.097545f) * AT(3, 5) + F(0.490393f) * AT(5, 5) + F(0.865723f) * AT(7, 5));
-      const Temp_Type X036 = D(F(0.022887f) * AT(1, 6) + F(-0.097545f) * AT(3, 6) + F(0.490393f) * AT(5, 6) + F(0.865723f) * AT(7, 6));
-      const Temp_Type X037 = D(F(0.022887f) * AT(1, 7) + F(-0.097545f) * AT(3, 7) + F(0.490393f) * AT(5, 7) + F(0.865723f) * AT(7, 7));
-
-      // 4x4 = 4x8 times 8x4, matrix 1 is constant
-      P.at(0, 0) = X000;
-      P.at(0, 1) = D(X001 * F(0.415735f) + X003 * F(0.791065f) + X005 * F(-0.352443f) + X007 * F(0.277785f));
-      P.at(0, 2) = X004;
-      P.at(0, 3) = D(X001 * F(0.022887f) + X003 * F(-0.097545f) + X005 * F(0.490393f) + X007 * F(0.865723f));
-      P.at(1, 0) = X010;
-      P.at(1, 1) = D(X011 * F(0.415735f) + X013 * F(0.791065f) + X015 * F(-0.352443f) + X017 * F(0.277785f));
-      P.at(1, 2) = X014;
-      P.at(1, 3) = D(X011 * F(0.022887f) + X013 * F(-0.097545f) + X015 * F(0.490393f) + X017 * F(0.865723f));
-      P.at(2, 0) = X020;
-      P.at(2, 1) = D(X021 * F(0.415735f) + X023 * F(0.791065f) + X025 * F(-0.352443f) + X027 * F(0.277785f));
-      P.at(2, 2) = X024;
-      P.at(2, 3) = D(X021 * F(0.022887f) + X023 * F(-0.097545f) + X025 * F(0.490393f) + X027 * F(0.865723f));
-      P.at(3, 0) = X030;
-      P.at(3, 1) = D(X031 * F(0.415735f) + X033 * F(0.791065f) + X035 * F(-0.352443f) + X037 * F(0.277785f));
-      P.at(3, 2) = X034;
-      P.at(3, 3) = D(X031 * F(0.022887f) + X033 * F(-0.097545f) + X035 * F(0.490393f) + X037 * F(0.865723f));
-      // 40 muls 24 adds
-
-      // 4x4 = 4x8 times 8x4, matrix 1 is constant
-      Q.at(0, 0) = D(X001 * F(0.906127f) + X003 * F(-0.318190f) + X005 * F(0.212608f) + X007 * F(-0.180240f));
-      Q.at(0, 1) = X002;
-      Q.at(0, 2) = D(X001 * F(-0.074658f) + X003 * F(0.513280f) + X005 * F(0.768178f) + X007 * F(-0.375330f));
-      Q.at(0, 3) = X006;
-      Q.at(1, 0) = D(X011 * F(0.906127f) + X013 * F(-0.318190f) + X015 * F(0.212608f) + X017 * F(-0.180240f));
-      Q.at(1, 1) = X012;
-      Q.at(1, 2) = D(X011 * F(-0.074658f) + X013 * F(0.513280f) + X015 * F(0.768178f) + X017 * F(-0.375330f));
-      Q.at(1, 3) = X016;
-      Q.at(2, 0) = D(X021 * F(0.906127f) + X023 * F(-0.318190f) + X025 * F(0.212608f) + X027 * F(-0.180240f));
-      Q.at(2, 1) = X022;
-      Q.at(2, 2) = D(X021 * F(-0.074658f) + X023 * F(0.513280f) + X025 * F(0.768178f) + X027 * F(-0.375330f));
-      Q.at(2, 3) = X026;
-      Q.at(3, 0) = D(X031 * F(0.906127f) + X033 * F(-0.318190f) + X035 * F(0.212608f) + X037 * F(-0.180240f));
-      Q.at(3, 1) = X032;
-      Q.at(3, 2) = D(X031 * F(-0.074658f) + X033 * F(0.513280f) + X035 * F(0.768178f) + X037 * F(-0.375330f));
-      Q.at(3, 3) = X036;
-      // 40 muls 24 adds
-    }
-  };
-
-  template<int NUM_ROWS, int NUM_COLS>
-  struct R_S
-  {
-    static void calc(Matrix44& R, Matrix44& S, const jpgd_block_t* pSrc)
-    {
-      // 4x8 = 4x8 times 8x8, matrix 0 is constant
-      const Temp_Type X100 = D(F(0.906127f) * AT(1, 0) + F(-0.318190f) * AT(3, 0) + F(0.212608f) * AT(5, 0) + F(-0.180240f) * AT(7, 0));
-      const Temp_Type X101 = D(F(0.906127f) * AT(1, 1) + F(-0.318190f) * AT(3, 1) + F(0.212608f) * AT(5, 1) + F(-0.180240f) * AT(7, 1));
-      const Temp_Type X102 = D(F(0.906127f) * AT(1, 2) + F(-0.318190f) * AT(3, 2) + F(0.212608f) * AT(5, 2) + F(-0.180240f) * AT(7, 2));
-      const Temp_Type X103 = D(F(0.906127f) * AT(1, 3) + F(-0.318190f) * AT(3, 3) + F(0.212608f) * AT(5, 3) + F(-0.180240f) * AT(7, 3));
-      const Temp_Type X104 = D(F(0.906127f) * AT(1, 4) + F(-0.318190f) * AT(3, 4) + F(0.212608f) * AT(5, 4) + F(-0.180240f) * AT(7, 4));
-      const Temp_Type X105 = D(F(0.906127f) * AT(1, 5) + F(-0.318190f) * AT(3, 5) + F(0.212608f) * AT(5, 5) + F(-0.180240f) * AT(7, 5));
-      const Temp_Type X106 = D(F(0.906127f) * AT(1, 6) + F(-0.318190f) * AT(3, 6) + F(0.212608f) * AT(5, 6) + F(-0.180240f) * AT(7, 6));
-      const Temp_Type X107 = D(F(0.906127f) * AT(1, 7) + F(-0.318190f) * AT(3, 7) + F(0.212608f) * AT(5, 7) + F(-0.180240f) * AT(7, 7));
-      const Temp_Type X110 = AT(2, 0);
-      const Temp_Type X111 = AT(2, 1);
-      const Temp_Type X112 = AT(2, 2);
-      const Temp_Type X113 = AT(2, 3);
-      const Temp_Type X114 = AT(2, 4);
-      const Temp_Type X115 = AT(2, 5);
-      const Temp_Type X116 = AT(2, 6);
-      const Temp_Type X117 = AT(2, 7);
-      const Temp_Type X120 = D(F(-0.074658f) * AT(1, 0) + F(0.513280f) * AT(3, 0) + F(0.768178f) * AT(5, 0) + F(-0.375330f) * AT(7, 0));
-      const Temp_Type X121 = D(F(-0.074658f) * AT(1, 1) + F(0.513280f) * AT(3, 1) + F(0.768178f) * AT(5, 1) + F(-0.375330f) * AT(7, 1));
-      const Temp_Type X122 = D(F(-0.074658f) * AT(1, 2) + F(0.513280f) * AT(3, 2) + F(0.768178f) * AT(5, 2) + F(-0.375330f) * AT(7, 2));
-      const Temp_Type X123 = D(F(-0.074658f) * AT(1, 3) + F(0.513280f) * AT(3, 3) + F(0.768178f) * AT(5, 3) + F(-0.375330f) * AT(7, 3));
-      const Temp_Type X124 = D(F(-0.074658f) * AT(1, 4) + F(0.513280f) * AT(3, 4) + F(0.768178f) * AT(5, 4) + F(-0.375330f) * AT(7, 4));
-      const Temp_Type X125 = D(F(-0.074658f) * AT(1, 5) + F(0.513280f) * AT(3, 5) + F(0.768178f) * AT(5, 5) + F(-0.375330f) * AT(7, 5));
-      const Temp_Type X126 = D(F(-0.074658f) * AT(1, 6) + F(0.513280f) * AT(3, 6) + F(0.768178f) * AT(5, 6) + F(-0.375330f) * AT(7, 6));
-      const Temp_Type X127 = D(F(-0.074658f) * AT(1, 7) + F(0.513280f) * AT(3, 7) + F(0.768178f) * AT(5, 7) + F(-0.375330f) * AT(7, 7));
-      const Temp_Type X130 = AT(6, 0);
-      const Temp_Type X131 = AT(6, 1);
-      const Temp_Type X132 = AT(6, 2);
-      const Temp_Type X133 = AT(6, 3);
-      const Temp_Type X134 = AT(6, 4);
-      const Temp_Type X135 = AT(6, 5);
-      const Temp_Type X136 = AT(6, 6);
-      const Temp_Type X137 = AT(6, 7);
-      // 80 muls 48 adds
-
-      // 4x4 = 4x8 times 8x4, matrix 1 is constant
-      R.at(0, 0) = X100;
-      R.at(0, 1) = D(X101 * F(0.415735f) + X103 * F(0.791065f) + X105 * F(-0.352443f) + X107 * F(0.277785f));
-      R.at(0, 2) = X104;
-      R.at(0, 3) = D(X101 * F(0.022887f) + X103 * F(-0.097545f) + X105 * F(0.490393f) + X107 * F(0.865723f));
-      R.at(1, 0) = X110;
-      R.at(1, 1) = D(X111 * F(0.415735f) + X113 * F(0.791065f) + X115 * F(-0.352443f) + X117 * F(0.277785f));
-      R.at(1, 2) = X114;
-      R.at(1, 3) = D(X111 * F(0.022887f) + X113 * F(-0.097545f) + X115 * F(0.490393f) + X117 * F(0.865723f));
-      R.at(2, 0) = X120;
-      R.at(2, 1) = D(X121 * F(0.415735f) + X123 * F(0.791065f) + X125 * F(-0.352443f) + X127 * F(0.277785f));
-      R.at(2, 2) = X124;
-      R.at(2, 3) = D(X121 * F(0.022887f) + X123 * F(-0.097545f) + X125 * F(0.490393f) + X127 * F(0.865723f));
-      R.at(3, 0) = X130;
-      R.at(3, 1) = D(X131 * F(0.415735f) + X133 * F(0.791065f) + X135 * F(-0.352443f) + X137 * F(0.277785f));
-      R.at(3, 2) = X134;
-      R.at(3, 3) = D(X131 * F(0.022887f) + X133 * F(-0.097545f) + X135 * F(0.490393f) + X137 * F(0.865723f));
-      // 40 muls 24 adds
-      // 4x4 = 4x8 times 8x4, matrix 1 is constant
-      S.at(0, 0) = D(X101 * F(0.906127f) + X103 * F(-0.318190f) + X105 * F(0.212608f) + X107 * F(-0.180240f));
-      S.at(0, 1) = X102;
-      S.at(0, 2) = D(X101 * F(-0.074658f) + X103 * F(0.513280f) + X105 * F(0.768178f) + X107 * F(-0.375330f));
-      S.at(0, 3) = X106;
-      S.at(1, 0) = D(X111 * F(0.906127f) + X113 * F(-0.318190f) + X115 * F(0.212608f) + X117 * F(-0.180240f));
-      S.at(1, 1) = X112;
-      S.at(1, 2) = D(X111 * F(-0.074658f) + X113 * F(0.513280f) + X115 * F(0.768178f) + X117 * F(-0.375330f));
-      S.at(1, 3) = X116;
-      S.at(2, 0) = D(X121 * F(0.906127f) + X123 * F(-0.318190f) + X125 * F(0.212608f) + X127 * F(-0.180240f));
-      S.at(2, 1) = X122;
-      S.at(2, 2) = D(X121 * F(-0.074658f) + X123 * F(0.513280f) + X125 * F(0.768178f) + X127 * F(-0.375330f));
-      S.at(2, 3) = X126;
-      S.at(3, 0) = D(X131 * F(0.906127f) + X133 * F(-0.318190f) + X135 * F(0.212608f) + X137 * F(-0.180240f));
-      S.at(3, 1) = X132;
-      S.at(3, 2) = D(X131 * F(-0.074658f) + X133 * F(0.513280f) + X135 * F(0.768178f) + X137 * F(-0.375330f));
-      S.at(3, 3) = X136;
-      // 40 muls 24 adds
-    }
-  };
-} // end namespace DCT_Upsample
-
-// Unconditionally frees all allocated m_blocks.
-void jpeg_decoder::free_all_blocks()
-{
-  m_pStream = NULL;
-  for (mem_block *b = m_pMem_blocks; b; )
-  {
-    mem_block *n = b->m_pNext;
-    jpgd_free(b);
-    b = n;
-  }
-  m_pMem_blocks = NULL;
-}
-
-// This method handles all errors. It will never return.
-// It could easily be changed to use C++ exceptions.
-JPGD_NORETURN void jpeg_decoder::stop_decoding(jpgd_status status)
-{
-  m_error_code = status;
-  free_all_blocks();
-  longjmp(m_jmp_state, status);
-}
-
-void *jpeg_decoder::alloc(size_t nSize, bool zero)
-{
-  nSize = (JPGD_MAX(nSize, 1) + 3) & ~3;
-  char *rv = NULL;
-  for (mem_block *b = m_pMem_blocks; b; b = b->m_pNext)
-  {
-    if ((b->m_used_count + nSize) <= b->m_size)
-    {
-      rv = b->m_data + b->m_used_count;
-      b->m_used_count += nSize;
-      break;
-    }
-  }
-  if (!rv)
-  {
-    int capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047);
-    mem_block *b = (mem_block*)jpgd_malloc(sizeof(mem_block) + capacity);
-    if (!b) { stop_decoding(JPGD_NOTENOUGHMEM); }
-    b->m_pNext = m_pMem_blocks; m_pMem_blocks = b;
-    b->m_used_count = nSize;
-    b->m_size = capacity;
-    rv = b->m_data;
-  }
-  if (zero) memset(rv, 0, nSize);
-  return rv;
-}
-
-void jpeg_decoder::word_clear(void *p, uint16 c, uint n)
-{
-  uint8 *pD = (uint8*)p;
-  const uint8 l = c & 0xFF, h = (c >> 8) & 0xFF;
-  while (n)
-  {
-    pD[0] = l; pD[1] = h; pD += 2;
-    n--;
-  }
-}
-
-// Refill the input buffer.
-// This method will sit in a loop until (A) the buffer is full or (B)
-// the stream's read() method reports and end of file condition.
-void jpeg_decoder::prep_in_buffer()
-{
-  m_in_buf_left = 0;
-  m_pIn_buf_ofs = m_in_buf;
-
-  if (m_eof_flag)
-    return;
-
-  do
-  {
-    int bytes_read = m_pStream->read(m_in_buf + m_in_buf_left, JPGD_IN_BUF_SIZE - m_in_buf_left, &m_eof_flag);
-    if (bytes_read == -1)
-      stop_decoding(JPGD_STREAM_READ);
-
-    m_in_buf_left += bytes_read;
-  } while ((m_in_buf_left < JPGD_IN_BUF_SIZE) && (!m_eof_flag));
-
-  m_total_bytes_read += m_in_buf_left;
-
-  // Pad the end of the block with M_EOI (prevents the decompressor from going off the rails if the stream is invalid).
-  // (This dates way back to when this decompressor was written in C/asm, and the all-asm Huffman decoder did some fancy things to increase perf.)
-  word_clear(m_pIn_buf_ofs + m_in_buf_left, 0xD9FF, 64);
-}
-
-// Read a Huffman code table.
-void jpeg_decoder::read_dht_marker()
-{
-  int i, index, count;
-  uint8 huff_num[17];
-  uint8 huff_val[256];
-
-  uint num_left = get_bits(16);
-
-  if (num_left < 2)
-    stop_decoding(JPGD_BAD_DHT_MARKER);
-
-  num_left -= 2;
-
-  while (num_left)
-  {
-    index = get_bits(8);
-
-    huff_num[0] = 0;
-
-    count = 0;
-
-    for (i = 1; i <= 16; i++)
-    {
-      huff_num[i] = static_cast<uint8>(get_bits(8));
-      count += huff_num[i];
-    }
-
-    if (count > 255)
-      stop_decoding(JPGD_BAD_DHT_COUNTS);
-
-    for (i = 0; i < count; i++)
-      huff_val[i] = static_cast<uint8>(get_bits(8));
-
-    i = 1 + 16 + count;
-
-    if (num_left < (uint)i)
-      stop_decoding(JPGD_BAD_DHT_MARKER);
-
-    num_left -= i;
-
-    if ((index & 0x10) > 0x10)
-      stop_decoding(JPGD_BAD_DHT_INDEX);
-
-    index = (index & 0x0F) + ((index & 0x10) >> 4) * (JPGD_MAX_HUFF_TABLES >> 1);
-
-    if (index >= JPGD_MAX_HUFF_TABLES)
-      stop_decoding(JPGD_BAD_DHT_INDEX);
-
-    if (!m_huff_num[index])
-      m_huff_num[index] = (uint8 *)alloc(17);
-
-    if (!m_huff_val[index])
-      m_huff_val[index] = (uint8 *)alloc(256);
-
-    m_huff_ac[index] = (index & 0x10) != 0;
-    memcpy(m_huff_num[index], huff_num, 17);
-    memcpy(m_huff_val[index], huff_val, 256);
-  }
-}
-
-// Read a quantization table.
-void jpeg_decoder::read_dqt_marker()
-{
-  int n, i, prec;
-  uint num_left;
-  uint temp;
-
-  num_left = get_bits(16);
-
-  if (num_left < 2)
-    stop_decoding(JPGD_BAD_DQT_MARKER);
-
-  num_left -= 2;
-
-  while (num_left)
-  {
-    n = get_bits(8);
-    prec = n >> 4;
-    n &= 0x0F;
-
-    if (n >= JPGD_MAX_QUANT_TABLES)
-      stop_decoding(JPGD_BAD_DQT_TABLE);
-
-    if (!m_quant[n])
-      m_quant[n] = (jpgd_quant_t *)alloc(64 * sizeof(jpgd_quant_t));
-
-    // read quantization entries, in zag order
-    for (i = 0; i < 64; i++)
-    {
-      temp = get_bits(8);
-
-      if (prec)
-        temp = (temp << 8) + get_bits(8);
-
-			m_quant[n][i] = static_cast<jpgd_quant_t>(temp);
-    }
-
-    i = 64 + 1;
-
-    if (prec)
-      i += 64;
-
-    if (num_left < (uint)i)
-      stop_decoding(JPGD_BAD_DQT_LENGTH);
-
-    num_left -= i;
-  }
-}
-
-// Read the start of frame (SOF) marker.
-void jpeg_decoder::read_sof_marker()
-{
-  int i;
-  uint num_left;
-
-  num_left = get_bits(16);
-
-  if (get_bits(8) != 8)   /* precision: sorry, only 8-bit precision is supported right now */
-    stop_decoding(JPGD_BAD_PRECISION);
-
-  m_image_y_size = get_bits(16);
-
-  if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT))
-    stop_decoding(JPGD_BAD_HEIGHT);
-
-  m_image_x_size = get_bits(16);
-
-  if ((m_image_x_size < 1) || (m_image_x_size > JPGD_MAX_WIDTH))
-    stop_decoding(JPGD_BAD_WIDTH);
-
-  m_comps_in_frame = get_bits(8);
-
-  if (m_comps_in_frame > JPGD_MAX_COMPONENTS)
-    stop_decoding(JPGD_TOO_MANY_COMPONENTS);
-
-  if (num_left != (uint)(m_comps_in_frame * 3 + 8))
-    stop_decoding(JPGD_BAD_SOF_LENGTH);
-
-  for (i = 0; i < m_comps_in_frame; i++)
-  {
-    m_comp_ident[i]  = get_bits(8);
-    m_comp_h_samp[i] = get_bits(4);
-    m_comp_v_samp[i] = get_bits(4);
-    m_comp_quant[i]  = get_bits(8);
-  }
-}
-
-// Used to skip unrecognized markers.
-void jpeg_decoder::skip_variable_marker()
-{
-  uint num_left;
-
-  num_left = get_bits(16);
-
-  if (num_left < 2)
-    stop_decoding(JPGD_BAD_VARIABLE_MARKER);
-
-  num_left -= 2;
-
-  while (num_left)
-  {
-    get_bits(8);
-    num_left--;
-  }
-}
-
-// Read a define restart interval (DRI) marker.
-void jpeg_decoder::read_dri_marker()
-{
-  if (get_bits(16) != 4)
-    stop_decoding(JPGD_BAD_DRI_LENGTH);
-
-  m_restart_interval = get_bits(16);
-}
-
-// Read a start of scan (SOS) marker.
-void jpeg_decoder::read_sos_marker()
-{
-  uint num_left;
-  int i, ci, n, c, cc;
-
-  num_left = get_bits(16);
-
-  n = get_bits(8);
-
-  m_comps_in_scan = n;
-
-  num_left -= 3;
-
-  if ( (num_left != (uint)(n * 2 + 3)) || (n < 1) || (n > JPGD_MAX_COMPS_IN_SCAN) )
-    stop_decoding(JPGD_BAD_SOS_LENGTH);
-
-  for (i = 0; i < n; i++)
-  {
-    cc = get_bits(8);
-    c = get_bits(8);
-    num_left -= 2;
-
-    for (ci = 0; ci < m_comps_in_frame; ci++)
-      if (cc == m_comp_ident[ci])
-        break;
-
-    if (ci >= m_comps_in_frame)
-      stop_decoding(JPGD_BAD_SOS_COMP_ID);
-
-    m_comp_list[i]    = ci;
-    m_comp_dc_tab[ci] = (c >> 4) & 15;
-    m_comp_ac_tab[ci] = (c & 15) + (JPGD_MAX_HUFF_TABLES >> 1);
-  }
-
-  m_spectral_start  = get_bits(8);
-  m_spectral_end    = get_bits(8);
-  m_successive_high = get_bits(4);
-  m_successive_low  = get_bits(4);
-
-  if (!m_progressive_flag)
-  {
-    m_spectral_start = 0;
-    m_spectral_end = 63;
-  }
-
-  num_left -= 3;
-
-  while (num_left)                  /* read past whatever is num_left */
-  {
-    get_bits(8);
-    num_left--;
-  }
-}
-
-// Finds the next marker.
-int jpeg_decoder::next_marker()
-{
-  uint c, bytes;
-
-  bytes = 0;
-
-  do
-  {
-    do
-    {
-      bytes++;
-      c = get_bits(8);
-    } while (c != 0xFF);
-
-    do
-    {
-      c = get_bits(8);
-    } while (c == 0xFF);
-
-  } while (c == 0);
-
-  // If bytes > 0 here, there where extra bytes before the marker (not good).
-
-  return c;
-}
-
-// Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
-// encountered.
-int jpeg_decoder::process_markers()
-{
-  int c;
-
-  for ( ; ; )
-  {
-    c = next_marker();
-
-    switch (c)
-    {
-      case M_SOF0:
-      case M_SOF1:
-      case M_SOF2:
-      case M_SOF3:
-      case M_SOF5:
-      case M_SOF6:
-      case M_SOF7:
-//      case M_JPG:
-      case M_SOF9:
-      case M_SOF10:
-      case M_SOF11:
-      case M_SOF13:
-      case M_SOF14:
-      case M_SOF15:
-      case M_SOI:
-      case M_EOI:
-      case M_SOS:
-      {
-        return c;
-      }
-      case M_DHT:
-      {
-        read_dht_marker();
-        break;
-      }
-      // No arithmitic support - dumb patents!
-      case M_DAC:
-      {
-        stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
-        break;
-      }
-      case M_DQT:
-      {
-        read_dqt_marker();
-        break;
-      }
-      case M_DRI:
-      {
-        read_dri_marker();
-        break;
-      }
-      //case M_APP0:  /* no need to read the JFIF marker */
-
-      case M_JPG:
-      case M_RST0:    /* no parameters */
-      case M_RST1:
-      case M_RST2:
-      case M_RST3:
-      case M_RST4:
-      case M_RST5:
-      case M_RST6:
-      case M_RST7:
-      case M_TEM:
-      {
-        stop_decoding(JPGD_UNEXPECTED_MARKER);
-        break;
-      }
-      default:    /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
-      {
-        skip_variable_marker();
-        break;
-      }
-    }
-  }
-}
-
-// Finds the start of image (SOI) marker.
-// This code is rather defensive: it only checks the first 512 bytes to avoid
-// false positives.
-void jpeg_decoder::locate_soi_marker()
-{
-  uint lastchar, thischar;
-  uint bytesleft;
-
-  lastchar = get_bits(8);
-
-  thischar = get_bits(8);
-
-  /* ok if it's a normal JPEG file without a special header */
-
-  if ((lastchar == 0xFF) && (thischar == M_SOI))
-    return;
-
-  bytesleft = 4096; //512;
-
-  for ( ; ; )
-  {
-    if (--bytesleft == 0)
-      stop_decoding(JPGD_NOT_JPEG);
-
-    lastchar = thischar;
-
-    thischar = get_bits(8);
-
-    if (lastchar == 0xFF)
-    {
-      if (thischar == M_SOI)
-        break;
-      else if (thischar == M_EOI) // get_bits will keep returning M_EOI if we read past the end
-        stop_decoding(JPGD_NOT_JPEG);
-    }
-  }
-
-  // Check the next character after marker: if it's not 0xFF, it can't be the start of the next marker, so the file is bad.
-  thischar = (m_bit_buf >> 24) & 0xFF;
-
-  if (thischar != 0xFF)
-    stop_decoding(JPGD_NOT_JPEG);
-}
-
-// Find a start of frame (SOF) marker.
-void jpeg_decoder::locate_sof_marker()
-{
-  locate_soi_marker();
-
-  int c = process_markers();
-
-  switch (c)
-  {
-    case M_SOF2:
-      m_progressive_flag = JPGD_TRUE;
-    case M_SOF0:  /* baseline DCT */
-    case M_SOF1:  /* extended sequential DCT */
-    {
-      read_sof_marker();
-      break;
-    }
-    case M_SOF9:  /* Arithmitic coding */
-    {
-      stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
-      break;
-    }
-    default:
-    {
-      stop_decoding(JPGD_UNSUPPORTED_MARKER);
-      break;
-    }
-  }
-}
-
-// Find a start of scan (SOS) marker.
-int jpeg_decoder::locate_sos_marker()
-{
-  int c;
-
-  c = process_markers();
-
-  if (c == M_EOI)
-    return JPGD_FALSE;
-  else if (c != M_SOS)
-    stop_decoding(JPGD_UNEXPECTED_MARKER);
-
-  read_sos_marker();
-
-  return JPGD_TRUE;
-}
-
-// Reset everything to default/uninitialized state.
-void jpeg_decoder::init(jpeg_decoder_stream *pStream)
-{
-  m_pMem_blocks = NULL;
-  m_error_code = JPGD_SUCCESS;
-  m_ready_flag = false;
-  m_image_x_size = m_image_y_size = 0;
-  m_pStream = pStream;
-  m_progressive_flag = JPGD_FALSE;
-
-  memset(m_huff_ac, 0, sizeof(m_huff_ac));
-  memset(m_huff_num, 0, sizeof(m_huff_num));
-  memset(m_huff_val, 0, sizeof(m_huff_val));
-  memset(m_quant, 0, sizeof(m_quant));
-
-  m_scan_type = 0;
-  m_comps_in_frame = 0;
-
-  memset(m_comp_h_samp, 0, sizeof(m_comp_h_samp));
-  memset(m_comp_v_samp, 0, sizeof(m_comp_v_samp));
-  memset(m_comp_quant, 0, sizeof(m_comp_quant));
-  memset(m_comp_ident, 0, sizeof(m_comp_ident));
-  memset(m_comp_h_blocks, 0, sizeof(m_comp_h_blocks));
-  memset(m_comp_v_blocks, 0, sizeof(m_comp_v_blocks));
-
-  m_comps_in_scan = 0;
-  memset(m_comp_list, 0, sizeof(m_comp_list));
-  memset(m_comp_dc_tab, 0, sizeof(m_comp_dc_tab));
-  memset(m_comp_ac_tab, 0, sizeof(m_comp_ac_tab));
-
-  m_spectral_start = 0;
-  m_spectral_end = 0;
-  m_successive_low = 0;
-  m_successive_high = 0;
-  m_max_mcu_x_size = 0;
-  m_max_mcu_y_size = 0;
-  m_blocks_per_mcu = 0;
-  m_max_blocks_per_row = 0;
-  m_mcus_per_row = 0;
-  m_mcus_per_col = 0;
-  m_expanded_blocks_per_component = 0;
-  m_expanded_blocks_per_mcu = 0;
-  m_expanded_blocks_per_row = 0;
-  m_freq_domain_chroma_upsample = false;
-
-  memset(m_mcu_org, 0, sizeof(m_mcu_org));
-
-  m_total_lines_left = 0;
-  m_mcu_lines_left = 0;
-  m_real_dest_bytes_per_scan_line = 0;
-  m_dest_bytes_per_scan_line = 0;
-  m_dest_bytes_per_pixel = 0;
-
-  memset(m_pHuff_tabs, 0, sizeof(m_pHuff_tabs));
-
-  memset(m_dc_coeffs, 0, sizeof(m_dc_coeffs));
-  memset(m_ac_coeffs, 0, sizeof(m_ac_coeffs));
-  memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
-
-  m_eob_run = 0;
-
-  memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
-
-  m_pIn_buf_ofs = m_in_buf;
-  m_in_buf_left = 0;
-  m_eof_flag = false;
-  m_tem_flag = 0;
-
-  memset(m_in_buf_pad_start, 0, sizeof(m_in_buf_pad_start));
-  memset(m_in_buf, 0, sizeof(m_in_buf));
-  memset(m_in_buf_pad_end, 0, sizeof(m_in_buf_pad_end));
-
-  m_restart_interval = 0;
-  m_restarts_left    = 0;
-  m_next_restart_num = 0;
-
-  m_max_mcus_per_row = 0;
-  m_max_blocks_per_mcu = 0;
-  m_max_mcus_per_col = 0;
-
-  memset(m_last_dc_val, 0, sizeof(m_last_dc_val));
-  m_pMCU_coefficients = NULL;
-  m_pSample_buf = NULL;
-
-  m_total_bytes_read = 0;
-
-  m_pScan_line_0 = NULL;
-  m_pScan_line_1 = NULL;
-
-  // Ready the input buffer.
-  prep_in_buffer();
-
-  // Prime the bit buffer.
-  m_bits_left = 16;
-  m_bit_buf = 0;
-
-  get_bits(16);
-  get_bits(16);
-
-  for (int i = 0; i < JPGD_MAX_BLOCKS_PER_MCU; i++)
-    m_mcu_block_max_zag[i] = 64;
-}
-
-#define SCALEBITS 16
-#define ONE_HALF  ((int) 1 << (SCALEBITS-1))
-#define FIX(x)    ((int) ((x) * (1L<<SCALEBITS) + 0.5f))
-
-// Create a few tables that allow us to quickly convert YCbCr to RGB.
-void jpeg_decoder::create_look_ups()
-{
-  for (int i = 0; i <= 255; i++)
-  {
-    int k = i - 128;
-    m_crr[i] = ( FIX(1.40200f)  * k + ONE_HALF) >> SCALEBITS;
-    m_cbb[i] = ( FIX(1.77200f)  * k + ONE_HALF) >> SCALEBITS;
-    m_crg[i] = (-FIX(0.71414f)) * k;
-    m_cbg[i] = (-FIX(0.34414f)) * k + ONE_HALF;
-  }
-}
-
-// This method throws back into the stream any bytes that where read
-// into the bit buffer during initial marker scanning.
-void jpeg_decoder::fix_in_buffer()
-{
-  // In case any 0xFF's where pulled into the buffer during marker scanning.
-  JPGD_ASSERT((m_bits_left & 7) == 0);
-
-  if (m_bits_left == 16)
-    stuff_char( (uint8)(m_bit_buf & 0xFF));
-
-  if (m_bits_left >= 8)
-    stuff_char( (uint8)((m_bit_buf >> 8) & 0xFF));
-
-  stuff_char((uint8)((m_bit_buf >> 16) & 0xFF));
-  stuff_char((uint8)((m_bit_buf >> 24) & 0xFF));
-
-  m_bits_left = 16;
-  get_bits_no_markers(16);
-  get_bits_no_markers(16);
-}
-
-void jpeg_decoder::transform_mcu(int mcu_row)
-{
-  jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
-  uint8* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64;
-
-  for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
-  {
-    idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
-    pSrc_ptr += 64;
-    pDst_ptr += 64;
-  }
-}
-
-static const uint8 s_max_rc[64] =
-{
-  17, 18, 34, 50, 50, 51, 52, 52, 52, 68, 84, 84, 84, 84, 85, 86, 86, 86, 86, 86,
-  102, 118, 118, 118, 118, 118, 118, 119, 120, 120, 120, 120, 120, 120, 120, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136
-};
-
-void jpeg_decoder::transform_mcu_expand(int mcu_row)
-{
-  jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
-  uint8* pDst_ptr = m_pSample_buf + mcu_row * m_expanded_blocks_per_mcu * 64;
-
-  // Y IDCT
-	int mcu_block;
-  for (mcu_block = 0; mcu_block < m_expanded_blocks_per_component; mcu_block++)
-  {
-    idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
-    pSrc_ptr += 64;
-    pDst_ptr += 64;
-  }
-
-  // Chroma IDCT, with upsampling
-	jpgd_block_t temp_block[64];
-
-  for (int i = 0; i < 2; i++)
-  {
-    DCT_Upsample::Matrix44 P, Q, R, S;
-
-    JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] >= 1);
-    JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] <= 64);
-
-    int max_zag = m_mcu_block_max_zag[mcu_block++] - 1;
-    if (max_zag <= 0) max_zag = 0; // should never happen, only here to shut up static analysis
-    switch (s_max_rc[max_zag])
-    {
-    case 1*16+1:
-      DCT_Upsample::P_Q<1, 1>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<1, 1>::calc(R, S, pSrc_ptr);
-      break;
-    case 1*16+2:
-      DCT_Upsample::P_Q<1, 2>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<1, 2>::calc(R, S, pSrc_ptr);
-      break;
-    case 2*16+2:
-      DCT_Upsample::P_Q<2, 2>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<2, 2>::calc(R, S, pSrc_ptr);
-      break;
-    case 3*16+2:
-      DCT_Upsample::P_Q<3, 2>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<3, 2>::calc(R, S, pSrc_ptr);
-      break;
-    case 3*16+3:
-      DCT_Upsample::P_Q<3, 3>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<3, 3>::calc(R, S, pSrc_ptr);
-      break;
-    case 3*16+4:
-      DCT_Upsample::P_Q<3, 4>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<3, 4>::calc(R, S, pSrc_ptr);
-      break;
-    case 4*16+4:
-      DCT_Upsample::P_Q<4, 4>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<4, 4>::calc(R, S, pSrc_ptr);
-      break;
-    case 5*16+4:
-      DCT_Upsample::P_Q<5, 4>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<5, 4>::calc(R, S, pSrc_ptr);
-      break;
-    case 5*16+5:
-      DCT_Upsample::P_Q<5, 5>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<5, 5>::calc(R, S, pSrc_ptr);
-      break;
-    case 5*16+6:
-      DCT_Upsample::P_Q<5, 6>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<5, 6>::calc(R, S, pSrc_ptr);
-      break;
-    case 6*16+6:
-      DCT_Upsample::P_Q<6, 6>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<6, 6>::calc(R, S, pSrc_ptr);
-      break;
-    case 7*16+6:
-      DCT_Upsample::P_Q<7, 6>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<7, 6>::calc(R, S, pSrc_ptr);
-      break;
-    case 7*16+7:
-      DCT_Upsample::P_Q<7, 7>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<7, 7>::calc(R, S, pSrc_ptr);
-      break;
-    case 7*16+8:
-      DCT_Upsample::P_Q<7, 8>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<7, 8>::calc(R, S, pSrc_ptr);
-      break;
-    case 8*16+8:
-      DCT_Upsample::P_Q<8, 8>::calc(P, Q, pSrc_ptr);
-      DCT_Upsample::R_S<8, 8>::calc(R, S, pSrc_ptr);
-      break;
-    default:
-      JPGD_ASSERT(false);
-    }
-
-    DCT_Upsample::Matrix44 a(P + Q); P -= Q;
-    DCT_Upsample::Matrix44& b = P;
-    DCT_Upsample::Matrix44 c(R + S); R -= S;
-    DCT_Upsample::Matrix44& d = R;
-
-    DCT_Upsample::Matrix44::add_and_store(temp_block, a, c);
-    idct_4x4(temp_block, pDst_ptr);
-    pDst_ptr += 64;
-
-    DCT_Upsample::Matrix44::sub_and_store(temp_block, a, c);
-    idct_4x4(temp_block, pDst_ptr);
-    pDst_ptr += 64;
-
-    DCT_Upsample::Matrix44::add_and_store(temp_block, b, d);
-    idct_4x4(temp_block, pDst_ptr);
-    pDst_ptr += 64;
-
-    DCT_Upsample::Matrix44::sub_and_store(temp_block, b, d);
-    idct_4x4(temp_block, pDst_ptr);
-    pDst_ptr += 64;
-
-    pSrc_ptr += 64;
-  }
-}
-
-// Loads and dequantizes the next row of (already decoded) coefficients.
-// Progressive images only.
-void jpeg_decoder::load_next_row()
-{
-  int i;
-  jpgd_block_t *p;
-  jpgd_quant_t *q;
-  int mcu_row, mcu_block, row_block = 0;
-  int component_num, component_id;
-  int block_x_mcu[JPGD_MAX_COMPONENTS];
-
-  memset(block_x_mcu, 0, JPGD_MAX_COMPONENTS * sizeof(int));
-
-  for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
-  {
-    int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
-
-    for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
-    {
-      component_id = m_mcu_org[mcu_block];
-      q = m_quant[m_comp_quant[component_id]];
-
-      p = m_pMCU_coefficients + 64 * mcu_block;
-
-      jpgd_block_t* pAC = coeff_buf_getp(m_ac_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
-      jpgd_block_t* pDC = coeff_buf_getp(m_dc_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
-      p[0] = pDC[0];
-      memcpy(&p[1], &pAC[1], 63 * sizeof(jpgd_block_t));
-
-      for (i = 63; i > 0; i--)
-        if (p[g_ZAG[i]])
-          break;
-
-      m_mcu_block_max_zag[mcu_block] = i + 1;
-
-      for ( ; i >= 0; i--)
-				if (p[g_ZAG[i]])
-					p[g_ZAG[i]] = static_cast<jpgd_block_t>(p[g_ZAG[i]] * q[i]);
-
-      row_block++;
-
-      if (m_comps_in_scan == 1)
-        block_x_mcu[component_id]++;
-      else
-      {
-        if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
-        {
-          block_x_mcu_ofs = 0;
-
-          if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
-          {
-            block_y_mcu_ofs = 0;
-
-            block_x_mcu[component_id] += m_comp_h_samp[component_id];
-          }
-        }
-      }
-    }
-
-    if (m_freq_domain_chroma_upsample)
-      transform_mcu_expand(mcu_row);
-    else
-      transform_mcu(mcu_row);
-  }
-
-  if (m_comps_in_scan == 1)
-    m_block_y_mcu[m_comp_list[0]]++;
-  else
-  {
-    for (component_num = 0; component_num < m_comps_in_scan; component_num++)
-    {
-      component_id = m_comp_list[component_num];
-
-      m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
-    }
-  }
-}
-
-// Restart interval processing.
-void jpeg_decoder::process_restart()
-{
-  int i;
-  int c = 0;
-
-  // Align to a byte boundry
-  // FIXME: Is this really necessary? get_bits_no_markers() never reads in markers!
-  //get_bits_no_markers(m_bits_left & 7);
-
-  // Let's scan a little bit to find the marker, but not _too_ far.
-  // 1536 is a "fudge factor" that determines how much to scan.
-  for (i = 1536; i > 0; i--)
-    if (get_char() == 0xFF)
-      break;
-
-  if (i == 0)
-    stop_decoding(JPGD_BAD_RESTART_MARKER);
-
-  for ( ; i > 0; i--)
-    if ((c = get_char()) != 0xFF)
-      break;
-
-  if (i == 0)
-    stop_decoding(JPGD_BAD_RESTART_MARKER);
-
-  // Is it the expected marker? If not, something bad happened.
-  if (c != (m_next_restart_num + M_RST0))
-    stop_decoding(JPGD_BAD_RESTART_MARKER);
-
-  // Reset each component's DC prediction values.
-  memset(&m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
-
-  m_eob_run = 0;
-
-  m_restarts_left = m_restart_interval;
-
-  m_next_restart_num = (m_next_restart_num + 1) & 7;
-
-  // Get the bit buffer going again...
-
-  m_bits_left = 16;
-  get_bits_no_markers(16);
-  get_bits_no_markers(16);
-}
-
-static inline int dequantize_ac(int c, int q) {	c *= q;	return c; }
-
-// Decodes and dequantizes the next row of coefficients.
-void jpeg_decoder::decode_next_row()
-{
-  int row_block = 0;
-
-  for (int mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
-  {
-    if ((m_restart_interval) && (m_restarts_left == 0))
-      process_restart();
-
-    jpgd_block_t* p = m_pMCU_coefficients;
-    for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64)
-    {
-      int component_id = m_mcu_org[mcu_block];
-      jpgd_quant_t* q = m_quant[m_comp_quant[component_id]];
-
-      int r, s;
-      s = huff_decode(m_pHuff_tabs[m_comp_dc_tab[component_id]], r);
-      s = JPGD_HUFF_EXTEND(r, s);
-
-      m_last_dc_val[component_id] = (s += m_last_dc_val[component_id]);
-
-      p[0] = static_cast<jpgd_block_t>(s * q[0]);
-
-      int prev_num_set = m_mcu_block_max_zag[mcu_block];
-
-      huff_tables *pH = m_pHuff_tabs[m_comp_ac_tab[component_id]];
-
-      int k;
-      for (k = 1; k < 64; k++)
-      {
-        int extra_bits;
-        s = huff_decode(pH, extra_bits);
-
-        r = s >> 4;
-        s &= 15;
-
-        if (s)
-        {
-          if (r)
-          {
-            if ((k + r) > 63)
-              stop_decoding(JPGD_DECODE_ERROR);
-
-            if (k < prev_num_set)
-            {
-              int n = JPGD_MIN(r, prev_num_set - k);
-              int kt = k;
-              while (n--)
-                p[g_ZAG[kt++]] = 0;
-            }
-
-            k += r;
-          }
-
-          s = JPGD_HUFF_EXTEND(extra_bits, s);
-
-          JPGD_ASSERT(k < 64);
-
-          p[g_ZAG[k]] = static_cast<jpgd_block_t>(dequantize_ac(s, q[k])); //s * q[k];
-        }
-        else
-        {
-          if (r == 15)
-          {
-            if ((k + 16) > 64)
-              stop_decoding(JPGD_DECODE_ERROR);
-
-            if (k < prev_num_set)
-            {
-              int n = JPGD_MIN(16, prev_num_set - k);
-              int kt = k;
-              while (n--)
-              {
-                JPGD_ASSERT(kt <= 63);
-                p[g_ZAG[kt++]] = 0;
-              }
-            }
-
-            k += 16 - 1; // - 1 because the loop counter is k
-            JPGD_ASSERT(p[g_ZAG[k]] == 0);
-          }
-          else
-            break;
-        }
-      }
-
-      if (k < prev_num_set)
-      {
-        int kt = k;
-        while (kt < prev_num_set)
-          p[g_ZAG[kt++]] = 0;
-      }
-
-      m_mcu_block_max_zag[mcu_block] = k;
-
-      row_block++;
-    }
-
-    if (m_freq_domain_chroma_upsample)
-      transform_mcu_expand(mcu_row);
-    else
-      transform_mcu(mcu_row);
-
-    m_restarts_left--;
-  }
-}
-
-// YCbCr H1V1 (1x1:1:1, 3 m_blocks per MCU) to RGB
-void jpeg_decoder::H1V1Convert()
-{
-  int row = m_max_mcu_y_size - m_mcu_lines_left;
-  uint8 *d = m_pScan_line_0;
-  uint8 *s = m_pSample_buf + row * 8;
-
-  for (int i = m_max_mcus_per_row; i > 0; i--)
-  {
-    for (int j = 0; j < 8; j++)
-    {
-      int y = s[j];
-      int cb = s[64+j];
-      int cr = s[128+j];
-
-      d[0] = clamp(y + m_crr[cr]);
-      d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
-      d[2] = clamp(y + m_cbb[cb]);
-      d[3] = 255;
-
-      d += 4;
-    }
-
-    s += 64*3;
-  }
-}
-
-// YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB
-void jpeg_decoder::H2V1Convert()
-{
-  int row = m_max_mcu_y_size - m_mcu_lines_left;
-  uint8 *d0 = m_pScan_line_0;
-  uint8 *y = m_pSample_buf + row * 8;
-  uint8 *c = m_pSample_buf + 2*64 + row * 8;
-
-  for (int i = m_max_mcus_per_row; i > 0; i--)
-  {
-    for (int l = 0; l < 2; l++)
-    {
-      for (int j = 0; j < 4; j++)
-      {
-        int cb = c[0];
-        int cr = c[64];
-
-        int rc = m_crr[cr];
-        int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
-        int bc = m_cbb[cb];
-
-        int yy = y[j<<1];
-        d0[0] = clamp(yy+rc);
-        d0[1] = clamp(yy+gc);
-        d0[2] = clamp(yy+bc);
-        d0[3] = 255;
-
-        yy = y[(j<<1)+1];
-        d0[4] = clamp(yy+rc);
-        d0[5] = clamp(yy+gc);
-        d0[6] = clamp(yy+bc);
-        d0[7] = 255;
-
-        d0 += 8;
-
-        c++;
-      }
-      y += 64;
-    }
-
-    y += 64*4 - 64*2;
-    c += 64*4 - 8;
-  }
-}
-
-// YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB
-void jpeg_decoder::H1V2Convert()
-{
-  int row = m_max_mcu_y_size - m_mcu_lines_left;
-  uint8 *d0 = m_pScan_line_0;
-  uint8 *d1 = m_pScan_line_1;
-  uint8 *y;
-  uint8 *c;
-
-  if (row < 8)
-    y = m_pSample_buf + row * 8;
-  else
-    y = m_pSample_buf + 64*1 + (row & 7) * 8;
-
-  c = m_pSample_buf + 64*2 + (row >> 1) * 8;
-
-  for (int i = m_max_mcus_per_row; i > 0; i--)
-  {
-    for (int j = 0; j < 8; j++)
-    {
-      int cb = c[0+j];
-      int cr = c[64+j];
-
-      int rc = m_crr[cr];
-      int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
-      int bc = m_cbb[cb];
-
-      int yy = y[j];
-      d0[0] = clamp(yy+rc);
-      d0[1] = clamp(yy+gc);
-      d0[2] = clamp(yy+bc);
-      d0[3] = 255;
-
-      yy = y[8+j];
-      d1[0] = clamp(yy+rc);
-      d1[1] = clamp(yy+gc);
-      d1[2] = clamp(yy+bc);
-      d1[3] = 255;
-
-      d0 += 4;
-      d1 += 4;
-    }
-
-    y += 64*4;
-    c += 64*4;
-  }
-}
-
-// YCbCr H2V2 (2x2:1:1, 6 m_blocks per MCU) to RGB
-void jpeg_decoder::H2V2Convert()
-{
-	int row = m_max_mcu_y_size - m_mcu_lines_left;
-	uint8 *d0 = m_pScan_line_0;
-	uint8 *d1 = m_pScan_line_1;
-	uint8 *y;
-	uint8 *c;
-
-	if (row < 8)
-		y = m_pSample_buf + row * 8;
-	else
-		y = m_pSample_buf + 64*2 + (row & 7) * 8;
-
-	c = m_pSample_buf + 64*4 + (row >> 1) * 8;
-
-	for (int i = m_max_mcus_per_row; i > 0; i--)
-	{
-		for (int l = 0; l < 2; l++)
-		{
-			for (int j = 0; j < 8; j += 2)
-			{
-				int cb = c[0];
-				int cr = c[64];
-
-				int rc = m_crr[cr];
-				int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
-				int bc = m_cbb[cb];
-
-				int yy = y[j];
-				d0[0] = clamp(yy+rc);
-				d0[1] = clamp(yy+gc);
-				d0[2] = clamp(yy+bc);
-				d0[3] = 255;
-
-				yy = y[j+1];
-				d0[4] = clamp(yy+rc);
-				d0[5] = clamp(yy+gc);
-				d0[6] = clamp(yy+bc);
-				d0[7] = 255;
-
-				yy = y[j+8];
-				d1[0] = clamp(yy+rc);
-				d1[1] = clamp(yy+gc);
-				d1[2] = clamp(yy+bc);
-				d1[3] = 255;
-
-				yy = y[j+8+1];
-				d1[4] = clamp(yy+rc);
-				d1[5] = clamp(yy+gc);
-				d1[6] = clamp(yy+bc);
-				d1[7] = 255;
-
-				d0 += 8;
-				d1 += 8;
-
-				c++;
-			}
-			y += 64;
-		}
-
-		y += 64*6 - 64*2;
-		c += 64*6 - 8;
-	}
-}
-
-// Y (1 block per MCU) to 8-bit grayscale
-void jpeg_decoder::gray_convert()
-{
-  int row = m_max_mcu_y_size - m_mcu_lines_left;
-  uint8 *d = m_pScan_line_0;
-  uint8 *s = m_pSample_buf + row * 8;
-
-  for (int i = m_max_mcus_per_row; i > 0; i--)
-  {
-    *(uint *)d = *(uint *)s;
-    *(uint *)(&d[4]) = *(uint *)(&s[4]);
-
-    s += 64;
-    d += 8;
-  }
-}
-
-void jpeg_decoder::expanded_convert()
-{
-  int row = m_max_mcu_y_size - m_mcu_lines_left;
-
-  uint8* Py = m_pSample_buf + (row / 8) * 64 * m_comp_h_samp[0] + (row & 7) * 8;
-
-  uint8* d = m_pScan_line_0;
-
-  for (int i = m_max_mcus_per_row; i > 0; i--)
-  {
-    for (int k = 0; k < m_max_mcu_x_size; k += 8)
-    {
-      const int Y_ofs = k * 8;
-      const int Cb_ofs = Y_ofs + 64 * m_expanded_blocks_per_component;
-      const int Cr_ofs = Y_ofs + 64 * m_expanded_blocks_per_component * 2;
-      for (int j = 0; j < 8; j++)
-      {
-        int y = Py[Y_ofs + j];
-        int cb = Py[Cb_ofs + j];
-        int cr = Py[Cr_ofs + j];
-
-        d[0] = clamp(y + m_crr[cr]);
-        d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
-        d[2] = clamp(y + m_cbb[cb]);
-        d[3] = 255;
-
-        d += 4;
-      }
-    }
-
-    Py += 64 * m_expanded_blocks_per_mcu;
-  }
-}
-
-// Find end of image (EOI) marker, so we can return to the user the exact size of the input stream.
-void jpeg_decoder::find_eoi()
-{
-  if (!m_progressive_flag)
-  {
-    // Attempt to read the EOI marker.
-    //get_bits_no_markers(m_bits_left & 7);
-
-    // Prime the bit buffer
-    m_bits_left = 16;
-    get_bits(16);
-    get_bits(16);
-
-    // The next marker _should_ be EOI
-    process_markers();
-  }
-
-  m_total_bytes_read -= m_in_buf_left;
-}
-
-int jpeg_decoder::decode(const void** pScan_line, uint* pScan_line_len)
-{
-  if ((m_error_code) || (!m_ready_flag))
-    return JPGD_FAILED;
-
-  if (m_total_lines_left == 0)
-    return JPGD_DONE;
-
-  if (m_mcu_lines_left == 0)
-  {
-    if (setjmp(m_jmp_state))
-      return JPGD_FAILED;
-
-    if (m_progressive_flag)
-      load_next_row();
-    else
-      decode_next_row();
-
-    // Find the EOI marker if that was the last row.
-    if (m_total_lines_left <= m_max_mcu_y_size)
-      find_eoi();
-
-    m_mcu_lines_left = m_max_mcu_y_size;
-  }
-
-  if (m_freq_domain_chroma_upsample)
-  {
-    expanded_convert();
-    *pScan_line = m_pScan_line_0;
-  }
-  else
-  {
-    switch (m_scan_type)
-    {
-      case JPGD_YH2V2:
-      {
-        if ((m_mcu_lines_left & 1) == 0)
-        {
-          H2V2Convert();
-          *pScan_line = m_pScan_line_0;
-        }
-        else
-          *pScan_line = m_pScan_line_1;
-
-        break;
-      }
-      case JPGD_YH2V1:
-      {
-        H2V1Convert();
-        *pScan_line = m_pScan_line_0;
-        break;
-      }
-      case JPGD_YH1V2:
-      {
-        if ((m_mcu_lines_left & 1) == 0)
-        {
-          H1V2Convert();
-          *pScan_line = m_pScan_line_0;
-        }
-        else
-          *pScan_line = m_pScan_line_1;
-
-        break;
-      }
-      case JPGD_YH1V1:
-      {
-        H1V1Convert();
-        *pScan_line = m_pScan_line_0;
-        break;
-      }
-      case JPGD_GRAYSCALE:
-      {
-        gray_convert();
-        *pScan_line = m_pScan_line_0;
-
-        break;
-      }
-    }
-  }
-
-  *pScan_line_len = m_real_dest_bytes_per_scan_line;
-
-  m_mcu_lines_left--;
-  m_total_lines_left--;
-
-  return JPGD_SUCCESS;
-}
-
-// Creates the tables needed for efficient Huffman decoding.
-void jpeg_decoder::make_huff_table(int index, huff_tables *pH)
-{
-  int p, i, l, si;
-  uint8 huffsize[257];
-  uint huffcode[257];
-  uint code;
-  uint subtree;
-  int code_size;
-  int lastp;
-  int nextfreeentry;
-  int currententry;
-
-  pH->ac_table = m_huff_ac[index] != 0;
-
-  p = 0;
-
-  for (l = 1; l <= 16; l++)
-  {
-    for (i = 1; i <= m_huff_num[index][l]; i++)
-      huffsize[p++] = static_cast<uint8>(l);
-  }
-
-  huffsize[p] = 0;
-
-  lastp = p;
-
-  code = 0;
-  si = huffsize[0];
-  p = 0;
-
-  while (huffsize[p])
-  {
-    while (huffsize[p] == si)
-    {
-      huffcode[p++] = code;
-      code++;
-    }
-
-    code <<= 1;
-    si++;
-  }
-
-  memset(pH->look_up, 0, sizeof(pH->look_up));
-  memset(pH->look_up2, 0, sizeof(pH->look_up2));
-  memset(pH->tree, 0, sizeof(pH->tree));
-  memset(pH->code_size, 0, sizeof(pH->code_size));
-
-  nextfreeentry = -1;
-
-  p = 0;
-
-  while (p < lastp)
-  {
-    i = m_huff_val[index][p];
-    code = huffcode[p];
-    code_size = huffsize[p];
-
-    pH->code_size[i] = static_cast<uint8>(code_size);
-
-    if (code_size <= 8)
-    {
-      code <<= (8 - code_size);
-
-      for (l = 1 << (8 - code_size); l > 0; l--)
-      {
-        JPGD_ASSERT(i < 256);
-
-        pH->look_up[code] = i;
-
-        bool has_extrabits = false;
-				int extra_bits = 0;
-        int num_extra_bits = i & 15;
-
-        int bits_to_fetch = code_size;
-        if (num_extra_bits)
-        {
-          int total_codesize = code_size + num_extra_bits;
-          if (total_codesize <= 8)
-          {
-            has_extrabits = true;
-            extra_bits = ((1 << num_extra_bits) - 1) & (code >> (8 - total_codesize));
-            JPGD_ASSERT(extra_bits <= 0x7FFF);
-            bits_to_fetch += num_extra_bits;
-          }
-        }
-
-        if (!has_extrabits)
-          pH->look_up2[code] = i | (bits_to_fetch << 8);
-        else
-          pH->look_up2[code] = i | 0x8000 | (extra_bits << 16) | (bits_to_fetch << 8);
-
-        code++;
-      }
-    }
-    else
-    {
-      subtree = (code >> (code_size - 8)) & 0xFF;
-
-      currententry = pH->look_up[subtree];
-
-      if (currententry == 0)
-      {
-        pH->look_up[subtree] = currententry = nextfreeentry;
-        pH->look_up2[subtree] = currententry = nextfreeentry;
-
-        nextfreeentry -= 2;
-      }
-
-      code <<= (16 - (code_size - 8));
-
-      for (l = code_size; l > 9; l--)
-      {
-        if ((code & 0x8000) == 0)
-          currententry--;
-
-        if (pH->tree[-currententry - 1] == 0)
-        {
-          pH->tree[-currententry - 1] = nextfreeentry;
-
-          currententry = nextfreeentry;
-
-          nextfreeentry -= 2;
-        }
-        else
-          currententry = pH->tree[-currententry - 1];
-
-        code <<= 1;
-      }
-
-      if ((code & 0x8000) == 0)
-        currententry--;
-
-      pH->tree[-currententry - 1] = i;
-    }
-
-    p++;
-  }
-}
-
-// Verifies the quantization tables needed for this scan are available.
-void jpeg_decoder::check_quant_tables()
-{
-  for (int i = 0; i < m_comps_in_scan; i++)
-    if (m_quant[m_comp_quant[m_comp_list[i]]] == NULL)
-      stop_decoding(JPGD_UNDEFINED_QUANT_TABLE);
-}
-
-// Verifies that all the Huffman tables needed for this scan are available.
-void jpeg_decoder::check_huff_tables()
-{
-  for (int i = 0; i < m_comps_in_scan; i++)
-  {
-    if ((m_spectral_start == 0) && (m_huff_num[m_comp_dc_tab[m_comp_list[i]]] == NULL))
-      stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
-
-    if ((m_spectral_end > 0) && (m_huff_num[m_comp_ac_tab[m_comp_list[i]]] == NULL))
-      stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
-  }
-
-  for (int i = 0; i < JPGD_MAX_HUFF_TABLES; i++)
-    if (m_huff_num[i])
-    {
-      if (!m_pHuff_tabs[i])
-        m_pHuff_tabs[i] = (huff_tables *)alloc(sizeof(huff_tables));
-
-      make_huff_table(i, m_pHuff_tabs[i]);
-    }
-}
-
-// Determines the component order inside each MCU.
-// Also calcs how many MCU's are on each row, etc.
-void jpeg_decoder::calc_mcu_block_order()
-{
-  int component_num, component_id;
-  int max_h_samp = 0, max_v_samp = 0;
-
-  for (component_id = 0; component_id < m_comps_in_frame; component_id++)
-  {
-    if (m_comp_h_samp[component_id] > max_h_samp)
-      max_h_samp = m_comp_h_samp[component_id];
-
-    if (m_comp_v_samp[component_id] > max_v_samp)
-      max_v_samp = m_comp_v_samp[component_id];
-  }
-
-  for (component_id = 0; component_id < m_comps_in_frame; component_id++)
-  {
-    m_comp_h_blocks[component_id] = ((((m_image_x_size * m_comp_h_samp[component_id]) + (max_h_samp - 1)) / max_h_samp) + 7) / 8;
-    m_comp_v_blocks[component_id] = ((((m_image_y_size * m_comp_v_samp[component_id]) + (max_v_samp - 1)) / max_v_samp) + 7) / 8;
-  }
-
-  if (m_comps_in_scan == 1)
-  {
-    m_mcus_per_row = m_comp_h_blocks[m_comp_list[0]];
-    m_mcus_per_col = m_comp_v_blocks[m_comp_list[0]];
-  }
-  else
-  {
-    m_mcus_per_row = (((m_image_x_size + 7) / 8) + (max_h_samp - 1)) / max_h_samp;
-    m_mcus_per_col = (((m_image_y_size + 7) / 8) + (max_v_samp - 1)) / max_v_samp;
-  }
-
-  if (m_comps_in_scan == 1)
-  {
-    m_mcu_org[0] = m_comp_list[0];
-
-    m_blocks_per_mcu = 1;
-  }
-  else
-  {
-    m_blocks_per_mcu = 0;
-
-    for (component_num = 0; component_num < m_comps_in_scan; component_num++)
-    {
-      int num_blocks;
-
-      component_id = m_comp_list[component_num];
-
-      num_blocks = m_comp_h_samp[component_id] * m_comp_v_samp[component_id];
-
-      while (num_blocks--)
-        m_mcu_org[m_blocks_per_mcu++] = component_id;
-    }
-  }
-}
-
-// Starts a new scan.
-int jpeg_decoder::init_scan()
-{
-  if (!locate_sos_marker())
-    return JPGD_FALSE;
-
-  calc_mcu_block_order();
-
-  check_huff_tables();
-
-  check_quant_tables();
-
-  memset(m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
-
-  m_eob_run = 0;
-
-  if (m_restart_interval)
-  {
-    m_restarts_left = m_restart_interval;
-    m_next_restart_num = 0;
-  }
-
-  fix_in_buffer();
-
-  return JPGD_TRUE;
-}
-
-// Starts a frame. Determines if the number of components or sampling factors
-// are supported.
-void jpeg_decoder::init_frame()
-{
-  int i;
-
-  if (m_comps_in_frame == 1)
-  {
-    if ((m_comp_h_samp[0] != 1) || (m_comp_v_samp[0] != 1))
-      stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
-
-    m_scan_type = JPGD_GRAYSCALE;
-    m_max_blocks_per_mcu = 1;
-    m_max_mcu_x_size = 8;
-    m_max_mcu_y_size = 8;
-  }
-  else if (m_comps_in_frame == 3)
-  {
-    if ( ((m_comp_h_samp[1] != 1) || (m_comp_v_samp[1] != 1)) ||
-         ((m_comp_h_samp[2] != 1) || (m_comp_v_samp[2] != 1)) )
-      stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
-
-    if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1))
-    {
-      m_scan_type = JPGD_YH1V1;
-
-      m_max_blocks_per_mcu = 3;
-      m_max_mcu_x_size = 8;
-      m_max_mcu_y_size = 8;
-    }
-    else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1))
-    {
-      m_scan_type = JPGD_YH2V1;
-      m_max_blocks_per_mcu = 4;
-      m_max_mcu_x_size = 16;
-      m_max_mcu_y_size = 8;
-    }
-    else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 2))
-    {
-      m_scan_type = JPGD_YH1V2;
-      m_max_blocks_per_mcu = 4;
-      m_max_mcu_x_size = 8;
-      m_max_mcu_y_size = 16;
-    }
-    else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2))
-    {
-      m_scan_type = JPGD_YH2V2;
-      m_max_blocks_per_mcu = 6;
-      m_max_mcu_x_size = 16;
-      m_max_mcu_y_size = 16;
-    }
-    else
-      stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
-  }
-  else
-    stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
-
-  m_max_mcus_per_row = (m_image_x_size + (m_max_mcu_x_size - 1)) / m_max_mcu_x_size;
-  m_max_mcus_per_col = (m_image_y_size + (m_max_mcu_y_size - 1)) / m_max_mcu_y_size;
-
-  // These values are for the *destination* pixels: after conversion.
-  if (m_scan_type == JPGD_GRAYSCALE)
-    m_dest_bytes_per_pixel = 1;
-  else
-    m_dest_bytes_per_pixel = 4;
-
-  m_dest_bytes_per_scan_line = ((m_image_x_size + 15) & 0xFFF0) * m_dest_bytes_per_pixel;
-
-  m_real_dest_bytes_per_scan_line = (m_image_x_size * m_dest_bytes_per_pixel);
-
-  // Initialize two scan line buffers.
-  m_pScan_line_0 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true);
-  if ((m_scan_type == JPGD_YH1V2) || (m_scan_type == JPGD_YH2V2))
-    m_pScan_line_1 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true);
-
-  m_max_blocks_per_row = m_max_mcus_per_row * m_max_blocks_per_mcu;
-
-  // Should never happen
-  if (m_max_blocks_per_row > JPGD_MAX_BLOCKS_PER_ROW)
-    stop_decoding(JPGD_ASSERTION_ERROR);
-
-  // Allocate the coefficient buffer, enough for one MCU
-  m_pMCU_coefficients = (jpgd_block_t*)alloc(m_max_blocks_per_mcu * 64 * sizeof(jpgd_block_t));
-
-  for (i = 0; i < m_max_blocks_per_mcu; i++)
-    m_mcu_block_max_zag[i] = 64;
-
-  m_expanded_blocks_per_component = m_comp_h_samp[0] * m_comp_v_samp[0];
-  m_expanded_blocks_per_mcu = m_expanded_blocks_per_component * m_comps_in_frame;
-  m_expanded_blocks_per_row = m_max_mcus_per_row * m_expanded_blocks_per_mcu;
-	// Freq. domain chroma upsampling is only supported for H2V2 subsampling factor (the most common one I've seen).
-  m_freq_domain_chroma_upsample = false;
-#if JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING
-  m_freq_domain_chroma_upsample = (m_expanded_blocks_per_mcu == 4*3);
-#endif
-
-  if (m_freq_domain_chroma_upsample)
-    m_pSample_buf = (uint8 *)alloc(m_expanded_blocks_per_row * 64);
-  else
-    m_pSample_buf = (uint8 *)alloc(m_max_blocks_per_row * 64);
-
-  m_total_lines_left = m_image_y_size;
-
-  m_mcu_lines_left = 0;
-
-  create_look_ups();
-}
-
-// The coeff_buf series of methods originally stored the coefficients
-// into a "virtual" file which was located in EMS, XMS, or a disk file. A cache
-// was used to make this process more efficient. Now, we can store the entire
-// thing in RAM.
-jpeg_decoder::coeff_buf* jpeg_decoder::coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y)
-{
-  coeff_buf* cb = (coeff_buf*)alloc(sizeof(coeff_buf));
-
-  cb->block_num_x = block_num_x;
-  cb->block_num_y = block_num_y;
-  cb->block_len_x = block_len_x;
-  cb->block_len_y = block_len_y;
-  cb->block_size = (block_len_x * block_len_y) * sizeof(jpgd_block_t);
-  cb->pData = (uint8 *)alloc(cb->block_size * block_num_x * block_num_y, true);
-  return cb;
-}
-
-inline jpgd_block_t *jpeg_decoder::coeff_buf_getp(coeff_buf *cb, int block_x, int block_y)
-{
-  JPGD_ASSERT((block_x < cb->block_num_x) && (block_y < cb->block_num_y));
-  return (jpgd_block_t *)(cb->pData + block_x * cb->block_size + block_y * (cb->block_size * cb->block_num_x));
-}
-
-// The following methods decode the various types of m_blocks encountered
-// in progressively encoded images.
-void jpeg_decoder::decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y)
-{
-  int s, r;
-  jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
-
-  if ((s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_dc_tab[component_id]])) != 0)
-  {
-    r = pD->get_bits_no_markers(s);
-    s = JPGD_HUFF_EXTEND(r, s);
-  }
-
-  pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]);
-
-  p[0] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
-}
-
-void jpeg_decoder::decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y)
-{
-  if (pD->get_bits_no_markers(1))
-  {
-    jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
-
-    p[0] |= (1 << pD->m_successive_low);
-  }
-}
-
-void jpeg_decoder::decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y)
-{
-  int k, s, r;
-
-  if (pD->m_eob_run)
-  {
-    pD->m_eob_run--;
-    return;
-  }
-
-  jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
-
-  for (k = pD->m_spectral_start; k <= pD->m_spectral_end; k++)
-  {
-    s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
-
-    r = s >> 4;
-    s &= 15;
-
-    if (s)
-    {
-      if ((k += r) > 63)
-        pD->stop_decoding(JPGD_DECODE_ERROR);
-
-      r = pD->get_bits_no_markers(s);
-      s = JPGD_HUFF_EXTEND(r, s);
-
-      p[g_ZAG[k]] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
-    }
-    else
-    {
-      if (r == 15)
-      {
-        if ((k += 15) > 63)
-          pD->stop_decoding(JPGD_DECODE_ERROR);
-      }
-      else
-      {
-        pD->m_eob_run = 1 << r;
-
-        if (r)
-          pD->m_eob_run += pD->get_bits_no_markers(r);
-
-        pD->m_eob_run--;
-
-        break;
-      }
-    }
-  }
-}
-
-void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y)
-{
-  int s, k, r;
-  int p1 = 1 << pD->m_successive_low;
-  int m1 = (-1) << pD->m_successive_low;
-  jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
-
-  JPGD_ASSERT(pD->m_spectral_end <= 63);
-
-  k = pD->m_spectral_start;
-
-  if (pD->m_eob_run == 0)
-  {
-    for ( ; k <= pD->m_spectral_end; k++)
-    {
-      s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
-
-      r = s >> 4;
-      s &= 15;
-
-      if (s)
-      {
-        if (s != 1)
-          pD->stop_decoding(JPGD_DECODE_ERROR);
-
-        if (pD->get_bits_no_markers(1))
-          s = p1;
-        else
-          s = m1;
-      }
-      else
-      {
-        if (r != 15)
-        {
-          pD->m_eob_run = 1 << r;
-
-          if (r)
-            pD->m_eob_run += pD->get_bits_no_markers(r);
-
-          break;
-        }
-      }
-
-      do
-      {
-        jpgd_block_t *this_coef = p + g_ZAG[k & 63];
-
-        if (*this_coef != 0)
-        {
-          if (pD->get_bits_no_markers(1))
-          {
-            if ((*this_coef & p1) == 0)
-            {
-              if (*this_coef >= 0)
-                *this_coef = static_cast<jpgd_block_t>(*this_coef + p1);
-              else
-                *this_coef = static_cast<jpgd_block_t>(*this_coef + m1);
-            }
-          }
-        }
-        else
-        {
-          if (--r < 0)
-            break;
-        }
-
-        k++;
-
-      } while (k <= pD->m_spectral_end);
-
-      if ((s) && (k < 64))
-      {
-        p[g_ZAG[k]] = static_cast<jpgd_block_t>(s);
-      }
-    }
-  }
-
-  if (pD->m_eob_run > 0)
-  {
-    for ( ; k <= pD->m_spectral_end; k++)
-    {
-      jpgd_block_t *this_coef = p + g_ZAG[k & 63]; // logical AND to shut up static code analysis
-
-      if (*this_coef != 0)
-      {
-        if (pD->get_bits_no_markers(1))
-        {
-          if ((*this_coef & p1) == 0)
-          {
-            if (*this_coef >= 0)
-              *this_coef = static_cast<jpgd_block_t>(*this_coef + p1);
-            else
-              *this_coef = static_cast<jpgd_block_t>(*this_coef + m1);
-          }
-        }
-      }
-    }
-
-    pD->m_eob_run--;
-  }
-}
-
-// Decode a scan in a progressively encoded image.
-void jpeg_decoder::decode_scan(pDecode_block_func decode_block_func)
-{
-  int mcu_row, mcu_col, mcu_block;
-  int block_x_mcu[JPGD_MAX_COMPONENTS], m_block_y_mcu[JPGD_MAX_COMPONENTS];
-
-  memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
-
-  for (mcu_col = 0; mcu_col < m_mcus_per_col; mcu_col++)
-  {
-    int component_num, component_id;
-
-    memset(block_x_mcu, 0, sizeof(block_x_mcu));
-
-    for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
-    {
-      int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
-
-      if ((m_restart_interval) && (m_restarts_left == 0))
-        process_restart();
-
-      for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
-      {
-        component_id = m_mcu_org[mcu_block];
-
-        decode_block_func(this, component_id, block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
-
-        if (m_comps_in_scan == 1)
-          block_x_mcu[component_id]++;
-        else
-        {
-          if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
-          {
-            block_x_mcu_ofs = 0;
-
-            if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
-            {
-              block_y_mcu_ofs = 0;
-              block_x_mcu[component_id] += m_comp_h_samp[component_id];
-            }
-          }
-        }
-      }
-
-      m_restarts_left--;
-    }
-
-    if (m_comps_in_scan == 1)
-      m_block_y_mcu[m_comp_list[0]]++;
-    else
-    {
-      for (component_num = 0; component_num < m_comps_in_scan; component_num++)
-      {
-        component_id = m_comp_list[component_num];
-        m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
-      }
-    }
-  }
-}
-
-// Decode a progressively encoded image.
-void jpeg_decoder::init_progressive()
-{
-  int i;
-
-  if (m_comps_in_frame == 4)
-    stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
-
-  // Allocate the coefficient buffers.
-  for (i = 0; i < m_comps_in_frame; i++)
-  {
-    m_dc_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 1, 1);
-    m_ac_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 8, 8);
-  }
-
-  for ( ; ; )
-  {
-    int dc_only_scan, refinement_scan;
-    pDecode_block_func decode_block_func;
-
-    if (!init_scan())
-      break;
-
-    dc_only_scan = (m_spectral_start == 0);
-    refinement_scan = (m_successive_high != 0);
-
-    if ((m_spectral_start > m_spectral_end) || (m_spectral_end > 63))
-      stop_decoding(JPGD_BAD_SOS_SPECTRAL);
-
-    if (dc_only_scan)
-    {
-      if (m_spectral_end)
-        stop_decoding(JPGD_BAD_SOS_SPECTRAL);
-    }
-    else if (m_comps_in_scan != 1)  /* AC scans can only contain one component */
-      stop_decoding(JPGD_BAD_SOS_SPECTRAL);
-
-    if ((refinement_scan) && (m_successive_low != m_successive_high - 1))
-      stop_decoding(JPGD_BAD_SOS_SUCCESSIVE);
-
-    if (dc_only_scan)
-    {
-      if (refinement_scan)
-        decode_block_func = decode_block_dc_refine;
-      else
-        decode_block_func = decode_block_dc_first;
-    }
-    else
-    {
-      if (refinement_scan)
-        decode_block_func = decode_block_ac_refine;
-      else
-        decode_block_func = decode_block_ac_first;
-    }
-
-    decode_scan(decode_block_func);
-
-    m_bits_left = 16;
-    get_bits(16);
-    get_bits(16);
-  }
-
-  m_comps_in_scan = m_comps_in_frame;
-
-  for (i = 0; i < m_comps_in_frame; i++)
-    m_comp_list[i] = i;
-
-  calc_mcu_block_order();
-}
-
-void jpeg_decoder::init_sequential()
-{
-  if (!init_scan())
-    stop_decoding(JPGD_UNEXPECTED_MARKER);
-}
-
-void jpeg_decoder::decode_start()
-{
-  init_frame();
-
-  if (m_progressive_flag)
-    init_progressive();
-  else
-    init_sequential();
-}
-
-void jpeg_decoder::decode_init(jpeg_decoder_stream *pStream)
-{
-  init(pStream);
-  locate_sof_marker();
-}
-
-jpeg_decoder::jpeg_decoder(jpeg_decoder_stream *pStream)
-{
-  if (setjmp(m_jmp_state))
-    return;
-  decode_init(pStream);
-}
-
-int jpeg_decoder::begin_decoding()
-{
-  if (m_ready_flag)
-    return JPGD_SUCCESS;
-
-  if (m_error_code)
-    return JPGD_FAILED;
-
-  if (setjmp(m_jmp_state))
-    return JPGD_FAILED;
-
-  decode_start();
-
-  m_ready_flag = true;
-
-  return JPGD_SUCCESS;
-}
-
-jpeg_decoder::~jpeg_decoder()
-{
-  free_all_blocks();
-}
-
-jpeg_decoder_file_stream::jpeg_decoder_file_stream()
-{
-  m_pFile = NULL;
-  m_eof_flag = false;
-  m_error_flag = false;
-}
-
-void jpeg_decoder_file_stream::close()
-{
-  if (m_pFile)
-  {
-    fclose(m_pFile);
-    m_pFile = NULL;
-  }
-
-  m_eof_flag = false;
-  m_error_flag = false;
-}
-
-jpeg_decoder_file_stream::~jpeg_decoder_file_stream()
-{
-  close();
-}
-
-bool jpeg_decoder_file_stream::open(const char *Pfilename)
-{
-  close();
-
-  m_eof_flag = false;
-  m_error_flag = false;
-
-#if defined(_MSC_VER)
-  m_pFile = NULL;
-  fopen_s(&m_pFile, Pfilename, "rb");
-#else
-  m_pFile = fopen(Pfilename, "rb");
-#endif
-  return m_pFile != NULL;
-}
-
-int jpeg_decoder_file_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag)
-{
-  if (!m_pFile)
-    return -1;
-
-  if (m_eof_flag)
-  {
-    *pEOF_flag = true;
-    return 0;
-  }
-
-  if (m_error_flag)
-    return -1;
-
-  int bytes_read = static_cast<int>(fread(pBuf, 1, max_bytes_to_read, m_pFile));
-  if (bytes_read < max_bytes_to_read)
-  {
-    if (ferror(m_pFile))
-    {
-      m_error_flag = true;
-      return -1;
-    }
-
-    m_eof_flag = true;
-    *pEOF_flag = true;
-  }
-
-  return bytes_read;
-}
-
-bool jpeg_decoder_mem_stream::open(const uint8 *pSrc_data, uint size)
-{
-  close();
-  m_pSrc_data = pSrc_data;
-  m_ofs = 0;
-  m_size = size;
-  return true;
-}
-
-int jpeg_decoder_mem_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag)
-{
-  *pEOF_flag = false;
-
-  if (!m_pSrc_data)
-    return -1;
-
-  uint bytes_remaining = m_size - m_ofs;
-  if ((uint)max_bytes_to_read > bytes_remaining)
-  {
-    max_bytes_to_read = bytes_remaining;
-    *pEOF_flag = true;
-  }
-
-  memcpy(pBuf, m_pSrc_data + m_ofs, max_bytes_to_read);
-  m_ofs += max_bytes_to_read;
-
-  return max_bytes_to_read;
-}
-
-unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps)
-{
-  if (!actual_comps)
-    return NULL;
-  *actual_comps = 0;
-
-  if ((!pStream) || (!width) || (!height) || (!req_comps))
-    return NULL;
-
-  if ((req_comps != 1) && (req_comps != 3) && (req_comps != 4))
-    return NULL;
-
-  jpeg_decoder decoder(pStream);
-  if (decoder.get_error_code() != JPGD_SUCCESS)
-    return NULL;
-
-  const int image_width = decoder.get_width(), image_height = decoder.get_height();
-  *width = image_width;
-  *height = image_height;
-  *actual_comps = decoder.get_num_components();
-
-  if (decoder.begin_decoding() != JPGD_SUCCESS)
-    return NULL;
-
-  const int dst_bpl = image_width * req_comps;
-
-  uint8 *pImage_data = (uint8*)jpgd_malloc(dst_bpl * image_height);
-  if (!pImage_data)
-    return NULL;
-
-  for (int y = 0; y < image_height; y++)
-  {
-    const uint8* pScan_line;
-    uint scan_line_len;
-    if (decoder.decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS)
-    {
-      jpgd_free(pImage_data);
-      return NULL;
-    }
-
-    uint8 *pDst = pImage_data + y * dst_bpl;
-
-    if (((req_comps == 1) && (decoder.get_num_components() == 1)) || ((req_comps == 4) && (decoder.get_num_components() == 3)))
-      memcpy(pDst, pScan_line, dst_bpl);
-    else if (decoder.get_num_components() == 1)
-    {
-      if (req_comps == 3)
-      {
-        for (int x = 0; x < image_width; x++)
-        {
-          uint8 luma = pScan_line[x];
-          pDst[0] = luma;
-          pDst[1] = luma;
-          pDst[2] = luma;
-          pDst += 3;
-        }
-      }
-      else
-      {
-        for (int x = 0; x < image_width; x++)
-        {
-          uint8 luma = pScan_line[x];
-          pDst[0] = luma;
-          pDst[1] = luma;
-          pDst[2] = luma;
-          pDst[3] = 255;
-          pDst += 4;
-        }
-      }
-    }
-    else if (decoder.get_num_components() == 3)
-    {
-      if (req_comps == 1)
-      {
-        const int YR = 19595, YG = 38470, YB = 7471;
-        for (int x = 0; x < image_width; x++)
-        {
-          int r = pScan_line[x*4+0];
-          int g = pScan_line[x*4+1];
-          int b = pScan_line[x*4+2];
-          *pDst++ = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
-        }
-      }
-      else
-      {
-        for (int x = 0; x < image_width; x++)
-        {
-          pDst[0] = pScan_line[x*4+0];
-          pDst[1] = pScan_line[x*4+1];
-          pDst[2] = pScan_line[x*4+2];
-          pDst += 3;
-        }
-      }
-    }
-  }
-
-  return pImage_data;
-}
-
-unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps)
-{
-  jpgd::jpeg_decoder_mem_stream mem_stream(pSrc_data, src_data_size);
-  return decompress_jpeg_image_from_stream(&mem_stream, width, height, actual_comps, req_comps);
-}
-
-unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps)
-{
-  jpgd::jpeg_decoder_file_stream file_stream;
-  if (!file_stream.open(pSrc_filename))
-    return NULL;
-  return decompress_jpeg_image_from_stream(&file_stream, width, height, actual_comps, req_comps);
-}
-
-} // namespace jpgd

+ 0 - 319
Source/ThirdParty/crunch/crnlib/crn_jpgd.h

@@ -1,319 +0,0 @@
-// jpgd.h - C++ class for JPEG decompression.
-// Public domain, Rich Geldreich <[email protected]>
-#ifndef JPEG_DECODER_H
-#define JPEG_DECODER_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <setjmp.h>
-
-#ifdef _MSC_VER
-  #define JPGD_NORETURN __declspec(noreturn) 
-#elif defined(__GNUC__)
-  #define JPGD_NORETURN __attribute__ ((noreturn))
-#else
-  #define JPGD_NORETURN
-#endif
-
-namespace jpgd
-{
-  typedef unsigned char  uint8;
-  typedef   signed short int16;
-  typedef unsigned short uint16;
-  typedef unsigned int   uint;
-  typedef   signed int   int32;
-
-  // Loads a JPEG image from a memory buffer or a file.
-  // req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA).
-  // On return, width/height will be set to the image's dimensions, and actual_comps will be set to the either 1 (grayscale) or 3 (RGB).
-  // Notes: For more control over where and how the source data is read, see the decompress_jpeg_image_from_stream() function below, or call the jpeg_decoder class directly.
-  // Requesting a 8 or 32bpp image is currently a little faster than 24bpp because the jpeg_decoder class itself currently always unpacks to either 8 or 32bpp.
-  unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps);
-  unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps);
-
-  // Success/failure error codes.
-  enum jpgd_status
-  {
-    JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1,
-    JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE, 
-    JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS, 
-    JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH,
-    JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER,
-    JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS,
-    JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE,
-    JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER, JPGD_ASSERTION_ERROR,
-    JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM
-  };
-    
-  // Input stream interface.
-  // Derive from this class to read input data from sources other than files or memory. Set m_eof_flag to true when no more data is available.
-  // The decoder is rather greedy: it will keep on calling this method until its internal input buffer is full, or until the EOF flag is set.
-  // It the input stream contains data after the JPEG stream's EOI (end of image) marker it will probably be pulled into the internal buffer.
-  // Call the get_total_bytes_read() method to determine the actual size of the JPEG stream after successful decoding.
-  class jpeg_decoder_stream
-  {
-  public:
-    jpeg_decoder_stream() { }
-    virtual ~jpeg_decoder_stream() { }
-
-    // The read() method is called when the internal input buffer is empty.
-    // Parameters:
-    // pBuf - input buffer
-    // max_bytes_to_read - maximum bytes that can be written to pBuf
-    // pEOF_flag - set this to true if at end of stream (no more bytes remaining)
-    // Returns -1 on error, otherwise return the number of bytes actually written to the buffer (which may be 0).
-    // Notes: This method will be called in a loop until you set *pEOF_flag to true or the internal buffer is full.
-    virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag) = 0;
-  };
-
-  // stdio FILE stream class.
-  class jpeg_decoder_file_stream : public jpeg_decoder_stream
-  {
-    jpeg_decoder_file_stream(const jpeg_decoder_file_stream &);
-    jpeg_decoder_file_stream &operator =(const jpeg_decoder_file_stream &);
-
-    FILE *m_pFile;
-    bool m_eof_flag, m_error_flag;
-
-  public:
-    jpeg_decoder_file_stream();
-    virtual ~jpeg_decoder_file_stream();
-    
-    bool open(const char *Pfilename);
-    void close();
-
-    virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
-  };
-
-  // Memory stream class.
-  class jpeg_decoder_mem_stream : public jpeg_decoder_stream
-  {
-    const uint8 *m_pSrc_data;
-    uint m_ofs, m_size;
-
-  public:
-    jpeg_decoder_mem_stream() : m_pSrc_data(NULL), m_ofs(0), m_size(0) { }
-    jpeg_decoder_mem_stream(const uint8 *pSrc_data, uint size) : m_pSrc_data(pSrc_data), m_ofs(0), m_size(size) { }
-
-    virtual ~jpeg_decoder_mem_stream() { }
-
-    bool open(const uint8 *pSrc_data, uint size);
-    void close() { m_pSrc_data = NULL; m_ofs = 0; m_size = 0; }
-    
-    virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
-  };
-
-  // Loads JPEG file from a jpeg_decoder_stream.
-  unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps);
-
-  enum 
-  { 
-    JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4, 
-    JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384 
-  };
-          
-  typedef int16 jpgd_quant_t;
-  typedef int16 jpgd_block_t;
-
-  class jpeg_decoder
-  {
-  public:
-    // Call get_error_code() after constructing to determine if the stream is valid or not. You may call the get_width(), get_height(), etc.
-    // methods after the constructor is called. You may then either destruct the object, or begin decoding the image by calling begin_decoding(), then decode() on each scanline.
-    jpeg_decoder(jpeg_decoder_stream *pStream);
-
-    ~jpeg_decoder();
-
-    // Call this method after constructing the object to begin decompression.
-    // If JPGD_SUCCESS is returned you may then call decode() on each scanline.
-    int begin_decoding();
-
-    // Returns the next scan line.
-    // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1). 
-    // Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4).
-    // Returns JPGD_SUCCESS if a scan line has been returned.
-    // Returns JPGD_DONE if all scan lines have been returned.
-    // Returns JPGD_FAILED if an error occurred. Call get_error_code() for a more info.
-    int decode(const void** pScan_line, uint* pScan_line_len);
-    
-    inline jpgd_status get_error_code() const { return m_error_code; }
-
-    inline int get_width() const { return m_image_x_size; }
-    inline int get_height() const { return m_image_y_size; }
-
-    inline int get_num_components() const { return m_comps_in_frame; }
-
-    inline int get_bytes_per_pixel() const { return m_dest_bytes_per_pixel; }
-    inline int get_bytes_per_scan_line() const { return m_image_x_size * get_bytes_per_pixel(); }
-
-    // Returns the total number of bytes actually consumed by the decoder (which should equal the actual size of the JPEG file).
-    inline int get_total_bytes_read() const { return m_total_bytes_read; }
-    
-  private:
-    jpeg_decoder(const jpeg_decoder &);
-    jpeg_decoder &operator =(const jpeg_decoder &);
-
-    typedef void (*pDecode_block_func)(jpeg_decoder *, int, int, int);
-
-    struct huff_tables
-    {
-      bool ac_table;
-      uint  look_up[256];
-      uint  look_up2[256];
-      uint8 code_size[256];
-      uint  tree[512];
-    };
-
-    struct coeff_buf
-    {
-      uint8 *pData;
-      int block_num_x, block_num_y;
-      int block_len_x, block_len_y;
-      int block_size;
-    };
-
-    struct mem_block
-    {
-      mem_block *m_pNext;
-      size_t m_used_count;
-      size_t m_size;
-      char m_data[1];
-    };
-
-    jmp_buf m_jmp_state;
-    mem_block *m_pMem_blocks;
-    int m_image_x_size;
-    int m_image_y_size;
-    jpeg_decoder_stream *m_pStream;
-    int m_progressive_flag;
-    uint8 m_huff_ac[JPGD_MAX_HUFF_TABLES];
-    uint8* m_huff_num[JPGD_MAX_HUFF_TABLES];      // pointer to number of Huffman codes per bit size
-    uint8* m_huff_val[JPGD_MAX_HUFF_TABLES];      // pointer to Huffman codes per bit size
-    jpgd_quant_t* m_quant[JPGD_MAX_QUANT_TABLES]; // pointer to quantization tables
-    int m_scan_type;                              // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no longer supported)
-    int m_comps_in_frame;                         // # of components in frame
-    int m_comp_h_samp[JPGD_MAX_COMPONENTS];       // component's horizontal sampling factor
-    int m_comp_v_samp[JPGD_MAX_COMPONENTS];       // component's vertical sampling factor
-    int m_comp_quant[JPGD_MAX_COMPONENTS];        // component's quantization table selector
-    int m_comp_ident[JPGD_MAX_COMPONENTS];        // component's ID
-    int m_comp_h_blocks[JPGD_MAX_COMPONENTS];
-    int m_comp_v_blocks[JPGD_MAX_COMPONENTS];
-    int m_comps_in_scan;                          // # of components in scan
-    int m_comp_list[JPGD_MAX_COMPS_IN_SCAN];      // components in this scan
-    int m_comp_dc_tab[JPGD_MAX_COMPONENTS];       // component's DC Huffman coding table selector
-    int m_comp_ac_tab[JPGD_MAX_COMPONENTS];       // component's AC Huffman coding table selector
-    int m_spectral_start;                         // spectral selection start
-    int m_spectral_end;                           // spectral selection end
-    int m_successive_low;                         // successive approximation low
-    int m_successive_high;                        // successive approximation high
-    int m_max_mcu_x_size;                         // MCU's max. X size in pixels
-    int m_max_mcu_y_size;                         // MCU's max. Y size in pixels
-    int m_blocks_per_mcu;
-    int m_max_blocks_per_row;
-    int m_mcus_per_row, m_mcus_per_col;
-    int m_mcu_org[JPGD_MAX_BLOCKS_PER_MCU];
-    int m_total_lines_left;                       // total # lines left in image
-    int m_mcu_lines_left;                         // total # lines left in this MCU
-    int m_real_dest_bytes_per_scan_line;
-    int m_dest_bytes_per_scan_line;               // rounded up
-    int m_dest_bytes_per_pixel;                   // 4 (RGB) or 1 (Y)
-    huff_tables* m_pHuff_tabs[JPGD_MAX_HUFF_TABLES];
-    coeff_buf* m_dc_coeffs[JPGD_MAX_COMPONENTS];
-    coeff_buf* m_ac_coeffs[JPGD_MAX_COMPONENTS];
-    int m_eob_run;
-    int m_block_y_mcu[JPGD_MAX_COMPONENTS];
-    uint8* m_pIn_buf_ofs;
-    int m_in_buf_left;
-    int m_tem_flag;
-    bool m_eof_flag;
-    uint8 m_in_buf_pad_start[128];
-    uint8 m_in_buf[JPGD_IN_BUF_SIZE + 128];
-    uint8 m_in_buf_pad_end[128];
-    int m_bits_left;
-    uint m_bit_buf;
-    int m_restart_interval;
-    int m_restarts_left;
-    int m_next_restart_num;
-    int m_max_mcus_per_row;
-    int m_max_blocks_per_mcu;
-    int m_expanded_blocks_per_mcu;
-    int m_expanded_blocks_per_row;
-    int m_expanded_blocks_per_component;
-    bool  m_freq_domain_chroma_upsample;
-    int m_max_mcus_per_col;
-    uint m_last_dc_val[JPGD_MAX_COMPONENTS];
-    jpgd_block_t* m_pMCU_coefficients;
-    int m_mcu_block_max_zag[JPGD_MAX_BLOCKS_PER_MCU];
-    uint8* m_pSample_buf;
-    int m_crr[256];
-    int m_cbb[256];
-    int m_crg[256];
-    int m_cbg[256];
-    uint8* m_pScan_line_0;
-    uint8* m_pScan_line_1;
-    jpgd_status m_error_code;
-    bool m_ready_flag;
-    int m_total_bytes_read;
-
-    void free_all_blocks();
-    JPGD_NORETURN void stop_decoding(jpgd_status status);
-    void *alloc(size_t n, bool zero = false);
-    void word_clear(void *p, uint16 c, uint n);
-    void prep_in_buffer();
-    void read_dht_marker();
-    void read_dqt_marker();
-    void read_sof_marker();
-    void skip_variable_marker();
-    void read_dri_marker();
-    void read_sos_marker();
-    int next_marker();
-    int process_markers();
-    void locate_soi_marker();
-    void locate_sof_marker();
-    int locate_sos_marker();
-    void init(jpeg_decoder_stream * pStream);
-    void create_look_ups();
-    void fix_in_buffer();
-    void transform_mcu(int mcu_row);
-    void transform_mcu_expand(int mcu_row);
-    coeff_buf* coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y);
-    inline jpgd_block_t *coeff_buf_getp(coeff_buf *cb, int block_x, int block_y);
-    void load_next_row();
-    void decode_next_row();
-    void make_huff_table(int index, huff_tables *pH);
-    void check_quant_tables();
-    void check_huff_tables();
-    void calc_mcu_block_order();
-    int init_scan();
-    void init_frame();
-    void process_restart();
-    void decode_scan(pDecode_block_func decode_block_func);
-    void init_progressive();
-    void init_sequential();
-    void decode_start();
-    void decode_init(jpeg_decoder_stream * pStream);
-    void H2V2Convert();
-    void H2V1Convert();
-    void H1V2Convert();
-    void H1V1Convert();
-    void gray_convert();
-    void expanded_convert();
-    void find_eoi();
-    inline uint get_char();
-    inline uint get_char(bool *pPadding_flag);
-    inline void stuff_char(uint8 q);
-    inline uint8 get_octet();
-    inline uint get_bits(int num_bits);
-    inline uint get_bits_no_markers(int numbits);
-    inline int huff_decode(huff_tables *pH);
-    inline int huff_decode(huff_tables *pH, int& extrabits);
-    static inline uint8 clamp(int i);
-    static void decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y);
-    static void decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y);
-    static void decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y);
-    static void decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y);
-  };
-  
-} // namespace jpgd
-
-#endif // JPEG_DECODER_H

+ 0 - 1044
Source/ThirdParty/crunch/crnlib/crn_jpge.cpp

@@ -1,1044 +0,0 @@
-// jpge.cpp - C++ class for JPEG compression.
-// Public domain, Rich Geldreich <[email protected]>
-// v1.01, Dec. 18, 2010 - Initial release
-// v1.02, Apr. 6, 2011 - Removed 2x2 ordered dither in H2V1 chroma subsampling method load_block_16_8_8(). (The rounding factor was 2, when it should have been 1. Either way, it wasn't helping.)
-// v1.03, Apr. 16, 2011 - Added support for optimized Huffman code tables, optimized dynamic memory allocation down to only 1 alloc.
-//                        Also from Alex Evans: Added RGBA support, linear memory allocator (no longer needed in v1.03).
-// v1.04, May. 19, 2012: Forgot to set m_pFile ptr to NULL in cfile_stream::close(). Thanks to Owen Kaluza for reporting this bug.
-//                       Code tweaks to fix VS2008 static code analysis warnings (all looked harmless).
-//                       Code review revealed method load_block_16_8_8() (used for the non-default H2V1 sampling mode to downsample chroma) somehow didn't get the rounding factor fix from v1.02.
-
-#include "crn_jpge.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <malloc.h>
-
-#include "crn_core.h"
-
-#define JPGE_MAX(a,b) (((a)>(b))?(a):(b))
-#define JPGE_MIN(a,b) (((a)<(b))?(a):(b))
-
-namespace jpge {
-
-  static inline void *jpge_malloc(size_t nSize) { return crnlib::crnlib_malloc(nSize); }
-  static inline void jpge_free(void *p) { crnlib::crnlib_free(p); }
-
-  // Various JPEG enums and tables.
-  enum { M_SOF0 = 0xC0, M_DHT = 0xC4, M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_APP0 = 0xE0 };
-  enum { DC_LUM_CODES = 12, AC_LUM_CODES = 256, DC_CHROMA_CODES = 12, AC_CHROMA_CODES = 256, MAX_HUFF_SYMBOLS = 257, MAX_HUFF_CODESIZE = 32 };
-
-  static uint8 s_zag[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 };
-  static int16 s_std_lum_quant[64] = { 16,11,12,14,12,10,16,14,13,14,18,17,16,19,24,40,26,24,22,22,24,49,35,37,29,40,58,51,61,60,57,51,56,55,64,72,92,78,64,68,87,69,55,56,80,109,81,87,95,98,103,104,103,62,77,113,121,112,100,120,92,101,103,99 };
-  static int16 s_std_croma_quant[64] = { 17,18,18,24,21,24,47,26,26,47,99,66,56,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99 };
-  static uint8 s_dc_lum_bits[17] = { 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 };
-  static uint8 s_dc_lum_val[DC_LUM_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
-  static uint8 s_ac_lum_bits[17] = { 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d };
-  static uint8 s_ac_lum_val[AC_LUM_CODES]  =
-  {
-    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
-    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
-    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
-    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
-    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
-    0xf9,0xfa
-  };
-  static uint8 s_dc_chroma_bits[17] = { 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 };
-  static uint8 s_dc_chroma_val[DC_CHROMA_CODES]  = { 0,1,2,3,4,5,6,7,8,9,10,11 };
-  static uint8 s_ac_chroma_bits[17] = { 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77 };
-  static uint8 s_ac_chroma_val[AC_CHROMA_CODES] =
-  {
-    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
-    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
-    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
-    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
-    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
-    0xf9,0xfa
-  };
-
-  // Low-level helper functions.
-  template <class T> inline void clear_obj(T &obj) { memset(&obj, 0, sizeof(obj)); }
-
-  const int YR = 19595, YG = 38470, YB = 7471, CB_R = -11059, CB_G = -21709, CB_B = 32768, CR_R = 32768, CR_G = -27439, CR_B = -5329;
-  static inline uint8 clamp(int i) { if (static_cast<uint>(i) > 255U) { if (i < 0) i = 0; else if (i > 255) i = 255; } return static_cast<uint8>(i); }
-
-  static void RGB_to_YCC(uint8* pDst, const uint8 *pSrc, int num_pixels)
-  {
-    for ( ; num_pixels; pDst += 3, pSrc += 3, num_pixels--)
-    {
-      const int r = pSrc[0], g = pSrc[1], b = pSrc[2];
-      pDst[0] = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
-      pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16));
-      pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16));
-    }
-  }
-
-  static void RGB_to_Y(uint8* pDst, const uint8 *pSrc, int num_pixels)
-  {
-    for ( ; num_pixels; pDst++, pSrc += 3, num_pixels--)
-      pDst[0] = static_cast<uint8>((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16);
-  }
-
-  static void RGBA_to_YCC(uint8* pDst, const uint8 *pSrc, int num_pixels)
-  {
-    for ( ; num_pixels; pDst += 3, pSrc += 4, num_pixels--)
-    {
-      const int r = pSrc[0], g = pSrc[1], b = pSrc[2];
-      pDst[0] = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
-      pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16));
-      pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16));
-    }
-  }
-
-  static void RGBA_to_Y(uint8* pDst, const uint8 *pSrc, int num_pixels)
-  {
-    for ( ; num_pixels; pDst++, pSrc += 4, num_pixels--)
-      pDst[0] = static_cast<uint8>((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16);
-  }
-
-  static void Y_to_YCC(uint8* pDst, const uint8* pSrc, int num_pixels)
-  {
-    for( ; num_pixels; pDst += 3, pSrc++, num_pixels--) { pDst[0] = pSrc[0]; pDst[1] = 128; pDst[2] = 128; }
-  }
-
-  // Forward DCT - DCT derived from jfdctint.
-  enum { CONST_BITS = 13, ROW_BITS = 2 };
-#define DCT_DESCALE(x, n) (((x) + (((int32)1) << ((n) - 1))) >> (n))
-#define DCT_MUL(var, c) (static_cast<int16>(var) * static_cast<int32>(c))
-#define DCT1D(s0, s1, s2, s3, s4, s5, s6, s7) \
-  int32 t0 = s0 + s7, t7 = s0 - s7, t1 = s1 + s6, t6 = s1 - s6, t2 = s2 + s5, t5 = s2 - s5, t3 = s3 + s4, t4 = s3 - s4; \
-  int32 t10 = t0 + t3, t13 = t0 - t3, t11 = t1 + t2, t12 = t1 - t2; \
-  int32 u1 = DCT_MUL(t12 + t13, 4433); \
-  s2 = u1 + DCT_MUL(t13, 6270); \
-  s6 = u1 + DCT_MUL(t12, -15137); \
-  u1 = t4 + t7; \
-  int32 u2 = t5 + t6, u3 = t4 + t6, u4 = t5 + t7; \
-  int32 z5 = DCT_MUL(u3 + u4, 9633); \
-  t4 = DCT_MUL(t4, 2446); t5 = DCT_MUL(t5, 16819); \
-  t6 = DCT_MUL(t6, 25172); t7 = DCT_MUL(t7, 12299); \
-  u1 = DCT_MUL(u1, -7373); u2 = DCT_MUL(u2, -20995); \
-  u3 = DCT_MUL(u3, -16069); u4 = DCT_MUL(u4, -3196); \
-  u3 += z5; u4 += z5; \
-  s0 = t10 + t11; s1 = t7 + u1 + u4; s3 = t6 + u2 + u3; s4 = t10 - t11; s5 = t5 + u2 + u4; s7 = t4 + u1 + u3;
-
-  static void DCT2D(int32 *p)
-  {
-    int32 c, *q = p;
-    for (c = 7; c >= 0; c--, q += 8)
-    {
-      int32 s0 = q[0], s1 = q[1], s2 = q[2], s3 = q[3], s4 = q[4], s5 = q[5], s6 = q[6], s7 = q[7];
-      DCT1D(s0, s1, s2, s3, s4, s5, s6, s7);
-      q[0] = s0 << ROW_BITS; q[1] = DCT_DESCALE(s1, CONST_BITS-ROW_BITS); q[2] = DCT_DESCALE(s2, CONST_BITS-ROW_BITS); q[3] = DCT_DESCALE(s3, CONST_BITS-ROW_BITS);
-      q[4] = s4 << ROW_BITS; q[5] = DCT_DESCALE(s5, CONST_BITS-ROW_BITS); q[6] = DCT_DESCALE(s6, CONST_BITS-ROW_BITS); q[7] = DCT_DESCALE(s7, CONST_BITS-ROW_BITS);
-    }
-    for (q = p, c = 7; c >= 0; c--, q++)
-    {
-      int32 s0 = q[0*8], s1 = q[1*8], s2 = q[2*8], s3 = q[3*8], s4 = q[4*8], s5 = q[5*8], s6 = q[6*8], s7 = q[7*8];
-      DCT1D(s0, s1, s2, s3, s4, s5, s6, s7);
-      q[0*8] = DCT_DESCALE(s0, ROW_BITS+3); q[1*8] = DCT_DESCALE(s1, CONST_BITS+ROW_BITS+3); q[2*8] = DCT_DESCALE(s2, CONST_BITS+ROW_BITS+3); q[3*8] = DCT_DESCALE(s3, CONST_BITS+ROW_BITS+3);
-      q[4*8] = DCT_DESCALE(s4, ROW_BITS+3); q[5*8] = DCT_DESCALE(s5, CONST_BITS+ROW_BITS+3); q[6*8] = DCT_DESCALE(s6, CONST_BITS+ROW_BITS+3); q[7*8] = DCT_DESCALE(s7, CONST_BITS+ROW_BITS+3);
-    }
-  }
-
-  struct sym_freq { uint m_key, m_sym_index; };
-
-  // Radix sorts sym_freq[] array by 32-bit key m_key. Returns ptr to sorted values.
-  static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* pSyms0, sym_freq* pSyms1)
-  {
-    const uint cMaxPasses = 4;
-    uint32 hist[256 * cMaxPasses]; clear_obj(hist);
-    for (uint i = 0; i < num_syms; i++) { uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; hist[256*2 + ((freq >> 16) & 0xFF)]++; hist[256*3 + ((freq >> 24) & 0xFF)]++; }
-    sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1;
-    uint total_passes = cMaxPasses; while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
-    for (uint pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
-    {
-      const uint32* pHist = &hist[pass << 8];
-      uint offsets[256], cur_ofs = 0;
-      for (uint i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
-      for (uint i = 0; i < num_syms; i++)
-        pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
-      sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t;
-    }
-    return pCur_syms;
-  }
-
-  // calculate_minimum_redundancy() originally written by: Alistair Moffat, [email protected], Jyrki Katajainen, [email protected], November 1996.
-  static void calculate_minimum_redundancy(sym_freq *A, int n)
-  {
-    int root, leaf, next, avbl, used, dpth;
-    if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
-    A[0].m_key += A[1].m_key; root = 0; leaf = 2;
-    for (next=1; next < n-1; next++)
-    {
-      if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = next; } else A[next].m_key = A[leaf++].m_key;
-      if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key += A[root].m_key; A[root++].m_key = next; } else A[next].m_key += A[leaf++].m_key;
-    }
-    A[n-2].m_key = 0;
-    for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
-    avbl = 1; used = dpth = 0; root = n-2; next = n-1;
-    while (avbl>0)
-    {
-      while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
-      while (avbl>used) { A[next--].m_key = dpth; avbl--; }
-      avbl = 2*used; dpth++; used = 0;
-    }
-  }
-
-  // Limits canonical Huffman code table's max code size to max_code_size.
-  static void huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
-  {
-    if (code_list_len <= 1) return;
-
-    for (int i = max_code_size + 1; i <= MAX_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
-
-    uint32 total = 0;
-    for (int i = max_code_size; i > 0; i--)
-      total += (((uint32)pNum_codes[i]) << (max_code_size - i));
-
-    while (total != (1UL << max_code_size))
-    {
-      pNum_codes[max_code_size]--;
-      for (int i = max_code_size - 1; i > 0; i--)
-      {
-        if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
-      }
-      total--;
-    }
-  }
-
-  // Generates an optimized offman table.
-  void jpeg_encoder::optimize_huffman_table(int table_num, int table_len)
-  {
-    sym_freq syms0[MAX_HUFF_SYMBOLS], syms1[MAX_HUFF_SYMBOLS];
-    syms0[0].m_key = 1; syms0[0].m_sym_index = 0;  // dummy symbol, assures that no valid code contains all 1's
-    int num_used_syms = 1;
-    const uint32 *pSym_count = &m_huff_count[table_num][0];
-    for (int i = 0; i < table_len; i++)
-      if (pSym_count[i]) { syms0[num_used_syms].m_key = pSym_count[i]; syms0[num_used_syms++].m_sym_index = i + 1; }
-      sym_freq* pSyms = radix_sort_syms(num_used_syms, syms0, syms1);
-      calculate_minimum_redundancy(pSyms, num_used_syms);
-
-      // Count the # of symbols of each code size.
-      int num_codes[1 + MAX_HUFF_CODESIZE]; clear_obj(num_codes);
-      for (int i = 0; i < num_used_syms; i++)
-        num_codes[pSyms[i].m_key]++;
-
-      const uint JPGE_CODE_SIZE_LIMIT = 16; // the maximum possible size of a JPEG Huffman code (valid range is [9,16] - 9 vs. 8 because of the dummy symbol)
-      huffman_enforce_max_code_size(num_codes, num_used_syms, JPGE_CODE_SIZE_LIMIT);
-
-      // Compute m_huff_bits array, which contains the # of symbols per code size.
-      clear_obj(m_huff_bits[table_num]);
-      for (int i = 1; i <= (int)JPGE_CODE_SIZE_LIMIT; i++)
-        m_huff_bits[table_num][i] = static_cast<uint8>(num_codes[i]);
-
-      // Remove the dummy symbol added above, which must be in largest bucket.
-      for (int i = JPGE_CODE_SIZE_LIMIT; i >= 1; i--)
-      {
-        if (m_huff_bits[table_num][i]) { m_huff_bits[table_num][i]--; break; }
-      }
-
-      // Compute the m_huff_val array, which contains the symbol indices sorted by code size (smallest to largest).
-      for (int i = num_used_syms - 1; i >= 1; i--)
-        m_huff_val[table_num][num_used_syms - 1 - i] = static_cast<uint8>(pSyms[i].m_sym_index - 1);
-  }
-
-  // JPEG marker generation.
-  void jpeg_encoder::emit_byte(uint8 i)
-  {
-    m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_obj(i);
-  }
-
-  void jpeg_encoder::emit_word(uint i)
-  {
-    emit_byte(uint8(i >> 8)); emit_byte(uint8(i & 0xFF));
-  }
-
-  void jpeg_encoder::emit_marker(int marker)
-  {
-    emit_byte(uint8(0xFF)); emit_byte(uint8(marker));
-  }
-
-  // Emit JFIF marker
-  void jpeg_encoder::emit_jfif_app0()
-  {
-    emit_marker(M_APP0);
-    emit_word(2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1);
-    emit_byte(0x4A); emit_byte(0x46); emit_byte(0x49); emit_byte(0x46); /* Identifier: ASCII "JFIF" */
-    emit_byte(0);
-    emit_byte(1);      /* Major version */
-    emit_byte(1);      /* Minor version */
-    emit_byte(0);      /* Density unit */
-    emit_word(1);
-    emit_word(1);
-    emit_byte(0);      /* No thumbnail image */
-    emit_byte(0);
-  }
-
-  // Emit quantization tables
-  void jpeg_encoder::emit_dqt()
-  {
-    for (int i = 0; i < ((m_num_components == 3) ? 2 : 1); i++)
-    {
-      emit_marker(M_DQT);
-      emit_word(64 + 1 + 2);
-      emit_byte(static_cast<uint8>(i));
-      for (int j = 0; j < 64; j++)
-        emit_byte(static_cast<uint8>(m_quantization_tables[i][j]));
-    }
-  }
-
-  // Emit start of frame marker
-  void jpeg_encoder::emit_sof()
-  {
-    emit_marker(M_SOF0);                           /* baseline */
-    emit_word(3 * m_num_components + 2 + 5 + 1);
-    emit_byte(8);                                  /* precision */
-    emit_word(m_image_y);
-    emit_word(m_image_x);
-    emit_byte(m_num_components);
-    for (int i = 0; i < m_num_components; i++)
-    {
-      emit_byte(static_cast<uint8>(i + 1));                                   /* component ID     */
-      emit_byte((m_comp_h_samp[i] << 4) + m_comp_v_samp[i]);  /* h and v sampling */
-      emit_byte(i > 0);                                   /* quant. table num */
-    }
-  }
-
-  // Emit Huffman table.
-  void jpeg_encoder::emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag)
-  {
-    emit_marker(M_DHT);
-
-    int length = 0;
-    for (int i = 1; i <= 16; i++)
-      length += bits[i];
-
-    emit_word(length + 2 + 1 + 16);
-    emit_byte(static_cast<uint8>(index + (ac_flag << 4)));
-
-    for (int i = 1; i <= 16; i++)
-      emit_byte(bits[i]);
-
-    for (int i = 0; i < length; i++)
-      emit_byte(val[i]);
-  }
-
-  // Emit all Huffman tables.
-  void jpeg_encoder::emit_dhts()
-  {
-    emit_dht(m_huff_bits[0+0], m_huff_val[0+0], 0, false);
-    emit_dht(m_huff_bits[2+0], m_huff_val[2+0], 0, true);
-    if (m_num_components == 3)
-    {
-      emit_dht(m_huff_bits[0+1], m_huff_val[0+1], 1, false);
-      emit_dht(m_huff_bits[2+1], m_huff_val[2+1], 1, true);
-    }
-  }
-
-  // emit start of scan
-  void jpeg_encoder::emit_sos()
-  {
-    emit_marker(M_SOS);
-    emit_word(2 * m_num_components + 2 + 1 + 3);
-    emit_byte(m_num_components);
-    for (int i = 0; i < m_num_components; i++)
-    {
-      emit_byte(static_cast<uint8>(i + 1));
-      if (i == 0)
-        emit_byte((0 << 4) + 0);
-      else
-        emit_byte((1 << 4) + 1);
-    }
-    emit_byte(0);     /* spectral selection */
-    emit_byte(63);
-    emit_byte(0);
-  }
-
-  // Emit all markers at beginning of image file.
-  void jpeg_encoder::emit_markers()
-  {
-    emit_marker(M_SOI);
-    emit_jfif_app0();
-    emit_dqt();
-    emit_sof();
-    emit_dhts();
-    emit_sos();
-  }
-
-  // Compute the actual canonical Huffman codes/code sizes given the JPEG huff bits and val arrays.
-  void jpeg_encoder::compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits, uint8 *val)
-  {
-    int i, l, last_p, si;
-    uint8 huff_size[257];
-    uint huff_code[257];
-    uint code;
-
-    int p = 0;
-    for (l = 1; l <= 16; l++)
-      for (i = 1; i <= bits[l]; i++)
-        huff_size[p++] = (char)l;
-
-    huff_size[p] = 0; last_p = p; // write sentinel
-
-    code = 0; si = huff_size[0]; p = 0;
-
-    while (huff_size[p])
-    {
-      while (huff_size[p] == si)
-        huff_code[p++] = code++;
-      code <<= 1;
-      si++;
-    }
-
-    memset(codes, 0, sizeof(codes[0])*256);
-    memset(code_sizes, 0, sizeof(code_sizes[0])*256);
-    for (p = 0; p < last_p; p++)
-    {
-      codes[val[p]]      = huff_code[p];
-      code_sizes[val[p]] = huff_size[p];
-    }
-  }
-
-  // Quantization table generation.
-  void jpeg_encoder::compute_quant_table(int32 *pDst, int16 *pSrc)
-  {
-    int32 q;
-    if (m_params.m_quality < 50)
-      q = 5000 / m_params.m_quality;
-    else
-      q = 200 - m_params.m_quality * 2;
-    for (int i = 0; i < 64; i++)
-    {
-      int32 j = *pSrc++; j = (j * q + 50L) / 100L;
-      *pDst++ = JPGE_MIN(JPGE_MAX(j, 1), 255);
-    }
-  }
-
-  // Higher-level methods.
-  void jpeg_encoder::first_pass_init()
-  {
-    m_bit_buffer = 0; m_bits_in = 0;
-    memset(m_last_dc_val, 0, 3 * sizeof(m_last_dc_val[0]));
-    m_mcu_y_ofs = 0;
-    m_pass_num = 1;
-  }
-
-  bool jpeg_encoder::second_pass_init()
-  {
-    compute_huffman_table(&m_huff_codes[0+0][0], &m_huff_code_sizes[0+0][0], m_huff_bits[0+0], m_huff_val[0+0]);
-    compute_huffman_table(&m_huff_codes[2+0][0], &m_huff_code_sizes[2+0][0], m_huff_bits[2+0], m_huff_val[2+0]);
-    if (m_num_components > 1)
-    {
-      compute_huffman_table(&m_huff_codes[0+1][0], &m_huff_code_sizes[0+1][0], m_huff_bits[0+1], m_huff_val[0+1]);
-      compute_huffman_table(&m_huff_codes[2+1][0], &m_huff_code_sizes[2+1][0], m_huff_bits[2+1], m_huff_val[2+1]);
-    }
-    first_pass_init();
-    emit_markers();
-    m_pass_num = 2;
-    return true;
-  }
-
-  bool jpeg_encoder::jpg_open(int p_x_res, int p_y_res, int src_channels)
-  {
-    m_num_components = 3;
-    switch (m_params.m_subsampling)
-    {
-    case Y_ONLY:
-      {
-        m_num_components = 1;
-        m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1;
-        m_mcu_x          = 8; m_mcu_y          = 8;
-        break;
-      }
-    case H1V1:
-      {
-        m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1;
-        m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
-        m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
-        m_mcu_x          = 8; m_mcu_y          = 8;
-        break;
-      }
-    case H2V1:
-      {
-        m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 1;
-        m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
-        m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
-        m_mcu_x          = 16; m_mcu_y         = 8;
-        break;
-      }
-    case H2V2:
-      {
-        m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 2;
-        m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
-        m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
-        m_mcu_x          = 16; m_mcu_y         = 16;
-      }
-    }
-
-    m_image_x        = p_x_res; m_image_y = p_y_res;
-    m_image_bpp      = src_channels;
-    m_image_bpl      = m_image_x * src_channels;
-    m_image_x_mcu    = (m_image_x + m_mcu_x - 1) & (~(m_mcu_x - 1));
-    m_image_y_mcu    = (m_image_y + m_mcu_y - 1) & (~(m_mcu_y - 1));
-    m_image_bpl_xlt  = m_image_x * m_num_components;
-    m_image_bpl_mcu  = m_image_x_mcu * m_num_components;
-    m_mcus_per_row   = m_image_x_mcu / m_mcu_x;
-
-    if ((m_mcu_lines[0] = static_cast<uint8*>(jpge_malloc(m_image_bpl_mcu * m_mcu_y))) == NULL) return false;
-    for (int i = 1; i < m_mcu_y; i++)
-      m_mcu_lines[i] = m_mcu_lines[i-1] + m_image_bpl_mcu;
-
-    compute_quant_table(m_quantization_tables[0], s_std_lum_quant);
-    compute_quant_table(m_quantization_tables[1], m_params.m_no_chroma_discrim_flag ? s_std_lum_quant : s_std_croma_quant);
-
-    m_out_buf_left = JPGE_OUT_BUF_SIZE;
-    m_pOut_buf = m_out_buf;
-
-    if (m_params.m_two_pass_flag)
-    {
-      clear_obj(m_huff_count);
-      first_pass_init();
-    }
-    else
-    {
-      memcpy(m_huff_bits[0+0], s_dc_lum_bits, 17);    memcpy(m_huff_val [0+0], s_dc_lum_val, DC_LUM_CODES);
-      memcpy(m_huff_bits[2+0], s_ac_lum_bits, 17);    memcpy(m_huff_val [2+0], s_ac_lum_val, AC_LUM_CODES);
-      memcpy(m_huff_bits[0+1], s_dc_chroma_bits, 17); memcpy(m_huff_val [0+1], s_dc_chroma_val, DC_CHROMA_CODES);
-      memcpy(m_huff_bits[2+1], s_ac_chroma_bits, 17); memcpy(m_huff_val [2+1], s_ac_chroma_val, AC_CHROMA_CODES);
-      if (!second_pass_init()) return false;   // in effect, skip over the first pass
-    }
-    return m_all_stream_writes_succeeded;
-  }
-
-  void jpeg_encoder::load_block_8_8_grey(int x)
-  {
-    uint8 *pSrc;
-    sample_array_t *pDst = m_sample_array;
-    x <<= 3;
-    for (int i = 0; i < 8; i++, pDst += 8)
-    {
-      pSrc = m_mcu_lines[i] + x;
-      pDst[0] = pSrc[0] - 128; pDst[1] = pSrc[1] - 128; pDst[2] = pSrc[2] - 128; pDst[3] = pSrc[3] - 128;
-      pDst[4] = pSrc[4] - 128; pDst[5] = pSrc[5] - 128; pDst[6] = pSrc[6] - 128; pDst[7] = pSrc[7] - 128;
-    }
-  }
-
-  void jpeg_encoder::load_block_8_8(int x, int y, int c)
-  {
-    uint8 *pSrc;
-    sample_array_t *pDst = m_sample_array;
-    x = (x * (8 * 3)) + c;
-    y <<= 3;
-    for (int i = 0; i < 8; i++, pDst += 8)
-    {
-      pSrc = m_mcu_lines[y + i] + x;
-      pDst[0] = pSrc[0 * 3] - 128; pDst[1] = pSrc[1 * 3] - 128; pDst[2] = pSrc[2 * 3] - 128; pDst[3] = pSrc[3 * 3] - 128;
-      pDst[4] = pSrc[4 * 3] - 128; pDst[5] = pSrc[5 * 3] - 128; pDst[6] = pSrc[6 * 3] - 128; pDst[7] = pSrc[7 * 3] - 128;
-    }
-  }
-
-  void jpeg_encoder::load_block_16_8(int x, int c)
-  {
-    uint8 *pSrc1, *pSrc2;
-    sample_array_t *pDst = m_sample_array;
-    x = (x * (16 * 3)) + c;
-    int a = 0, b = 2;
-    for (int i = 0; i < 16; i += 2, pDst += 8)
-    {
-      pSrc1 = m_mcu_lines[i + 0] + x;
-      pSrc2 = m_mcu_lines[i + 1] + x;
-      pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3] + pSrc2[ 0 * 3] + pSrc2[ 1 * 3] + a) >> 2) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3] + pSrc2[ 2 * 3] + pSrc2[ 3 * 3] + b) >> 2) - 128;
-      pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3] + pSrc2[ 4 * 3] + pSrc2[ 5 * 3] + a) >> 2) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3] + pSrc2[ 6 * 3] + pSrc2[ 7 * 3] + b) >> 2) - 128;
-      pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3] + pSrc2[ 8 * 3] + pSrc2[ 9 * 3] + a) >> 2) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3] + pSrc2[10 * 3] + pSrc2[11 * 3] + b) >> 2) - 128;
-      pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3] + pSrc2[12 * 3] + pSrc2[13 * 3] + a) >> 2) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3] + pSrc2[14 * 3] + pSrc2[15 * 3] + b) >> 2) - 128;
-      int temp = a; a = b; b = temp;
-    }
-  }
-
-  void jpeg_encoder::load_block_16_8_8(int x, int c)
-  {
-    uint8 *pSrc1;
-    sample_array_t *pDst = m_sample_array;
-    x = (x * (16 * 3)) + c;
-    for (int i = 0; i < 8; i++, pDst += 8)
-    {
-      pSrc1 = m_mcu_lines[i + 0] + x;
-      pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3]) >> 1) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3]) >> 1) - 128;
-      pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3]) >> 1) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3]) >> 1) - 128;
-      pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3]) >> 1) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3]) >> 1) - 128;
-      pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3]) >> 1) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3]) >> 1) - 128;
-    }
-  }
-
-  void jpeg_encoder::load_quantized_coefficients(int component_num)
-  {
-    int32 *q = m_quantization_tables[component_num > 0];
-    int16 *pDst = m_coefficient_array;
-    for (int i = 0; i < 64; i++)
-    {
-      sample_array_t j = m_sample_array[s_zag[i]];
-      if (j < 0)
-      {
-        if ((j = -j + (*q >> 1)) < *q)
-          *pDst++ = 0;
-        else
-          *pDst++ = static_cast<int16>(-(j / *q));
-      }
-      else
-      {
-        if ((j = j + (*q >> 1)) < *q)
-          *pDst++ = 0;
-        else
-          *pDst++ = static_cast<int16>((j / *q));
-      }
-      q++;
-    }
-  }
-
-  void jpeg_encoder::flush_output_buffer()
-  {
-    if (m_out_buf_left != JPGE_OUT_BUF_SIZE)
-      m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_buf(m_out_buf, JPGE_OUT_BUF_SIZE - m_out_buf_left);
-    m_pOut_buf = m_out_buf;
-    m_out_buf_left = JPGE_OUT_BUF_SIZE;
-  }
-
-  void jpeg_encoder::put_bits(uint bits, uint len)
-  {
-    m_bit_buffer |= ((uint32)bits << (24 - (m_bits_in += len)));
-    while (m_bits_in >= 8)
-    {
-      uint8 c;
-#define JPGE_PUT_BYTE(c) { *m_pOut_buf++ = (c); if (--m_out_buf_left == 0) flush_output_buffer(); }
-      JPGE_PUT_BYTE(c = (uint8)((m_bit_buffer >> 16) & 0xFF));
-      if (c == 0xFF) JPGE_PUT_BYTE(0);
-      m_bit_buffer <<= 8;
-      m_bits_in -= 8;
-    }
-  }
-
-  void jpeg_encoder::code_coefficients_pass_one(int component_num)
-  {
-    if (component_num >= 3) return; // just to shut up static analysis
-    int i, run_len, nbits, temp1;
-    int16 *src = m_coefficient_array;
-    uint32 *dc_count = component_num ? m_huff_count[0 + 1] : m_huff_count[0 + 0], *ac_count = component_num ? m_huff_count[2 + 1] : m_huff_count[2 + 0];
-
-    temp1 = src[0] - m_last_dc_val[component_num];
-    m_last_dc_val[component_num] = src[0];
-    if (temp1 < 0) temp1 = -temp1;
-
-    nbits = 0;
-    while (temp1)
-    {
-      nbits++; temp1 >>= 1;
-    }
-
-    dc_count[nbits]++;
-    for (run_len = 0, i = 1; i < 64; i++)
-    {
-      if ((temp1 = m_coefficient_array[i]) == 0)
-        run_len++;
-      else
-      {
-        while (run_len >= 16)
-        {
-          ac_count[0xF0]++;
-          run_len -= 16;
-        }
-        if (temp1 < 0) temp1 = -temp1;
-        nbits = 1;
-        while (temp1 >>= 1) nbits++;
-        ac_count[(run_len << 4) + nbits]++;
-        run_len = 0;
-      }
-    }
-    if (run_len) ac_count[0]++;
-  }
-
-  void jpeg_encoder::code_coefficients_pass_two(int component_num)
-  {
-    int i, j, run_len, nbits, temp1, temp2;
-    int16 *pSrc = m_coefficient_array;
-    uint *codes[2];
-    uint8 *code_sizes[2];
-
-    if (component_num == 0)
-    {
-      codes[0] = m_huff_codes[0 + 0]; codes[1] = m_huff_codes[2 + 0];
-      code_sizes[0] = m_huff_code_sizes[0 + 0]; code_sizes[1] = m_huff_code_sizes[2 + 0];
-    }
-    else
-    {
-      codes[0] = m_huff_codes[0 + 1]; codes[1] = m_huff_codes[2 + 1];
-      code_sizes[0] = m_huff_code_sizes[0 + 1]; code_sizes[1] = m_huff_code_sizes[2 + 1];
-    }
-
-    temp1 = temp2 = pSrc[0] - m_last_dc_val[component_num];
-    m_last_dc_val[component_num] = pSrc[0];
-
-    if (temp1 < 0)
-    {
-      temp1 = -temp1; temp2--;
-    }
-
-    nbits = 0;
-    while (temp1)
-    {
-      nbits++; temp1 >>= 1;
-    }
-
-    put_bits(codes[0][nbits], code_sizes[0][nbits]);
-    if (nbits) put_bits(temp2 & ((1 << nbits) - 1), nbits);
-
-    for (run_len = 0, i = 1; i < 64; i++)
-    {
-      if ((temp1 = m_coefficient_array[i]) == 0)
-        run_len++;
-      else
-      {
-        while (run_len >= 16)
-        {
-          put_bits(codes[1][0xF0], code_sizes[1][0xF0]);
-          run_len -= 16;
-        }
-        if ((temp2 = temp1) < 0)
-        {
-          temp1 = -temp1;
-          temp2--;
-        }
-        nbits = 1;
-        while (temp1 >>= 1)
-          nbits++;
-        j = (run_len << 4) + nbits;
-        put_bits(codes[1][j], code_sizes[1][j]);
-        put_bits(temp2 & ((1 << nbits) - 1), nbits);
-        run_len = 0;
-      }
-    }
-    if (run_len)
-      put_bits(codes[1][0], code_sizes[1][0]);
-  }
-
-  void jpeg_encoder::code_block(int component_num)
-  {
-    DCT2D(m_sample_array);
-    load_quantized_coefficients(component_num);
-    if (m_pass_num == 1)
-      code_coefficients_pass_one(component_num);
-    else
-      code_coefficients_pass_two(component_num);
-  }
-
-  void jpeg_encoder::process_mcu_row()
-  {
-    if (m_num_components == 1)
-    {
-      for (int i = 0; i < m_mcus_per_row; i++)
-      {
-        load_block_8_8_grey(i); code_block(0);
-      }
-    }
-    else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1))
-    {
-      for (int i = 0; i < m_mcus_per_row; i++)
-      {
-        load_block_8_8(i, 0, 0); code_block(0); load_block_8_8(i, 0, 1); code_block(1); load_block_8_8(i, 0, 2); code_block(2);
-      }
-    }
-    else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1))
-    {
-      for (int i = 0; i < m_mcus_per_row; i++)
-      {
-        load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0);
-        load_block_16_8_8(i, 1); code_block(1); load_block_16_8_8(i, 2); code_block(2);
-      }
-    }
-    else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2))
-    {
-      for (int i = 0; i < m_mcus_per_row; i++)
-      {
-        load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0);
-        load_block_8_8(i * 2 + 0, 1, 0); code_block(0); load_block_8_8(i * 2 + 1, 1, 0); code_block(0);
-        load_block_16_8(i, 1); code_block(1); load_block_16_8(i, 2); code_block(2);
-      }
-    }
-  }
-
-  bool jpeg_encoder::terminate_pass_one()
-  {
-    optimize_huffman_table(0+0, DC_LUM_CODES); optimize_huffman_table(2+0, AC_LUM_CODES);
-    if (m_num_components > 1)
-    {
-      optimize_huffman_table(0+1, DC_CHROMA_CODES); optimize_huffman_table(2+1, AC_CHROMA_CODES);
-    }
-    return second_pass_init();
-  }
-
-  bool jpeg_encoder::terminate_pass_two()
-  {
-    put_bits(0x7F, 7);
-    flush_output_buffer();
-    emit_marker(M_EOI);
-    m_pass_num++; // purposely bump up m_pass_num, for debugging
-    return true;
-  }
-
-  bool jpeg_encoder::process_end_of_image()
-  {
-    if (m_mcu_y_ofs)
-    {
-      if (m_mcu_y_ofs < 16) // check here just to shut up static analysis
-      {
-        for (int i = m_mcu_y_ofs; i < m_mcu_y; i++)
-          memcpy(m_mcu_lines[i], m_mcu_lines[m_mcu_y_ofs - 1], m_image_bpl_mcu);
-      }
-
-      process_mcu_row();
-    }
-
-    if (m_pass_num == 1)
-      return terminate_pass_one();
-    else
-      return terminate_pass_two();
-  }
-
-  void jpeg_encoder::load_mcu(const void *pSrc)
-  {
-    const uint8* Psrc = reinterpret_cast<const uint8*>(pSrc);
-
-    uint8* pDst = m_mcu_lines[m_mcu_y_ofs]; // OK to write up to m_image_bpl_xlt bytes to pDst
-
-    if (m_num_components == 1)
-    {
-      if (m_image_bpp == 4)
-        RGBA_to_Y(pDst, Psrc, m_image_x);
-      else if (m_image_bpp == 3)
-        RGB_to_Y(pDst, Psrc, m_image_x);
-      else
-        memcpy(pDst, Psrc, m_image_x);
-    }
-    else
-    {
-      if (m_image_bpp == 4)
-        RGBA_to_YCC(pDst, Psrc, m_image_x);
-      else if (m_image_bpp == 3)
-        RGB_to_YCC(pDst, Psrc, m_image_x);
-      else
-        Y_to_YCC(pDst, Psrc, m_image_x);
-    }
-
-    // Possibly duplicate pixels at end of scanline if not a multiple of 8 or 16
-    if (m_num_components == 1)
-      memset(m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt, pDst[m_image_bpl_xlt - 1], m_image_x_mcu - m_image_x);
-    else
-    {
-      const uint8 y = pDst[m_image_bpl_xlt - 3 + 0], cb = pDst[m_image_bpl_xlt - 3 + 1], cr = pDst[m_image_bpl_xlt - 3 + 2];
-      uint8 *q = m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt;
-      for (int i = m_image_x; i < m_image_x_mcu; i++)
-      {
-        *q++ = y; *q++ = cb; *q++ = cr;
-      }
-    }
-
-    if (++m_mcu_y_ofs == m_mcu_y)
-    {
-      process_mcu_row();
-      m_mcu_y_ofs = 0;
-    }
-  }
-
-  void jpeg_encoder::clear()
-  {
-    m_mcu_lines[0] = NULL;
-    m_pass_num = 0;
-    m_all_stream_writes_succeeded = true;
-  }
-
-  jpeg_encoder::jpeg_encoder()
-  {
-    clear();
-  }
-
-  jpeg_encoder::~jpeg_encoder()
-  {
-    deinit();
-  }
-
-  bool jpeg_encoder::init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params)
-  {
-    deinit();
-    if (((!pStream) || (width < 1) || (height < 1)) || ((src_channels != 1) && (src_channels != 3) && (src_channels != 4)) || (!comp_params.check())) return false;
-    m_pStream = pStream;
-    m_params = comp_params;
-    return jpg_open(width, height, src_channels);
-  }
-
-  void jpeg_encoder::deinit()
-  {
-    jpge_free(m_mcu_lines[0]);
-    clear();
-  }
-
-  bool jpeg_encoder::process_scanline(const void* pScanline)
-  {
-    if ((m_pass_num < 1) || (m_pass_num > 2)) return false;
-    if (m_all_stream_writes_succeeded)
-    {
-      if (!pScanline)
-      {
-        if (!process_end_of_image()) return false;
-      }
-      else
-      {
-        load_mcu(pScanline);
-      }
-    }
-    return m_all_stream_writes_succeeded;
-  }
-
-  // Higher level wrappers/examples (optional).
-#include <stdio.h>
-
-  class cfile_stream : public output_stream
-  {
-    cfile_stream(const cfile_stream &);
-    cfile_stream &operator= (const cfile_stream &);
-
-    FILE* m_pFile;
-    bool m_bStatus;
-
-  public:
-    cfile_stream() : m_pFile(NULL), m_bStatus(false) { }
-
-    virtual ~cfile_stream()
-    {
-      close();
-    }
-
-    bool open(const char *pFilename)
-    {
-      close();
-#ifdef _MSC_VER
-      fopen_s(&m_pFile, pFilename, "wb");
-#else
-      m_pFile = fopen(pFilename, "wb");
-#endif
-      m_bStatus = (m_pFile != NULL);
-      return m_bStatus;
-    }
-
-    bool close()
-    {
-      if (m_pFile)
-      {
-        if (fclose(m_pFile) == EOF)
-        {
-          m_bStatus = false;
-        }
-        m_pFile = NULL;
-      }
-      return m_bStatus;
-    }
-
-    virtual bool put_buf(const void* pBuf, int len)
-    {
-      m_bStatus = m_bStatus && (fwrite(pBuf, len, 1, m_pFile) == 1);
-      return m_bStatus;
-    }
-
-    uint get_size() const
-    {
-      return m_pFile ? ftell(m_pFile) : 0;
-    }
-  };
-
-  // Writes JPEG image to file.
-  bool compress_image_to_jpeg_file(const char *pFilename, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params)
-  {
-    cfile_stream dst_stream;
-    if (!dst_stream.open(pFilename))
-      return false;
-
-    jpge::jpeg_encoder dst_image;
-    if (!dst_image.init(&dst_stream, width, height, num_channels, comp_params))
-      return false;
-
-    for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++)
-    {
-      for (int i = 0; i < height; i++)
-      {
-        const uint8* pBuf = pImage_data + i * width * num_channels;
-        if (!dst_image.process_scanline(pBuf))
-          return false;
-      }
-      if (!dst_image.process_scanline(NULL))
-        return false;
-    }
-
-    dst_image.deinit();
-
-    return dst_stream.close();
-  }
-
-  class memory_stream : public output_stream
-  {
-    memory_stream(const memory_stream &);
-    memory_stream &operator= (const memory_stream &);
-
-    uint8 *m_pBuf;
-    uint m_buf_size, m_buf_ofs;
-
-  public:
-    memory_stream(void *pBuf, uint buf_size) : m_pBuf(static_cast<uint8*>(pBuf)), m_buf_size(buf_size), m_buf_ofs(0) { }
-
-    virtual ~memory_stream() { }
-
-    virtual bool put_buf(const void* pBuf, int len)
-    {
-      uint buf_remaining = m_buf_size - m_buf_ofs;
-      if ((uint)len > buf_remaining)
-        return false;
-      memcpy(m_pBuf + m_buf_ofs, pBuf, len);
-      m_buf_ofs += len;
-      return true;
-    }
-
-    uint get_size() const
-    {
-      return m_buf_ofs;
-    }
-  };
-
-  bool compress_image_to_jpeg_file_in_memory(void *pDstBuf, int &buf_size, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params)
-  {
-    if ((!pDstBuf) || (!buf_size))
-      return false;
-
-    memory_stream dst_stream(pDstBuf, buf_size);
-
-    buf_size = 0;
-
-    jpge::jpeg_encoder dst_image;
-    if (!dst_image.init(&dst_stream, width, height, num_channels, comp_params))
-      return false;
-
-    for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++)
-    {
-      for (int i = 0; i < height; i++)
-      {
-        const uint8* pScanline = pImage_data + i * width * num_channels;
-        if (!dst_image.process_scanline(pScanline))
-          return false;
-      }
-      if (!dst_image.process_scanline(NULL))
-        return false;
-    }
-
-    dst_image.deinit();
-
-    buf_size = dst_stream.get_size();
-    return true;
-  }
-
-} // namespace jpge

+ 0 - 169
Source/ThirdParty/crunch/crnlib/crn_jpge.h

@@ -1,169 +0,0 @@
-// jpge.h - C++ class for JPEG compression.
-// Public domain, Rich Geldreich <[email protected]>
-// Alex Evans: Added RGBA support, linear memory allocator.
-#ifndef JPEG_ENCODER_H
-#define JPEG_ENCODER_H
-
-namespace jpge
-{
-  typedef unsigned char  uint8;
-  typedef signed short   int16;
-  typedef signed int     int32;
-  typedef unsigned short uint16;
-  typedef unsigned int   uint32;
-  typedef unsigned int   uint;
-
-  // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common.
-  enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 };
-
-  // JPEG compression parameters structure.
-  struct params
-  {
-    inline params() : m_quality(85), m_subsampling(H2V2), m_no_chroma_discrim_flag(false), m_two_pass_flag(false) { }
-
-    inline bool check() const
-    {
-      if ((m_quality < 1) || (m_quality > 100)) return false;
-      if ((uint)m_subsampling > (uint)H2V2) return false;
-      return true;
-    }
-
-    // Quality: 1-100, higher is better. Typical values are around 50-95.
-    int m_quality;
-
-    // m_subsampling:
-    // 0 = Y (grayscale) only
-    // 1 = YCbCr, no subsampling (H1V1, YCbCr 1x1x1, 3 blocks per MCU)
-    // 2 = YCbCr, H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU)
-    // 3 = YCbCr, H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common)
-    subsampling_t m_subsampling;
-
-    // Disables CbCr discrimination - only intended for testing.
-    // If true, the Y quantization table is also used for the CbCr channels.
-    bool m_no_chroma_discrim_flag;
-
-    bool m_two_pass_flag;
-  };
-
-  // Writes JPEG image to a file. 
-  // num_channels must be 1 (Y) or 3 (RGB), image pitch must be width*num_channels.
-  bool compress_image_to_jpeg_file(const char *pFilename, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params = params());
-
-  // Writes JPEG image to memory buffer. 
-  // On entry, buf_size is the size of the output buffer pointed at by pBuf, which should be at least ~1024 bytes. 
-  // If return value is true, buf_size will be set to the size of the compressed data.
-  bool compress_image_to_jpeg_file_in_memory(void *pBuf, int &buf_size, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params = params());
-
-  // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. 
-  // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts.
-  class output_stream
-  {
-  public:
-    virtual ~output_stream() { };
-    virtual bool put_buf(const void* Pbuf, int len) = 0;
-    template<class T> inline bool put_obj(const T& obj) { return put_buf(&obj, sizeof(T)); }
-  };
-
-  // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions.
-  class jpeg_encoder
-  {
-  public:
-    jpeg_encoder();
-    ~jpeg_encoder();
-
-    // Initializes the compressor.
-    // pStream: The stream object to use for writing compressed data.
-    // params - Compression parameters structure, defined above.
-    // width, height  - Image dimensions.
-    // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data.
-    // Returns false on out of memory or if a stream write fails.
-    bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params());
-
-    const params &get_params() const { return m_params; }
-
-    // Deinitializes the compressor, freeing any allocated memory. May be called at any time.
-    void deinit();
-
-    uint get_total_passes() const { return m_params.m_two_pass_flag ? 2 : 1; }
-    inline uint get_cur_pass() { return m_pass_num; }
-
-    // Call this method with each source scanline.
-    // width * src_channels bytes per scanline is expected (RGB or Y format).
-    // You must call with NULL after all scanlines are processed to finish compression.
-    // Returns false on out of memory or if a stream write fails.
-    bool process_scanline(const void* pScanline);
-
-  private:
-    jpeg_encoder(const jpeg_encoder &);
-    jpeg_encoder &operator =(const jpeg_encoder &);
-
-    typedef int32 sample_array_t;
-
-    output_stream *m_pStream;
-    params m_params;
-    uint8 m_num_components;
-    uint8 m_comp_h_samp[3], m_comp_v_samp[3];
-    int m_image_x, m_image_y, m_image_bpp, m_image_bpl;
-    int m_image_x_mcu, m_image_y_mcu;
-    int m_image_bpl_xlt, m_image_bpl_mcu;
-    int m_mcus_per_row;
-    int m_mcu_x, m_mcu_y;
-    uint8 *m_mcu_lines[16];
-    uint8 m_mcu_y_ofs;
-    sample_array_t m_sample_array[64];
-    int16 m_coefficient_array[64];
-    int32 m_quantization_tables[2][64];
-    uint m_huff_codes[4][256];
-    uint8 m_huff_code_sizes[4][256];
-    uint8 m_huff_bits[4][17];
-    uint8 m_huff_val[4][256];
-    uint32 m_huff_count[4][256];
-    int m_last_dc_val[3];
-    enum { JPGE_OUT_BUF_SIZE = 2048 };
-    uint8 m_out_buf[JPGE_OUT_BUF_SIZE];
-    uint8 *m_pOut_buf;
-    uint m_out_buf_left;
-    uint32 m_bit_buffer;
-    uint m_bits_in;
-    uint8 m_pass_num;
-    bool m_all_stream_writes_succeeded;
-
-    void optimize_huffman_table(int table_num, int table_len);
-    void emit_byte(uint8 i);
-    void emit_word(uint i);
-    void emit_marker(int marker);
-    void emit_jfif_app0();
-    void emit_dqt();
-    void emit_sof();
-    void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag);
-    void emit_dhts();
-    void emit_sos();
-    void emit_markers();
-    void compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits, uint8 *val);
-    void compute_quant_table(int32 *dst, int16 *src);
-    void adjust_quant_table(int32 *dst, int32 *src);
-    void first_pass_init();
-    bool second_pass_init();
-    bool jpg_open(int p_x_res, int p_y_res, int src_channels);
-    void load_block_8_8_grey(int x);
-    void load_block_8_8(int x, int y, int c);
-    void load_block_16_8(int x, int c);
-    void load_block_16_8_8(int x, int c);
-    void load_quantized_coefficients(int component_num);
-    void flush_output_buffer();
-    void put_bits(uint bits, uint len);
-    void code_coefficients_pass_one(int component_num);
-    void code_coefficients_pass_two(int component_num);
-    void code_block(int component_num);
-    void process_mcu_row();
-    bool terminate_pass_one();
-    bool terminate_pass_two();
-    bool process_end_of_image();
-    void load_mcu(const void* src);
-    void clear();
-    void init();
-  };
-
-} // namespace jpge
-
-#endif // JPEG_ENCODER

+ 0 - 920
Source/ThirdParty/crunch/crnlib/crn_ktx_texture.cpp

@@ -1,920 +0,0 @@
-// File: crn_ktx_texture.cpp
-#include "crn_core.h"
-#include "crn_ktx_texture.h"
-#include "crn_console.h"
-
-// Set #if CRNLIB_KTX_PVRTEX_WORKAROUNDS to 1 to enable various workarounds for oddball KTX files written by PVRTexTool.
-#define CRNLIB_KTX_PVRTEX_WORKAROUNDS 1
-
-namespace crnlib
-{
-   const uint8 s_ktx_file_id[12] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
-
-   bool is_packed_pixel_ogl_type(uint32 ogl_type)
-   {
-      switch (ogl_type)
-      {
-         case KTX_UNSIGNED_BYTE_3_3_2:
-         case KTX_UNSIGNED_BYTE_2_3_3_REV:
-         case KTX_UNSIGNED_SHORT_5_6_5:
-         case KTX_UNSIGNED_SHORT_5_6_5_REV:
-         case KTX_UNSIGNED_SHORT_4_4_4_4:
-         case KTX_UNSIGNED_SHORT_4_4_4_4_REV:
-         case KTX_UNSIGNED_SHORT_5_5_5_1:
-         case KTX_UNSIGNED_SHORT_1_5_5_5_REV:
-         case KTX_UNSIGNED_INT_8_8_8_8:
-         case KTX_UNSIGNED_INT_8_8_8_8_REV:
-         case KTX_UNSIGNED_INT_10_10_10_2:
-         case KTX_UNSIGNED_INT_2_10_10_10_REV:
-         case KTX_UNSIGNED_INT_24_8:
-         case KTX_UNSIGNED_INT_10F_11F_11F_REV:
-         case KTX_UNSIGNED_INT_5_9_9_9_REV:
-            return true;
-      }
-      return false;
-   }
-
-   uint get_ogl_type_size(uint32 ogl_type)
-   {
-      switch (ogl_type)
-      {
-         case KTX_UNSIGNED_BYTE:
-         case KTX_BYTE:
-            return 1;
-         case KTX_HALF_FLOAT:
-         case KTX_UNSIGNED_SHORT:
-         case KTX_SHORT:
-            return 2;
-         case KTX_FLOAT:
-         case KTX_UNSIGNED_INT:
-         case KTX_INT:
-            return 4;
-         case KTX_UNSIGNED_BYTE_3_3_2:
-         case KTX_UNSIGNED_BYTE_2_3_3_REV:
-            return 1;
-         case KTX_UNSIGNED_SHORT_5_6_5:
-         case KTX_UNSIGNED_SHORT_5_6_5_REV:
-         case KTX_UNSIGNED_SHORT_4_4_4_4:
-         case KTX_UNSIGNED_SHORT_4_4_4_4_REV:
-         case KTX_UNSIGNED_SHORT_5_5_5_1:
-         case KTX_UNSIGNED_SHORT_1_5_5_5_REV:
-            return 2;
-         case KTX_UNSIGNED_INT_8_8_8_8:
-         case KTX_UNSIGNED_INT_8_8_8_8_REV:
-         case KTX_UNSIGNED_INT_10_10_10_2:
-         case KTX_UNSIGNED_INT_2_10_10_10_REV:
-         case KTX_UNSIGNED_INT_24_8:
-         case KTX_UNSIGNED_INT_10F_11F_11F_REV:
-         case KTX_UNSIGNED_INT_5_9_9_9_REV:
-            return 4;
-      }
-      return 0;
-   }
-
-   uint32 get_ogl_base_internal_fmt(uint32 ogl_fmt)
-   {
-      switch (ogl_fmt)
-      {
-         case KTX_ETC1_RGB8_OES:
-         case KTX_RGB_S3TC:
-         case KTX_RGB4_S3TC:
-         case KTX_COMPRESSED_RGB_S3TC_DXT1_EXT:
-         case KTX_COMPRESSED_SRGB_S3TC_DXT1_EXT:
-            return KTX_RGB;
-         case KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-         case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
-         case KTX_RGBA_S3TC:
-         case KTX_RGBA4_S3TC:
-         case KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-         case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
-         case KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-         case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
-         case KTX_RGBA_DXT5_S3TC:
-         case KTX_RGBA4_DXT5_S3TC:
-            return KTX_RGBA;
-         case 1:
-         case KTX_RED:
-         case KTX_RED_INTEGER:
-         case KTX_GREEN:
-         case KTX_GREEN_INTEGER:
-         case KTX_BLUE:
-         case KTX_BLUE_INTEGER:
-         case KTX_R8:
-         case KTX_R8UI:
-         case KTX_LUMINANCE8:
-         case KTX_ALPHA:
-         case KTX_LUMINANCE:
-         case KTX_COMPRESSED_RED_RGTC1_EXT:
-         case KTX_COMPRESSED_SIGNED_RED_RGTC1_EXT:
-         case KTX_COMPRESSED_LUMINANCE_LATC1_EXT:
-         case KTX_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
-            return KTX_RED;
-         case 2:
-         case KTX_RG:
-         case KTX_RG8:
-         case KTX_RG_INTEGER:
-         case KTX_LUMINANCE_ALPHA:
-         case KTX_COMPRESSED_RED_GREEN_RGTC2_EXT:
-         case KTX_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
-         case KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
-         case KTX_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
-            return KTX_RG;
-         case 3:
-         case KTX_SRGB:
-         case KTX_RGB:
-         case KTX_RGB_INTEGER:
-         case KTX_BGR:
-         case KTX_BGR_INTEGER:
-         case KTX_RGB8:
-         case KTX_SRGB8:
-            return KTX_RGB;
-         case 4:
-         case KTX_RGBA:
-         case KTX_BGRA:
-         case KTX_RGBA_INTEGER:
-         case KTX_BGRA_INTEGER:
-         case KTX_SRGB_ALPHA:
-         case KTX_SRGB8_ALPHA8:
-         case KTX_RGBA8:
-            return KTX_RGBA;
-      }
-      return 0;
-   }
-
-   bool get_ogl_fmt_desc(uint32 ogl_fmt, uint32 ogl_type, uint& block_dim, uint& bytes_per_block)
-   {
-      uint ogl_type_size = get_ogl_type_size(ogl_type);
-
-      block_dim = 1;
-      bytes_per_block = 0;
-
-      switch (ogl_fmt)
-      {
-         case KTX_COMPRESSED_RED_RGTC1_EXT:
-         case KTX_COMPRESSED_SIGNED_RED_RGTC1_EXT:
-         case KTX_COMPRESSED_LUMINANCE_LATC1_EXT:
-         case KTX_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
-         case KTX_ETC1_RGB8_OES:
-         case KTX_RGB_S3TC:
-         case KTX_RGB4_S3TC:
-         case KTX_COMPRESSED_RGB_S3TC_DXT1_EXT:
-         case KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-         case KTX_COMPRESSED_SRGB_S3TC_DXT1_EXT:
-         case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
-         {
-            block_dim = 4;
-            bytes_per_block = 8;
-            break;
-         }
-         case KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
-         case KTX_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
-         case KTX_COMPRESSED_RED_GREEN_RGTC2_EXT:
-         case KTX_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
-         case KTX_RGBA_S3TC:
-         case KTX_RGBA4_S3TC:
-         case KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-         case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
-         case KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-         case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
-         case KTX_RGBA_DXT5_S3TC:
-         case KTX_RGBA4_DXT5_S3TC:
-         {
-            block_dim = 4;
-            bytes_per_block = 16;
-            break;
-         }
-         case 1:
-         case KTX_ALPHA:
-         case KTX_RED:
-         case KTX_GREEN:
-         case KTX_BLUE:
-         case KTX_RED_INTEGER:
-         case KTX_GREEN_INTEGER:
-         case KTX_BLUE_INTEGER:
-         case KTX_LUMINANCE:
-         {
-            bytes_per_block = ogl_type_size;
-            break;
-         }
-         case KTX_R8:
-         case KTX_R8UI:
-         case KTX_ALPHA8:
-         case KTX_LUMINANCE8:
-         {
-            bytes_per_block = 1;
-            break;
-         }
-         case 2:
-         case KTX_RG:
-         case KTX_RG_INTEGER:
-         case KTX_LUMINANCE_ALPHA:
-         {
-            bytes_per_block = 2 * ogl_type_size;
-            break;
-         }
-         case KTX_RG8:
-         case KTX_LUMINANCE8_ALPHA8:
-         {
-            bytes_per_block = 2;
-            break;
-         }
-         case 3:
-         case KTX_SRGB:
-         case KTX_RGB:
-         case KTX_BGR:
-         case KTX_RGB_INTEGER:
-         case KTX_BGR_INTEGER:
-         {
-            bytes_per_block = is_packed_pixel_ogl_type(ogl_type) ? ogl_type_size : (3 * ogl_type_size);
-            break;
-         }
-         case KTX_RGB8:
-         case KTX_SRGB8:
-         {
-            bytes_per_block = 3;
-            break;
-         }
-         case 4:
-         case KTX_RGBA:
-         case KTX_BGRA:
-         case KTX_RGBA_INTEGER:
-         case KTX_BGRA_INTEGER:
-         case KTX_SRGB_ALPHA:
-         {
-            bytes_per_block = is_packed_pixel_ogl_type(ogl_type) ? ogl_type_size : (4 * ogl_type_size);
-            break;
-         }
-         case KTX_SRGB8_ALPHA8:
-         case KTX_RGBA8:
-         {
-            bytes_per_block = 4;
-            break;
-         }
-         default:
-            return false;
-      }
-      return true;
-   }
-
-   bool ktx_texture::compute_pixel_info()
-   {
-      if ((!m_header.m_glType) || (!m_header.m_glFormat))
-      {
-         if ((m_header.m_glType) || (m_header.m_glFormat))
-            return false;
-
-         // Must be a compressed format.
-         if (!get_ogl_fmt_desc(m_header.m_glInternalFormat, m_header.m_glType, m_block_dim, m_bytes_per_block))
-         {
-#if CRNLIB_KTX_PVRTEX_WORKAROUNDS
-            if ((!m_header.m_glInternalFormat) && (!m_header.m_glType) && (!m_header.m_glTypeSize) && (!m_header.m_glBaseInternalFormat))
-            {
-               // PVRTexTool writes bogus headers when outputting ETC1.
-               console::warning("ktx_texture::compute_pixel_info: Header doesn't specify any format, assuming ETC1 and hoping for the best");
-               m_header.m_glBaseInternalFormat = KTX_RGB;
-               m_header.m_glInternalFormat = KTX_ETC1_RGB8_OES;
-               m_header.m_glTypeSize = 1;
-               m_block_dim = 4;
-               m_bytes_per_block = 8;
-               return true;
-            }
-#endif
-            return false;
-         }
-
-         if (m_block_dim == 1)
-            return false;
-      }
-      else
-      {
-         // Must be an uncompressed format.
-         if (!get_ogl_fmt_desc(m_header.m_glFormat, m_header.m_glType, m_block_dim, m_bytes_per_block))
-            return false;
-
-         if (m_block_dim > 1)
-            return false;
-      }
-      return true;
-   }
-
-   bool ktx_texture::read_from_stream(data_stream_serializer& serializer)
-   {
-      clear();
-
-      // Read header
-      if (serializer.read(&m_header, 1, sizeof(m_header)) != sizeof(ktx_header))
-         return false;
-
-      // Check header
-      if (memcmp(s_ktx_file_id, m_header.m_identifier, sizeof(m_header.m_identifier)))
-         return false;
-
-      if ((m_header.m_endianness != KTX_OPPOSITE_ENDIAN) && (m_header.m_endianness != KTX_ENDIAN))
-         return false;
-
-      m_opposite_endianness = (m_header.m_endianness == KTX_OPPOSITE_ENDIAN);
-      if (m_opposite_endianness)
-      {
-         m_header.endian_swap();
-
-         if ((m_header.m_glTypeSize != sizeof(uint8)) && (m_header.m_glTypeSize != sizeof(uint16)) && (m_header.m_glTypeSize != sizeof(uint32)))
-            return false;
-      }
-
-      if (!check_header())
-         return false;
-
-      if (!compute_pixel_info())
-         return false;
-
-      uint8 pad_bytes[3];
-
-      // Read the key value entries
-      uint num_key_value_bytes_remaining = m_header.m_bytesOfKeyValueData;
-      while (num_key_value_bytes_remaining)
-      {
-         if (num_key_value_bytes_remaining < sizeof(uint32))
-            return false;
-
-         uint32 key_value_byte_size;
-         if (serializer.read(&key_value_byte_size, 1, sizeof(uint32)) != sizeof(uint32))
-            return false;
-
-         num_key_value_bytes_remaining -= sizeof(uint32);
-
-         if (m_opposite_endianness)
-            key_value_byte_size = utils::swap32(key_value_byte_size);
-
-         if (key_value_byte_size > num_key_value_bytes_remaining)
-            return false;
-
-         uint8_vec key_value_data;
-         if (key_value_byte_size)
-         {
-            key_value_data.resize(key_value_byte_size);
-            if (serializer.read(&key_value_data[0], 1, key_value_byte_size) != key_value_byte_size)
-               return false;
-         }
-
-         m_key_values.push_back(key_value_data);
-
-         uint padding = 3 - ((key_value_byte_size + 3) % 4);
-         if (padding)
-         {
-            if (serializer.read(pad_bytes, 1, padding) != padding)
-               return false;
-         }
-
-         num_key_value_bytes_remaining -= key_value_byte_size;
-         if (num_key_value_bytes_remaining < padding)
-            return false;
-         num_key_value_bytes_remaining -= padding;
-      }
-
-      // Now read the mip levels
-      uint total_faces = get_num_mips() * get_array_size() * get_num_faces() * get_depth();
-      if ((!total_faces) || (total_faces > 65535))
-         return false;
-
-      // See Section 2.8 of KTX file format: No rounding to block sizes should be applied for block compressed textures.
-      // OK, I'm going to break that rule otherwise KTX can only store a subset of textures that DDS can handle for no good reason.
-#if 0
-      const uint mip0_row_blocks = m_header.m_pixelWidth / m_block_dim;
-      const uint mip0_col_blocks = CRNLIB_MAX(1, m_header.m_pixelHeight) / m_block_dim;
-#else
-      const uint mip0_row_blocks = (m_header.m_pixelWidth + m_block_dim - 1) / m_block_dim;
-      const uint mip0_col_blocks = (CRNLIB_MAX(1, m_header.m_pixelHeight) + m_block_dim - 1) / m_block_dim;
-#endif
-      if ((!mip0_row_blocks) || (!mip0_col_blocks))
-         return false;
-
-      const uint mip0_depth = CRNLIB_MAX(1, m_header.m_pixelDepth); mip0_depth;
-
-      bool has_valid_image_size_fields = true;
-      bool disable_mip_and_cubemap_padding = false;
-
-#if CRNLIB_KTX_PVRTEX_WORKAROUNDS
-      {
-         // PVRTexTool has a bogus KTX writer that doesn't write any imageSize fields. Nice.
-         size_t expected_bytes_remaining = 0;
-         for (uint mip_level = 0; mip_level < get_num_mips(); mip_level++)
-         {
-            uint mip_width, mip_height, mip_depth;
-            get_mip_dim(mip_level, mip_width, mip_height, mip_depth);
-
-            const uint mip_row_blocks = (mip_width + m_block_dim - 1) / m_block_dim;
-            const uint mip_col_blocks = (mip_height + m_block_dim - 1) / m_block_dim;
-            if ((!mip_row_blocks) || (!mip_col_blocks))
-               return false;
-
-            expected_bytes_remaining += sizeof(uint32);
-
-            if ((!m_header.m_numberOfArrayElements) && (get_num_faces() == 6))
-            {
-               for (uint face = 0; face < get_num_faces(); face++)
-               {
-                  uint slice_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
-                  expected_bytes_remaining += slice_size;
-
-                  uint num_cube_pad_bytes = 3 - ((slice_size + 3) % 4);
-                  expected_bytes_remaining += num_cube_pad_bytes;
-               }
-            }
-            else
-            {
-               uint total_mip_size = 0;
-               for (uint array_element = 0; array_element < get_array_size(); array_element++)
-               {
-                  for (uint face = 0; face < get_num_faces(); face++)
-                  {
-                     for (uint zslice = 0; zslice < mip_depth; zslice++)
-                     {
-                        uint slice_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
-                        total_mip_size += slice_size;
-                     }
-                  }
-               }
-               expected_bytes_remaining += total_mip_size;
-
-               uint num_mip_pad_bytes = 3 - ((total_mip_size + 3) % 4);
-               expected_bytes_remaining += num_mip_pad_bytes;
-            }
-         }
-
-         if (serializer.get_stream()->get_remaining() < expected_bytes_remaining)
-         {
-            has_valid_image_size_fields = false;
-            disable_mip_and_cubemap_padding = true;
-            console::warning("ktx_texture::read_from_stream: KTX file size is smaller than expected - trying to read anyway without imageSize fields");
-         }
-      }
-#endif
-
-      for (uint mip_level = 0; mip_level < get_num_mips(); mip_level++)
-      {
-         uint mip_width, mip_height, mip_depth;
-         get_mip_dim(mip_level, mip_width, mip_height, mip_depth);
-
-         const uint mip_row_blocks = (mip_width + m_block_dim - 1) / m_block_dim;
-         const uint mip_col_blocks = (mip_height + m_block_dim - 1) / m_block_dim;
-         if ((!mip_row_blocks) || (!mip_col_blocks))
-            return false;
-
-         uint32 image_size = 0;
-         if (!has_valid_image_size_fields)
-            image_size = mip_depth * mip_row_blocks * mip_col_blocks * m_bytes_per_block * get_array_size() * get_num_faces();
-         else
-         {
-            if (serializer.read(&image_size, 1, sizeof(image_size)) != sizeof(image_size))
-               return false;
-
-            if (m_opposite_endianness)
-               image_size = utils::swap32(image_size);
-         }
-
-         if (!image_size)
-            return false;
-
-         uint total_mip_size = 0;
-
-         if ((!m_header.m_numberOfArrayElements) && (get_num_faces() == 6))
-         {
-            // plain non-array cubemap
-            for (uint face = 0; face < get_num_faces(); face++)
-            {
-               CRNLIB_ASSERT(m_image_data.size() == get_image_index(mip_level, 0, face, 0));
-
-               m_image_data.push_back(uint8_vec());
-               uint8_vec& image_data = m_image_data.back();
-
-               image_data.resize(image_size);
-               if (serializer.read(&image_data[0], 1, image_size) != image_size)
-                  return false;
-
-               if (m_opposite_endianness)
-                  utils::endian_swap_mem(&image_data[0], image_size, m_header.m_glTypeSize);
-
-               uint num_cube_pad_bytes = disable_mip_and_cubemap_padding ? 0 : (3 - ((image_size + 3) % 4));
-               if (serializer.read(pad_bytes, 1, num_cube_pad_bytes) != num_cube_pad_bytes)
-                  return false;
-
-               total_mip_size += image_size + num_cube_pad_bytes;
-            }
-         }
-         else
-         {
-            // 1D, 2D, 3D (normal or array texture), or array cubemap
-            uint num_image_bytes_remaining = image_size;
-
-            for (uint array_element = 0; array_element < get_array_size(); array_element++)
-            {
-               for (uint face = 0; face < get_num_faces(); face++)
-               {
-                  for (uint zslice = 0; zslice < mip_depth; zslice++)
-                  {
-                     CRNLIB_ASSERT(m_image_data.size() == get_image_index(mip_level, array_element, face, zslice));
-
-                     uint slice_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
-                     if ((!slice_size) || (slice_size > num_image_bytes_remaining))
-                        return false;
-
-                     m_image_data.push_back(uint8_vec());
-                     uint8_vec& image_data = m_image_data.back();
-
-                     image_data.resize(slice_size);
-                     if (serializer.read(&image_data[0], 1, slice_size) != slice_size)
-                        return false;
-
-                     if (m_opposite_endianness)
-                        utils::endian_swap_mem(&image_data[0], slice_size, m_header.m_glTypeSize);
-
-                     num_image_bytes_remaining -= slice_size;
-
-                     total_mip_size += slice_size;
-                  }
-               }
-            }
-
-            if (num_image_bytes_remaining)
-               return false;
-         }
-
-         uint num_mip_pad_bytes = disable_mip_and_cubemap_padding ? 0 : (3 - ((total_mip_size + 3) % 4));
-         if (serializer.read(pad_bytes, 1, num_mip_pad_bytes) != num_mip_pad_bytes)
-            return false;
-      }
-      return true;
-   }
-
-   bool ktx_texture::write_to_stream(data_stream_serializer& serializer, bool no_keyvalue_data)
-   {
-      if (!consistency_check())
-      {
-         CRNLIB_ASSERT(0);
-         return false;
-      }
-
-      memcpy(m_header.m_identifier, s_ktx_file_id, sizeof(m_header.m_identifier));
-      m_header.m_endianness = m_opposite_endianness ? KTX_OPPOSITE_ENDIAN : KTX_ENDIAN;
-
-      if (m_block_dim == 1)
-      {
-         m_header.m_glTypeSize = get_ogl_type_size(m_header.m_glType);
-         m_header.m_glBaseInternalFormat = m_header.m_glFormat;
-      }
-      else
-      {
-         m_header.m_glBaseInternalFormat = get_ogl_base_internal_fmt(m_header.m_glInternalFormat);
-      }
-
-      m_header.m_bytesOfKeyValueData = 0;
-      if (!no_keyvalue_data)
-      {
-         for (uint i = 0; i < m_key_values.size(); i++)
-            m_header.m_bytesOfKeyValueData += sizeof(uint32) + ((m_key_values[i].size() + 3) & ~3);
-      }
-
-      if (m_opposite_endianness)
-         m_header.endian_swap();
-
-      bool success = (serializer.write(&m_header, sizeof(m_header), 1) == 1);
-
-      if (m_opposite_endianness)
-         m_header.endian_swap();
-
-      if (!success)
-         return success;
-
-      uint total_key_value_bytes = 0;
-      const uint8 padding[3] = { 0, 0, 0 };
-
-      if (!no_keyvalue_data)
-      {
-         for (uint i = 0; i < m_key_values.size(); i++)
-         {
-            uint32 key_value_size = m_key_values[i].size();
-
-            if (m_opposite_endianness)
-               key_value_size = utils::swap32(key_value_size);
-
-            success = (serializer.write(&key_value_size, sizeof(key_value_size), 1) == 1);
-            total_key_value_bytes += sizeof(key_value_size);
-
-            if (m_opposite_endianness)
-               key_value_size = utils::swap32(key_value_size);
-
-            if (!success)
-               return false;
-
-            if (key_value_size)
-            {
-               if (serializer.write(&m_key_values[i][0], key_value_size, 1) != 1)
-                  return false;
-               total_key_value_bytes += key_value_size;
-
-               uint num_padding = 3 - ((key_value_size + 3) % 4);
-               if ((num_padding) && (serializer.write(padding, num_padding, 1) != 1))
-                  return false;
-               total_key_value_bytes += num_padding;
-            }
-         }
-         (void)total_key_value_bytes;
-      }
-
-      CRNLIB_ASSERT(total_key_value_bytes == m_header.m_bytesOfKeyValueData);
-
-      for (uint mip_level = 0; mip_level < get_num_mips(); mip_level++)
-      {
-         uint mip_width, mip_height, mip_depth;
-         get_mip_dim(mip_level, mip_width, mip_height, mip_depth);
-
-         const uint mip_row_blocks = (mip_width + m_block_dim - 1) / m_block_dim;
-         const uint mip_col_blocks = (mip_height + m_block_dim - 1) / m_block_dim;
-         if ((!mip_row_blocks) || (!mip_col_blocks))
-            return false;
-
-         uint32 image_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
-         if ((m_header.m_numberOfArrayElements) || (get_num_faces() == 1))
-            image_size *= (get_array_size() * get_num_faces() * get_depth());
-
-         if (!image_size)
-            return false;
-
-         if (m_opposite_endianness)
-            image_size = utils::swap32(image_size);
-
-         success = (serializer.write(&image_size, sizeof(image_size), 1) == 1);
-
-         if (m_opposite_endianness)
-            image_size = utils::swap32(image_size);
-
-         if (!success)
-            return false;
-
-         uint total_mip_size = 0;
-
-         if ((!m_header.m_numberOfArrayElements) && (get_num_faces() == 6))
-         {
-            // plain non-array cubemap
-            for (uint face = 0; face < get_num_faces(); face++)
-            {
-               const uint8_vec& image_data = get_image_data(get_image_index(mip_level, 0, face, 0));
-               if ((!image_data.size()) || (image_data.size() != image_size))
-                  return false;
-
-               if (m_opposite_endianness)
-               {
-                  uint8_vec tmp_image_data(image_data);
-                  utils::endian_swap_mem(&tmp_image_data[0], tmp_image_data.size(), m_header.m_glTypeSize);
-                  if (serializer.write(&tmp_image_data[0], tmp_image_data.size(), 1) != 1)
-                     return false;
-               }
-               else if (serializer.write(&image_data[0], image_data.size(), 1) != 1)
-                  return false;
-
-               uint num_cube_pad_bytes = 3 - ((image_data.size() + 3) % 4);
-               if ((num_cube_pad_bytes) && (serializer.write(padding, num_cube_pad_bytes, 1) != 1))
-                  return false;
-
-               total_mip_size += image_size + num_cube_pad_bytes;
-            }
-         }
-         else
-         {
-            // 1D, 2D, 3D (normal or array texture), or array cubemap
-            for (uint array_element = 0; array_element < get_array_size(); array_element++)
-            {
-               for (uint face = 0; face < get_num_faces(); face++)
-               {
-                  for (uint zslice = 0; zslice < mip_depth; zslice++)
-                  {
-                     const uint8_vec& image_data = get_image_data(get_image_index(mip_level, array_element, face, zslice));
-                     if (!image_data.size())
-                        return false;
-
-                     if (m_opposite_endianness)
-                     {
-                        uint8_vec tmp_image_data(image_data);
-                        utils::endian_swap_mem(&tmp_image_data[0], tmp_image_data.size(), m_header.m_glTypeSize);
-                        if (serializer.write(&tmp_image_data[0], tmp_image_data.size(), 1) != 1)
-                           return false;
-                     }
-                     else if (serializer.write(&image_data[0], image_data.size(), 1) != 1)
-                        return false;
-
-                     total_mip_size += image_data.size();
-                  }
-               }
-            }
-
-            uint num_mip_pad_bytes = 3 - ((total_mip_size + 3) % 4);
-            if ((num_mip_pad_bytes) && (serializer.write(padding, num_mip_pad_bytes, 1) != 1))
-               return false;
-            total_mip_size += num_mip_pad_bytes;
-         }
-         CRNLIB_ASSERT((total_mip_size & 3) == 0);
-      }
-
-      return true;
-   }
-
-   bool ktx_texture::init_2D(uint width, uint height, uint num_mips, uint32 ogl_internal_fmt, uint32 ogl_fmt, uint32 ogl_type)
-   {
-      clear();
-
-      m_header.m_pixelWidth = width;
-      m_header.m_pixelHeight = height;
-      m_header.m_numberOfMipmapLevels = num_mips;
-      m_header.m_glInternalFormat = ogl_internal_fmt;
-      m_header.m_glFormat = ogl_fmt;
-      m_header.m_glType = ogl_type;
-      m_header.m_numberOfFaces = 1;
-
-      if (!compute_pixel_info())
-         return false;
-
-      return true;
-   }
-
-   bool ktx_texture::init_2D_array(uint width, uint height, uint num_mips, uint array_size, uint32 ogl_internal_fmt, uint32 ogl_fmt, uint32 ogl_type)
-   {
-      clear();
-
-      m_header.m_pixelWidth = width;
-      m_header.m_pixelHeight = height;
-      m_header.m_numberOfMipmapLevels = num_mips;
-      m_header.m_numberOfArrayElements = array_size;
-      m_header.m_glInternalFormat = ogl_internal_fmt;
-      m_header.m_glFormat = ogl_fmt;
-      m_header.m_glType = ogl_type;
-      m_header.m_numberOfFaces = 1;
-
-      if (!compute_pixel_info())
-         return false;
-
-      return true;
-   }
-
-   bool ktx_texture::init_3D(uint width, uint height, uint depth, uint num_mips, uint32 ogl_internal_fmt, uint32 ogl_fmt, uint32 ogl_type)
-   {
-      clear();
-
-      m_header.m_pixelWidth = width;
-      m_header.m_pixelHeight = height;
-      m_header.m_pixelDepth = depth;
-      m_header.m_numberOfMipmapLevels = num_mips;
-      m_header.m_glInternalFormat = ogl_internal_fmt;
-      m_header.m_glFormat = ogl_fmt;
-      m_header.m_glType = ogl_type;
-      m_header.m_numberOfFaces = 1;
-
-      if (!compute_pixel_info())
-         return false;
-
-      return true;
-   }
-
-   bool ktx_texture::init_cubemap(uint dim, uint num_mips, uint32 ogl_internal_fmt, uint32 ogl_fmt, uint32 ogl_type)
-   {
-      clear();
-
-      m_header.m_pixelWidth = dim;
-      m_header.m_pixelHeight = dim;
-      m_header.m_numberOfMipmapLevels = num_mips;
-      m_header.m_glInternalFormat = ogl_internal_fmt;
-      m_header.m_glFormat = ogl_fmt;
-      m_header.m_glType = ogl_type;
-      m_header.m_numberOfFaces = 6;
-
-      if (!compute_pixel_info())
-         return false;
-
-      return true;
-   }
-
-   bool ktx_texture::check_header() const
-   {
-      if (((get_num_faces() != 1) && (get_num_faces() != 6)) || (!m_header.m_pixelWidth))
-         return false;
-
-      if ((!m_header.m_pixelHeight) && (m_header.m_pixelDepth))
-         return false;
-
-      if ((get_num_faces() == 6) && ((m_header.m_pixelDepth) || (!m_header.m_pixelHeight)))
-         return false;
-
-      if (m_header.m_numberOfMipmapLevels)
-      {
-         const uint max_mipmap_dimension = 1U << (m_header.m_numberOfMipmapLevels - 1U);
-         if (max_mipmap_dimension > (CRNLIB_MAX(CRNLIB_MAX(m_header.m_pixelWidth, m_header.m_pixelHeight), m_header.m_pixelDepth)))
-            return false;
-      }
-
-      return true;
-   }
-
-   bool ktx_texture::consistency_check() const
-   {
-      if (!check_header())
-         return false;
-
-      uint block_dim = 0, bytes_per_block = 0;
-      if ((!m_header.m_glType) || (!m_header.m_glFormat))
-      {
-         if ((m_header.m_glType) || (m_header.m_glFormat))
-            return false;
-         if (!get_ogl_fmt_desc(m_header.m_glInternalFormat, m_header.m_glType, block_dim, bytes_per_block))
-            return false;
-         if (block_dim == 1)
-            return false;
-         //if ((get_width() % block_dim) || (get_height() % block_dim))
-         //   return false;
-      }
-      else
-      {
-         if (!get_ogl_fmt_desc(m_header.m_glFormat, m_header.m_glType, block_dim, bytes_per_block))
-            return false;
-         if (block_dim > 1)
-            return false;
-      }
-      if ((m_block_dim != block_dim) || (m_bytes_per_block != bytes_per_block))
-         return false;
-
-      if (m_image_data.size() != get_total_images())
-         return false;
-
-      for (uint mip_level = 0; mip_level < get_num_mips(); mip_level++)
-      {
-         uint mip_width, mip_height, mip_depth;
-         get_mip_dim(mip_level, mip_width, mip_height, mip_depth);
-
-         const uint mip_row_blocks = (mip_width + m_block_dim - 1) / m_block_dim;
-         const uint mip_col_blocks = (mip_height + m_block_dim - 1) / m_block_dim;
-         if ((!mip_row_blocks) || (!mip_col_blocks))
-            return false;
-
-         for (uint array_element = 0; array_element < get_array_size(); array_element++)
-         {
-            for (uint face = 0; face < get_num_faces(); face++)
-            {
-               for (uint zslice = 0; zslice < mip_depth; zslice++)
-               {
-                  const uint8_vec& image_data = get_image_data(get_image_index(mip_level, array_element, face, zslice));
-
-                  uint expected_image_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
-                  if (image_data.size() != expected_image_size)
-                     return false;
-               }
-            }
-         }
-      }
-
-      return true;
-   }
-
-   const uint8_vec* ktx_texture::find_key(const char* pKey) const
-   {
-      const size_t n = strlen(pKey) + 1;
-      for (uint i = 0; i < m_key_values.size(); i++)
-      {
-         const uint8_vec& v = m_key_values[i];
-         if ((v.size() >= n) && (!memcmp(&v[0], pKey, n)))
-            return &v;
-      }
-
-      return NULL;
-   }
-
-   bool ktx_texture::get_key_value_as_string(const char* pKey, dynamic_string& str) const
-   {
-      const uint8_vec* p = find_key(pKey);
-      if (!p)
-      {
-         str.clear();
-         return false;
-      }
-
-      const uint ofs = (static_cast<uint>(strlen(pKey)) + 1);
-      const uint8* pValue = p->get_ptr() + ofs;
-      const uint n = p->size() - ofs;
-
-      uint i;
-      for (i = 0; i < n; i++)
-         if (!pValue[i])
-            break;
-
-      str.set_from_buf(pValue, i);
-      return true;
-   }
-
-   uint ktx_texture::add_key_value(const char* pKey, const void* pVal, uint val_size)
-   {
-      const uint idx = m_key_values.size();
-      m_key_values.resize(idx + 1);
-      uint8_vec& v = m_key_values.back();
-      v.append(reinterpret_cast<const uint8*>(pKey), static_cast<uint>(strlen(pKey)) + 1);
-      v.append(static_cast<const uint8*>(pVal), val_size);
-      return idx;
-   }
-
-} // namespace crnlib

+ 0 - 244
Source/ThirdParty/crunch/crnlib/crn_ktx_texture.h

@@ -1,244 +0,0 @@
-// File: crn_ktx_texture.h
-#ifndef _KTX_TEXTURE_H_
-#define _KTX_TEXTURE_H_
-#ifdef _MSC_VER
-#pragma once
-#endif
-
-#include "crn_data_stream_serializer.h"
-
-#define KTX_ENDIAN 0x04030201
-#define KTX_OPPOSITE_ENDIAN 0x01020304
-
-namespace crnlib
-{
-   extern const uint8 s_ktx_file_id[12];
-
-   struct ktx_header
-   {
-      uint8 m_identifier[12];
-      uint32 m_endianness;
-      uint32 m_glType;
-      uint32 m_glTypeSize;
-      uint32 m_glFormat;
-      uint32 m_glInternalFormat;
-      uint32 m_glBaseInternalFormat;
-      uint32 m_pixelWidth;
-      uint32 m_pixelHeight;
-      uint32 m_pixelDepth;
-      uint32 m_numberOfArrayElements;
-      uint32 m_numberOfFaces;
-      uint32 m_numberOfMipmapLevels;
-      uint32 m_bytesOfKeyValueData;
-
-      void clear()
-      {
-         memset(this, 0, sizeof(*this));
-      }
-
-      void endian_swap()
-      {
-         utils::endian_swap_mem32(&m_endianness, (sizeof(*this) - sizeof(m_identifier)) / sizeof(uint32));
-      }
-   };
-
-   typedef crnlib::vector<uint8_vec> ktx_key_value_vec;
-   typedef crnlib::vector<uint8_vec> ktx_image_data_vec;
-
-   // Compressed pixel data formats: ETC1, DXT1, DXT3, DXT5
-   enum 
-   { 
-      KTX_ETC1_RGB8_OES = 0x8D64, KTX_RGB_S3TC = 0x83A0, KTX_RGB4_S3TC = 0x83A1, KTX_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0,
-      KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1, KTX_COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C, KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D,
-      KTX_RGBA_S3TC = 0x83A2, KTX_RGBA4_S3TC = 0x83A3, KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2, KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E,
-      KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3, KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F, KTX_RGBA_DXT5_S3TC = 0x83A4, KTX_RGBA4_DXT5_S3TC = 0x83A5,
-      KTX_COMPRESSED_RED_RGTC1_EXT = 0x8DBB, KTX_COMPRESSED_SIGNED_RED_RGTC1_EXT = 0x8DBC, KTX_COMPRESSED_RED_GREEN_RGTC2_EXT = 0x8DBD, KTX_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT = 0x8DBE,
-      KTX_COMPRESSED_LUMINANCE_LATC1_EXT = 0x8C70, KTX_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT = 0x8C71, KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT = 0x8C72, KTX_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT = 0x8C73
-   };
-
-   // Pixel formats (various internal, base, and base internal formats)
-   enum 
-   { 
-      KTX_R8 = 0x8229, KTX_R8UI = 0x8232, KTX_RGB8 = 0x8051, KTX_SRGB8 = 0x8C41, KTX_SRGB = 0x8C40, KTX_SRGB_ALPHA = 0x8C42,
-      KTX_SRGB8_ALPHA8 = 0x8C43, KTX_RGBA8 = 0x8058, KTX_STENCIL_INDEX = 0x1901, KTX_DEPTH_COMPONENT = 0x1902, KTX_DEPTH_STENCIL = 0x84F9, KTX_RED = 0x1903,
-      KTX_GREEN = 0x1904, KTX_BLUE = 0x1905, KTX_ALPHA = 0x1906, KTX_RG = 0x8227, KTX_RGB = 0x1907, KTX_RGBA = 0x1908, KTX_BGR = 0x80E0, KTX_BGRA = 0x80E1,
-      KTX_RED_INTEGER = 0x8D94, KTX_GREEN_INTEGER = 0x8D95, KTX_BLUE_INTEGER = 0x8D96, KTX_ALPHA_INTEGER = 0x8D97, KTX_RGB_INTEGER = 0x8D98, KTX_RGBA_INTEGER = 0x8D99,
-      KTX_BGR_INTEGER = 0x8D9A, KTX_BGRA_INTEGER = 0x8D9B, KTX_LUMINANCE = 0x1909, KTX_LUMINANCE_ALPHA = 0x190A, KTX_RG_INTEGER = 0x8228, KTX_RG8 = 0x822B,
-      KTX_ALPHA8 = 0x803C, KTX_LUMINANCE8 = 0x8040, KTX_LUMINANCE8_ALPHA8 = 0x8045
-   };
-
-   // Pixel data types
-   enum 
-   {
-      KTX_UNSIGNED_BYTE = 0x1401, KTX_BYTE = 0x1400, KTX_UNSIGNED_SHORT = 0x1403, KTX_SHORT = 0x1402,
-      KTX_UNSIGNED_INT = 0x1405, KTX_INT = 0x1404, KTX_HALF_FLOAT = 0x140B, KTX_FLOAT = 0x1406,
-      KTX_UNSIGNED_BYTE_3_3_2 = 0x8032, KTX_UNSIGNED_BYTE_2_3_3_REV = 0x8362, KTX_UNSIGNED_SHORT_5_6_5 = 0x8363,
-      KTX_UNSIGNED_SHORT_5_6_5_REV = 0x8364, KTX_UNSIGNED_SHORT_4_4_4_4 = 0x8033, KTX_UNSIGNED_SHORT_4_4_4_4_REV = 0x8365,
-      KTX_UNSIGNED_SHORT_5_5_5_1 = 0x8034, KTX_UNSIGNED_SHORT_1_5_5_5_REV = 0x8366, KTX_UNSIGNED_INT_8_8_8_8 = 0x8035,
-      KTX_UNSIGNED_INT_8_8_8_8_REV = 0x8367, KTX_UNSIGNED_INT_10_10_10_2 = 0x8036, KTX_UNSIGNED_INT_2_10_10_10_REV = 0x8368,
-      KTX_UNSIGNED_INT_24_8 = 0x84FA, KTX_UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B, KTX_UNSIGNED_INT_5_9_9_9_REV = 0x8C3E, 
-      KTX_FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD
-   };
-   
-   bool is_packed_pixel_ogl_type(uint32 ogl_type);
-   uint get_ogl_type_size(uint32 ogl_type);
-   bool get_ogl_fmt_desc(uint32 ogl_fmt, uint32 ogl_type, uint& block_dim, uint& bytes_per_block);
-   uint get_ogl_type_size(uint32 ogl_type);
-   uint32 get_ogl_base_internal_fmt(uint32 ogl_fmt);
-
-   class ktx_texture
-   {
-   public:
-      ktx_texture()
-      {
-         clear();
-      }
-
-      ktx_texture(const ktx_texture& other)
-      {
-         *this = other;
-      }
-
-      ktx_texture& operator= (const ktx_texture& rhs)
-      {
-         if (this == &rhs)
-            return *this;
-
-         clear();
-
-         m_header = rhs.m_header;
-         m_key_values = rhs.m_key_values;
-         m_image_data = rhs.m_image_data;
-         m_block_dim = rhs.m_block_dim;
-         m_bytes_per_block = rhs.m_bytes_per_block;
-         m_opposite_endianness = rhs.m_opposite_endianness;
-
-         return *this;
-      }
-
-      void clear()
-      {
-         m_header.clear();
-         m_key_values.clear();
-         m_image_data.clear();
-         
-         m_block_dim = 0;
-         m_bytes_per_block = 0;
-
-         m_opposite_endianness = false;
-      }
-
-      // High level methods
-      bool read_from_stream(data_stream_serializer& serializer);
-      bool write_to_stream(data_stream_serializer& serializer, bool no_keyvalue_data = false);
-      
-      bool init_2D(uint width, uint height, uint num_mips, uint32 ogl_internal_fmt, uint32 ogl_fmt, uint32 ogl_type);
-      bool init_2D_array(uint width, uint height, uint num_mips, uint array_size, uint32 ogl_internal_fmt, uint32 ogl_fmt, uint32 ogl_type);
-      bool init_3D(uint width, uint height, uint depth, uint num_mips, uint32 ogl_internal_fmt, uint32 ogl_fmt, uint32 ogl_type);
-      bool init_cubemap(uint dim, uint num_mips, uint32 ogl_internal_fmt, uint32 ogl_fmt, uint32 ogl_type);
-
-      bool check_header() const;
-      bool consistency_check() const;
-
-      // General info
-
-      bool is_valid() const { return (m_header.m_pixelWidth > 0) && (m_image_data.size() > 0); }
-
-      uint get_width() const { return m_header.m_pixelWidth; }
-      uint get_height() const { return CRNLIB_MAX(m_header.m_pixelHeight, 1); }
-      uint get_depth() const { return CRNLIB_MAX(m_header.m_pixelDepth, 1); }
-      uint get_num_mips() const { return CRNLIB_MAX(m_header.m_numberOfMipmapLevels, 1); }
-      uint get_array_size() const { return CRNLIB_MAX(m_header.m_numberOfArrayElements, 1); }
-      uint get_num_faces() const { return m_header.m_numberOfFaces; }
-
-      uint32 get_ogl_type() const { return m_header.m_glType; }
-      uint32 get_ogl_fmt() const { return m_header.m_glFormat; }
-      uint32 get_ogl_base_fmt() const { return m_header.m_glBaseInternalFormat; }
-      uint32 get_ogl_internal_fmt() const { return m_header.m_glInternalFormat; }
-            
-      uint get_total_images() const { return get_num_mips() * (get_depth() * get_num_faces() * get_array_size()); }
-
-      bool is_compressed() const { return m_block_dim > 1; }
-      bool is_uncompressed() const { return !is_compressed(); }
-     
-      bool get_opposite_endianness() const { return m_opposite_endianness; }
-      void set_opposite_endianness(bool flag) { m_opposite_endianness = flag; }
-
-      uint32 get_block_dim() const { return m_block_dim; }
-      uint32 get_bytes_per_block() const { return m_bytes_per_block; }
-
-      const ktx_header& get_header() const { return m_header; }
-
-      // Key values
-      const ktx_key_value_vec& get_key_value_vec() const { return m_key_values; }
-            ktx_key_value_vec& get_key_value_vec()       { return m_key_values; }
-
-      const uint8_vec* find_key(const char* pKey) const;
-      bool get_key_value_as_string(const char* pKey, dynamic_string& str) const;
-
-      uint add_key_value(const char* pKey, const void* pVal, uint val_size);
-      uint add_key_value(const char* pKey, const char* pVal) { return add_key_value(pKey, pVal, static_cast<uint>(strlen(pVal)) + 1); }
-
-      // Image data
-      uint get_num_images() const { return m_image_data.size(); }
-
-      const uint8_vec& get_image_data(uint image_index) const  { return m_image_data[image_index]; }
-            uint8_vec& get_image_data(uint image_index)        { return m_image_data[image_index]; }
-
-      const uint8_vec& get_image_data(uint mip_index, uint array_index, uint face_index, uint zslice_index) const  { return get_image_data(get_image_index(mip_index, array_index, face_index, zslice_index)); }
-            uint8_vec& get_image_data(uint mip_index, uint array_index, uint face_index, uint zslice_index)        { return get_image_data(get_image_index(mip_index, array_index, face_index, zslice_index)); }
-      
-      const ktx_image_data_vec& get_image_data_vec() const  { return m_image_data; }
-            ktx_image_data_vec& get_image_data_vec()        { return m_image_data; }
-
-      void add_image(uint face_index, uint mip_index, const void* pImage, uint image_size) 
-      { 
-         const uint image_index = get_image_index(mip_index, 0, face_index, 0);
-         if (image_index >= m_image_data.size())
-            m_image_data.resize(image_index + 1);
-         if (image_size)
-         {  
-            uint8_vec& v = m_image_data[image_index];
-            v.resize(image_size);
-            memcpy(&v[0], pImage, image_size);
-         }
-      }
-
-      uint get_image_index(uint mip_index, uint array_index, uint face_index, uint zslice_index) const
-      {
-         CRNLIB_ASSERT((mip_index < get_num_mips()) && (array_index < get_array_size()) && (face_index < get_num_faces()) && (zslice_index < get_depth()));
-         return zslice_index + (face_index * get_depth()) + (array_index * (get_depth() * get_num_faces())) + (mip_index * (get_depth() * get_num_faces() * get_array_size()));
-      }
-      
-      void get_mip_dim(uint mip_index, uint& mip_width, uint& mip_height) const
-      {
-         CRNLIB_ASSERT(mip_index < get_num_mips());
-         mip_width = CRNLIB_MAX(get_width() >> mip_index, 1);
-         mip_height = CRNLIB_MAX(get_height() >> mip_index, 1);
-      }
-
-      void get_mip_dim(uint mip_index, uint& mip_width, uint& mip_height, uint& mip_depth) const
-      {
-         CRNLIB_ASSERT(mip_index < get_num_mips());
-         mip_width = CRNLIB_MAX(get_width() >> mip_index, 1);
-         mip_height = CRNLIB_MAX(get_height() >> mip_index, 1);
-         mip_depth = CRNLIB_MAX(get_depth() >> mip_index, 1);
-      }
-         
-   private:
-      ktx_header                 m_header;
-      
-      ktx_key_value_vec          m_key_values;
-      ktx_image_data_vec         m_image_data;
-
-      uint32                     m_block_dim;
-      uint32                     m_bytes_per_block;
-            
-      bool                       m_opposite_endianness;
-      
-      bool compute_pixel_info();
-   };
-   
-} // namespace crnlib
-
-#endif // #ifndef _KTX_TEXTURE_H_

+ 0 - 142
Source/ThirdParty/crunch/crnlib/crn_lzma_codec.cpp

@@ -1,142 +0,0 @@
-// File: crn_lzma_codec.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_lzma_codec.h"
-#include "crn_strutils.h"
-#include "crn_checksum.h"
-#include "lzma_LzmaLib.h"
-#include "crn_threading.h"
-
-namespace crnlib
-{
-   lzma_codec::lzma_codec() :
-      m_pCompress(LzmaCompress),
-      m_pUncompress(LzmaUncompress)
-   {
-      CRNLIB_ASSUME(cLZMAPropsSize == LZMA_PROPS_SIZE);
-   }
-
-   lzma_codec::~lzma_codec()
-   {
-   }
-
-   bool lzma_codec::pack(const void* p, uint n, crnlib::vector<uint8>& buf)
-   {
-      if (n > 1024U*1024U*1024U)
-         return false;
-
-      uint max_comp_size = n + math::maximum<uint>(128, n >> 8);
-      buf.resize(sizeof(header) + max_comp_size);
-
-      header* pHDR = reinterpret_cast<header*>(&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<const unsigned char*>(p), n,
-               pHDR->m_lzma_props, &outPropsSize,
-               -1,      /* 0 <= level <= 9, default = 5 */
-               0,       /* default = (1 << 24) */
-               -1,        /* 0 <= lc <= 8, default = 3  */
-               -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<header*>(&buf[0]);
-            pComp_data = &buf[sizeof(header)];
-         }
-
-         if (status != SZ_OK)
-         {
-            buf.clear();
-            return false;
-         }
-
-         pHDR->m_comp_size = static_cast<uint>(destLen);
-
-         buf.resize(CRNLIB_SIZEOF_U32(header) + static_cast<uint32>(destLen));
-      }
-
-      pHDR->m_sig = header::cSig;
-      pHDR->m_checksum = static_cast<uint8>(adler32((uint8*)pHDR + header::cChecksumSkipBytes, sizeof(header) - header::cChecksumSkipBytes));
-
-      return true;
-   }
-
-   bool lzma_codec::unpack(const void* p, uint n, crnlib::vector<uint8>& buf)
-   {
-      buf.resize(0);
-
-      if (n < sizeof(header))
-         return false;
-
-      const header& hdr = *static_cast<const header*>(p);
-      if (hdr.m_sig != header::cSig)
-         return false;
-
-      if (static_cast<uint8>(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))
-         return false;
-
-      const uint8* pComp_data = static_cast<const uint8*>(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);
-
-      if ((status != SZ_OK) || (destLen != hdr.m_uncomp_size))
-      {
-         buf.clear();
-         return false;
-      }
-
-      if (adler32(&buf[0], buf.size()) != hdr.m_adler32)
-      {
-         buf.clear();
-         return false;
-      }
-
-      return true;
-   }
-
-} // namespace crnlib

+ 0 - 60
Source/ThirdParty/crunch/crnlib/crn_lzma_codec.h

@@ -1,60 +0,0 @@
-// File: crn_lzma_codec.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_packed_uint.h"
-
-namespace crnlib
-{
-   class lzma_codec
-   {
-   public:
-      lzma_codec();
-      ~lzma_codec();
-
-      // Always available, because we're statically linking in lzmalib now vs. dynamically loading the DLL.
-      bool is_initialized() const { return true; }
-
-      bool pack(const void* p, uint n, crnlib::vector<uint8>& buf);
-
-      bool unpack(const void* p, uint n, crnlib::vector<uint8>& buf);
-
-   private:
-      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) */
-         int lc,        /* 0 <= lc <= 8, default = 3  */
-         int lp,        /* 0 <= lp <= 4, default = 0  */
-         int pb,        /* 0 <= pb <= 4, default = 2  */
-         int fb,        /* 5 <= fb <= 273, default = 32 */
-         int numThreads /* 1 or 2, default = 2 */
-         );
-
-      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;
-      LzmaUncompressFuncPtr   m_pUncompress;
-
-      enum { cLZMAPropsSize = 5 };
-
-#pragma pack(push)
-#pragma pack(1)
-      struct header
-      {
-         enum { cSig = 'L' | ('0' << 8), cChecksumSkipBytes = 3 };
-         packed_uint<2> m_sig;
-         uint8          m_checksum;
-
-         uint8          m_lzma_props[cLZMAPropsSize];
-
-         packed_uint<4> m_comp_size;
-         packed_uint<4> m_uncomp_size;
-
-         packed_uint<4> m_adler32;
-      };
-#pragma pack(pop)
-
-   };
-
-} // namespace crnlib

+ 0 - 76
Source/ThirdParty/crunch/crnlib/crn_math.cpp

@@ -1,76 +0,0 @@
-// File: crn_math.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-
-namespace crnlib
-{
-   namespace math
-   {
-      uint g_bitmasks[32] =
-      {
-         1U <<  0U,         1U <<  1U,          1U <<  2U,        1U <<  3U,
-         1U <<  4U,         1U <<  5U,          1U <<  6U,        1U <<  7U,
-         1U <<  8U,         1U <<  9U,          1U << 10U,        1U << 11U,
-         1U << 12U,         1U << 13U,          1U << 14U,        1U << 15U,
-         1U << 16U,         1U << 17U,          1U << 18U,        1U << 19U,
-         1U << 20U,         1U << 21U,          1U << 22U,        1U << 23U,
-         1U << 24U,         1U << 25U,          1U << 26U,        1U << 27U,
-         1U << 28U,         1U << 29U,          1U << 30U,        1U << 31U
-      };
-      
-      double compute_entropy(const uint8* p, uint n)
-      {
-         uint hist[256];
-         utils::zero_object(hist);
-         
-         for (uint i = 0; i < n; i++)
-            hist[*p++]++;
-         
-         double entropy = 0.0f;
-         
-         const double invln2 = 1.0f/log(2.0f);
-         for (uint i = 0; i < 256; i++)
-         {
-            if (!hist[i])
-               continue;
-               
-            double prob = static_cast<double>(hist[i]) / n;
-            entropy += (-log(prob) * invln2) * hist[i];
-         }
-         
-         return entropy;
-      }
-
-      void compute_lower_pow2_dim(int& width, int& height)
-      {
-         const int tex_width = width;
-         const int tex_height = height;
-
-         width = 1;
-         for ( ; ; )
-         {
-            if ((width * 2) > tex_width)
-               break;
-            width *= 2;
-         }
-
-         height = 1;
-         for ( ; ; )
-         {
-            if ((height * 2) > tex_height)
-               break;
-            height *= 2;
-         }
-      }         
-
-      void compute_upper_pow2_dim(int& width, int& height)
-      {
-         if (!math::is_power_of_2((uint32)width))
-            width = math::next_pow2((uint32)width);
-
-         if (!math::is_power_of_2((uint32)height))
-            height = math::next_pow2((uint32)height);
-      }         
-      
-   } // namespace math
-} // namespace crnlib

+ 0 - 237
Source/ThirdParty/crunch/crnlib/crn_math.h

@@ -1,237 +0,0 @@
-// File: crn_math.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-#if defined(_M_IX86) && defined(_MSC_VER)
-   #include <intrin.h>
-   #pragma intrinsic(__emulu)
-   unsigned __int64 __emulu(unsigned int a,unsigned int b );
-#endif
-
-namespace crnlib
-{
-   namespace math
-   {
-      const float cNearlyInfinite = 1.0e+37f;
-						
-      const float cDegToRad = 0.01745329252f;
-      const float cRadToDeg = 57.29577951f;
-
-      extern uint g_bitmasks[32];
-
-      template<typename T> inline bool within_closed_range(T a, T b, T c) { return (a >= b) && (a <= c); }
-
-      template<typename T> inline bool within_open_range(T a, T b, T c) { return (a >= b) && (a < c); }
-
-      // Yes I know these should probably be pass by ref, not val:
-      // http://www.stepanovpapers.com/notes.pdf
-      // Just don't use them on non-simple (non built-in) types!
-      template<typename T> inline T minimum(T a, T b) { return (a < b) ? a : b; }
-
-      template<typename T> inline T minimum(T a, T b, T c) { return minimum(minimum(a, b), c); }
-
-      template<typename T> inline T maximum(T a, T b) { return (a > b) ? a : b; }
-
-      template<typename T> inline T maximum(T a, T b, T c) { return maximum(maximum(a, b), c); }
-
-      template<typename T, typename U> inline T lerp(T a, T b, U c) { return a + (b - a) * c; }
-
-      template<typename T> inline T clamp(T value, T low, T high) { return (value < low) ? low : ((value > high) ? high : value); }
-
-      template<typename T> inline T saturate(T value) { return (value < 0.0f) ? 0.0f : ((value > 1.0f) ? 1.0f : value); }
-
-      inline int float_to_int(float f) { return static_cast<int>(f); }
-
-      inline uint float_to_uint(float f) { return static_cast<uint>(f); }
-
-      inline int float_to_int(double f) { return static_cast<int>(f); }
-
-      inline uint float_to_uint(double f) { return static_cast<uint>(f); }
-
-      inline int float_to_int_round(float f) { return static_cast<int>((f < 0.0f) ? -floor(-f + .5f) : floor(f + .5f)); }
-
-      inline uint float_to_uint_round(float f) { return static_cast<uint>((f < 0.0f) ? 0.0f : floor(f + .5f)); }
-
-      template<typename T> inline int sign(T value) { return (value < 0) ? -1 : ((value > 0) ? 1 : 0); }
-
-      template<typename T> inline T square(T value) { return value * value; }
-
-      inline bool is_power_of_2(uint32 x) { return x && ((x & (x - 1U)) == 0U); }
-      inline bool is_power_of_2(uint64 x) { return x && ((x & (x - 1U)) == 0U); }
-
-      template<typename T> inline T align_up_value(T x, uint alignment)
-      {
-         CRNLIB_ASSERT(is_power_of_2(alignment));
-         uint q = static_cast<uint>(x);
-         q = (q + alignment - 1) & (~(alignment - 1));
-         return static_cast<T>(q);
-      }
-
-      template<typename T> inline T align_down_value(T x, uint alignment)
-      {
-         CRNLIB_ASSERT(is_power_of_2(alignment));
-         uint q = static_cast<uint>(x);
-         q = q & (~(alignment - 1));
-         return static_cast<T>(q);
-      }
-
-      template<typename T> inline T get_align_up_value_delta(T x, uint alignment)
-      {
-         return align_up_value(x, alignment) - x;
-      }
-		      
-		// From "Hackers Delight"
-      inline uint32 next_pow2(uint32 val)
-      {
-         val--;
-         val |= val >> 16;
-         val |= val >> 8;
-         val |= val >> 4;
-         val |= val >> 2;
-         val |= val >> 1;
-         return val + 1;
-      }
-
-      inline uint64 next_pow2(uint64 val)
-      {
-         val--;
-         val |= val >> 32;
-         val |= val >> 16;
-         val |= val >> 8;
-         val |= val >> 4;
-         val |= val >> 2;
-         val |= val >> 1;
-         return val + 1;
-      }
-            
-      inline uint floor_log2i(uint v)
-      {
-         uint l = 0;
-         while (v > 1U)
-         {
-            v >>= 1;
-            l++;
-         }
-         return l;
-      }
-
-      inline uint ceil_log2i(uint v)
-      {
-         uint l = floor_log2i(v);
-         if ((l != cIntBits) && (v > (1U << l)))
-            l++;
-         return l;
-      }
-
-      // Returns the total number of bits needed to encode v.
-      inline uint total_bits(uint v)
-      {
-         uint l = 0;
-         while (v > 0U)
-         {
-            v >>= 1;
-            l++;
-         }
-         return l;
-      }
-
-      // Actually counts the number of set bits, but hey
-      inline uint bitmask_size(uint mask)
-      {
-         uint size = 0;
-         while (mask)
-         {
-            mask &= (mask - 1U);
-            size++;
-         }
-         return size;
-      }
-
-      inline uint bitmask_ofs(uint mask)
-      {
-         if (!mask)
-            return 0;
-         uint ofs = 0;
-         while ((mask & 1U) == 0)
-         {
-            mask >>= 1U;
-            ofs++;
-         }
-         return ofs;
-      }
-
-      // See Bit Twiddling Hacks (public domain)
-      // http://www-graphics.stanford.edu/~seander/bithacks.html
-      inline uint count_trailing_zero_bits(uint v)
-      {
-         uint c = 32; // c will be the number of zero bits on the right
-
-         static const unsigned int B[] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF };
-         static const unsigned int S[] = { 1, 2, 4, 8, 16 }; // Our Magic Binary Numbers
-
-         for (int i = 4; i >= 0; --i) // unroll for more speed
-         {
-            if (v & B[i])
-            {
-               v <<= S[i];
-               c -= S[i];
-            }
-         }
-
-         if (v)
-         {
-            c--;
-         }
-
-         return c;
-      }
-
-      inline uint count_leading_zero_bits(uint v)
-      {
-         uint temp;
-         uint result = 32U;
-
-         temp = (v >> 16U); if (temp) { result -= 16U; v = temp; }
-         temp = (v >>  8U); if (temp) { result -=  8U; v = temp; }
-         temp = (v >>  4U); if (temp) { result -=  4U; v = temp; }
-         temp = (v >>  2U); if (temp) { result -=  2U; v = temp; }
-         temp = (v >>  1U); if (temp) { result -=  1U; v = temp; }
-
-         if (v & 1U)
-            result--;
-
-         return result;
-      }
-
-      inline uint64 emulu(uint32 a, uint32 b)
-      {
-#if defined(_M_IX86) && defined(_MSC_VER)
-         return __emulu(a, b);
-#else
-         return static_cast<uint64>(a) * static_cast<uint64>(b);
-#endif
-      }
-
-      double compute_entropy(const uint8* p, uint n);
-
-      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
-
-
-
-
-
-

+ 0 - 565
Source/ThirdParty/crunch/crnlib/crn_matrix.h

@@ -1,565 +0,0 @@
-// File: crn_matrix.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-#include "crn_vec.h"
-
-namespace crnlib
-{
-   template<class X, class Y, class Z> Z& matrix_mul_helper(Z& result, const X& lhs, const Y& rhs)
-   {
-      CRNLIB_ASSUME(Z::num_rows == X::num_rows);
-      CRNLIB_ASSUME(Z::num_cols == Y::num_cols);
-      CRNLIB_ASSUME(X::num_cols == Y::num_rows);
-      CRNLIB_ASSERT((&result != &lhs) && (&result != &rhs));
-      for (int r = 0; r < X::num_rows; r++)
-         for (int c = 0; c < Y::num_cols; c++)
-         {
-            typename Z::scalar_type s = lhs(r, 0) * rhs(0, c);
-            for (uint i = 1; i < X::num_cols; i++)
-               s += lhs(r, i) * rhs(i, c);
-            result(r, c) = s;
-         }
-         return result;
-   }
-
-   template<class X, class Y, class Z> Z& matrix_mul_helper_transpose_lhs(Z& result, const X& lhs, const Y& rhs)
-   {
-      CRNLIB_ASSUME(Z::num_rows == X::num_cols);
-      CRNLIB_ASSUME(Z::num_cols == Y::num_cols);
-      CRNLIB_ASSUME(X::num_rows == Y::num_rows);
-      for (int r = 0; r < X::num_cols; r++)
-         for (int c = 0; c < Y::num_cols; c++)
-         {
-            typename Z::scalar_type s = lhs(0, r) * rhs(0, c);
-            for (uint i = 1; i < X::num_rows; i++)
-               s += lhs(i, r) * rhs(i, c);
-            result(r, c) = s;
-         }
-         return result;
-   }
-
-   template<class X, class Y, class Z> Z& matrix_mul_helper_transpose_rhs(Z& result, const X& lhs, const Y& rhs)
-   {
-      CRNLIB_ASSUME(Z::num_rows == X::num_rows);
-      CRNLIB_ASSUME(Z::num_cols == Y::num_rows);
-      CRNLIB_ASSUME(X::num_cols == Y::num_cols);
-      for (int r = 0; r < X::num_rows; r++)
-         for (int c = 0; c < Y::num_rows; c++)
-         {
-            typename Z::scalar_type s = lhs(r, 0) * rhs(c, 0);
-            for (uint i = 1; i < X::num_cols; i++)
-               s += lhs(r, i) * rhs(c, i);
-            result(r, c) = s;
-         }
-         return result;
-   }
-
-   template<uint R, uint C, typename T>
-   class matrix
-   {
-   public:
-      typedef T scalar_type;
-      enum { num_rows = R, num_cols = C };
-
-      typedef vec<R, T> col_vec;
-      typedef vec<(R > 1) ? (R - 1) : 0, T> subcol_vec;
-
-      typedef vec<C, T> row_vec;
-      typedef vec<(C > 1) ? (C - 1) : 0, T> subrow_vec;
-
-      inline matrix() { }
-
-      inline matrix(eClear) { clear(); }
-
-      inline matrix(const T* p) { set(p); }
-
-      inline matrix(const matrix& other)
-      {
-         for (uint i = 0; i < R; i++)
-            m_rows[i] = other.m_rows[i];
-      }
-
-      inline matrix& operator= (const matrix& rhs)
-      {
-         if (this != &rhs)
-            for (uint i = 0; i < R; i++)
-               m_rows[i] = rhs.m_rows[i];
-         return *this;
-      }
-
-      inline matrix(T val00, T val01,
-                    T val10, T val11)
-      {
-         set(val00, val01,  val10, val11);
-      }
-
-      inline matrix(T val00, T val01, T val02,
-                    T val10, T val11, T val12,
-                    T val20, T val21, T val22)
-      {
-         set(val00, val01, val02,  val10, val11, val12,  val20, val21, val22);
-      }
-
-      inline matrix(T val00, T val01, T val02, T val03,
-                    T val10, T val11, T val12, T val13,
-                    T val20, T val21, T val22, T val23,
-                    T val30, T val31, T val32, T val33)
-      {
-         set(val00, val01, val02, val03, val10, val11, val12, val13, val20, val21, val22, val23, val30, val31, val32, val33);
-      }
-
-      inline void set(const float* p)
-      {
-         for (uint i = 0; i < R; i++)
-         {
-            m_rows[i].set(p);
-            p += C;
-         }
-      }
-
-      inline void set(T val00, T val01,
-                      T val10, T val11)
-      {
-         m_rows[0].set(val00, val01);
-         if (R >= 2)
-         {
-            m_rows[1].set(val10, val11);
-
-            for (uint i = 2; i < R; i++)
-               m_rows[i].clear();
-         }
-      }
-
-      inline void set(T val00, T val01, T val02,
-                      T val10, T val11, T val12,
-                      T val20, T val21, T val22)
-      {
-         m_rows[0].set(val00, val01, val02);
-         if (R >= 2)
-         {
-            m_rows[1].set(val10, val11, val12);
-            if (R >= 3)
-            {
-               m_rows[2].set(val20, val21, val22);
-
-               for (uint i = 3; i < R; i++)
-                  m_rows[i].clear();
-            }
-         }
-      }
-
-      inline void set(T val00, T val01, T val02, T val03,
-                      T val10, T val11, T val12, T val13,
-                      T val20, T val21, T val22, T val23,
-                      T val30, T val31, T val32, T val33)
-      {
-         m_rows[0].set(val00, val01, val02, val03);
-         if (R >= 2)
-         {
-            m_rows[1].set(val10, val11, val12, val13);
-            if (R >= 3)
-            {
-               m_rows[2].set(val20, val21, val22, val23);
-
-               if (R >= 4)
-               {
-                  m_rows[3].set(val30, val31, val32, val33);
-
-                  for (uint i = 4; i < R; i++)
-                     m_rows[i].clear();
-               }
-            }
-         }
-      }
-
-      inline T operator() (uint r, uint c) const
-      {
-         CRNLIB_ASSERT((r < R) && (c < C));
-         return m_rows[r][c];
-      }
-
-      inline T& operator() (uint r, uint c)
-      {
-         CRNLIB_ASSERT((r < R) && (c < C));
-         return m_rows[r][c];
-      }
-
-      inline const row_vec& operator[] (uint r) const
-      {
-         CRNLIB_ASSERT(r < R);
-         return m_rows[r];
-      }
-
-      inline row_vec& operator[] (uint r)
-      {
-         CRNLIB_ASSERT(r < R);
-         return m_rows[r];
-      }
-
-      inline const row_vec& get_row (uint r) const  { return (*this)[r]; }
-      inline       row_vec& get_row (uint r)        { return (*this)[r]; }
-
-      inline col_vec get_col(uint c) const
-      {
-         CRNLIB_ASSERT(c < C);
-         col_vec result;
-         for (uint i = 0; i < R; i++)
-            result[i] = m_rows[i][c];
-         return result;
-      }
-
-      inline void set_col(uint c, const col_vec& col)
-      {
-         CRNLIB_ASSERT(c < C);
-         for (uint i = 0; i < R; i++)
-            m_rows[i][c] = col[i];
-      }
-
-      inline void set_col(uint c, const subcol_vec& col)
-      {
-         CRNLIB_ASSERT(c < C);
-         for (uint i = 0; i < (R - 1); i++)
-            m_rows[i][c] = col[i];
-
-         m_rows[R - 1][c] = 0.0f;
-      }
-
-      inline const row_vec& get_translate() const
-      {
-         return m_rows[R - 1];
-      }
-
-      inline matrix& set_translate(const row_vec& r)
-      {
-         m_rows[R - 1] = r;
-         return *this;
-      }
-
-      inline matrix& set_translate(const subrow_vec& r)
-      {
-         m_rows[R - 1] = row_vec(r).as_point();
-         return *this;
-      }
-
-      inline const T* get_ptr() const   { return reinterpret_cast<const T*>(&m_rows[0]); }
-      inline       T* get_ptr()         { return reinterpret_cast<      T*>(&m_rows[0]); }
-
-      inline matrix& operator+= (const matrix& other)
-      {
-         for (uint i = 0; i < R; i++)
-            m_rows[i] += other.m_rows[i];
-         return *this;
-      }
-
-      inline matrix& operator-= (const matrix& other)
-      {
-         for (uint i = 0; i < R; i++)
-            m_rows[i] -= other.m_rows[i];
-         return *this;
-      }
-
-      inline matrix& operator*= (T val)
-      {
-         for (uint i = 0; i < R; i++)
-            m_rows[i] *= val;
-         return *this;
-      }
-
-      inline matrix& operator/= (T val)
-      {
-         for (uint i = 0; i < R; i++)
-            m_rows[i] /= val;
-         return *this;
-      }
-
-      inline matrix& operator*= (const matrix& other)
-      {
-         matrix result;
-         matrix_mul_helper(result, *this, other);
-         *this = result;
-         return *this;
-      }
-
-      friend inline matrix operator+ (const matrix& lhs, const matrix& rhs)
-      {
-         matrix result;
-         for (uint i = 0; i < R; i++)
-            result[i] = lhs.m_rows[i] + rhs.m_rows[i];
-         return result;
-      }
-
-      friend inline matrix operator- (const matrix& lhs, const matrix& rhs)
-      {
-         matrix result;
-         for (uint i = 0; i < R; i++)
-            result[i] = lhs.m_rows[i] - rhs.m_rows[i];
-         return result;
-      }
-
-      friend inline matrix operator* (const matrix& lhs, T val)
-      {
-         matrix result;
-         for (uint i = 0; i < R; i++)
-            result[i] = lhs.m_rows[i] * val;
-         return result;
-      }
-
-      friend inline matrix operator/ (const matrix& lhs, T val)
-      {
-         matrix result;
-         for (uint i = 0; i < R; i++)
-            result[i] = lhs.m_rows[i] / val;
-         return result;
-      }
-
-      friend inline matrix operator* (T val, const matrix& rhs)
-      {
-         matrix result;
-         for (uint i = 0; i < R; i++)
-            result[i] = val * rhs.m_rows[i];
-         return result;
-      }
-
-      friend inline matrix operator* (const matrix& lhs, const matrix& rhs)
-      {
-         matrix result;
-         return matrix_mul_helper(result, lhs, rhs);
-      }
-
-      friend inline row_vec operator* (const col_vec& a, const matrix& b)
-      {
-         return transform(a, b);
-      }
-
-      inline matrix operator+ () const
-      {
-         return *this;
-      }
-
-      inline matrix operator- () const
-      {
-         matrix result;
-         for (uint i = 0; i < R; i++)
-            result[i] = -m_rows[i];
-         return result;
-      }
-
-      inline void clear(void)
-      {
-         for (uint i = 0; i < R; i++)
-            m_rows[i].clear();
-      }
-
-      inline void set_zero_matrix()
-      {
-         clear();
-      }
-
-      inline void set_identity_matrix()
-      {
-         for (uint i = 0; i < R; i++)
-         {
-            m_rows[i].clear();
-            m_rows[i][i] = 1.0f;
-         }
-      }
-
-      inline matrix& set_scale_matrix(float s)
-      {
-         clear();
-         for (int i = 0; i < (R - 1); i++)
-            m_rows[i][i] = s;
-         m_rows[R - 1][C - 1] = 1.0f;
-         return *this;
-      }
-
-      inline matrix& set_scale_matrix(const row_vec& s)
-      {
-         clear();
-         for (uint i = 0; i < R; i++)
-            m_rows[i][i] = s[i];
-         return *this;
-      }
-
-      inline matrix& set_translate_matrix(const row_vec& s)
-      {
-         set_identity_matrix();
-         set_translate(s);
-         return *this;
-      }
-
-      inline matrix& set_translate_matrix(float x, float y)
-      {
-         set_identity_matrix();
-         set_translate(row_vec(x, y).as_point());
-         return *this;
-      }
-
-      inline matrix& set_translate_matrix(float x, float y, float z)
-      {
-         set_identity_matrix();
-         set_translate(row_vec(x, y, z).as_point());
-         return *this;
-      }
-
-      inline matrix get_transposed(void) const
-      {
-         matrix result;
-         for (uint i = 0; i < R; i++)
-            for (uint j = 0; j < C; j++)
-               result.m_rows[i][j] = m_rows[j][i];
-         return result;
-      }
-
-      inline matrix& transpose_in_place(void)
-      {
-         matrix result;
-         for (uint i = 0; i < R; i++)
-            for (uint j = 0; j < C; j++)
-               result.m_rows[i][j] = m_rows[j][i];
-         *this = result;
-         return *this;
-      }
-                  
-      // This method transforms a column vec by a matrix (D3D-style).
-      static inline row_vec transform(const col_vec& a, const matrix& b)
-      {
-         row_vec result(b[0] * a[0]);
-         for (uint r = 1; r < R; r++)
-            result += b[r] * a[r];
-         return result;
-      }
-
-      // This method transforms a column vec by a matrix. Last component of vec is assumed to be 1.
-      static inline row_vec transform_point(const col_vec& a, const matrix& b)
-      {
-         row_vec result(0);
-         for (int r = 0; r < (R - 1); r++)
-            result += b[r] * a[r];
-         result += b[R - 1];
-         return result;
-      }
-
-      // This method transforms a column vec by a matrix. Last component of vec is assumed to be 0.
-      static inline row_vec transform_vector(const col_vec& a, const matrix& b)
-      {
-         row_vec result(0);
-         for (int r = 0; r < (R - 1); r++)
-            result += b[r] * a[r];
-         return result;
-      }
-
-      static inline subcol_vec transform_point(const subcol_vec& a, const matrix& b)
-      {
-         subcol_vec result(0);
-         for (int r = 0; r < R; r++)
-         {
-            const T s = (r < subcol_vec::num_elements) ? a[r] : 1.0f;
-            for (int c = 0; c < (C - 1); c++)
-               result[c] += b[r][c] * s;
-         }
-         return result;
-      }
-
-      static inline subcol_vec transform_vector(const subcol_vec& a, const matrix& b)
-      {
-         subcol_vec result(0);
-         for (int r = 0; r < (R - 1); r++)
-         {
-            const T s = a[r];
-            for (int c = 0; c < (C - 1); c++)
-               result[c] += b[r][c] * s;
-         }
-         return result;
-      }
-
-      // This method transforms a column vec by the transpose of a matrix.
-      static inline col_vec transform_transposed(const matrix& b, const col_vec& a)
-      {
-         CRNLIB_ASSUME(R == C);
-         col_vec result;
-         for (uint r = 0; r < R; r++)
-            result[r] = b[r] * a;
-         return result;
-      }
-
-      // This method transforms a column vec by the transpose of a matrix. Last component of vec is assumed to be 0.
-      static inline col_vec transform_vector_transposed(const matrix& b, const col_vec& a)
-      {
-         CRNLIB_ASSUME(R == C);
-         col_vec result;
-         for (uint r = 0; r < R; r++)
-         {
-            T s = 0;
-            for (uint c = 0; c < (C - 1); c++)
-               s += b[r][c] * a[c];
-
-            result[r] = s;
-         }
-         return result;
-      }
-
-      // This method transforms a matrix by a row vector (OGL style).
-      static inline col_vec transform(const matrix& b, const row_vec& a)
-      {
-         col_vec result;
-         for (int r = 0; r < R; r++)
-            result[r] = b[r] * a;
-         return result;
-      }
-
-      static inline matrix& multiply(matrix& result, const matrix& lhs, const matrix& rhs)
-      {
-         return matrix_mul_helper(result, lhs, rhs);
-      }
-
-      static inline matrix make_scale_matrix(float s)
-      {
-         return matrix().set_scale_matrix(s);
-      }
-
-      static inline matrix make_scale_matrix(const row_vec& s)
-      {
-         return matrix().set_scale_matrix(s);
-      }
-
-      static inline matrix make_scale_matrix(float x, float y)
-      {
-         CRNLIB_ASSUME(R >= 3 && C >= 3);
-         matrix result;
-         result.clear();
-         result.m_rows[0][0] = x;
-         result.m_rows[1][1] = y;
-         result.m_rows[2][2] = 1.0f;
-         return result;
-      }
-
-      static inline matrix make_scale_matrix(float x, float y, float z)
-      {
-         CRNLIB_ASSUME(R >= 4 && C >= 4);
-         matrix result;
-         result.clear();
-         result.m_rows[0][0] = x;
-         result.m_rows[1][1] = y;
-         result.m_rows[2][2] = z;
-         result.m_rows[3][3] = 1.0f;
-         return result;
-      }
-
-   private:
-      row_vec m_rows[R];
-   };
-
-   typedef matrix<2, 2, float> matrix22F;
-   typedef matrix<2, 2, double> matrix22D;
-
-   typedef matrix<3, 3, float> matrix33F;
-   typedef matrix<3, 3, double> matrix33D;
-
-   typedef matrix<4, 4, float> matrix44F;
-   typedef matrix<4, 4, double> matrix44D;
-
-   typedef matrix<8, 8, float> matrix88F;
-   
-} // namespace crnlib

+ 0 - 379
Source/ThirdParty/crunch/crnlib/crn_mem.cpp

@@ -1,379 +0,0 @@
-// File: crn_mem.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_console.h"
-#include "../inc/crnlib.h"
-#include <malloc.h>
-#if CRNLIB_USE_WIN32_API
-#include "crn_winhdr.h"
-#endif
-
-#define CRNLIB_MEM_STATS 0
-
-#if !CRNLIB_USE_WIN32_API
-#define _msize malloc_usable_size
-#endif
-
-namespace crnlib
-{
-#if CRNLIB_MEM_STATS
-   #if CRNLIB_64BIT_POINTERS
-      typedef LONGLONG mem_stat_t;
-      #define CRNLIB_MEM_COMPARE_EXCHANGE InterlockedCompareExchange64
-   #else
-      typedef LONG mem_stat_t;
-      #define CRNLIB_MEM_COMPARE_EXCHANGE InterlockedCompareExchange
-   #endif
-
-   static volatile mem_stat_t g_total_blocks;
-   static volatile mem_stat_t g_total_allocated;
-   static volatile mem_stat_t g_max_allocated;
-
-   static mem_stat_t update_total_allocated(int block_delta, mem_stat_t byte_delta)
-   {
-      mem_stat_t cur_total_blocks;
-      for ( ; ; )
-      {
-         cur_total_blocks = (mem_stat_t)g_total_blocks;
-         mem_stat_t new_total_blocks = static_cast<mem_stat_t>(cur_total_blocks + block_delta);
-         CRNLIB_ASSERT(new_total_blocks >= 0);
-         if (CRNLIB_MEM_COMPARE_EXCHANGE(&g_total_blocks, new_total_blocks, cur_total_blocks) == cur_total_blocks)
-            break;
-      }
-
-      mem_stat_t cur_total_allocated, new_total_allocated;
-      for ( ; ; )
-      {
-         cur_total_allocated = g_total_allocated;
-         new_total_allocated = static_cast<mem_stat_t>(cur_total_allocated + byte_delta);
-         CRNLIB_ASSERT(new_total_allocated >= 0);
-         if (CRNLIB_MEM_COMPARE_EXCHANGE(&g_total_allocated, new_total_allocated, cur_total_allocated) == cur_total_allocated)
-            break;
-      }
-      for ( ; ; )
-      {
-         mem_stat_t cur_max_allocated = g_max_allocated;
-         mem_stat_t new_max_allocated = CRNLIB_MAX(new_total_allocated, cur_max_allocated);
-         if (CRNLIB_MEM_COMPARE_EXCHANGE(&g_max_allocated, new_max_allocated, cur_max_allocated) == cur_max_allocated)
-            break;
-      }
-      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;
-
-      void* p_new;
-
-      if (!p)
-      {
-         p_new = ::malloc(size);
-         CRNLIB_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
-
-         if (!p_new)
-         {
-            printf("WARNING: ::malloc() of size %u failed!\n", (uint)size);
-         }
-
-         if (pActual_size)
-            *pActual_size = p_new ? ::_msize(p_new) : 0;
-      }
-      else if (!size)
-      {
-         ::free(p);
-         p_new = NULL;
-
-         if (pActual_size)
-            *pActual_size = 0;
-      }
-      else
-      {
-         void* p_final_block = p;
-#ifdef WIN32
-         p_new = ::_expand(p, size);
-#else
-         p_new = NULL;
-#endif
-
-         if (p_new)
-         {
-            CRNLIB_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
-            p_final_block = p_new;
-         }
-         else if (movable)
-         {
-            p_new = ::realloc(p, size);
-
-            if (p_new)
-            {
-               CRNLIB_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
-               p_final_block = p_new;
-            }
-            else
-            {
-               printf("WARNING: ::realloc() of size %u failed!\n", (uint)size);
-            }
-         }
-
-         if (pActual_size)
-            *pActual_size = ::_msize(p_final_block);
-      }
-
-      return p_new;
-   }
-
-   static size_t crnlib_default_msize(void* p, void* pUser_data)
-   {
-      pUser_data;
-      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);
-      if (!size)
-         size = sizeof(uint32);
-
-      if (size > CRNLIB_MAX_POSSIBLE_BLOCK_SIZE)
-      {
-         crnlib_mem_error("crnlib_malloc: size too big");
-         return NULL;
-      }
-
-      size_t actual_size = size;
-      uint8* p_new = static_cast<uint8*>((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data));
-
-      if (pActual_size)
-         *pActual_size = actual_size;
-
-      if ((!p_new) || (actual_size < size))
-      {
-         crnlib_mem_error("crnlib_malloc: out of memory");
-         return NULL;
-      }
-
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0);
-
-#if CRNLIB_MEM_STATS
-      CRNLIB_ASSERT((*g_pMSize)(p_new, g_pUser_data) == actual_size);
-      update_total_allocated(1, static_cast<mem_stat_t>(actual_size));
-#endif
-
-      return p_new;
-   }
-
-   void* crnlib_realloc(void* p, size_t size, size_t* pActual_size, bool movable)
-   {
-      if ((ptr_bits_t)p & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1))
-      {
-         crnlib_mem_error("crnlib_realloc: bad ptr");
-         return NULL;
-      }
-
-      if (size > CRNLIB_MAX_POSSIBLE_BLOCK_SIZE)
-      {
-         crnlib_mem_error("crnlib_malloc: size too big");
-         return NULL;
-      }
-
-#if CRNLIB_MEM_STATS
-      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)))
-         size = sizeof(uint32);
-
-      size_t actual_size = size;
-      void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data);
-
-      if (pActual_size)
-         *pActual_size = actual_size;
-
-      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0);
-
-#if CRNLIB_MEM_STATS
-      CRNLIB_ASSERT(!p_new || ((*g_pMSize)(p_new, g_pUser_data) == actual_size));
-
-      int num_new_blocks = 0;
-      if (p)
-      {
-         if (!p_new)
-            num_new_blocks = -1;
-      }
-      else if (p_new)
-      {
-         num_new_blocks = 1;
-      }
-      update_total_allocated(num_new_blocks, static_cast<mem_stat_t>(actual_size) - static_cast<mem_stat_t>(cur_size));
-#endif
-
-      return p_new;
-   }
-
-   void* crnlib_calloc(size_t count, size_t size, size_t* pActual_size)
-   {
-      size_t total = count * size;
-      void *p = crnlib_malloc(total, pActual_size);
-      if (p) memset(p, 0, total);
-      return p;
-   }
-
-   void crnlib_free(void* p)
-   {
-      if (!p)
-         return;
-
-      if (reinterpret_cast<ptr_bits_t>(p) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1))
-      {
-         crnlib_mem_error("crnlib_free: bad ptr");
-         return;
-      }
-
-#if CRNLIB_MEM_STATS
-      size_t cur_size = (*g_pMSize)(p, g_pUser_data);
-      CRNLIB_ASSERT(cur_size >= sizeof(uint32));
-      update_total_allocated(-1, -static_cast<mem_stat_t>(cur_size));
-#endif
-
-      (*g_pRealloc)(p, 0, NULL, true, g_pUser_data);
-   }
-
-   size_t crnlib_msize(void* p)
-   {
-      if (!p)
-         return 0;
-
-      if (reinterpret_cast<ptr_bits_t>(p) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1))
-      {
-         crnlib_mem_error("crnlib_msize: bad ptr");
-         return 0;
-      }
-
-      return (*g_pMSize)(p, g_pUser_data);
-   }
-
-   void crnlib_print_mem_stats()
-   {
-#if CRNLIB_MEM_STATS
-      if (console::is_initialized())
-      {
-         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: " CRNLIB_INT64_FORMAT_SPECIFIER ", max ever allocated: " CRNLIB_INT64_FORMAT_SPECIFIER "\n", g_total_blocks, (int64)g_total_allocated, (int64)g_max_allocated);
-      }
-#endif
-   }
-
-} // namespace crnlib
-
-void crn_set_memory_callbacks(crn_realloc_func pRealloc, crn_msize_func pMSize, void* pUser_data)
-{
-   if ((!pRealloc) || (!pMSize))
-   {
-      crnlib::g_pRealloc = crnlib::crnlib_default_realloc;
-      crnlib::g_pMSize = crnlib::crnlib_default_msize;
-      crnlib::g_pUser_data = NULL;
-   }
-   else
-   {
-      crnlib::g_pRealloc = pRealloc;
-      crnlib::g_pMSize = pMSize;
-      crnlib::g_pUser_data = pUser_data;
-   }
-}

+ 0 - 209
Source/ThirdParty/crunch/crnlib/crn_mem.h

@@ -1,209 +0,0 @@
-// File: crn_mem.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-#ifndef CRNLIB_MIN_ALLOC_ALIGNMENT
-#define CRNLIB_MIN_ALLOC_ALIGNMENT sizeof(size_t) * 2
-#endif
-
-namespace crnlib
-{
-#if CRNLIB_64BIT_POINTERS
-   const uint64 CRNLIB_MAX_POSSIBLE_BLOCK_SIZE = 0x400000000ULL;
-#else
-   const uint32 CRNLIB_MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U;
-#endif
-
-   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);
-   size_t   crnlib_msize(void* p);
-   void     crnlib_print_mem_stats();
-   void     crnlib_mem_error(const char* p_msg);
-   
-   // omfg - there must be a better way
-   
-   template<typename T>
-   inline T* crnlib_new()
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      if (CRNLIB_IS_SCALAR_TYPE(T))
-         return p;
-      return helpers::construct(p);
-   }
-
-   template<typename T, typename A>
-   inline T* crnlib_new(const A& init0)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0); 
-   }
-
-   template<typename T, typename A>
-   inline T* crnlib_new(A& init0)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0); 
-   }
-
-   template<typename T, typename A, typename B>
-   inline T* crnlib_new(const A& init0, const B& init1)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1); 
-   }
-
-   template<typename T, typename A, typename B, typename C>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D, typename E>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D, typename E, typename F>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7, const I& init8)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7, init8); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7, const I& init8, const J& init9)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7, init8, init9); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7, const I& init8, const J& init9, const K& init10)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7, init8, init9, init10); 
-   }
-
-   template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L>
-   inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7, const I& init8, const J& init9, const K& init10, const L& init11)
-   {
-      T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
-      return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7, init8, init9, init10, init11); 
-   }
-
-   template<typename T>
-   inline T* crnlib_new_array(uint32 num)
-   {
-      if (!num) num = 1;
-
-      uint64 total = CRNLIB_MIN_ALLOC_ALIGNMENT + sizeof(T) * num;
-      if (total > CRNLIB_MAX_POSSIBLE_BLOCK_SIZE)
-      {
-         crnlib_mem_error("crnlib_new_array: Array too large!");
-         return NULL;
-      }
-      uint8* q = static_cast<uint8*>(crnlib_malloc(static_cast<size_t>(total)));
-
-      T* p = reinterpret_cast<T*>(q + CRNLIB_MIN_ALLOC_ALIGNMENT);
-
-      reinterpret_cast<uint32*>(p)[-1] = num;
-      reinterpret_cast<uint32*>(p)[-2] = ~num;
-
-      if (!CRNLIB_IS_SCALAR_TYPE(T))
-      {
-         helpers::construct_array(p, num);
-      }
-      return p;
-   }
-
-   template<typename T> 
-   inline void crnlib_delete(T* p)
-   {
-      if (p) 
-      {
-         if (!CRNLIB_IS_SCALAR_TYPE(T))
-         {
-            helpers::destruct(p);
-         }
-         crnlib_free(p);
-      }         
-   }
-
-   template<typename T> 
-   inline void crnlib_delete_array(T* p)
-   {
-      if (p)
-      {
-         const uint32 num = reinterpret_cast<uint32*>(p)[-1];
-         const uint32 num_check = reinterpret_cast<uint32*>(p)[-2];
-         CRNLIB_ASSERT(num && (num == ~num_check));
-         if (num == ~num_check)
-         {
-            if (!CRNLIB_IS_SCALAR_TYPE(T))
-            {
-               helpers::destruct_array(p, num);
-            }
-
-            crnlib_free(reinterpret_cast<uint8*>(p) - CRNLIB_MIN_ALLOC_ALIGNMENT);
-         }
-      }
-   }   
-   
-} // 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); \
-   }

+ 0 - 3948
Source/ThirdParty/crunch/crnlib/crn_miniz.cpp

@@ -1,3948 +0,0 @@
-// File: crn_miniz.cpp
-#include "crn_core.h"
-#include "crn_miniz.h"
-
-// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)
-
-#ifndef MINIZ_HEADER_FILE_ONLY
-
-typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
-typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
-typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];
-
-#include <string.h>
-#include <assert.h>
-
-#include "crn_core.h"
-
-#define MZ_ASSERT(x) assert(x)
-
-#ifdef MINIZ_NO_MALLOC
-  #define MZ_MALLOC(x) NULL
-  #define MZ_FREE(x) (void)x, ((void)0)
-  #define MZ_REALLOC(p, x) NULL
-#else
-  #define MZ_MALLOC(x) crnlib::crnlib_malloc(x)
-  #define MZ_FREE(x) crnlib::crnlib_free(x)
-  #define MZ_REALLOC(p, x) crnlib::crnlib_realloc(p, x)
-#endif
-
-#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
-#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
-#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
-
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
-  #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
-  #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
-#else
-  #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
-  #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
-#endif
-
-#ifdef _MSC_VER
-  #define MZ_FORCEINLINE __forceinline
-#elif defined(__GNUC__)
-  #define MZ_FORCEINLINE __attribute__((__always_inline__))
-#else
-  #define MZ_FORCEINLINE
-#endif
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-// ------------------- zlib-style API's
-
-mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
-{
-  mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
-  if (!ptr) return MZ_ADLER32_INIT;
-  while (buf_len) {
-    for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
-      s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
-      s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
-    }
-    for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
-    s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
-  }
-  return (s2 << 16) + s1;
-}
-
-// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/
-mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
-{
-  static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
-    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
-  mz_uint32 crcu32 = (mz_uint32)crc;
-  if (!ptr) return MZ_CRC32_INIT;
-  crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; }
-  return ~crcu32;
-}
-
-void mz_free(void *p)
-{
-  MZ_FREE(p);
-}
-
-#ifndef MINIZ_NO_ZLIB_APIS
-
-static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); }
-static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
-static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); }
-
-const char *mz_version(void)
-{
-  return MZ_VERSION;
-}
-
-int mz_deflateInit(mz_streamp pStream, int level)
-{
-  return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
-}
-
-int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
-{
-  tdefl_compressor *pComp;
-  mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
-
-  if (!pStream) return MZ_STREAM_ERROR;
-  if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR;
-
-  pStream->data_type = 0;
-  pStream->adler = MZ_ADLER32_INIT;
-  pStream->msg = NULL;
-  pStream->reserved = 0;
-  pStream->total_in = 0;
-  pStream->total_out = 0;
-  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
-  if (!pStream->zfree) pStream->zfree = def_free_func;
-
-  pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
-  if (!pComp)
-    return MZ_MEM_ERROR;
-
-  pStream->state = (struct mz_internal_state *)pComp;
-
-  if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
-  {
-    mz_deflateEnd(pStream);
-    return MZ_PARAM_ERROR;
-  }
-
-  return MZ_OK;
-}
-
-int mz_deflateReset(mz_streamp pStream)
-{
-  if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
-  pStream->total_in = pStream->total_out = 0;
-  tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
-  return MZ_OK;
-}
-
-int mz_deflate(mz_streamp pStream, int flush)
-{
-  size_t in_bytes, out_bytes;
-  mz_ulong orig_total_in, orig_total_out;
-  int mz_status = MZ_OK;
-
-  if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
-  if (!pStream->avail_out) return MZ_BUF_ERROR;
-
-  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
-
-  if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
-    return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
-
-  orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
-  for ( ; ; )
-  {
-    tdefl_status defl_status;
-    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
-
-    defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
-    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
-    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);
-
-    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
-    pStream->total_out += (mz_uint)out_bytes;
-
-    if (defl_status < 0)
-    {
-      mz_status = MZ_STREAM_ERROR;
-      break;
-    }
-    else if (defl_status == TDEFL_STATUS_DONE)
-    {
-      mz_status = MZ_STREAM_END;
-      break;
-    }
-    else if (!pStream->avail_out)
-      break;
-    else if ((!pStream->avail_in) && (flush != MZ_FINISH))
-    {
-      if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
-        break;
-      return MZ_BUF_ERROR; // Can't make forward progress without some input.
-    }
-  }
-  return mz_status;
-}
-
-int mz_deflateEnd(mz_streamp pStream)
-{
-  if (!pStream) return MZ_STREAM_ERROR;
-  if (pStream->state)
-  {
-    pStream->zfree(pStream->opaque, pStream->state);
-    pStream->state = NULL;
-  }
-  return MZ_OK;
-}
-
-mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
-{
-  (void)pStream;
-  // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.)
-  return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
-}
-
-int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
-{
-  int status;
-  mz_stream stream;
-  memset(&stream, 0, sizeof(stream));
-
-  // In case mz_ulong is 64-bits (argh I hate longs).
-  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
-
-  stream.next_in = pSource;
-  stream.avail_in = (mz_uint32)source_len;
-  stream.next_out = pDest;
-  stream.avail_out = (mz_uint32)*pDest_len;
-
-  status = mz_deflateInit(&stream, level);
-  if (status != MZ_OK) return status;
-
-  status = mz_deflate(&stream, MZ_FINISH);
-  if (status != MZ_STREAM_END)
-  {
-    mz_deflateEnd(&stream);
-    return (status == MZ_OK) ? MZ_BUF_ERROR : status;
-  }
-
-  *pDest_len = stream.total_out;
-  return mz_deflateEnd(&stream);
-}
-
-int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
-{
-  return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
-}
-
-mz_ulong mz_compressBound(mz_ulong source_len)
-{
-  return mz_deflateBound(NULL, source_len);
-}
-
-typedef struct
-{
-  tinfl_decompressor m_decomp;
-  mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
-  mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
-  tinfl_status m_last_status;
-} inflate_state;
-
-int mz_inflateInit2(mz_streamp pStream, int window_bits)
-{
-  inflate_state *pDecomp;
-  if (!pStream) return MZ_STREAM_ERROR;
-  if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
-
-  pStream->data_type = 0;
-  pStream->adler = 0;
-  pStream->msg = NULL;
-  pStream->total_in = 0;
-  pStream->total_out = 0;
-  pStream->reserved = 0;
-  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
-  if (!pStream->zfree) pStream->zfree = def_free_func;
-
-  pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
-  if (!pDecomp) return MZ_MEM_ERROR;
-
-  pStream->state = (struct mz_internal_state *)pDecomp;
-
-  tinfl_init(&pDecomp->m_decomp);
-  pDecomp->m_dict_ofs = 0;
-  pDecomp->m_dict_avail = 0;
-  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
-  pDecomp->m_first_call = 1;
-  pDecomp->m_has_flushed = 0;
-  pDecomp->m_window_bits = window_bits;
-
-  return MZ_OK;
-}
-
-int mz_inflateInit(mz_streamp pStream)
-{
-   return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
-}
-
-int mz_inflate(mz_streamp pStream, int flush)
-{
-  inflate_state* pState;
-  mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
-  size_t in_bytes, out_bytes, orig_avail_in;
-  tinfl_status status;
-
-  if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
-  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
-  if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
-
-  pState = (inflate_state*)pStream->state;
-  if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
-  orig_avail_in = pStream->avail_in;
-
-  first_call = pState->m_first_call; pState->m_first_call = 0;
-  if (pState->m_last_status < 0) return MZ_DATA_ERROR;
-
-  if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
-  pState->m_has_flushed |= (flush == MZ_FINISH);
-
-  if ((flush == MZ_FINISH) && (first_call))
-  {
-    // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file.
-    decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
-    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
-    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
-    pState->m_last_status = status;
-    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
-    pStream->adler = tinfl_get_adler32(&pState->m_decomp);
-    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
-
-    if (status < 0)
-      return MZ_DATA_ERROR;
-    else if (status != TINFL_STATUS_DONE)
-    {
-      pState->m_last_status = TINFL_STATUS_FAILED;
-      return MZ_BUF_ERROR;
-    }
-    return MZ_STREAM_END;
-  }
-  // flush != MZ_FINISH then we must assume there's more input.
-  if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
-
-  if (pState->m_dict_avail)
-  {
-    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
-    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
-    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
-    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
-    return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
-  }
-
-  for ( ; ; )
-  {
-    in_bytes = pStream->avail_in;
-    out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
-
-    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
-    pState->m_last_status = status;
-
-    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
-    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
-
-    pState->m_dict_avail = (mz_uint)out_bytes;
-
-    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
-    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
-    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
-    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
-
-    if (status < 0)
-       return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
-    else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
-      return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH.
-    else if (flush == MZ_FINISH)
-    {
-       // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
-       if (status == TINFL_STATUS_DONE)
-          return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
-       // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong.
-       else if (!pStream->avail_out)
-          return MZ_BUF_ERROR;
-    }
-    else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
-      break;
-  }
-
-  return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
-}
-
-int mz_inflateEnd(mz_streamp pStream)
-{
-  if (!pStream)
-    return MZ_STREAM_ERROR;
-  if (pStream->state)
-  {
-    pStream->zfree(pStream->opaque, pStream->state);
-    pStream->state = NULL;
-  }
-  return MZ_OK;
-}
-
-int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
-{
-  mz_stream stream;
-  int status;
-  memset(&stream, 0, sizeof(stream));
-
-  // In case mz_ulong is 64-bits (argh I hate longs).
-  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
-
-  stream.next_in = pSource;
-  stream.avail_in = (mz_uint32)source_len;
-  stream.next_out = pDest;
-  stream.avail_out = (mz_uint32)*pDest_len;
-
-  status = mz_inflateInit(&stream);
-  if (status != MZ_OK)
-    return status;
-
-  status = mz_inflate(&stream, MZ_FINISH);
-  if (status != MZ_STREAM_END)
-  {
-    mz_inflateEnd(&stream);
-    return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
-  }
-  *pDest_len = stream.total_out;
-
-  return mz_inflateEnd(&stream);
-}
-
-const char *mz_error(int err)
-{
-  static struct { int m_err; const char *m_pDesc; } s_error_descs[] =
-  {
-    { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
-    { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
-  };
-  mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
-  return NULL;
-}
-
-#endif //MINIZ_NO_ZLIB_APIS
-
-// ------------------- Low-level Decompression (completely independent from all compression API's)
-
-#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
-#define TINFL_MEMSET(p, c, l) memset(p, c, l)
-
-#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
-#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
-#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
-#define TINFL_CR_FINISH }
-
-// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
-// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
-#define TINFL_GET_BYTE(state_index, c) do { \
-  if (pIn_buf_cur >= pIn_buf_end) { \
-    for ( ; ; ) { \
-      if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
-        TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
-        if (pIn_buf_cur < pIn_buf_end) { \
-          c = *pIn_buf_cur++; \
-          break; \
-        } \
-      } else { \
-        c = 0; \
-        break; \
-      } \
-    } \
-  } else c = *pIn_buf_cur++; } MZ_MACRO_END
-
-#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
-#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
-#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
-
-// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
-// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
-// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
-// bit buffer contains >=15 bits (deflate's max. Huffman code size).
-#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
-  do { \
-    temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
-    if (temp >= 0) { \
-      code_len = temp >> 9; \
-      if ((code_len) && (num_bits >= code_len)) \
-      break; \
-    } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
-       code_len = TINFL_FAST_LOOKUP_BITS; \
-       do { \
-          temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
-       } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
-    } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
-  } while (num_bits < 15);
-
-// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
-// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
-// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
-// The slow path is only executed at the very end of the input buffer.
-#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
-  int temp; mz_uint code_len, c; \
-  if (num_bits < 15) { \
-    if ((pIn_buf_end - pIn_buf_cur) < 2) { \
-       TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
-    } else { \
-       bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
-    } \
-  } \
-  if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
-    code_len = temp >> 9, temp &= 511; \
-  else { \
-    code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
-  } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
-
-tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
-{
-  static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
-  static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
-  static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
-  static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
-  static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
-  static const int s_min_table_sizes[3] = { 257, 1, 4 };
-
-  tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
-  const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
-  mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
-  size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
-
-  // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
-  if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
-
-  num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
-  TINFL_CR_BEGIN
-
-  bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
-  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
-  {
-    TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
-    counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
-    if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
-    if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
-  }
-
-  do
-  {
-    TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
-    if (r->m_type == 0)
-    {
-      TINFL_SKIP_BITS(5, num_bits & 7);
-      for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
-      if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
-      while ((counter) && (num_bits))
-      {
-        TINFL_GET_BITS(51, dist, 8);
-        while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
-        *pOut_buf_cur++ = (mz_uint8)dist;
-        counter--;
-      }
-      while (counter)
-      {
-        size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
-        while (pIn_buf_cur >= pIn_buf_end)
-        {
-          if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
-          {
-            TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
-          }
-          else
-          {
-            TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
-          }
-        }
-        n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
-        TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
-      }
-    }
-    else if (r->m_type == 3)
-    {
-      TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
-    }
-    else
-    {
-      if (r->m_type == 1)
-      {
-        mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
-        r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
-        for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
-      }
-      else
-      {
-        for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
-        MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
-        r->m_table_sizes[2] = 19;
-      }
-      for ( ; (int)r->m_type >= 0; r->m_type--)
-      {
-        int tree_next, tree_cur; tinfl_huff_table *pTable;
-        mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
-        for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
-        used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
-        for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
-        if ((65536 != total) && (used_syms > 1))
-        {
-          TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
-        }
-        for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
-        {
-          mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
-          cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
-          if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
-          if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
-          rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
-          for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
-          {
-            tree_cur -= ((rev_code >>= 1) & 1);
-            if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
-          }
-          tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
-        }
-        if (r->m_type == 2)
-        {
-          for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
-          {
-            mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
-            if ((dist == 16) && (!counter))
-            {
-              TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
-            }
-            num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
-            TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
-          }
-          if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
-          {
-            TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
-          }
-          TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
-        }
-      }
-      for ( ; ; )
-      {
-        mz_uint8 *pSrc;
-        for ( ; ; )
-        {
-          if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
-          {
-            TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
-            if (counter >= 256)
-              break;
-            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
-            *pOut_buf_cur++ = (mz_uint8)counter;
-          }
-          else
-          {
-            int sym2; mz_uint code_len;
-#if TINFL_USE_64BIT_BITBUF
-            if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
-#else
-            if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
-#endif
-            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
-              code_len = sym2 >> 9;
-            else
-            {
-              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
-            }
-            counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
-            if (counter & 256)
-              break;
-
-#if !TINFL_USE_64BIT_BITBUF
-            if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
-#endif
-            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
-              code_len = sym2 >> 9;
-            else
-            {
-              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
-            }
-            bit_buf >>= code_len; num_bits -= code_len;
-
-            pOut_buf_cur[0] = (mz_uint8)counter;
-            if (sym2 & 256)
-            {
-              pOut_buf_cur++;
-              counter = sym2;
-              break;
-            }
-            pOut_buf_cur[1] = (mz_uint8)sym2;
-            pOut_buf_cur += 2;
-          }
-        }
-        if ((counter &= 511) == 256) break;
-
-        num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
-        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
-
-        TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
-        num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
-        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
-
-        dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
-        if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
-        {
-          TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
-        }
-
-        pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
-
-        if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
-        {
-          while (counter--)
-          {
-            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
-            *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
-          }
-          continue;
-        }
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
-        else if ((counter >= 9) && (counter <= dist))
-        {
-          const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
-          do
-          {
-            ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
-            ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
-            pOut_buf_cur += 8;
-          } while ((pSrc += 8) < pSrc_end);
-          if ((counter &= 7) < 3)
-          {
-            if (counter)
-            {
-              pOut_buf_cur[0] = pSrc[0];
-              if (counter > 1)
-                pOut_buf_cur[1] = pSrc[1];
-              pOut_buf_cur += counter;
-            }
-            continue;
-          }
-        }
-#endif
-        do
-        {
-          pOut_buf_cur[0] = pSrc[0];
-          pOut_buf_cur[1] = pSrc[1];
-          pOut_buf_cur[2] = pSrc[2];
-          pOut_buf_cur += 3; pSrc += 3;
-        } while ((int)(counter -= 3) > 2);
-        if ((int)counter > 0)
-        {
-          pOut_buf_cur[0] = pSrc[0];
-          if ((int)counter > 1)
-            pOut_buf_cur[1] = pSrc[1];
-          pOut_buf_cur += counter;
-        }
-      }
-    }
-  } while (!(r->m_final & 1));
-  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
-  {
-    TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
-  }
-  TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
-  TINFL_CR_FINISH
-
-common_exit:
-  r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
-  *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
-  if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
-  {
-    const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
-    mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
-    while (buf_len)
-    {
-      for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
-      {
-        s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
-        s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
-      }
-      for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
-      s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
-    }
-    r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
-  }
-  return status;
-}
-
-// Higher level helper functions.
-void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
-{
-  tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
-  *pOut_len = 0;
-  tinfl_init(&decomp);
-  for ( ; ; )
-  {
-    size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
-    tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size,
-      (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
-    if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
-    {
-      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
-    }
-    src_buf_ofs += src_buf_size;
-    *pOut_len += dst_buf_size;
-    if (status == TINFL_STATUS_DONE) break;
-    new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
-    pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
-    if (!pNew_buf)
-    {
-      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
-    }
-    pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
-  }
-  return pBuf;
-}
-
-size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
-{
-  tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
-  status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
-  return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
-}
-
-int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
-{
-  int result = 0;
-  tinfl_decompressor decomp;
-  mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
-  if (!pDict)
-    return TINFL_STATUS_FAILED;
-  tinfl_init(&decomp);
-  for ( ; ; )
-  {
-    size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
-    tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
-      (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
-    in_buf_ofs += in_buf_size;
-    if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
-      break;
-    if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
-    {
-      result = (status == TINFL_STATUS_DONE);
-      break;
-    }
-    dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
-  }
-  MZ_FREE(pDict);
-  *pIn_buf_size = in_buf_ofs;
-  return result;
-}
-
-// ------------------- Low-level Compression (independent from all decompression API's)
-
-// Purposely making these tables static for faster init and thread safety.
-static const mz_uint16 s_tdefl_len_sym[256] = {
-  257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272,
-  273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276,
-  277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
-  279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
-  281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
-  282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,
-  283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,
-  284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 };
-
-static const mz_uint8 s_tdefl_len_extra[256] = {
-  0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
-  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 };
-
-static const mz_uint8 s_tdefl_small_dist_sym[512] = {
-  0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
-  11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,
-  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,
-  14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
-  14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
-  15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,
-  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 };
-
-static const mz_uint8 s_tdefl_small_dist_extra[512] = {
-  0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
-  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7 };
-
-static const mz_uint8 s_tdefl_large_dist_sym[128] = {
-  0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,
-  26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
-  28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 };
-
-static const mz_uint8 s_tdefl_large_dist_extra[128] = {
-  0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
-  12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
-  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 };
-
-// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
-typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
-static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
-{
-  mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist);
-  for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
-  while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
-  for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
-  {
-    const mz_uint32* pHist = &hist[pass << 8];
-    mz_uint offsets[256], cur_ofs = 0;
-    for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
-    for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
-    { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
-  }
-  return pCur_syms;
-}
-
-// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, [email protected], Jyrki Katajainen, [email protected], November 1996.
-static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
-{
-  int root, leaf, next, avbl, used, dpth;
-  if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
-  A[0].m_key += A[1].m_key; root = 0; leaf = 2;
-  for (next=1; next < n-1; next++)
-  {
-    if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
-    if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
-  }
-  A[n-2].m_key = 0; for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
-  avbl = 1; used = dpth = 0; root = n-2; next = n-1;
-  while (avbl>0)
-  {
-    while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
-    while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
-    avbl = 2*used; dpth++; used = 0;
-  }
-}
-
-// Limits canonical Huffman code table's max code size.
-enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
-static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
-{
-  int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
-  for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
-  for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
-  while (total != (1UL << max_code_size))
-  {
-    pNum_codes[max_code_size]--;
-    for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
-    total--;
-  }
-}
-
-static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
-{
-  int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes);
-  if (static_table)
-  {
-    for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
-  }
-  else
-  {
-    tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
-    int num_used_syms = 0;
-    const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
-    for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; }
-
-    pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
-
-    for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
-
-    tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
-
-    MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
-    for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
-      for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
-  }
-
-  next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
-
-  for (i = 0; i < table_len; i++)
-  {
-    mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
-    code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
-    d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
-  }
-}
-
-#define TDEFL_PUT_BITS(b, l) do { \
-  mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
-  d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
-  while (d->m_bits_in >= 8) { \
-    if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
-      *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
-      d->m_bit_buffer >>= 8; \
-      d->m_bits_in -= 8; \
-  } \
-} MZ_MACRO_END
-
-#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
-  if (rle_repeat_count < 3) { \
-    d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
-    while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
-  } else { \
-    d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
-} rle_repeat_count = 0; } }
-
-#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
-  if (rle_z_count < 3) { \
-    d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
-  } else if (rle_z_count <= 10) { \
-    d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
-  } else { \
-    d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
-} rle_z_count = 0; } }
-
-static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
-
-static void tdefl_start_dynamic_block(tdefl_compressor *d)
-{
-  int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
-  mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
-
-  d->m_huff_count[0][256] = 1;
-
-  tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
-  tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
-
-  for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
-  for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
-
-  memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
-  memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
-  total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;
-
-  memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
-  for (i = 0; i < total_code_sizes_to_pack; i++)
-  {
-    mz_uint8 code_size = code_sizes_to_pack[i];
-    if (!code_size)
-    {
-      TDEFL_RLE_PREV_CODE_SIZE();
-      if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
-    }
-    else
-    {
-      TDEFL_RLE_ZERO_CODE_SIZE();
-      if (code_size != prev_code_size)
-      {
-        TDEFL_RLE_PREV_CODE_SIZE();
-        d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size;
-      }
-      else if (++rle_repeat_count == 6)
-      {
-        TDEFL_RLE_PREV_CODE_SIZE();
-      }
-    }
-    prev_code_size = code_size;
-  }
-  if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
-
-  tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
-
-  TDEFL_PUT_BITS(2, 2);
-
-  TDEFL_PUT_BITS(num_lit_codes - 257, 5);
-  TDEFL_PUT_BITS(num_dist_codes - 1, 5);
-
-  for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break;
-  num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
-  for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
-
-  for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
-  {
-    mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
-    TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
-    if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
-  }
-}
-
-static void tdefl_start_static_block(tdefl_compressor *d)
-{
-  mz_uint i;
-  mz_uint8 *p = &d->m_huff_code_sizes[0][0];
-
-  for (i = 0; i <= 143; ++i) *p++ = 8;
-  for ( ; i <= 255; ++i) *p++ = 9;
-  for ( ; i <= 279; ++i) *p++ = 7;
-  for ( ; i <= 287; ++i) *p++ = 8;
-
-  memset(d->m_huff_code_sizes[1], 5, 32);
-
-  tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
-  tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
-
-  TDEFL_PUT_BITS(1, 2);
-}
-
-static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
-
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
-static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
-{
-  mz_uint flags;
-  mz_uint8 *pLZ_codes;
-  mz_uint8 *pOutput_buf = d->m_pOutput_buf;
-  mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
-  mz_uint64 bit_buffer = d->m_bit_buffer;
-  mz_uint bits_in = d->m_bits_in;
-
-#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }
-
-  flags = 1;
-  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
-  {
-    if (flags == 1)
-      flags = *pLZ_codes++ | 0x100;
-
-    if (flags & 1)
-    {
-      mz_uint s0, s1, n0, n1, sym, num_extra_bits;
-      mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;
-
-      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
-      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
-      TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
-
-      // This sequence coaxes MSVC into using cmov's vs. jmp's.
-      s0 = s_tdefl_small_dist_sym[match_dist & 511];
-      n0 = s_tdefl_small_dist_extra[match_dist & 511];
-      s1 = s_tdefl_large_dist_sym[match_dist >> 8];
-      n1 = s_tdefl_large_dist_extra[match_dist >> 8];
-      sym = (match_dist < 512) ? s0 : s1;
-      num_extra_bits = (match_dist < 512) ? n0 : n1;
-
-      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
-      TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
-      TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
-    }
-    else
-    {
-      mz_uint lit = *pLZ_codes++;
-      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
-      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
-
-      if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
-      {
-        flags >>= 1;
-        lit = *pLZ_codes++;
-        MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
-        TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
-
-        if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
-        {
-          flags >>= 1;
-          lit = *pLZ_codes++;
-          MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
-          TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
-        }
-      }
-    }
-
-    if (pOutput_buf >= d->m_pOutput_buf_end)
-      return MZ_FALSE;
-
-    *(mz_uint64*)pOutput_buf = bit_buffer;
-    pOutput_buf += (bits_in >> 3);
-    bit_buffer >>= (bits_in & ~7);
-    bits_in &= 7;
-  }
-
-#undef TDEFL_PUT_BITS_FAST
-
-  d->m_pOutput_buf = pOutput_buf;
-  d->m_bits_in = 0;
-  d->m_bit_buffer = 0;
-
-  while (bits_in)
-  {
-    mz_uint32 n = MZ_MIN(bits_in, 16);
-    TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
-    bit_buffer >>= n;
-    bits_in -= n;
-  }
-
-  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
-
-  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
-}
-#else
-static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
-{
-  mz_uint flags;
-  mz_uint8 *pLZ_codes;
-
-  flags = 1;
-  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
-  {
-    if (flags == 1)
-      flags = *pLZ_codes++ | 0x100;
-    if (flags & 1)
-    {
-      mz_uint sym, num_extra_bits;
-      mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
-
-      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
-      TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
-      TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
-
-      if (match_dist < 512)
-      {
-        sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
-      }
-      else
-      {
-        sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
-      }
-      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
-      TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
-      TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
-    }
-    else
-    {
-      mz_uint lit = *pLZ_codes++;
-      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
-      TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
-    }
-  }
-
-  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
-
-  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
-}
-#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
-
-static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
-{
-  if (static_block)
-    tdefl_start_static_block(d);
-  else
-    tdefl_start_dynamic_block(d);
-  return tdefl_compress_lz_codes(d);
-}
-
-static int tdefl_flush_block(tdefl_compressor *d, int flush)
-{
-  mz_uint saved_bit_buf, saved_bits_in;
-  mz_uint8 *pSaved_output_buf;
-  mz_bool comp_block_succeeded = MZ_FALSE;
-  int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
-  mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
-
-  d->m_pOutput_buf = pOutput_buf_start;
-  d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
-
-  MZ_ASSERT(!d->m_output_flush_remaining);
-  d->m_output_flush_ofs = 0;
-  d->m_output_flush_remaining = 0;
-
-  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
-  d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
-
-  if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
-  {
-    TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
-  }
-
-  TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
-
-  pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
-
-  if (!use_raw_block)
-    comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
-
-  // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
-  if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
-       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
-  {
-    mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
-    TDEFL_PUT_BITS(0, 2);
-    if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
-    for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
-    {
-      TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
-    }
-    for (i = 0; i < d->m_total_lz_bytes; ++i)
-    {
-      TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
-    }
-  }
-  // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
-  else if (!comp_block_succeeded)
-  {
-    d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
-    tdefl_compress_block(d, MZ_TRUE);
-  }
-
-  if (flush)
-  {
-    if (flush == TDEFL_FINISH)
-    {
-      if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
-      if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } }
-    }
-    else
-    {
-      mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); }
-    }
-  }
-
-  MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
-
-  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
-  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
-
-  d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++;
-
-  if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
-  {
-    if (d->m_pPut_buf_func)
-    {
-      *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
-      if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
-        return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
-    }
-    else if (pOutput_buf_start == d->m_output_buf)
-    {
-      int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
-      memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
-      d->m_out_buf_ofs += bytes_to_copy;
-      if ((n -= bytes_to_copy) != 0)
-      {
-        d->m_output_flush_ofs = bytes_to_copy;
-        d->m_output_flush_remaining = n;
-      }
-    }
-    else
-    {
-      d->m_out_buf_ofs += n;
-    }
-  }
-
-  return d->m_output_flush_remaining;
-}
-
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
-#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
-static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
-{
-  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
-  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
-  const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
-  mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
-  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
-  for ( ; ; )
-  {
-    for ( ; ; )
-    {
-      if (--num_probes_left == 0) return;
-      #define TDEFL_PROBE \
-        next_probe_pos = d->m_next[probe_pos]; \
-        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
-        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
-        if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
-      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
-    }
-    if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32;
-    do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
-                   (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
-    if (!probe_len)
-    {
-      *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
-    }
-    else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
-    {
-      *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
-      c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
-    }
-  }
-}
-#else
-static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
-{
-  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
-  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
-  const mz_uint8 *s = d->m_dict + pos, *p, *q;
-  mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
-  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
-  for ( ; ; )
-  {
-    for ( ; ; )
-    {
-      if (--num_probes_left == 0) return;
-      #define TDEFL_PROBE \
-        next_probe_pos = d->m_next[probe_pos]; \
-        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
-        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
-        if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
-      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
-    }
-    if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
-    if (probe_len > match_len)
-    {
-      *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
-      c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
-    }
-  }
-}
-#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
-
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
-static mz_bool tdefl_compress_fast(tdefl_compressor *d)
-{
-  // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio.
-  mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
-  mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
-  mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
-
-  while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
-  {
-    const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
-    mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
-    mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
-    d->m_src_buf_left -= num_bytes_to_process;
-    lookahead_size += num_bytes_to_process;
-
-    while (num_bytes_to_process)
-    {
-      mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
-      memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
-      if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
-        memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
-      d->m_pSrc += n;
-      dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
-      num_bytes_to_process -= n;
-    }
-
-    dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
-    if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;
-
-    while (lookahead_size >= 4)
-    {
-      mz_uint cur_match_dist, cur_match_len = 1;
-      mz_uint8 *pCur_dict = d->m_dict + cur_pos;
-      mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
-      mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
-      mz_uint probe_pos = d->m_hash[hash];
-      d->m_hash[hash] = (mz_uint16)lookahead_pos;
-
-      if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
-      {
-        const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
-        const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
-        mz_uint32 probe_len = 32;
-        do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
-          (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
-        cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
-        if (!probe_len)
-          cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
-
-        if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
-        {
-          cur_match_len = 1;
-          *pLZ_code_buf++ = (mz_uint8)first_trigram;
-          *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
-          d->m_huff_count[0][(mz_uint8)first_trigram]++;
-        }
-        else
-        {
-          mz_uint32 s0, s1;
-          cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
-
-          MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
-
-          cur_match_dist--;
-
-          pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
-          *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
-          pLZ_code_buf += 3;
-          *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
-
-          s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
-          s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
-          d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
-
-          d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
-        }
-      }
-      else
-      {
-        *pLZ_code_buf++ = (mz_uint8)first_trigram;
-        *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
-        d->m_huff_count[0][(mz_uint8)first_trigram]++;
-      }
-
-      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
-
-      total_lz_bytes += cur_match_len;
-      lookahead_pos += cur_match_len;
-      dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
-      cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
-      MZ_ASSERT(lookahead_size >= cur_match_len);
-      lookahead_size -= cur_match_len;
-
-      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
-      {
-        int n;
-        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
-        d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
-        if ((n = tdefl_flush_block(d, 0)) != 0)
-          return (n < 0) ? MZ_FALSE : MZ_TRUE;
-        total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
-      }
-    }
-
-    while (lookahead_size)
-    {
-      mz_uint8 lit = d->m_dict[cur_pos];
-
-      total_lz_bytes++;
-      *pLZ_code_buf++ = lit;
-      *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
-      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
-
-      d->m_huff_count[0][lit]++;
-
-      lookahead_pos++;
-      dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
-      cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
-      lookahead_size--;
-
-      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
-      {
-        int n;
-        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
-        d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
-        if ((n = tdefl_flush_block(d, 0)) != 0)
-          return (n < 0) ? MZ_FALSE : MZ_TRUE;
-        total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
-      }
-    }
-  }
-
-  d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
-  d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
-  return MZ_TRUE;
-}
-#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
-
-static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
-{
-  d->m_total_lz_bytes++;
-  *d->m_pLZ_code_buf++ = lit;
-  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
-  d->m_huff_count[0][lit]++;
-}
-
-static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
-{
-  mz_uint32 s0, s1;
-
-  MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
-
-  d->m_total_lz_bytes += match_len;
-
-  d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
-
-  match_dist -= 1;
-  d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
-  d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
-
-  *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
-
-  s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
-  d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
-
-  if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
-}
-
-static mz_bool tdefl_compress_normal(tdefl_compressor *d)
-{
-  const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
-  tdefl_flush flush = d->m_flush;
-
-  while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
-  {
-    mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
-    // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
-    if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
-    {
-      mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
-      mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
-      mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
-      const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
-      src_buf_left -= num_bytes_to_process;
-      d->m_lookahead_size += num_bytes_to_process;
-      while (pSrc != pSrc_end)
-      {
-        mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
-        hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
-        d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
-        dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
-      }
-    }
-    else
-    {
-      while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
-      {
-        mz_uint8 c = *pSrc++;
-        mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
-        src_buf_left--;
-        d->m_dict[dst_pos] = c;
-        if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
-          d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
-        if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
-        {
-          mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
-          mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
-          d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
-        }
-      }
-    }
-    d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
-    if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
-      break;
-
-    // Simple lazy/greedy parsing state machine.
-    len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
-    if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
-    {
-      if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
-      {
-        mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
-        cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; }
-        if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
-      }
-    }
-    else
-    {
-      tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
-    }
-    if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
-    {
-      cur_match_dist = cur_match_len = 0;
-    }
-    if (d->m_saved_match_len)
-    {
-      if (cur_match_len > d->m_saved_match_len)
-      {
-        tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
-        if (cur_match_len >= 128)
-        {
-          tdefl_record_match(d, cur_match_len, cur_match_dist);
-          d->m_saved_match_len = 0; len_to_move = cur_match_len;
-        }
-        else
-        {
-          d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
-        }
-      }
-      else
-      {
-        tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
-        len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
-      }
-    }
-    else if (!cur_match_dist)
-      tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
-    else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
-    {
-      tdefl_record_match(d, cur_match_len, cur_match_dist);
-      len_to_move = cur_match_len;
-    }
-    else
-    {
-      d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
-    }
-    // Move the lookahead forward by len_to_move bytes.
-    d->m_lookahead_pos += len_to_move;
-    MZ_ASSERT(d->m_lookahead_size >= len_to_move);
-    d->m_lookahead_size -= len_to_move;
-    d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
-    // Check if it's time to flush the current LZ codes to the internal output buffer.
-    if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
-         ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) )
-    {
-      int n;
-      d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
-      if ((n = tdefl_flush_block(d, 0)) != 0)
-        return (n < 0) ? MZ_FALSE : MZ_TRUE;
-    }
-  }
-
-  d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
-  return MZ_TRUE;
-}
-
-static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
-{
-  if (d->m_pIn_buf_size)
-  {
-    *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
-  }
-
-  if (d->m_pOut_buf_size)
-  {
-    size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
-    memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
-    d->m_output_flush_ofs += (mz_uint)n;
-    d->m_output_flush_remaining -= (mz_uint)n;
-    d->m_out_buf_ofs += n;
-
-    *d->m_pOut_buf_size = d->m_out_buf_ofs;
-  }
-
-  return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
-}
-
-tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
-{
-  if (!d)
-  {
-    if (pIn_buf_size) *pIn_buf_size = 0;
-    if (pOut_buf_size) *pOut_buf_size = 0;
-    return TDEFL_STATUS_BAD_PARAM;
-  }
-
-  d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size;
-  d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size;
-  d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
-  d->m_out_buf_ofs = 0;
-  d->m_flush = flush;
-
-  if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
-        (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) )
-  {
-    if (pIn_buf_size) *pIn_buf_size = 0;
-    if (pOut_buf_size) *pOut_buf_size = 0;
-    return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
-  }
-  d->m_wants_to_finish |= (flush == TDEFL_FINISH);
-
-  if ((d->m_output_flush_remaining) || (d->m_finished))
-    return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
-
-#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
-  if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
-      ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
-      ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
-  {
-    if (!tdefl_compress_fast(d))
-      return d->m_prev_return_status;
-  }
-  else
-#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
-  {
-    if (!tdefl_compress_normal(d))
-      return d->m_prev_return_status;
-  }
-
-  if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
-    d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
-
-  if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
-  {
-    if (tdefl_flush_block(d, flush) < 0)
-      return d->m_prev_return_status;
-    d->m_finished = (flush == TDEFL_FINISH);
-    if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; }
-  }
-
-  return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
-}
-
-tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
-{
-  MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
-}
-
-tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
-{
-  d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user;
-  d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
-  d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
-  if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
-  d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
-  d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
-  d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
-  d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
-  d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
-  d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
-  d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
-  d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
-  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
-  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
-  return TDEFL_STATUS_OKAY;
-}
-
-tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
-{
-  return d->m_prev_return_status;
-}
-
-mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
-{
-  return d->m_adler32;
-}
-
-mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
-{
-  tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
-  pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
-  succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
-  succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
-  MZ_FREE(pComp); return succeeded;
-}
-
-typedef struct
-{
-  size_t m_size, m_capacity;
-  mz_uint8 *m_pBuf;
-  mz_bool m_expandable;
-} tdefl_output_buffer;
-
-static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
-{
-  tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
-  size_t new_size = p->m_size + len;
-  if (new_size > p->m_capacity)
-  {
-    size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE;
-    do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity);
-    pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE;
-    p->m_pBuf = pNew_buf; p->m_capacity = new_capacity;
-  }
-  memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size;
-  return MZ_TRUE;
-}
-
-void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
-{
-  tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
-  if (!pOut_len) return MZ_FALSE; else *pOut_len = 0;
-  out_buf.m_expandable = MZ_TRUE;
-  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL;
-  *pOut_len = out_buf.m_size; return out_buf.m_pBuf;
-}
-
-size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
-{
-  tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
-  if (!pOut_buf) return 0;
-  out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len;
-  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0;
-  return out_buf.m_size;
-}
-
-#ifndef MINIZ_NO_ZLIB_APIS
-static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 };
-
-// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files).
-mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
-{
-  mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
-  if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
-
-  if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
-  else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES;
-  else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK;
-  else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
-  else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES;
-
-  return comp_flags;
-}
-#endif //MINIZ_NO_ZLIB_APIS
-
-#ifdef _MSC_VER
-#pragma warning (push)
-#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal)
-#endif
-
-// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
-// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
-void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
-{
-  tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0;
-  if (!pComp) return NULL;
-  MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
-  // write dummy header
-  for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
-  // compress image data
-  tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, TDEFL_DEFAULT_MAX_PROBES | TDEFL_WRITE_ZLIB_HEADER);
-  for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + y * bpl, bpl, TDEFL_NO_FLUSH); }
-  if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
-  // write real header
-  *pLen_out = out_buf.m_size-41;
-  {
-    mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
-      0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,"\0\0\04\02\06"[num_chans],0,0,0,0,0,0,0,
-      (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54};
-    c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24);
-    memcpy(out_buf.m_pBuf, pnghdr, 41);
-  }
-  // write footer (IDAT CRC-32, followed by IEND chunk)
-  if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
-  c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24);
-  // compute final size of file, grab compressed data buffer and return
-  *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf;
-}
-
-#ifdef _MSC_VER
-#pragma warning (pop)
-#endif
-
-// ------------------- .ZIP archive reading
-
-#ifndef MINIZ_NO_ARCHIVE_APIS
-
-#ifdef MINIZ_NO_STDIO
-  #define MZ_FILE void *
-#else
-  #include <stdio.h>
-  #include <sys/stat.h>
-
-  #if defined(_MSC_VER)
-    static FILE *mz_fopen(const char *pFilename, const char *pMode)
-    {
-      FILE* pFile = NULL;
-      fopen_s(&pFile, pFilename, pMode);
-      return pFile;
-    }
-    static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
-    {
-      FILE* pFile = NULL;
-      if (freopen_s(&pFile, pPath, pMode, pStream))
-        return NULL;
-      return pFile;
-    }
-  #else
-    static FILE *mz_fopen(const char *pFilename, const char *pMode)
-    {
-      return fopen(pFilename, pMode);
-    }
-    static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
-    {
-      return freopen(pPath, pMode, pStream);
-    }
-  #endif // #if defined(_MSC_VER)
-
-  #if defined(_MSC_VER) || defined(__MINGW64__)
-    #ifndef MINIZ_NO_TIME
-      #include <sys/utime.h>
-    #endif
-    #define MZ_FILE FILE
-    #define MZ_FOPEN mz_fopen
-    #define MZ_FCLOSE fclose
-    #define MZ_FREAD fread
-    #define MZ_FWRITE fwrite
-    #define MZ_FTELL64 _ftelli64
-    #define MZ_FSEEK64 _fseeki64
-    #define MZ_FILE_STAT_STRUCT _stat
-    #define MZ_FILE_STAT _stat
-    #define MZ_FFLUSH fflush
-    #define MZ_FREOPEN mz_freopen
-    #define MZ_DELETE_FILE remove
-  #elif defined(__MINGW32__)
-    #ifndef MINIZ_NO_TIME
-      #include <sys/utime.h>
-    #endif
-    #define MZ_FILE FILE
-    #define MZ_FOPEN mz_fopen
-    #define MZ_FCLOSE fclose
-    #define MZ_FREAD fread
-    #define MZ_FWRITE fwrite
-    #define MZ_FTELL64 ftello64
-    #define MZ_FSEEK64 fseeko64
-    #define MZ_FILE_STAT_STRUCT _stat
-    #define MZ_FILE_STAT _stat
-    #define MZ_FFLUSH fflush
-    #define MZ_FREOPEN mz_freopen
-    #define MZ_DELETE_FILE remove
-  #elif defined(__TINYC__)
-    #ifndef MINIZ_NO_TIME
-      #include <sys\utime.h>
-    #endif
-    #define MZ_FILE FILE
-    #define MZ_FOPEN mz_fopen
-    #define MZ_FCLOSE fclose
-    #define MZ_FREAD fread
-    #define MZ_FWRITE fwrite
-    #define MZ_FTELL64 ftell
-    #define MZ_FSEEK64 fseek
-    #define MZ_FILE_STAT_STRUCT stat
-    #define MZ_FILE_STAT stat
-    #define MZ_FFLUSH fflush
-    #define MZ_FREOPEN mz_freopen
-    #define MZ_DELETE_FILE remove
-  #else
-    #ifndef MINIZ_NO_TIME
-      #include <utime.h>
-    #endif
-    #define MZ_FILE FILE
-    #define MZ_FOPEN mz_fopen
-    #define MZ_FCLOSE fclose
-    #define MZ_FREAD fread
-    #define MZ_FWRITE fwrite
-    #define MZ_FTELL64 ftello
-    #define MZ_FSEEK64 fseeko
-    #define MZ_FILE_STAT_STRUCT stat
-    #define MZ_FILE_STAT stat
-    #define MZ_FFLUSH fflush
-    #define MZ_FREOPEN mz_freopen
-    #define MZ_DELETE_FILE remove
-  #endif // #ifdef _MSC_VER
-#endif // #ifdef MINIZ_NO_STDIO
-
-#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
-
-// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff.
-enum
-{
-  // ZIP archive identifiers and record sizes
-  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
-  MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
-  // Central directory header record offsets
-  MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
-  MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16,
-  MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
-  MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
-  // Local directory header offsets
-  MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10,
-  MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
-  MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
-  // End of central directory offsets
-  MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
-  MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
-};
-
-typedef struct
-{
-  void *m_p;
-  size_t m_size, m_capacity;
-  mz_uint m_element_size;
-} mz_zip_array;
-
-struct mz_zip_internal_state_tag
-{
-  mz_zip_array m_central_dir;
-  mz_zip_array m_central_dir_offsets;
-  mz_zip_array m_sorted_central_dir_offsets;
-  MZ_FILE *m_pFile;
-  void *m_pMem;
-  size_t m_mem_size;
-  size_t m_mem_capacity;
-};
-
-#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
-#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
-
-static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
-{
-  pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
-  memset(pArray, 0, sizeof(mz_zip_array));
-}
-
-static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
-{
-  void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
-  if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; }
-  if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE;
-  pArray->m_p = pNew_p; pArray->m_capacity = new_capacity;
-  return MZ_TRUE;
-}
-
-static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
-{
-  if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; }
-  return MZ_TRUE;
-}
-
-static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
-{
-  if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; }
-  pArray->m_size = new_size;
-  return MZ_TRUE;
-}
-
-static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
-{
-  return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
-}
-
-static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
-{
-  size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE;
-  memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
-  return MZ_TRUE;
-}
-
-#ifndef MINIZ_NO_TIME
-static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date)
-{
-  struct tm tm;
-  memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1;
-  tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31;
-  tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62;
-  return mktime(&tm);
-}
-
-static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
-{
-#ifdef _MSC_VER
-  struct tm tm_struct;
-  struct tm *tm = &tm_struct;
-  errno_t err = localtime_s(tm, &time);
-  if (err)
-  {
-    *pDOS_date = 0; *pDOS_time = 0;
-    return;
-  }
-#else
-  struct tm *tm = localtime(&time);
-#endif
-  *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
-  *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
-}
-#endif
-
-#ifndef MINIZ_NO_STDIO
-static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
-{
-#ifdef MINIZ_NO_TIME
-  (void)pFilename; *pDOS_date = *pDOS_time = 0;
-#else
-  struct MZ_FILE_STAT_STRUCT file_stat; if (MZ_FILE_STAT(pFilename, &file_stat) != 0) return MZ_FALSE;
-  mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
-#endif // #ifdef MINIZ_NO_TIME
-  return MZ_TRUE;
-}
-
-static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time)
-{
-#ifndef MINIZ_NO_TIME
-  struct utimbuf t; t.actime = access_time; t.modtime = modified_time;
-  return !utime(pFilename, &t);
-#else
-  (void)pFilename, (void)access_time, (void)modified_time;
-  return MZ_TRUE;
-#endif // #ifndef MINIZ_NO_TIME
-}
-#endif
-
-static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags)
-{
-  (void)flags;
-  if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
-    return MZ_FALSE;
-
-  if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
-  if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
-  if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
-
-  pZip->m_zip_mode = MZ_ZIP_MODE_READING;
-  pZip->m_archive_size = 0;
-  pZip->m_central_directory_file_ofs = 0;
-  pZip->m_total_files = 0;
-
-  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
-    return MZ_FALSE;
-  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
-  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
-  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
-  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
-  return MZ_TRUE;
-}
-
-static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
-{
-  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
-  const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
-  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
-  mz_uint8 l = 0, r = 0;
-  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
-  pE = pL + MZ_MIN(l_len, r_len);
-  while (pL < pE)
-  {
-    if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
-      break;
-    pL++; pR++;
-  }
-  return (pL == pE) ? (l_len < r_len) : (l < r);
-}
-
-#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END
-
-// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.)
-static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
-{
-  mz_zip_internal_state *pState = pZip->m_pState;
-  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
-  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
-  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
-  const int size = pZip->m_total_files;
-  int start = (size - 2) >> 1, end;
-  while (start >= 0)
-  {
-    int child, root = start;
-    for ( ; ; )
-    {
-      if ((child = (root << 1) + 1) >= size)
-        break;
-      child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])));
-      if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
-        break;
-      MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
-    }
-    start--;
-  }
-
-  end = size - 1;
-  while (end > 0)
-  {
-    int child, root = 0;
-    MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
-    for ( ; ; )
-    {
-      if ((child = (root << 1) + 1) >= end)
-        break;
-      child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]));
-      if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
-        break;
-      MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
-    }
-    end--;
-  }
-}
-
-static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags)
-{
-  mz_uint cdir_size, num_this_disk, cdir_disk_index;
-  mz_uint64 cdir_ofs;
-  mz_int64 cur_file_ofs;
-  const mz_uint8 *p;
-  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
-  // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there.
-  if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
-    return MZ_FALSE;
-  // Find the end of central directory record by scanning the file from the end towards the beginning.
-  cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
-  for ( ; ; )
-  {
-    int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
-    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
-      return MZ_FALSE;
-    for (i = n - 4; i >= 0; --i)
-      if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
-        break;
-    if (i >= 0)
-    {
-      cur_file_ofs += i;
-      break;
-    }
-    if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
-      return MZ_FALSE;
-    cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
-  }
-  // Read and verify the end of central directory record.
-  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
-    return MZ_FALSE;
-  if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
-      ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
-    return MZ_FALSE;
-
-  num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
-  cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
-  if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
-    return MZ_FALSE;
-
-  if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
-    return MZ_FALSE;
-
-  cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
-  if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
-    return MZ_FALSE;
-
-  pZip->m_central_directory_file_ofs = cdir_ofs;
-
-  if (pZip->m_total_files)
-  {
-     mz_uint i, n;
-    // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices.
-    if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
-        (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) ||
-        (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
-      return MZ_FALSE;
-    if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
-      return MZ_FALSE;
-
-    // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported).
-    p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
-    for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
-    {
-      mz_uint total_header_size, comp_size, decomp_size, disk_index;
-      if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
-        return MZ_FALSE;
-      MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
-      MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
-      comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
-      decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
-      if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF))
-        return MZ_FALSE;
-      disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
-      if ((disk_index != num_this_disk) && (disk_index != 1))
-        return MZ_FALSE;
-      if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
-        return MZ_FALSE;
-      if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
-        return MZ_FALSE;
-      n -= total_header_size; p += total_header_size;
-    }
-  }
-
-  if ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0)
-    mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
-
-  return MZ_TRUE;
-}
-
-mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags)
-{
-  if ((!pZip) || (!pZip->m_pRead))
-    return MZ_FALSE;
-  if (!mz_zip_reader_init_internal(pZip, flags))
-    return MZ_FALSE;
-  pZip->m_archive_size = size;
-  if (!mz_zip_reader_read_central_dir(pZip, flags))
-  {
-    mz_zip_reader_end(pZip);
-    return MZ_FALSE;
-  }
-  return MZ_TRUE;
-}
-
-static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
-{
-  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
-  size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
-  memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
-  return s;
-}
-
-mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags)
-{
-  if (!mz_zip_reader_init_internal(pZip, flags))
-    return MZ_FALSE;
-  pZip->m_archive_size = size;
-  pZip->m_pRead = mz_zip_mem_read_func;
-  pZip->m_pIO_opaque = pZip;
-  pZip->m_pState->m_pMem = (void *)pMem;
-  pZip->m_pState->m_mem_size = size;
-  if (!mz_zip_reader_read_central_dir(pZip, flags))
-  {
-    mz_zip_reader_end(pZip);
-    return MZ_FALSE;
-  }
-  return MZ_TRUE;
-}
-
-#ifndef MINIZ_NO_STDIO
-static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
-{
-  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
-  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
-  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
-    return 0;
-  return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
-}
-
-mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
-{
-  mz_uint64 file_size;
-  MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
-  if (!pFile)
-    return MZ_FALSE;
-  if (MZ_FSEEK64(pFile, 0, SEEK_END))
-    return MZ_FALSE;
-  file_size = MZ_FTELL64(pFile);
-  if (!mz_zip_reader_init_internal(pZip, flags))
-  {
-    MZ_FCLOSE(pFile);
-    return MZ_FALSE;
-  }
-  pZip->m_pRead = mz_zip_file_read_func;
-  pZip->m_pIO_opaque = pZip;
-  pZip->m_pState->m_pFile = pFile;
-  pZip->m_archive_size = file_size;
-  if (!mz_zip_reader_read_central_dir(pZip, flags))
-  {
-    mz_zip_reader_end(pZip);
-    return MZ_FALSE;
-  }
-  return MZ_TRUE;
-}
-#endif // #ifndef MINIZ_NO_STDIO
-
-mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
-{
-  return pZip ? pZip->m_total_files : 0;
-}
-
-static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
-{
-  if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
-    return NULL;
-  return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
-}
-
-mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
-{
-  mz_uint m_bit_flag;
-  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
-  if (!p)
-    return MZ_FALSE;
-  m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
-  return (m_bit_flag & 1);
-}
-
-mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
-{
-  mz_uint filename_len, internal_attr, external_attr;
-  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
-  if (!p)
-    return MZ_FALSE;
-
-  internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
-  external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
-  if ((!internal_attr) && ((external_attr & 0x10) != 0))
-    return MZ_TRUE;
-
-  filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
-  if (filename_len)
-  {
-    if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
-      return MZ_TRUE;
-  }
-
-  return MZ_FALSE;
-}
-
-mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
-{
-  mz_uint n;
-  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
-  if ((!p) || (!pStat))
-    return MZ_FALSE;
-
-  // Unpack the central directory record.
-  pStat->m_file_index = file_index;
-  pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
-  pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
-  pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
-  pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
-  pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
-#ifndef MINIZ_NO_TIME
-  pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
-#endif
-  pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
-  pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
-  pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
-  pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
-  pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
-  pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
-
-  // Copy as much of the filename and comment as possible.
-  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
-  memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0';
-
-  n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
-  pStat->m_comment_size = n;
-  memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0';
-
-  return MZ_TRUE;
-}
-
-mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
-{
-  mz_uint n;
-  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
-  if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; }
-  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
-  if (filename_buf_size)
-  {
-    n = MZ_MIN(n, filename_buf_size - 1);
-    memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
-    pFilename[n] = '\0';
-  }
-  return n + 1;
-}
-
-static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
-{
-  mz_uint i;
-  if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
-    return 0 == memcmp(pA, pB, len);
-  for (i = 0; i < len; ++i)
-    if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
-      return MZ_FALSE;
-  return MZ_TRUE;
-}
-
-static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
-{
-  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
-  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
-  mz_uint8 l = 0, r = 0;
-  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
-  pE = pL + MZ_MIN(l_len, r_len);
-  while (pL < pE)
-  {
-    if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
-      break;
-    pL++; pR++;
-  }
-  return (pL == pE) ? (int)(l_len - r_len) : (l - r);
-}
-
-static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename)
-{
-  mz_zip_internal_state *pState = pZip->m_pState;
-  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
-  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
-  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
-  const int size = pZip->m_total_files;
-  const mz_uint filename_len = (mz_uint)strlen(pFilename);
-  int l = 0, h = size - 1;
-  while (l <= h)
-  {
-    int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
-    if (!comp)
-      return file_index;
-    else if (comp < 0)
-      l = m + 1;
-    else
-      h = m - 1;
-  }
-  return -1;
-}
-
-int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
-{
-  mz_uint file_index; size_t name_len, comment_len;
-  if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
-    return -1;
-  if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_p))
-    return mz_zip_reader_locate_file_binary_search(pZip, pName);
-  name_len = strlen(pName); if (name_len > 0xFFFF) return -1;
-  comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1;
-  for (file_index = 0; file_index < pZip->m_total_files; file_index++)
-  {
-    const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
-    mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
-    const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
-    if (filename_len < name_len)
-      continue;
-    if (comment_len)
-    {
-      mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
-      const char *pFile_comment = pFilename + filename_len + file_extra_len;
-      if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags)))
-        continue;
-    }
-    if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
-    {
-      int ofs = filename_len - 1;
-      do
-      {
-        if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
-          break;
-      } while (--ofs >= 0);
-      ofs++;
-      pFilename += ofs; filename_len -= ofs;
-    }
-    if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
-      return file_index;
-  }
-  return -1;
-}
-
-mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
-{
-  int status = TINFL_STATUS_DONE;
-  mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
-  mz_zip_archive_file_stat file_stat;
-  void *pRead_buf;
-  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
-  tinfl_decompressor inflator;
-
-  if ((buf_size) && (!pBuf))
-    return MZ_FALSE;
-
-  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
-    return MZ_FALSE;
-
-  if (!file_stat.m_comp_size)
-    return MZ_TRUE;
-
-  // Encryption and patch files are not supported.
-  if (file_stat.m_bit_flag & (1 | 32))
-    return MZ_FALSE;
-
-  // This function only supports stored and deflate.
-  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
-    return MZ_FALSE;
-
-  // Ensure supplied output buffer is large enough.
-  needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
-  if (buf_size < needed_size)
-    return MZ_FALSE;
-
-  // Read and parse the local directory entry.
-  cur_file_ofs = file_stat.m_local_header_ofs;
-  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
-    return MZ_FALSE;
-  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
-    return MZ_FALSE;
-
-  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
-  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
-    return MZ_FALSE;
-
-  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
-  {
-    // The file is stored or the caller has requested the compressed data.
-    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
-      return MZ_FALSE;
-    return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
-  }
-
-  // Decompress the file either directly from memory or from a file input buffer.
-  tinfl_init(&inflator);
-
-  if (pZip->m_pState->m_pMem)
-  {
-    // Read directly from the archive in memory.
-    pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
-    read_buf_size = read_buf_avail = file_stat.m_comp_size;
-    comp_remaining = 0;
-  }
-  else if (pUser_read_buf)
-  {
-    // Use a user provided read buffer.
-    if (!user_read_buf_size)
-      return MZ_FALSE;
-    pRead_buf = (mz_uint8 *)pUser_read_buf;
-    read_buf_size = user_read_buf_size;
-    read_buf_avail = 0;
-    comp_remaining = file_stat.m_uncomp_size;
-  }
-  else
-  {
-    // Temporarily allocate a read buffer.
-    read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
-#ifdef _MSC_VER
-    if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
-#else
-    if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
-#endif
-      return MZ_FALSE;
-    if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
-      return MZ_FALSE;
-    read_buf_avail = 0;
-    comp_remaining = file_stat.m_comp_size;
-  }
-
-  do
-  {
-    size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
-    if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
-    {
-      read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
-      if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
-      {
-        status = TINFL_STATUS_FAILED;
-        break;
-      }
-      cur_file_ofs += read_buf_avail;
-      comp_remaining -= read_buf_avail;
-      read_buf_ofs = 0;
-    }
-    in_buf_size = (size_t)read_buf_avail;
-    status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
-    read_buf_avail -= in_buf_size;
-    read_buf_ofs += in_buf_size;
-    out_buf_ofs += out_buf_size;
-  } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
-
-  if (status == TINFL_STATUS_DONE)
-  {
-    // Make sure the entire file was decompressed, and check its CRC.
-    if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
-      status = TINFL_STATUS_FAILED;
-  }
-
-  if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
-
-  return status == TINFL_STATUS_DONE;
-}
-
-mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
-{
-  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
-  if (file_index < 0)
-    return MZ_FALSE;
-  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
-}
-
-mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
-{
-  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
-}
-
-mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
-{
-  return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
-}
-
-void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
-{
-  mz_uint64 comp_size, uncomp_size, alloc_size;
-  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
-  void *pBuf;
-
-  if (pSize)
-    *pSize = 0;
-  if (!p)
-    return NULL;
-
-  comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
-  uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
-
-  alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
-#ifdef _MSC_VER
-  if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
-#else
-  if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
-#endif
-    return NULL;
-  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
-    return NULL;
-
-  if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
-  {
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
-    return NULL;
-  }
-
-  if (pSize) *pSize = (size_t)alloc_size;
-  return pBuf;
-}
-
-void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
-{
-  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
-  if (file_index < 0)
-  {
-    if (pSize) *pSize = 0;
-    return MZ_FALSE;
-  }
-  return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
-}
-
-mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
-{
-  int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT;
-  mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
-  mz_zip_archive_file_stat file_stat;
-  void *pRead_buf = NULL; void *pWrite_buf = NULL;
-  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
-
-  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
-    return MZ_FALSE;
-
-  if (!file_stat.m_comp_size)
-    return MZ_TRUE;
-
-  // Encryption and patch files are not supported.
-  if (file_stat.m_bit_flag & (1 | 32))
-    return MZ_FALSE;
-
-  // This function only supports stored and deflate.
-  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
-    return MZ_FALSE;
-
-  // Read and parse the local directory entry.
-  cur_file_ofs = file_stat.m_local_header_ofs;
-  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
-    return MZ_FALSE;
-  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
-    return MZ_FALSE;
-
-  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
-  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
-    return MZ_FALSE;
-
-  // Decompress the file either directly from memory or from a file input buffer.
-  if (pZip->m_pState->m_pMem)
-  {
-    pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
-    read_buf_size = read_buf_avail = file_stat.m_comp_size;
-    comp_remaining = 0;
-  }
-  else
-  {
-    read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
-    if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
-      return MZ_FALSE;
-    read_buf_avail = 0;
-    comp_remaining = file_stat.m_comp_size;
-  }
-
-  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
-  {
-    // The file is stored or the caller has requested the compressed data.
-    if (pZip->m_pState->m_pMem)
-    {
-#ifdef _MSC_VER
-      if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
-#else
-      if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
-#endif
-        return MZ_FALSE;
-      if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
-        status = TINFL_STATUS_FAILED;
-      else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
-        file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
-      cur_file_ofs += file_stat.m_comp_size;
-      out_buf_ofs += file_stat.m_comp_size;
-      comp_remaining = 0;
-    }
-    else
-    {
-      while (comp_remaining)
-      {
-        read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
-        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
-        {
-          status = TINFL_STATUS_FAILED;
-          break;
-        }
-
-        if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
-          file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
-
-        if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
-        {
-          status = TINFL_STATUS_FAILED;
-          break;
-        }
-        cur_file_ofs += read_buf_avail;
-        out_buf_ofs += read_buf_avail;
-        comp_remaining -= read_buf_avail;
-      }
-    }
-  }
-  else
-  {
-    tinfl_decompressor inflator;
-    tinfl_init(&inflator);
-
-    if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
-      status = TINFL_STATUS_FAILED;
-    else
-    {
-      do
-      {
-        mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
-        size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
-        if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
-        {
-          read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
-          if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
-          {
-            status = TINFL_STATUS_FAILED;
-            break;
-          }
-          cur_file_ofs += read_buf_avail;
-          comp_remaining -= read_buf_avail;
-          read_buf_ofs = 0;
-        }
-
-        in_buf_size = (size_t)read_buf_avail;
-        status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
-        read_buf_avail -= in_buf_size;
-        read_buf_ofs += in_buf_size;
-
-        if (out_buf_size)
-        {
-          if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
-          {
-            status = TINFL_STATUS_FAILED;
-            break;
-          }
-          file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
-          if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
-          {
-            status = TINFL_STATUS_FAILED;
-            break;
-          }
-        }
-      } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
-    }
-  }
-
-  if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
-  {
-    // Make sure the entire file was decompressed, and check its CRC.
-    if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32))
-      status = TINFL_STATUS_FAILED;
-  }
-
-  if (!pZip->m_pState->m_pMem)
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
-  if (pWrite_buf)
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
-
-  return status == TINFL_STATUS_DONE;
-}
-
-mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
-{
-  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
-  if (file_index < 0)
-    return MZ_FALSE;
-  return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
-}
-
-#ifndef MINIZ_NO_STDIO
-static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
-{
-  (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque);
-}
-
-mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
-{
-  mz_bool status;
-  mz_zip_archive_file_stat file_stat;
-  MZ_FILE *pFile;
-  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
-    return MZ_FALSE;
-  pFile = MZ_FOPEN(pDst_filename, "wb");
-  if (!pFile)
-    return MZ_FALSE;
-  status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
-  if (MZ_FCLOSE(pFile) == EOF)
-    return MZ_FALSE;
-#ifndef MINIZ_NO_TIME
-  if (status)
-    mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
-#endif
-  return status;
-}
-#endif // #ifndef MINIZ_NO_STDIO
-
-mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
-{
-  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
-    return MZ_FALSE;
-
-  if (pZip->m_pState)
-  {
-    mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL;
-    mz_zip_array_clear(pZip, &pState->m_central_dir);
-    mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
-    mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
-
-#ifndef MINIZ_NO_STDIO
-    if (pState->m_pFile)
-    {
-      MZ_FCLOSE(pState->m_pFile);
-      pState->m_pFile = NULL;
-    }
-#endif // #ifndef MINIZ_NO_STDIO
-
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
-  }
-  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
-
-  return MZ_TRUE;
-}
-
-#ifndef MINIZ_NO_STDIO
-mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
-{
-  int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
-  if (file_index < 0)
-    return MZ_FALSE;
-  return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
-}
-#endif
-
-// ------------------- .ZIP archive writing
-
-#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
-
-static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); }
-static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); }
-#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
-#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
-
-mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
-{
-  if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
-    return MZ_FALSE;
-
-  if (pZip->m_file_offset_alignment)
-  {
-    // Ensure user specified file offset alignment is a power of 2.
-    if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
-      return MZ_FALSE;
-  }
-
-  if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
-  if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
-  if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
-
-  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
-  pZip->m_archive_size = existing_size;
-  pZip->m_central_directory_file_ofs = 0;
-  pZip->m_total_files = 0;
-
-  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
-    return MZ_FALSE;
-  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
-  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
-  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
-  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
-  return MZ_TRUE;
-}
-
-static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
-{
-  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
-  mz_zip_internal_state *pState = pZip->m_pState;
-  mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
-#ifdef _MSC_VER
-  if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
-#else
-  if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
-#endif
-    return 0;
-  if (new_size > pState->m_mem_capacity)
-  {
-    void *pNew_block;
-    size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2;
-    if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
-      return 0;
-    pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity;
-  }
-  memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
-  pState->m_mem_size = (size_t)new_size;
-  return n;
-}
-
-mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
-{
-  pZip->m_pWrite = mz_zip_heap_write_func;
-  pZip->m_pIO_opaque = pZip;
-  if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
-    return MZ_FALSE;
-  if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
-  {
-    if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
-    {
-      mz_zip_writer_end(pZip);
-      return MZ_FALSE;
-    }
-    pZip->m_pState->m_mem_capacity = initial_allocation_size;
-  }
-  return MZ_TRUE;
-}
-
-#ifndef MINIZ_NO_STDIO
-static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
-{
-  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
-  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
-  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
-    return 0;
-  return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
-}
-
-mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
-{
-  MZ_FILE *pFile;
-  pZip->m_pWrite = mz_zip_file_write_func;
-  pZip->m_pIO_opaque = pZip;
-  if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
-    return MZ_FALSE;
-  if (NULL == (pFile = MZ_FOPEN(pFilename, "wb")))
-  {
-    mz_zip_writer_end(pZip);
-    return MZ_FALSE;
-  }
-  pZip->m_pState->m_pFile = pFile;
-  if (size_to_reserve_at_beginning)
-  {
-    mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf);
-    do
-    {
-      size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
-      if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
-      {
-        mz_zip_writer_end(pZip);
-        return MZ_FALSE;
-      }
-      cur_ofs += n; size_to_reserve_at_beginning -= n;
-    } while (size_to_reserve_at_beginning);
-  }
-  return MZ_TRUE;
-}
-#endif // #ifndef MINIZ_NO_STDIO
-
-mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
-{
-  mz_zip_internal_state *pState;
-  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
-    return MZ_FALSE;
-  // No sense in trying to write to an archive that's already at the support max size
-  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
-    return MZ_FALSE;
-
-  pState = pZip->m_pState;
-
-  if (pState->m_pFile)
-  {
-#ifdef MINIZ_NO_STDIO
-    pFilename; return MZ_FALSE;
-#else
-    // Archive is being read from stdio - try to reopen as writable.
-    if (pZip->m_pIO_opaque != pZip)
-      return MZ_FALSE;
-    if (!pFilename)
-      return MZ_FALSE;
-    pZip->m_pWrite = mz_zip_file_write_func;
-    if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
-    {
-      // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it.
-      mz_zip_reader_end(pZip);
-      return MZ_FALSE;
-    }
-#endif // #ifdef MINIZ_NO_STDIO
-  }
-  else if (pState->m_pMem)
-  {
-    // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback.
-    if (pZip->m_pIO_opaque != pZip)
-      return MZ_FALSE;
-    pState->m_mem_capacity = pState->m_mem_size;
-    pZip->m_pWrite = mz_zip_heap_write_func;
-  }
-  // Archive is being read via a user provided read function - make sure the user has specified a write function too.
-  else if (!pZip->m_pWrite)
-    return MZ_FALSE;
-
-  // Start writing new files at the archive's current central directory location.
-  pZip->m_archive_size = pZip->m_central_directory_file_ofs;
-  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
-  pZip->m_central_directory_file_ofs = 0;
-
-  return MZ_TRUE;
-}
-
-mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
-{
-  return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
-}
-
-typedef struct
-{
-  mz_zip_archive *m_pZip;
-  mz_uint64 m_cur_archive_file_ofs;
-  mz_uint64 m_comp_size;
-} mz_zip_writer_add_state;
-
-static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser)
-{
-  mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
-  if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
-    return MZ_FALSE;
-  pState->m_cur_archive_file_ofs += len;
-  pState->m_comp_size += len;
-  return MZ_TRUE;
-}
-
-static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
-{
-  (void)pZip;
-  memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
-  return MZ_TRUE;
-}
-
-static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
-{
-  (void)pZip;
-  memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
-  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
-  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
-  return MZ_TRUE;
-}
-
-static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
-{
-  mz_zip_internal_state *pState = pZip->m_pState;
-  mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
-  size_t orig_central_dir_size = pState->m_central_dir.m_size;
-  mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
-
-  // No zip64 support yet
-  if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF))
-    return MZ_FALSE;
-
-  if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
-    return MZ_FALSE;
-
-  if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
-      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
-      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
-      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
-      (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
-  {
-    // Try to push the central directory array back into its original state.
-    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
-    return MZ_FALSE;
-  }
-
-  return MZ_TRUE;
-}
-
-static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
-{
-  // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes.
-  if (*pArchive_name == '/')
-    return MZ_FALSE;
-  while (*pArchive_name)
-  {
-    if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
-      return MZ_FALSE;
-    pArchive_name++;
-  }
-  return MZ_TRUE;
-}
-
-static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
-{
-  mz_uint32 n;
-  if (!pZip->m_file_offset_alignment)
-    return 0;
-  n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
-  return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1);
-}
-
-static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
-{
-  char buf[4096];
-  memset(buf, 0, MZ_MIN(sizeof(buf), n));
-  while (n)
-  {
-    mz_uint32 s = MZ_MIN(sizeof(buf), n);
-    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
-      return MZ_FALSE;
-    cur_file_ofs += s; n -= s;
-  }
-  return MZ_TRUE;
-}
-
-mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
-{
-  mz_uint16 method = 0, dos_time = 0, dos_date = 0;
-  mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
-  mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
-  size_t archive_name_size;
-  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
-  tdefl_compressor *pComp = NULL;
-  mz_bool store_data_uncompressed;
-  mz_zip_internal_state *pState;
-
-  if ((int)level_and_flags < 0)
-    level_and_flags = MZ_DEFAULT_LEVEL;
-  level = level_and_flags & 0xF;
-  store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
-
-  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
-    return MZ_FALSE;
-
-  pState = pZip->m_pState;
-
-  if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
-    return MZ_FALSE;
-  // No zip64 support yet
-  if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
-    return MZ_FALSE;
-  if (!mz_zip_writer_validate_archive_name(pArchive_name))
-    return MZ_FALSE;
-
-#ifndef MINIZ_NO_TIME
-  {
-    time_t cur_time; time(&cur_time);
-    mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
-  }
-#endif // #ifndef MINIZ_NO_TIME
-
-  archive_name_size = strlen(pArchive_name);
-  if (archive_name_size > 0xFFFF)
-    return MZ_FALSE;
-
-  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
-
-  // no zip64 support yet
-  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
-    return MZ_FALSE;
-
-  if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
-  {
-    // Set DOS Subdirectory attribute bit.
-    ext_attributes |= 0x10;
-    // Subdirectories cannot contain data.
-    if ((buf_size) || (uncomp_size))
-      return MZ_FALSE;
-  }
-
-  // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.)
-  if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
-    return MZ_FALSE;
-
-  if ((!store_data_uncompressed) && (buf_size))
-  {
-    if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
-      return MZ_FALSE;
-  }
-
-  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
-  {
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
-    return MZ_FALSE;
-  }
-  local_dir_header_ofs += num_alignment_padding_bytes;
-  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
-  cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
-
-  MZ_CLEAR_OBJ(local_dir_header);
-  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
-  {
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
-    return MZ_FALSE;
-  }
-  cur_archive_file_ofs += archive_name_size;
-
-  if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
-  {
-    uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size);
-    uncomp_size = buf_size;
-    if (uncomp_size <= 3)
-    {
-      level = 0;
-      store_data_uncompressed = MZ_TRUE;
-    }
-  }
-
-  if (store_data_uncompressed)
-  {
-    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
-    {
-      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
-      return MZ_FALSE;
-    }
-
-    cur_archive_file_ofs += buf_size;
-    comp_size = buf_size;
-
-    if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
-      method = MZ_DEFLATED;
-  }
-  else if (buf_size)
-  {
-    mz_zip_writer_add_state state;
-
-    state.m_pZip = pZip;
-    state.m_cur_archive_file_ofs = cur_archive_file_ofs;
-    state.m_comp_size = 0;
-
-    if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
-        (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
-    {
-      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
-      return MZ_FALSE;
-    }
-
-    comp_size = state.m_comp_size;
-    cur_archive_file_ofs = state.m_cur_archive_file_ofs;
-
-    method = MZ_DEFLATED;
-  }
-
-  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
-  pComp = NULL;
-
-  // no zip64 support yet
-  if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
-    return MZ_FALSE;
-
-  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
-    return MZ_FALSE;
-
-  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
-    return MZ_FALSE;
-
-  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
-    return MZ_FALSE;
-
-  pZip->m_total_files++;
-  pZip->m_archive_size = cur_archive_file_ofs;
-
-  return MZ_TRUE;
-}
-
-#ifndef MINIZ_NO_STDIO
-mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
-{
-  mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
-  mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
-  mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
-  size_t archive_name_size;
-  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
-  MZ_FILE *pSrc_file = NULL;
-
-  if ((int)level_and_flags < 0)
-    level_and_flags = MZ_DEFAULT_LEVEL;
-  level = level_and_flags & 0xF;
-
-  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
-    return MZ_FALSE;
-  if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
-    return MZ_FALSE;
-  if (!mz_zip_writer_validate_archive_name(pArchive_name))
-    return MZ_FALSE;
-
-  archive_name_size = strlen(pArchive_name);
-  if (archive_name_size > 0xFFFF)
-    return MZ_FALSE;
-
-  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
-
-  // no zip64 support yet
-  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
-    return MZ_FALSE;
-
-  if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
-    return MZ_FALSE;
-
-  pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
-  if (!pSrc_file)
-    return MZ_FALSE;
-  MZ_FSEEK64(pSrc_file, 0, SEEK_END);
-  uncomp_size = MZ_FTELL64(pSrc_file);
-  MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
-
-  if (uncomp_size > 0xFFFFFFFF)
-  {
-    // No zip64 support yet
-    MZ_FCLOSE(pSrc_file);
-    return MZ_FALSE;
-  }
-  if (uncomp_size <= 3)
-    level = 0;
-
-  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
-    return MZ_FALSE;
-  local_dir_header_ofs += num_alignment_padding_bytes;
-  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
-  cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
-
-  MZ_CLEAR_OBJ(local_dir_header);
-  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
-  {
-    MZ_FCLOSE(pSrc_file);
-    return MZ_FALSE;
-  }
-  cur_archive_file_ofs += archive_name_size;
-
-  if (uncomp_size)
-  {
-    mz_uint64 uncomp_remaining = uncomp_size;
-    void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
-    if (!pRead_buf)
-    {
-      MZ_FCLOSE(pSrc_file);
-      return MZ_FALSE;
-    }
-
-    if (!level)
-    {
-      while (uncomp_remaining)
-      {
-        mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
-        if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
-        {
-          pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
-          MZ_FCLOSE(pSrc_file);
-          return MZ_FALSE;
-        }
-        uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
-        uncomp_remaining -= n;
-        cur_archive_file_ofs += n;
-      }
-      comp_size = uncomp_size;
-    }
-    else
-    {
-      mz_bool result = MZ_FALSE;
-      mz_zip_writer_add_state state;
-      tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
-      if (!pComp)
-      {
-        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
-        MZ_FCLOSE(pSrc_file);
-        return MZ_FALSE;
-      }
-
-      state.m_pZip = pZip;
-      state.m_cur_archive_file_ofs = cur_archive_file_ofs;
-      state.m_comp_size = 0;
-
-      if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
-      {
-        pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
-        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
-        MZ_FCLOSE(pSrc_file);
-        return MZ_FALSE;
-      }
-
-      for ( ; ; )
-      {
-        size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
-        tdefl_status status;
-
-        if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
-          break;
-
-        uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
-        uncomp_remaining -= in_buf_size;
-
-        status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
-        if (status == TDEFL_STATUS_DONE)
-        {
-          result = MZ_TRUE;
-          break;
-        }
-        else if (status != TDEFL_STATUS_OKAY)
-          break;
-      }
-
-      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
-
-      if (!result)
-      {
-        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
-        MZ_FCLOSE(pSrc_file);
-        return MZ_FALSE;
-      }
-
-      comp_size = state.m_comp_size;
-      cur_archive_file_ofs = state.m_cur_archive_file_ofs;
-
-      method = MZ_DEFLATED;
-    }
-
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
-  }
-
-  MZ_FCLOSE(pSrc_file); pSrc_file = NULL;
-
-  // no zip64 support yet
-  if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
-    return MZ_FALSE;
-
-  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
-    return MZ_FALSE;
-
-  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
-    return MZ_FALSE;
-
-  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
-    return MZ_FALSE;
-
-  pZip->m_total_files++;
-  pZip->m_archive_size = cur_archive_file_ofs;
-
-  return MZ_TRUE;
-}
-#endif // #ifndef MINIZ_NO_STDIO
-
-mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index)
-{
-  mz_uint n, bit_flags, num_alignment_padding_bytes;
-  mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
-  mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
-  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
-  mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
-  size_t orig_central_dir_size;
-  mz_zip_internal_state *pState;
-  void *pBuf; const mz_uint8 *pSrc_central_header;
-
-  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
-    return MZ_FALSE;
-  if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
-    return MZ_FALSE;
-  pState = pZip->m_pState;
-
-  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
-
-  // no zip64 support yet
-  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
-    return MZ_FALSE;
-
-  cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
-  cur_dst_file_ofs = pZip->m_archive_size;
-
-  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
-    return MZ_FALSE;
-  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
-    return MZ_FALSE;
-  cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
-
-  if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
-    return MZ_FALSE;
-  cur_dst_file_ofs += num_alignment_padding_bytes;
-  local_dir_header_ofs = cur_dst_file_ofs;
-  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
-
-  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
-    return MZ_FALSE;
-  cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
-
-  n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
-  comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
-
-  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining)))))
-    return MZ_FALSE;
-
-  while (comp_bytes_remaining)
-  {
-    n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
-    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
-    {
-      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
-      return MZ_FALSE;
-    }
-    cur_src_file_ofs += n;
-
-    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
-    {
-      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
-      return MZ_FALSE;
-    }
-    cur_dst_file_ofs += n;
-
-    comp_bytes_remaining -= n;
-  }
-
-  bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
-  if (bit_flags & 8)
-  {
-    // Copy data descriptor
-    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
-    {
-      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
-      return MZ_FALSE;
-    }
-
-    n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
-    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
-    {
-      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
-      return MZ_FALSE;
-    }
-
-    cur_src_file_ofs += n;
-    cur_dst_file_ofs += n;
-  }
-  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
-
-  // no zip64 support yet
-  if (cur_dst_file_ofs > 0xFFFFFFFF)
-    return MZ_FALSE;
-
-  orig_central_dir_size = pState->m_central_dir.m_size;
-
-  memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
-  MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
-  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
-    return MZ_FALSE;
-
-  n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
-  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n))
-  {
-    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
-    return MZ_FALSE;
-  }
-
-  if (pState->m_central_dir.m_size > 0xFFFFFFFF)
-    return MZ_FALSE;
-  n = (mz_uint32)pState->m_central_dir.m_size;
-  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
-  {
-    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
-    return MZ_FALSE;
-  }
-
-  pZip->m_total_files++;
-  pZip->m_archive_size = cur_dst_file_ofs;
-
-  return MZ_TRUE;
-}
-
-mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
-{
-  mz_zip_internal_state *pState;
-  mz_uint64 central_dir_ofs, central_dir_size;
-  mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
-
-  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
-    return MZ_FALSE;
-
-  pState = pZip->m_pState;
-
-  // no zip64 support yet
-  if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
-    return MZ_FALSE;
-
-  central_dir_ofs = 0;
-  central_dir_size = 0;
-  if (pZip->m_total_files)
-  {
-    // Write central directory
-    central_dir_ofs = pZip->m_archive_size;
-    central_dir_size = pState->m_central_dir.m_size;
-    pZip->m_central_directory_file_ofs = central_dir_ofs;
-    if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
-      return MZ_FALSE;
-    pZip->m_archive_size += central_dir_size;
-  }
-
-  // Write end of central directory record
-  MZ_CLEAR_OBJ(hdr);
-  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
-  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
-  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
-  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
-  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
-
-  if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr))
-    return MZ_FALSE;
-#ifndef MINIZ_NO_STDIO
-  if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
-    return MZ_FALSE;
-#endif // #ifndef MINIZ_NO_STDIO
-
-  pZip->m_archive_size += sizeof(hdr);
-
-  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
-  return MZ_TRUE;
-}
-
-mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize)
-{
-  if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
-    return MZ_FALSE;
-  if (pZip->m_pWrite != mz_zip_heap_write_func)
-    return MZ_FALSE;
-  if (!mz_zip_writer_finalize_archive(pZip))
-    return MZ_FALSE;
-
-  *pBuf = pZip->m_pState->m_pMem;
-  *pSize = pZip->m_pState->m_mem_size;
-  pZip->m_pState->m_pMem = NULL;
-  pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
-  return MZ_TRUE;
-}
-
-mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
-{
-  mz_zip_internal_state *pState;
-  mz_bool status = MZ_TRUE;
-  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
-    return MZ_FALSE;
-
-  pState = pZip->m_pState;
-  pZip->m_pState = NULL;
-  mz_zip_array_clear(pZip, &pState->m_central_dir);
-  mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
-  mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
-
-#ifndef MINIZ_NO_STDIO
-  if (pState->m_pFile)
-  {
-    MZ_FCLOSE(pState->m_pFile);
-    pState->m_pFile = NULL;
-  }
-#endif // #ifndef MINIZ_NO_STDIO
-
-  if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
-  {
-    pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
-    pState->m_pMem = NULL;
-  }
-
-  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
-  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
-  return status;
-}
-
-#ifndef MINIZ_NO_STDIO
-mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
-{
-  mz_bool status, created_new_archive = MZ_FALSE;
-  mz_zip_archive zip_archive;
-  struct MZ_FILE_STAT_STRUCT file_stat;
-  MZ_CLEAR_OBJ(zip_archive);
-  if ((int)level_and_flags < 0)
-     level_and_flags = MZ_DEFAULT_LEVEL;
-  if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
-    return MZ_FALSE;
-  if (!mz_zip_writer_validate_archive_name(pArchive_name))
-    return MZ_FALSE;
-  if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
-  {
-    // Create a new archive.
-    if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
-      return MZ_FALSE;
-    created_new_archive = MZ_TRUE;
-  }
-  else
-  {
-    // Append to an existing archive.
-    if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
-      return MZ_FALSE;
-    if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename))
-    {
-      mz_zip_reader_end(&zip_archive);
-      return MZ_FALSE;
-    }
-  }
-  status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
-  // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.)
-  if (!mz_zip_writer_finalize_archive(&zip_archive))
-    status = MZ_FALSE;
-  if (!mz_zip_writer_end(&zip_archive))
-    status = MZ_FALSE;
-  if ((!status) && (created_new_archive))
-  {
-    // It's a new archive and something went wrong, so just delete it.
-    int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
-    (void)ignoredStatus;
-  }
-  return status;
-}
-
-void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags)
-{
-  int file_index;
-  mz_zip_archive zip_archive;
-  void *p = NULL;
-
-  if (pSize)
-    *pSize = 0;
-
-  if ((!pZip_filename) || (!pArchive_name))
-    return NULL;
-
-  MZ_CLEAR_OBJ(zip_archive);
-  if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
-    return NULL;
-
-  if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, pComment, flags)) >= 0)
-    p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
-
-  mz_zip_reader_end(&zip_archive);
-  return p;
-}
-
-#endif // #ifndef MINIZ_NO_STDIO
-
-#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
-
-#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // MINIZ_HEADER_FILE_ONLY
-
-/*
-  This is free and unencumbered software released into the public domain.
-
-  Anyone is free to copy, modify, publish, use, compile, sell, or
-  distribute this software, either in source code form or as a compiled
-  binary, for any purpose, commercial or non-commercial, and by any
-  means.
-
-  In jurisdictions that recognize copyright laws, the author or authors
-  of this software dedicate any and all copyright interest in the
-  software to the public domain. We make this dedication for the benefit
-  of the public at large and to the detriment of our heirs and
-  successors. We intend this dedication to be an overt act of
-  relinquishment in perpetuity of all present and future rights to this
-  software under copyright law.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-  OTHER DEALINGS IN THE SOFTWARE.
-
-  For more information, please refer to <http://unlicense.org/>
-*/

+ 0 - 893
Source/ThirdParty/crunch/crnlib/crn_miniz.h

@@ -1,893 +0,0 @@
-/* miniz.c v1.14 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
-   See "unlicense" statement at the end of this file.
-   Rich Geldreich <[email protected]>, last updated May 20, 2012
-   Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
-
-   Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define
-   MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
-
-   * Change History
-     5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
-     5/19/12 v1.13 - From [email protected] and [email protected] - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
-       Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files.
-       Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
-       Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly
-       "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
-       Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.
-       Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.
-       Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.
-       Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
-       Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).
-     4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.
-      level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <[email protected]> for the feedback/bug report.
-     5/28/11 v1.11 - Added statement from unlicense.org
-     5/27/11 v1.10 - Substantial compressor optimizations:
-      Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a
-      Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).
-      Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.
-      Refactored the compression code for better readability and maintainability.
-      Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large
-      drop in throughput on some files).
-     5/15/11 v1.09 - Initial stable release.
-
-   * Low-level Deflate/Inflate implementation notes:
-
-     Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or
-     greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses
-     approximately as well as zlib.
-
-     Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function
-     coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory
-     block large enough to hold the entire file.
-
-     The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation.
-
-   * zlib-style API notes:
-
-     miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in
-     zlib replacement in many apps:
-        The z_stream struct, optional memory allocation callbacks
-        deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
-        inflateInit/inflateInit2/inflate/inflateEnd
-        compress, compress2, compressBound, uncompress
-        CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines.
-        Supports raw deflate streams or standard zlib streams with adler-32 checking.
-
-     Limitations:
-      The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries.
-      I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but
-      there are no guarantees that miniz.c pulls this off perfectly.
-
-   * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by
-     Alex Evans. Supports 1-4 bytes/pixel images.
-
-   * ZIP archive API notes:
-
-     The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to
-     get the job done with minimal fuss. There are simple API's to retrieve file information, read files from
-     existing archives, create new archives, append new files to existing archives, or clone archive data from
-     one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h),
-     or you can specify custom file read/write callbacks.
-
-     - Archive reading: Just call this function to read a single file from a disk archive:
-
-      void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name,
-        size_t *pSize, mz_uint zip_flags);
-
-     For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central
-     directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files.
-
-     - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file:
-
-     int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
-
-     The locate operation can optionally check file comments too, which (as one example) can be used to identify
-     multiple versions of the same file in an archive. This function uses a simple linear search through the central
-     directory, so it's not very fast.
-
-     Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and
-     retrieve detailed info on each file by calling mz_zip_reader_file_stat().
-
-     - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data
-     to disk and builds an exact image of the central directory in memory. The central directory image is written
-     all at once at the end of the archive file when the archive is finalized.
-
-     The archive writer can optionally align each file's local header and file data to any power of 2 alignment,
-     which can be useful when the archive will be read from optical media. Also, the writer supports placing
-     arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still
-     readable by any ZIP tool.
-
-     - Archive appending: The simple way to add a single file to an archive is to call this function:
-
-      mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name,
-        const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
-
-     The archive will be created if it doesn't already exist, otherwise it'll be appended to.
-     Note the appending is done in-place and is not an atomic operation, so if something goes wrong
-     during the operation it's possible the archive could be left without a central directory (although the local
-     file headers and file data will be fine, so the archive will be recoverable).
-
-     For more complex archive modification scenarios:
-     1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to
-     preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the
-     compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and
-     you're done. This is safe but requires a bunch of temporary disk space or heap memory.
-
-     2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(),
-     append new files as needed, then finalize the archive which will write an updated central directory to the
-     original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a
-     possibility that the archive's central directory could be lost with this method if anything goes wrong, though.
-
-     - ZIP archive support limitations:
-     No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
-     Requires streams capable of seeking.
-
-   * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the
-     below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
-
-   * Important: For best perf. be sure to customize the below macros for your target platform:
-     #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
-     #define MINIZ_LITTLE_ENDIAN 1
-     #define MINIZ_HAS_64BIT_REGISTERS 1
-*/
-#pragma once
-
-#ifndef MINIZ_HEADER_INCLUDED
-#define MINIZ_HEADER_INCLUDED
-
-#include <stdlib.h>
-
-#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
-#include <time.h>
-#endif
-
-// Defines to completely disable specific portions of miniz.c:
-// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
-
-// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
-//#define MINIZ_NO_STDIO
-
-// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
-// get/set file times.
-//#define MINIZ_NO_TIME
-
-// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
-//#define MINIZ_NO_ARCHIVE_APIS
-
-// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
-//#define MINIZ_NO_ARCHIVE_WRITING_APIS
-
-// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
-//#define MINIZ_NO_ZLIB_APIS
-
-// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
-//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
-
-// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
-// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
-// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
-// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
-//#define MINIZ_NO_MALLOC
-
-#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
-// MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
-#define MINIZ_X86_OR_X64_CPU 1
-#endif
-
-#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
-// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
-#define MINIZ_LITTLE_ENDIAN 1
-#endif
-
-#if MINIZ_X86_OR_X64_CPU
-// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
-#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
-#endif
-
-#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
-// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
-#define MINIZ_HAS_64BIT_REGISTERS 1
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// ------------------- zlib-style API Definitions.
-
-// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
-typedef unsigned long mz_ulong;
-
-// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
-void mz_free(void *p);
-
-#define MZ_ADLER32_INIT (1)
-// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
-mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
-
-#define MZ_CRC32_INIT (0)
-// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
-mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
-
-// Compression strategies.
-enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
-
-// Method
-#define MZ_DEFLATED 8
-
-#ifndef MINIZ_NO_ZLIB_APIS
-
-// Heap allocation callbacks.
-// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
-typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
-typedef void (*mz_free_func)(void *opaque, void *address);
-typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
-
-#define MZ_VERSION          "9.1.14"
-#define MZ_VERNUM           0x91E0
-#define MZ_VER_MAJOR        9
-#define MZ_VER_MINOR        1
-#define MZ_VER_REVISION     14
-#define MZ_VER_SUBREVISION  0
-
-// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
-enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };
-
-// Return status codes. MZ_PARAM_ERROR is non-standard.
-enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
-
-// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
-enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };
-
-// Window bits
-#define MZ_DEFAULT_WINDOW_BITS 15
-
-struct mz_internal_state;
-
-// Compression/decompression stream struct.
-typedef struct mz_stream_s
-{
-  const unsigned char *next_in;     // pointer to next byte to read
-  unsigned int avail_in;            // number of bytes available at next_in
-  mz_ulong total_in;                // total number of bytes consumed so far
-
-  unsigned char *next_out;          // pointer to next byte to write
-  unsigned int avail_out;           // number of bytes that can be written to next_out
-  mz_ulong total_out;               // total number of bytes produced so far
-
-  char *msg;                        // error msg (unused)
-  struct mz_internal_state *state;  // internal state, allocated by zalloc/zfree
-
-  mz_alloc_func zalloc;             // optional heap allocation function (defaults to malloc)
-  mz_free_func zfree;               // optional heap free function (defaults to free)
-  void *opaque;                     // heap alloc function user pointer
-
-  int data_type;                    // data_type (unused)
-  mz_ulong adler;                   // adler32 of the source or uncompressed data
-  mz_ulong reserved;                // not used
-} mz_stream;
-
-typedef mz_stream *mz_streamp;
-
-// Returns the version string of miniz.c.
-const char *mz_version(void);
-
-// mz_deflateInit() initializes a compressor with default options:
-// Parameters:
-//  pStream must point to an initialized mz_stream struct.
-//  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
-//  level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
-//  (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
-// Return values:
-//  MZ_OK on success.
-//  MZ_STREAM_ERROR if the stream is bogus.
-//  MZ_PARAM_ERROR if the input parameters are bogus.
-//  MZ_MEM_ERROR on out of memory.
-int mz_deflateInit(mz_streamp pStream, int level);
-
-// mz_deflateInit2() is like mz_deflate(), except with more control:
-// Additional parameters:
-//   method must be MZ_DEFLATED
-//   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
-//   mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
-int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
-
-// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
-int mz_deflateReset(mz_streamp pStream);
-
-// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
-// Parameters:
-//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
-//   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
-// Return values:
-//   MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
-//   MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
-//   MZ_STREAM_ERROR if the stream is bogus.
-//   MZ_PARAM_ERROR if one of the parameters is invalid.
-//   MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
-int mz_deflate(mz_streamp pStream, int flush);
-
-// mz_deflateEnd() deinitializes a compressor:
-// Return values:
-//  MZ_OK on success.
-//  MZ_STREAM_ERROR if the stream is bogus.
-int mz_deflateEnd(mz_streamp pStream);
-
-// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
-mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
-
-// Single-call compression functions mz_compress() and mz_compress2():
-// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
-int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
-int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
-
-// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
-mz_ulong mz_compressBound(mz_ulong source_len);
-
-// Initializes a decompressor.
-int mz_inflateInit(mz_streamp pStream);
-
-// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
-// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
-int mz_inflateInit2(mz_streamp pStream, int window_bits);
-
-// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
-// Parameters:
-//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
-//   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
-//   On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
-//   MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
-// Return values:
-//   MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
-//   MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
-//   MZ_STREAM_ERROR if the stream is bogus.
-//   MZ_DATA_ERROR if the deflate stream is invalid.
-//   MZ_PARAM_ERROR if one of the parameters is invalid.
-//   MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
-//   with more input data, or with more room in the output buffer (except when using single call decompression, described above).
-int mz_inflate(mz_streamp pStream, int flush);
-
-// Deinitializes a decompressor.
-int mz_inflateEnd(mz_streamp pStream);
-
-// Single-call decompression.
-// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
-int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
-
-// Returns a string description of the specified error code, or NULL if the error code is invalid.
-const char *mz_error(int err);
-
-// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
-// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
-#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
-  typedef unsigned char Byte;
-  typedef unsigned int uInt;
-  typedef mz_ulong uLong;
-  typedef Byte Bytef;
-  typedef uInt uIntf;
-  typedef char charf;
-  typedef int intf;
-  typedef void *voidpf;
-  typedef uLong uLongf;
-  typedef void *voidp;
-  typedef void *const voidpc;
-  #define Z_NULL                0
-  #define Z_NO_FLUSH            MZ_NO_FLUSH
-  #define Z_PARTIAL_FLUSH       MZ_PARTIAL_FLUSH
-  #define Z_SYNC_FLUSH          MZ_SYNC_FLUSH
-  #define Z_FULL_FLUSH          MZ_FULL_FLUSH
-  #define Z_FINISH              MZ_FINISH
-  #define Z_BLOCK               MZ_BLOCK
-  #define Z_OK                  MZ_OK
-  #define Z_STREAM_END          MZ_STREAM_END
-  #define Z_NEED_DICT           MZ_NEED_DICT
-  #define Z_ERRNO               MZ_ERRNO
-  #define Z_STREAM_ERROR        MZ_STREAM_ERROR
-  #define Z_DATA_ERROR          MZ_DATA_ERROR
-  #define Z_MEM_ERROR           MZ_MEM_ERROR
-  #define Z_BUF_ERROR           MZ_BUF_ERROR
-  #define Z_VERSION_ERROR       MZ_VERSION_ERROR
-  #define Z_PARAM_ERROR         MZ_PARAM_ERROR
-  #define Z_NO_COMPRESSION      MZ_NO_COMPRESSION
-  #define Z_BEST_SPEED          MZ_BEST_SPEED
-  #define Z_BEST_COMPRESSION    MZ_BEST_COMPRESSION
-  #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
-  #define Z_DEFAULT_STRATEGY    MZ_DEFAULT_STRATEGY
-  #define Z_FILTERED            MZ_FILTERED
-  #define Z_HUFFMAN_ONLY        MZ_HUFFMAN_ONLY
-  #define Z_RLE                 MZ_RLE
-  #define Z_FIXED               MZ_FIXED
-  #define Z_DEFLATED            MZ_DEFLATED
-  #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
-  #define alloc_func            mz_alloc_func
-  #define free_func             mz_free_func
-  #define internal_state        mz_internal_state
-  #define z_stream              mz_stream
-  #define deflateInit           mz_deflateInit
-  #define deflateInit2          mz_deflateInit2
-  #define deflateReset          mz_deflateReset
-  #define deflate               mz_deflate
-  #define deflateEnd            mz_deflateEnd
-  #define deflateBound          mz_deflateBound
-  #define compress              mz_compress
-  #define compress2             mz_compress2
-  #define compressBound         mz_compressBound
-  #define inflateInit           mz_inflateInit
-  #define inflateInit2          mz_inflateInit2
-  #define inflate               mz_inflate
-  #define inflateEnd            mz_inflateEnd
-  #define uncompress            mz_uncompress
-  #define crc32                 mz_crc32
-  #define adler32               mz_adler32
-  #define MAX_WBITS             15
-  #define MAX_MEM_LEVEL         9
-  #define zError                mz_error
-  #define ZLIB_VERSION          MZ_VERSION
-  #define ZLIB_VERNUM           MZ_VERNUM
-  #define ZLIB_VER_MAJOR        MZ_VER_MAJOR
-  #define ZLIB_VER_MINOR        MZ_VER_MINOR
-  #define ZLIB_VER_REVISION     MZ_VER_REVISION
-  #define ZLIB_VER_SUBREVISION  MZ_VER_SUBREVISION
-  #define zlibVersion           mz_version
-  #define zlib_version          mz_version()
-#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
-
-#endif // MINIZ_NO_ZLIB_APIS
-
-// ------------------- Types and macros
-
-typedef unsigned char mz_uint8;
-typedef signed short mz_int16;
-typedef unsigned short mz_uint16;
-typedef unsigned int mz_uint32;
-typedef unsigned int mz_uint;
-typedef long long mz_int64;
-typedef unsigned long long mz_uint64;
-typedef int mz_bool;
-
-#define MZ_FALSE (0)
-#define MZ_TRUE (1)
-
-// Works around MSVC's spammy "warning C4127: conditional expression is constant" message.
-#ifdef _MSC_VER
-   #define MZ_MACRO_END while (0, 0)
-#else
-   #define MZ_MACRO_END while (0)
-#endif
-
-// ------------------- ZIP archive reading/writing
-
-#ifndef MINIZ_NO_ARCHIVE_APIS
-
-enum
-{
-  MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024,
-  MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
-  MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
-};
-
-typedef struct
-{
-  mz_uint32 m_file_index;
-  mz_uint32 m_central_dir_ofs;
-  mz_uint16 m_version_made_by;
-  mz_uint16 m_version_needed;
-  mz_uint16 m_bit_flag;
-  mz_uint16 m_method;
-#ifndef MINIZ_NO_TIME
-  time_t m_time;
-#endif
-  mz_uint32 m_crc32;
-  mz_uint64 m_comp_size;
-  mz_uint64 m_uncomp_size;
-  mz_uint16 m_internal_attr;
-  mz_uint32 m_external_attr;
-  mz_uint64 m_local_header_ofs;
-  mz_uint32 m_comment_size;
-  char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
-  char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
-} mz_zip_archive_file_stat;
-
-typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
-typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);
-
-struct mz_zip_internal_state_tag;
-typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
-
-typedef enum
-{
-  MZ_ZIP_MODE_INVALID = 0,
-  MZ_ZIP_MODE_READING = 1,
-  MZ_ZIP_MODE_WRITING = 2,
-  MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
-} mz_zip_mode;
-
-typedef struct
-{
-  mz_uint64 m_archive_size;
-  mz_uint64 m_central_directory_file_ofs;
-  mz_uint m_total_files;
-  mz_zip_mode m_zip_mode;
-
-  mz_uint m_file_offset_alignment;
-
-  mz_alloc_func m_pAlloc;
-  mz_free_func m_pFree;
-  mz_realloc_func m_pRealloc;
-  void *m_pAlloc_opaque;
-
-  mz_file_read_func m_pRead;
-  mz_file_write_func m_pWrite;
-  void *m_pIO_opaque;
-
-  mz_zip_internal_state *m_pState;
-
-} mz_zip_archive;
-
-typedef enum
-{
-  MZ_ZIP_FLAG_CASE_SENSITIVE                = 0x0100,
-  MZ_ZIP_FLAG_IGNORE_PATH                   = 0x0200,
-  MZ_ZIP_FLAG_COMPRESSED_DATA               = 0x0400,
-  MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
-} mz_zip_flags;
-
-// ZIP archive reading
-
-// Inits a ZIP archive reader.
-// These functions read and validate the archive's central directory.
-mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
-mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);
-
-#ifndef MINIZ_NO_STDIO
-mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
-#endif
-
-// Returns the total number of files in the archive.
-mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
-
-// Returns detailed information about an archive file entry.
-mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
-
-// Determines if an archive file entry is a directory entry.
-mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
-mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
-
-// Retrieves the filename of an archive file entry.
-// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
-mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
-
-// Attempts to locates a file in the archive's central directory.
-// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
-// Returns -1 if the file cannot be found.
-int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
-
-// Extracts a archive file to a memory buffer using no memory allocation.
-mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
-mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
-
-// Extracts a archive file to a memory buffer.
-mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
-mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
-
-// Extracts a archive file to a dynamically allocated heap buffer.
-void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
-void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
-
-// Extracts a archive file using a callback function to output the file's data.
-mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
-mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
-
-#ifndef MINIZ_NO_STDIO
-// Extracts a archive file to a disk file and sets its last accessed and modified times.
-// This function only extracts files, not archive directory records.
-mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
-mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
-#endif
-
-// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
-mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
-
-// ZIP archive writing
-
-#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
-
-// Inits a ZIP archive writer.
-mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
-mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
-
-#ifndef MINIZ_NO_STDIO
-mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
-#endif
-
-// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
-// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
-// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
-// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
-// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
-// the archive is finalized the file's central directory will be hosed.
-mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
-
-// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
-// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
-// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
-mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
-mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
-
-#ifndef MINIZ_NO_STDIO
-// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
-// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
-mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
-#endif
-
-// Adds a file to an archive by fully cloning the data from another archive.
-// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
-mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);
-
-// Finalizes the archive by writing the central directory records followed by the end of central directory record.
-// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
-// An archive must be manually finalized by calling this function for it to be valid.
-mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
-mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);
-
-// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
-// Note for the archive to be valid, it must have been finalized before ending.
-mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
-
-// Misc. high-level helper functions:
-
-// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
-// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
-mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
-
-// Reads a single file from an archive into a heap block.
-// If pComment is not NULL, only the file with the specified comment will be extracted.
-// Returns NULL on failure.
-void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags);
-
-#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
-
-#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
-
-// ------------------- Low-level Decompression API Definitions
-
-// Decompression flags used by tinfl_decompress().
-// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
-// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
-// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
-// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
-enum
-{
-  TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
-  TINFL_FLAG_HAS_MORE_INPUT = 2,
-  TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
-  TINFL_FLAG_COMPUTE_ADLER32 = 8
-};
-
-// High level decompression functions:
-// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
-// On entry:
-//  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
-// On return:
-//  Function returns a pointer to the decompressed data, or NULL on failure.
-//  *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
-//  The caller must call mz_free() on the returned block when it's no longer needed.
-void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
-
-// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
-// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
-#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
-size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
-
-// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
-// Returns 1 on success or 0 on failure.
-typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
-int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
-
-struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
-
-// Max size of LZ dictionary.
-#define TINFL_LZ_DICT_SIZE 32768
-
-// Return status.
-typedef enum
-{
-  TINFL_STATUS_BAD_PARAM = -3,
-  TINFL_STATUS_ADLER32_MISMATCH = -2,
-  TINFL_STATUS_FAILED = -1,
-  TINFL_STATUS_DONE = 0,
-  TINFL_STATUS_NEEDS_MORE_INPUT = 1,
-  TINFL_STATUS_HAS_MORE_OUTPUT = 2
-} tinfl_status;
-
-// Initializes the decompressor to its initial state.
-#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
-#define tinfl_get_adler32(r) (r)->m_check_adler32
-
-// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
-// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
-tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
-
-// Internal/private bits follow.
-enum
-{
-  TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
-  TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
-};
-
-typedef struct
-{
-  mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
-  mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
-} tinfl_huff_table;
-
-#if MINIZ_HAS_64BIT_REGISTERS
-  #define TINFL_USE_64BIT_BITBUF 1
-#endif
-
-#if TINFL_USE_64BIT_BITBUF
-  typedef mz_uint64 tinfl_bit_buf_t;
-  #define TINFL_BITBUF_SIZE (64)
-#else
-  typedef mz_uint32 tinfl_bit_buf_t;
-  #define TINFL_BITBUF_SIZE (32)
-#endif
-
-struct tinfl_decompressor_tag
-{
-  mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
-  tinfl_bit_buf_t m_bit_buf;
-  size_t m_dist_from_out_buf_start;
-  tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
-  mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
-};
-
-// ------------------- Low-level Compression API Definitions
-
-// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
-#define TDEFL_LESS_MEMORY 0
-
-// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
-// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
-enum
-{
-  TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
-};
-
-// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
-// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
-// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
-// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
-// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
-// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
-// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
-// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
-enum
-{
-  TDEFL_WRITE_ZLIB_HEADER             = 0x01000,
-  TDEFL_COMPUTE_ADLER32               = 0x02000,
-  TDEFL_GREEDY_PARSING_FLAG           = 0x04000,
-  TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
-  TDEFL_RLE_MATCHES                   = 0x10000,
-  TDEFL_FILTER_MATCHES                = 0x20000,
-  TDEFL_FORCE_ALL_STATIC_BLOCKS       = 0x40000,
-  TDEFL_FORCE_ALL_RAW_BLOCKS          = 0x80000
-};
-
-// High level compression functions:
-// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
-// On entry:
-//  pSrc_buf, src_buf_len: Pointer and size of source block to compress.
-//  flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
-// On return:
-//  Function returns a pointer to the compressed data, or NULL on failure.
-//  *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
-//  The caller must free() the returned block when it's no longer needed.
-void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
-
-// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
-// Returns 0 on failure.
-size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
-
-// Compresses an image to a compressed PNG file in memory.
-// On entry:
-//  pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. 
-//  The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
-// On return:
-//  Function returns a pointer to the compressed data, or NULL on failure.
-//  *pLen_out will be set to the size of the PNG image file.
-//  The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
-void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
-
-// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
-typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
-
-// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
-mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
-
-enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
-
-// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
-#if TDEFL_LESS_MEMORY
-enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
-#else
-enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
-#endif
-
-// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
-typedef enum
-{
-  TDEFL_STATUS_BAD_PARAM = -2,
-  TDEFL_STATUS_PUT_BUF_FAILED = -1,
-  TDEFL_STATUS_OKAY = 0,
-  TDEFL_STATUS_DONE = 1,
-} tdefl_status;
-
-// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
-typedef enum
-{
-  TDEFL_NO_FLUSH = 0,
-  TDEFL_SYNC_FLUSH = 2,
-  TDEFL_FULL_FLUSH = 3,
-  TDEFL_FINISH = 4
-} tdefl_flush;
-
-// tdefl's compression state structure.
-typedef struct
-{
-  tdefl_put_buf_func_ptr m_pPut_buf_func;
-  void *m_pPut_buf_user;
-  mz_uint m_flags, m_max_probes[2];
-  int m_greedy_parsing;
-  mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
-  mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
-  mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
-  mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
-  tdefl_status m_prev_return_status;
-  const void *m_pIn_buf;
-  void *m_pOut_buf;
-  size_t *m_pIn_buf_size, *m_pOut_buf_size;
-  tdefl_flush m_flush;
-  const mz_uint8 *m_pSrc;
-  size_t m_src_buf_left, m_out_buf_ofs;
-  mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
-  mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
-  mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
-  mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
-  mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
-  mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
-  mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
-  mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
-} tdefl_compressor;
-
-// Initializes the compressor.
-// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
-// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
-// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
-// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
-tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
-
-// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
-tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
-
-// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
-// tdefl_compress_buffer() always consumes the entire input buffer.
-tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
-
-tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
-mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
-
-// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
-#ifndef MINIZ_NO_ZLIB_APIS
-// Create tdefl_compress() flags given zlib-style compression parameters.
-// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
-// window_bits may be -15 (raw deflate) or 15 (zlib)
-// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
-mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
-#endif // #ifndef MINIZ_NO_ZLIB_APIS
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // MINIZ_HEADER_INCLUDED

+ 0 - 3374
Source/ThirdParty/crunch/crnlib/crn_mipmapped_texture.cpp

@@ -1,3374 +0,0 @@
-// File: crn_dds_texture.cpp - Actually supports both .DDS and .KTX. Probably will rename this eventually.
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_mipmapped_texture.h"
-#include "crn_cfile_stream.h"
-#include "crn_image_utils.h"
-#include "crn_console.h"
-#include "crn_texture_comp.h"
-#include "crn_ktx_texture.h"
-
-#define CRND_HEADER_FILE_ONLY
-#include "../inc/crn_decomp.h"
-
-namespace crnlib
-{
-   const vec2I g_vertical_cross_image_offsets[6] = { vec2I(2, 1), vec2I(0, 1), vec2I(1, 0), vec2I(1, 2), vec2I(1, 1), vec2I(1, 3) };
-
-   mip_level::mip_level() :
-      m_width(0),
-      m_height(0),
-      m_comp_flags(pixel_format_helpers::cDefaultCompFlags),
-      m_format(PIXEL_FMT_INVALID),
-      m_pImage(NULL),
-      m_pDXTImage(NULL),
-      m_orient_flags(cDefaultOrientationFlags)
-   {
-   }
-
-   mip_level::mip_level(const mip_level& other) :
-      m_width(0),
-      m_height(0),
-      m_comp_flags(pixel_format_helpers::cDefaultCompFlags),
-      m_format(PIXEL_FMT_INVALID),
-      m_pImage(NULL),
-      m_pDXTImage(NULL),
-      m_orient_flags(cDefaultOrientationFlags)
-   {
-      *this = other;
-   }
-
-   mip_level& mip_level::operator= (const mip_level& rhs)
-   {
-      clear();
-
-      m_width = rhs.m_width;
-      m_height = rhs.m_height;
-      m_comp_flags = rhs.m_comp_flags;
-      m_format = rhs.m_format;
-      m_orient_flags = rhs.m_orient_flags;
-
-      if (rhs.m_pImage)
-         m_pImage = crnlib_new<image_u8>(*rhs.m_pImage);
-
-      if (rhs.m_pDXTImage)
-         m_pDXTImage = crnlib_new<dxt_image>(*rhs.m_pDXTImage);
-
-      return *this;
-   }
-
-   mip_level::~mip_level()
-   {
-      crnlib_delete(m_pImage);
-      crnlib_delete(m_pDXTImage);
-   }
-
-   void mip_level::clear()
-   {
-      m_width = 0;
-      m_height = 0;
-      m_comp_flags = pixel_format_helpers::cDefaultCompFlags;
-      m_format = PIXEL_FMT_INVALID;
-      m_orient_flags = cDefaultOrientationFlags;
-
-      if (m_pImage)
-      {
-         crnlib_delete(m_pImage);
-         m_pImage = NULL;
-      }
-
-      if (m_pDXTImage)
-      {
-         crnlib_delete(m_pDXTImage);
-         m_pDXTImage = NULL;
-      }
-   }
-
-   void mip_level::assign(image_u8* p, pixel_format fmt, orientation_flags_t orient_flags)
-   {
-      CRNLIB_ASSERT(p);
-
-      clear();
-
-      m_pImage = p;
-
-      m_width = p->get_width();
-      m_height = p->get_height();
-      m_orient_flags = orient_flags;
-
-      if (fmt != PIXEL_FMT_INVALID)
-         m_format = fmt;
-      else
-      {
-         if (p->is_grayscale())
-            m_format = p->is_component_valid(3) ? PIXEL_FMT_A8L8 : PIXEL_FMT_L8;
-         else
-            m_format = p->is_component_valid(3) ? PIXEL_FMT_A8R8G8B8 : PIXEL_FMT_R8G8B8;
-      }
-
-      m_comp_flags = p->get_comp_flags(); //pixel_format_helpers::get_component_flags(m_format);
-   }
-
-   void mip_level::assign(dxt_image* p, pixel_format fmt, orientation_flags_t orient_flags)
-   {
-      CRNLIB_ASSERT(p);
-
-      clear();
-
-      m_pDXTImage = p;
-
-      m_width = p->get_width();
-      m_height = p->get_height();
-      m_orient_flags = orient_flags;
-
-      if (fmt != PIXEL_FMT_INVALID)
-         m_format = fmt;
-      else
-         m_format = pixel_format_helpers::from_dxt_format(p->get_format());
-
-      m_comp_flags = pixel_format_helpers::get_component_flags(m_format);
-   }
-
-   bool mip_level::pack_to_dxt(const image_u8& img, pixel_format fmt, bool cook, const dxt_image::pack_params& orig_params, orientation_flags_t orient_flags)
-   {
-      CRNLIB_ASSERT(pixel_format_helpers::is_dxt(fmt));
-      if (!pixel_format_helpers::is_dxt(fmt))
-         return false;
-
-      dxt_image::pack_params p(orig_params);
-      if (pixel_format_helpers::is_pixel_format_non_srgb(fmt) || (img.get_comp_flags() & pixel_format_helpers::cCompFlagNormalMap) || (img.get_comp_flags() & pixel_format_helpers::cCompFlagLumaChroma))
-      {
-         // Disable perceptual colorspace metrics when packing to swizzled or non-RGB pixel formats.
-         p.m_perceptual = false;
-      }
-
-      image_u8 tmp_img(img);
-
-      clear();
-
-      m_format = fmt;
-
-      if (cook)
-         cook_image(tmp_img);
-
-      if ((pixel_format_helpers::is_alpha_only(fmt)) && (!tmp_img.has_alpha()))
-         tmp_img.set_alpha_to_luma();
-
-      dxt_format dxt_fmt = pixel_format_helpers::get_dxt_format(fmt);
-
-      dxt_image* pDXT_image = crnlib_new<dxt_image>();
-      if (!pDXT_image->init(dxt_fmt, tmp_img, p))
-      {
-         clear();
-         return false;
-      }
-
-      assign(pDXT_image, fmt, orient_flags);
-
-      return true;
-   }
-
-   bool mip_level::pack_to_dxt(pixel_format fmt, bool cook, const dxt_image::pack_params& p)
-   {
-      CRNLIB_ASSERT(pixel_format_helpers::is_dxt(fmt));
-      if (!pixel_format_helpers::is_dxt(fmt))
-         return false;
-
-      image_u8 tmp_img;
-      image_u8* pImage = get_unpacked_image(tmp_img, cUnpackFlagUncook);
-
-      return pack_to_dxt(*pImage, fmt, cook, p, m_orient_flags);
-   }
-
-   bool mip_level::unpack_from_dxt(bool uncook)
-   {
-      if (!m_pDXTImage)
-         return false;
-
-      image_u8* pNew_img = crnlib_new<image_u8>();
-      image_u8* pImg = get_unpacked_image(*pNew_img, uncook ? cUnpackFlagUncook : 0);
-      pImg;
-
-      CRNLIB_ASSERT(pImg == pNew_img);
-
-      assign(pNew_img, PIXEL_FMT_INVALID, m_orient_flags);
-      return true;
-   }
-
-   bool mip_level::is_flipped() const
-   {
-      return ((m_orient_flags & (cOrientationFlagXFlipped | cOrientationFlagYFlipped)) != 0);
-   }
-
-   bool mip_level::is_x_flipped() const
-   {
-      return ((m_orient_flags & cOrientationFlagXFlipped) != 0);
-   }
-
-   bool mip_level::is_y_flipped() const
-   {
-      return ((m_orient_flags & cOrientationFlagYFlipped) != 0);
-   }
-
-   bool mip_level::can_unflip_without_unpacking() const
-   {
-      if (!is_valid())
-         return false;
-
-      if (!is_packed())
-         return true;
-
-      bool can_unflip = true;
-      if (m_orient_flags & cOrientationFlagXFlipped)
-      {
-         if (!m_pDXTImage->can_flip(0))
-            can_unflip = false;
-      }
-      if (m_orient_flags & cOrientationFlagYFlipped)
-      {
-         if (!m_pDXTImage->can_flip(1))
-            can_unflip = false;
-      }
-
-      return can_unflip;
-   }
-
-   bool mip_level::unflip(bool allow_unpacking_to_flip, bool uncook_if_necessary_to_unpack)
-   {
-      if (!is_valid())
-         return false;
-
-      if (!is_flipped())
-         return false;
-
-      if (is_packed())
-      {
-         if (can_unflip_without_unpacking())
-         {
-            if (m_orient_flags & cOrientationFlagXFlipped)
-            {
-               m_pDXTImage->flip_x();
-               m_orient_flags = static_cast<orientation_flags_t>(m_orient_flags & ~cOrientationFlagXFlipped);
-            }
-
-            if (m_orient_flags & cOrientationFlagYFlipped)
-            {
-               m_pDXTImage->flip_y();
-               m_orient_flags = static_cast<orientation_flags_t>(m_orient_flags & ~cOrientationFlagYFlipped);
-            }
-
-            return true;
-         }
-         
-         if (!allow_unpacking_to_flip)
-            return false;
-      }
-      
-      unpack_from_dxt(uncook_if_necessary_to_unpack);
-
-      if (m_orient_flags & cOrientationFlagXFlipped)
-      {
-         m_pImage->flip_x();
-         m_orient_flags = static_cast<orientation_flags_t>(m_orient_flags & ~cOrientationFlagXFlipped);
-      }
-
-      if (m_orient_flags & cOrientationFlagYFlipped)
-      {
-         m_pImage->flip_y();
-         m_orient_flags = static_cast<orientation_flags_t>(m_orient_flags & ~cOrientationFlagYFlipped);
-      }
-
-      return true;
-   }
-
-   bool mip_level::set_alpha_to_luma()
-   {
-      if (m_pDXTImage)
-         unpack_from_dxt(true);
-
-      m_pImage->set_alpha_to_luma();
-
-      m_comp_flags = m_pImage->get_comp_flags();
-
-      if (m_pImage->is_grayscale())
-         m_format = PIXEL_FMT_A8L8;
-      else
-         m_format = PIXEL_FMT_A8R8G8B8;
-
-      return true;
-   }
-
-   bool mip_level::convert(image_utils::conversion_type conv_type)
-   {
-      if (m_pDXTImage)
-         unpack_from_dxt(true);
-
-      image_utils::convert_image(*m_pImage, conv_type);
-
-      m_comp_flags = m_pImage->get_comp_flags();
-
-      if (m_pImage->is_grayscale())
-         m_format = m_pImage->has_alpha() ? PIXEL_FMT_A8L8 : PIXEL_FMT_L8;
-      else
-         m_format = m_pImage->has_alpha() ? PIXEL_FMT_A8R8G8B8 : PIXEL_FMT_R8G8B8;
-
-      return true;
-   }
-
-   bool mip_level::convert(pixel_format fmt, bool cook, const dxt_image::pack_params& p)
-   {
-      if (pixel_format_helpers::is_dxt(fmt))
-         return pack_to_dxt(fmt, cook, p);
-
-      image_u8 tmp_img;
-      image_u8* pImg = get_unpacked_image(tmp_img, cUnpackFlagUncook);
-
-      image_u8* pImage = crnlib_new<image_u8>();
-      pImage->set_comp_flags(pixel_format_helpers::get_component_flags(fmt));
-      
-      if (!pImage->resize(pImg->get_width(), pImg->get_height()))
-         return false;
-
-      for (uint y = 0; y < pImg->get_height(); y++)
-      {
-         for (uint x = 0; x < pImg->get_width(); x++)
-         {
-            color_quad_u8 c((*pImg)(x, y));
-
-            if ((pixel_format_helpers::is_alpha_only(fmt)) && (!pImg->has_alpha()))
-            {
-               c.a = static_cast<uint8>(c.get_luma());
-            }
-            else
-            {
-               if (pImage->is_grayscale())
-               {
-                  uint8 g = static_cast<uint8>(c.get_luma());
-                  c.r = g;
-                  c.g = g;
-                  c.b = g;
-               }
-
-               if (!pImage->is_component_valid(3))
-                  c.a = 255;
-            }
-
-            (*pImage)(x, y) = c;
-         }
-      }
-
-      assign(pImage, fmt, m_orient_flags);
-
-      return true;
-   }
-
-   void mip_level::cook_image(image_u8& img) const
-   {
-      image_utils::conversion_type conv_type = image_utils::get_conversion_type(true, m_format);
-
-      if (conv_type != image_utils::cConversion_Invalid)
-         image_utils::convert_image(img, conv_type);
-   }
-
-   void mip_level::uncook_image(image_u8& img) const
-   {
-      image_utils::conversion_type conv_type = image_utils::get_conversion_type(false, m_format);
-
-      if (conv_type != image_utils::cConversion_Invalid)
-         image_utils::convert_image(img, conv_type);
-   }
-
-   image_u8* mip_level::get_unpacked_image(image_u8& tmp, uint unpack_flags) const
-   {
-      if (!is_valid())
-         return NULL;
-
-      if (m_pDXTImage)
-      {
-         m_pDXTImage->unpack(tmp);
-
-         tmp.set_comp_flags(m_comp_flags);
-
-         if (unpack_flags & cUnpackFlagUncook)
-            uncook_image(tmp);
-      }
-      else if ((unpack_flags & cUnpackFlagUnflip) && (m_orient_flags & (cOrientationFlagXFlipped | cOrientationFlagYFlipped)))
-         tmp = *m_pImage;
-      else
-         return m_pImage;
-
-      if (unpack_flags & cUnpackFlagUnflip)
-      {
-         if (m_orient_flags & cOrientationFlagXFlipped) tmp.flip_x();
-         if (m_orient_flags & cOrientationFlagYFlipped) tmp.flip_y();
-      }
-
-      return &tmp;
-   }
-   
-   bool mip_level::flip_x()
-   {
-      if (!is_valid())
-         return false;
-
-      if (m_pDXTImage)
-         return m_pDXTImage->flip_x();
-      else if (m_pImage)
-      {
-         m_pImage->flip_x();
-         return true;
-      }
-
-      return false;
-   }
-
-   bool mip_level::flip_y()
-   {
-      if (!is_valid())
-         return false;
-
-      if (m_pDXTImage)
-         return m_pDXTImage->flip_y();
-      else if (m_pImage)
-      {
-         m_pImage->flip_y();
-         return true;
-      }
-
-      return false;
-   }
-
-   // -------------------------------------------------------------------------
-
-   mipmapped_texture::mipmapped_texture() :
-      m_width(0),
-      m_height(0),
-      m_comp_flags(pixel_format_helpers::cDefaultCompFlags),
-      m_format(PIXEL_FMT_INVALID),
-      m_source_file_type(texture_file_types::cFormatInvalid)
-   {
-   }
-
-   mipmapped_texture::~mipmapped_texture()
-   {
-      free_all_mips();
-   }
-
-   void mipmapped_texture::clear()
-   {
-      free_all_mips();
-
-      m_name.clear();
-      m_width = 0;
-      m_height = 0;
-      m_comp_flags = pixel_format_helpers::cDefaultCompFlags;
-      m_format = PIXEL_FMT_INVALID;
-      m_source_file_type = texture_file_types::cFormatInvalid;
-      m_last_error.clear();
-   }
-
-   void mipmapped_texture::free_all_mips()
-   {
-      for (uint i = 0; i < m_faces.size(); i++)
-         for (uint j = 0; j < m_faces[i].size(); j++)
-            crnlib_delete(m_faces[i][j]);
-
-      m_faces.clear();
-   }
-
-   mipmapped_texture::mipmapped_texture(const mipmapped_texture& other) :
-      m_width(0),
-      m_height(0),
-      m_comp_flags(pixel_format_helpers::cDefaultCompFlags),
-      m_format(PIXEL_FMT_INVALID)
-   {
-      *this = other;
-   }
-
-   mipmapped_texture& mipmapped_texture::operator= (const mipmapped_texture& rhs)
-   {
-      if (this == &rhs)
-         return *this;
-
-      clear();
-
-      m_name = rhs.m_name;
-      m_width = rhs.m_width;
-      m_height = rhs.m_height;
-
-      m_comp_flags = rhs.m_comp_flags;
-      m_format = rhs.m_format;
-
-      m_faces.resize(rhs.m_faces.size());
-      for (uint i = 0; i < m_faces.size(); i++)
-      {
-         m_faces[i].resize(rhs.m_faces[i].size());
-
-         for (uint j = 0; j < rhs.m_faces[i].size(); j++)
-            m_faces[i][j] = crnlib_new<mip_level>(*rhs.m_faces[i][j]);
-      }
-
-      CRNLIB_ASSERT((!is_valid()) || check());
-
-      return *this;
-   }
-   
-   bool mipmapped_texture::read_dds(data_stream_serializer& serializer)
-   {
-      if (!read_dds_internal(serializer))
-      {
-         clear();
-         return false;
-      }
-
-      return true;
-   }
-
-   bool mipmapped_texture::read_dds_internal(data_stream_serializer& serializer)
-   {
-      CRNLIB_ASSERT(serializer.get_little_endian());
-
-      clear();
-
-      set_last_error("Not a DDS file");
-
-      uint8 hdr[4];
-      if (!serializer.read(hdr, sizeof(hdr)))
-         return false;
-
-      if (memcmp(hdr, "DDS ", 4) != 0)
-         return false;
-
-      DDSURFACEDESC2 desc;
-      if (!serializer.read(&desc, sizeof(desc)))
-         return false;
-
-      if (!c_crnlib_little_endian_platform)
-         utils::endian_switch_dwords(reinterpret_cast<uint32*>(&desc), sizeof(desc) / sizeof(uint32));
-
-      if (desc.dwSize != sizeof(desc))
-         return false;
-
-      if ((!desc.dwHeight) || (!desc.dwWidth) || (desc.dwHeight > cDDSMaxImageDimensions) || (desc.dwWidth > cDDSMaxImageDimensions))
-         return false;
-
-      m_width = desc.dwWidth;
-      m_height = desc.dwHeight;
-
-      uint num_mip_levels = 1;
-
-      if ((desc.dwFlags & DDSD_MIPMAPCOUNT) && (desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) && (desc.dwMipMapCount))
-      {
-         num_mip_levels = desc.dwMipMapCount;
-         if (num_mip_levels > utils::compute_max_mips(desc.dwWidth, desc.dwHeight))
-            return false;
-      }
-
-      uint num_faces = 1;
-
-      if (desc.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
-      {
-         if (desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
-         {
-            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("Incomplete cubemaps unsupported");
-               return false;
-            }
-
-            num_faces = 6;
-         }
-         else if (desc.ddsCaps.dwCaps2 & DDSCAPS2_VOLUME)
-         {
-            set_last_error("Volume textures unsupported");
-            return false;
-         }
-      }
-
-      if (desc.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
-      {
-         // It's difficult to even make P8 textures with existing tools:
-         // nvdxt just hangs
-         // dxtex.exe just makes all-white textures
-         // So screw it.
-         set_last_error("Palettized textures unsupported");
-         return false;
-      }
-
-      dxt_format dxt_fmt = cDXTInvalid;
-
-      if (desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
-      {
-         // http://code.google.com/p/nvidia-texture-tools/issues/detail?id=41
-         // ATI2 YX:            0 (0x00000000)
-         // ATI2 XY:   1498952257 (0x59583241) (BC5)
-         // ATI Compressonator obeys this stuff, nvidia's tools (like readdxt) don't - oh great
-
-         switch (desc.ddpfPixelFormat.dwFourCC)
-         {
-            case PIXEL_FMT_DXT1:
-            {
-               m_format = PIXEL_FMT_DXT1;
-               dxt_fmt = cDXT1;
-               break;
-            }
-            case PIXEL_FMT_DXT2:
-            case PIXEL_FMT_DXT3:
-            {
-               m_format = PIXEL_FMT_DXT3;
-               dxt_fmt = cDXT3;
-               break;
-            }
-            case PIXEL_FMT_DXT4:
-            case PIXEL_FMT_DXT5:
-            {
-               switch (desc.ddpfPixelFormat.dwRGBBitCount)
-               {
-                  case PIXEL_FMT_DXT5_CCxY:
-                     m_format = PIXEL_FMT_DXT5_CCxY;
-                     break;
-                  case PIXEL_FMT_DXT5_xGxR:
-                     m_format = PIXEL_FMT_DXT5_xGxR;
-                     break;
-                  case PIXEL_FMT_DXT5_xGBR:
-                     m_format = PIXEL_FMT_DXT5_xGBR;
-                     break;
-                  case PIXEL_FMT_DXT5_AGBR:
-                     m_format = PIXEL_FMT_DXT5_AGBR;
-                     break;
-                  default:
-                     m_format = PIXEL_FMT_DXT5;
-                     break;
-               }
-
-               dxt_fmt = cDXT5;
-               break;
-            }
-            case PIXEL_FMT_3DC:
-            {
-               if (desc.ddpfPixelFormat.dwRGBBitCount == CRNLIB_PIXEL_FMT_FOURCC('A', '2', 'X', 'Y'))
-               {
-                  dxt_fmt = cDXN_XY;
-                  m_format = PIXEL_FMT_DXN;
-               }
-               else
-               {
-                  dxt_fmt = cDXN_YX; // aka ATI2
-                  m_format = PIXEL_FMT_3DC;
-               }
-
-               break;
-            }
-            case PIXEL_FMT_DXT5A:
-            {
-               m_format = PIXEL_FMT_DXT5A;
-               dxt_fmt = cDXT5A;
-               break;
-            }
-            case PIXEL_FMT_ETC1:
-            {
-               m_format = PIXEL_FMT_ETC1;
-               dxt_fmt = cETC1;
-               break;
-            }
-            default:
-            {
-               dynamic_string err_msg(cVarArg, "Unsupported DDS FOURCC format: 0x%08X", desc.ddpfPixelFormat.dwFourCC);
-               set_last_error(err_msg.get_ptr());
-               return false;
-            }
-         }
-      }
-      else if ((desc.ddpfPixelFormat.dwRGBBitCount < 8) || (desc.ddpfPixelFormat.dwRGBBitCount > 32) || (desc.ddpfPixelFormat.dwRGBBitCount & 7))
-      {
-         set_last_error("Unsupported bit count");
-         return false;
-      }
-      else if (desc.ddpfPixelFormat.dwFlags & DDPF_RGB)
-      {
-         if (desc.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE)
-         {
-            if (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)
-               m_format = PIXEL_FMT_A8L8;
-            else
-               m_format = PIXEL_FMT_L8;
-         }
-         else if (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)
-            m_format = PIXEL_FMT_A8R8G8B8;
-         else
-            m_format = PIXEL_FMT_R8G8B8;
-      }
-      else if (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)
-      {
-         if (desc.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE)
-            m_format = PIXEL_FMT_A8L8;
-         else
-            m_format = PIXEL_FMT_A8;
-      }
-      else if (desc.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE)
-      {
-         m_format = PIXEL_FMT_L8;
-      }
-      else if (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHA)
-      {
-         m_format = PIXEL_FMT_A8;
-      }
-      else
-      {
-         set_last_error("Unsupported format");
-         return false;
-      }
-
-      m_comp_flags = pixel_format_helpers::get_component_flags(m_format);
-
-      uint bits_per_pixel = desc.ddpfPixelFormat.dwRGBBitCount;
-
-      if (desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
-         bits_per_pixel = pixel_format_helpers::get_bpp(m_format);
-
-      set_last_error("Load failed");
-
-      uint default_pitch;
-      if (desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
-         default_pitch = (((desc.dwWidth + 3) & ~3) * ((desc.dwHeight + 3) & ~3) * bits_per_pixel) >> 3;
-      else
-         default_pitch = (desc.dwWidth * bits_per_pixel) >> 3;
-
-      uint pitch = 0;
-      if ( ( desc.dwFlags & DDSD_PITCH ) && ( !( desc.dwFlags & DDSD_LINEARSIZE ) ) )
-      {
-         pitch = desc.lPitch;
-      }
-                  
-      if (!pitch)
-         pitch = default_pitch;
-#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("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("Invalid pitch");
-         return false;
-      }
-
-      crnlib::vector<uint8> load_buf;
-
-      uint mask_size[4];
-      mask_size[0] = math::bitmask_size(desc.ddpfPixelFormat.dwRBitMask);
-      mask_size[1] = math::bitmask_size(desc.ddpfPixelFormat.dwGBitMask);
-      mask_size[2] = math::bitmask_size(desc.ddpfPixelFormat.dwBBitMask);
-      mask_size[3] = math::bitmask_size(desc.ddpfPixelFormat.dwRGBAlphaBitMask);
-
-      uint mask_ofs[4];
-      mask_ofs[0] = math::bitmask_ofs(desc.ddpfPixelFormat.dwRBitMask);
-      mask_ofs[1] = math::bitmask_ofs(desc.ddpfPixelFormat.dwGBitMask);
-      mask_ofs[2] = math::bitmask_ofs(desc.ddpfPixelFormat.dwBBitMask);
-      mask_ofs[3] = math::bitmask_ofs(desc.ddpfPixelFormat.dwRGBAlphaBitMask);
-
-      if ((desc.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) && (!mask_size[0]))
-      {
-         mask_size[0] = desc.ddpfPixelFormat.dwRGBBitCount >> 3;
-         if (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)
-            mask_size[0] /= 2;
-      }
-
-      m_faces.resize(num_faces);
-
-      bool dxt1_alpha = false;
-
-      for (uint face_index = 0; face_index < num_faces; face_index++)
-      {
-         m_faces[face_index].resize(num_mip_levels);
-
-         for (uint level_index = 0; level_index < num_mip_levels; level_index++)
-         {
-            const uint width = math::maximum<uint>(desc.dwWidth >> level_index, 1U);
-            const uint height = math::maximum<uint>(desc.dwHeight >> level_index, 1U);
-
-            mip_level* pMip = crnlib_new<mip_level>();
-            m_faces[face_index][level_index] = pMip;
-
-            if (desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
-            {
-               const uint bytes_per_block = pixel_format_helpers::get_dxt_bytes_per_block(m_format);
-
-               const uint num_blocks_x = (width + 3) >> 2;
-               const uint num_blocks_y = (height + 3) >> 2;
-
-               const uint actual_level_pitch = num_blocks_x * num_blocks_y * bytes_per_block;
-               const uint level_pitch = level_index ? actual_level_pitch : pitch;
-
-               dxt_image* pDXTImage = crnlib_new<dxt_image>();
-               if (!pDXTImage->init(dxt_fmt, width, height, false))
-               {
-                  crnlib_delete(pDXTImage);
-
-                  CRNLIB_ASSERT(0);
-                  return false;
-               }
-               
-               CRNLIB_ASSERT(pDXTImage->get_element_vec().size() * sizeof(dxt_image::element) == actual_level_pitch);
-
-               if (!serializer.read(&pDXTImage->get_element_vec()[0], actual_level_pitch))
-               {
-                  crnlib_delete(pDXTImage);
-
-                  return false;
-               }
-
-               // DDS image in memory are always assumed to be little endian - the same as DDS itself.
-               //if (c_crnlib_big_endian_platform)
-               //   utils::endian_switch_words(reinterpret_cast<uint16*>(&pDXTImage->get_element_vec()[0]), actual_level_pitch / sizeof(uint16));
-
-               if (level_pitch > actual_level_pitch)
-               {
-                  if (!serializer.skip(level_pitch - actual_level_pitch))
-                  {
-                     crnlib_delete(pDXTImage);
-
-                     return false;
-                  }
-               }
-
-               if ((m_format == PIXEL_FMT_DXT1) && (!dxt1_alpha))
-                  dxt1_alpha = pDXTImage->has_alpha();
-
-               pMip->assign(pDXTImage, m_format);
-            }
-            else
-            {
-               image_u8* pImage = crnlib_new<image_u8>(width, height);
-
-               pImage->set_comp_flags(m_comp_flags);
-
-               const uint bytes_per_pixel = desc.ddpfPixelFormat.dwRGBBitCount >> 3;
-               const uint actual_line_pitch = width * bytes_per_pixel;
-               const uint line_pitch = level_index ? actual_line_pitch : pitch;
-
-               if (load_buf.size() < line_pitch)
-                  load_buf.resize(line_pitch);
-
-               color_quad_u8 q(0, 0, 0, 255);
-
-               for (uint y = 0; y < height; y++)
-               {
-                  if (!serializer.read(&load_buf[0], line_pitch))
-                  {
-                     crnlib_delete(pImage);
-                     return false;
-                  }
-
-                  color_quad_u8* pDst = pImage->get_scanline(y);
-
-                  for (uint x = 0; x < width; x++)
-                  {
-                     const uint8* pPixel = &load_buf[x * bytes_per_pixel];
-
-                     uint c = 0;
-                     // Assumes DDS is always little endian.
-                     for (uint l = 0; l < bytes_per_pixel; l++)
-                        c |= (pPixel[l] << (l * 8U));
-
-                     for (uint i = 0; i < 4; i++)
-                     {
-                        if (!mask_size[i])
-                           continue;
-
-                        uint mask = (1U << mask_size[i]) - 1U;
-                        uint bits = (c >> mask_ofs[i]) & mask;
-
-                        uint v = (bits * 255 + (mask >> 1)) / mask;
-
-                        q.set_component(i, v);
-                     }
-
-                     if (desc.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE)
-                     {
-                        q.g = q.r;
-                        q.b = q.r;
-                     }
-
-                     *pDst++ = q;
-                  }
-               }
-
-               pMip->assign(pImage, m_format);
-               
-               CRNLIB_ASSERT(pMip->get_comp_flags() == m_comp_flags);
-            }
-         }
-      }
-      
-      clear_last_error();
-
-      if (dxt1_alpha)
-         change_dxt1_to_dxt1a();
-      
-      return true;
-   }
-
-   void mipmapped_texture::change_dxt1_to_dxt1a()
-   {
-      if (m_format != PIXEL_FMT_DXT1)
-         return;
-
-      m_format = PIXEL_FMT_DXT1A;
-
-      m_comp_flags = pixel_format_helpers::get_component_flags(m_format);
-
-      for (uint f = 0; f < m_faces.size(); f++)
-      {
-         for (uint l = 0; l < m_faces[f].size(); l++)
-         {
-            if (m_faces[f][l]->get_dxt_image())
-            {
-               m_faces[f][l]->set_format(m_format);
-               m_faces[f][l]->set_comp_flags(m_comp_flags);
-
-               m_faces[f][l]->get_dxt_image()->change_dxt1_to_dxt1a();
-            }
-         }
-      }
-   }
-
-   bool mipmapped_texture::check() const
-   {
-      uint levels = 0;
-      orientation_flags_t orient_flags = cDefaultOrientationFlags;
-      for (uint f = 0; f < m_faces.size(); f++)
-      {
-         if (!f)
-         {
-            levels = m_faces[f].size();
-            if ((levels) && (m_faces[f][0]))
-               orient_flags = m_faces[f][0]->get_orientation_flags();
-         }
-         else if (m_faces[f].size() != levels)
-            return false;
-
-         for (uint l = 0; l < m_faces[f].size(); l++)
-         {
-            mip_level* p = m_faces[f][l];
-            if (!p)
-               return false;
-
-            if (!p->is_valid())
-               return false;
-
-            if (p->get_orientation_flags() != orient_flags)
-               return false;
-
-            if (!l)
-            {
-               if (m_width != p->get_width())
-                  return false;
-               if (m_height != p->get_height())
-                  return false;
-            }
-
-            if (p->get_comp_flags() != m_comp_flags)
-               return false;
-
-            if (p->get_format() != m_format)
-               return false;
-
-            if (p->get_image())
-            {
-               if (pixel_format_helpers::is_dxt(p->get_format()))
-                  return false;
-
-               if (p->get_image()->get_width() != p->get_width())
-                  return false;
-               if (p->get_image()->get_height() != p->get_height())
-                  return false;
-               if (p->get_image()->get_comp_flags() != m_comp_flags)
-                  return false;
-            }
-            else if (!pixel_format_helpers::is_dxt(p->get_format()))
-               return false;
-         }
-      }
-
-      return true;
-   }
-
-   bool mipmapped_texture::write_dds(data_stream_serializer& serializer) const
-   {
-      if (!m_width)
-      {
-         set_last_error("Nothing to write");
-         return false;
-      }
-
-      set_last_error("write_dds() failed");
-
-      if (!serializer.write("DDS ", sizeof(uint32)))
-         return false;
-
-      DDSURFACEDESC2 desc;
-      utils::zero_object(desc);
-
-      desc.dwSize = sizeof(desc);
-      desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
-            
-      desc.dwWidth = m_width;
-      desc.dwHeight = m_height;
-
-      desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
-      desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
-
-      if (get_num_levels() > 1)
-      {
-         desc.dwMipMapCount = get_num_levels();
-         desc.dwFlags |= DDSD_MIPMAPCOUNT;
-         desc.ddsCaps.dwCaps |= (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX);
-      }
-
-      if (get_num_faces() > 1)
-      {
-         desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
-         desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP;
-         desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX|DDSCAPS2_CUBEMAP_NEGATIVEX|DDSCAPS2_CUBEMAP_POSITIVEY|DDSCAPS2_CUBEMAP_NEGATIVEY|DDSCAPS2_CUBEMAP_POSITIVEZ|DDSCAPS2_CUBEMAP_NEGATIVEZ;
-      }
-
-      bool dxt_format = false;
-      if (pixel_format_helpers::is_dxt(m_format))
-      {
-         dxt_format = true;
-
-         desc.ddpfPixelFormat.dwFlags |= DDPF_FOURCC;
-
-         switch (m_format)
-         {
-            case PIXEL_FMT_ETC1:
-            {
-               desc.ddpfPixelFormat.dwFourCC = (uint32)PIXEL_FMT_ETC1;
-               desc.ddpfPixelFormat.dwRGBBitCount = 0;
-               break;
-            }
-            case PIXEL_FMT_DXN:
-            {
-               desc.ddpfPixelFormat.dwFourCC = (uint32)PIXEL_FMT_3DC;
-               desc.ddpfPixelFormat.dwRGBBitCount = PIXEL_FMT_DXN;
-               break;
-            }
-            case PIXEL_FMT_DXT1A:
-            {
-               desc.ddpfPixelFormat.dwFourCC = (uint32)PIXEL_FMT_DXT1;
-               desc.ddpfPixelFormat.dwRGBBitCount = 0;
-               break;
-            }
-            case PIXEL_FMT_DXT5_CCxY:
-            {
-               desc.ddpfPixelFormat.dwFourCC = (uint32)PIXEL_FMT_DXT5;
-               desc.ddpfPixelFormat.dwRGBBitCount = (uint32)PIXEL_FMT_DXT5_CCxY;
-               break;
-            }
-            case PIXEL_FMT_DXT5_xGxR:
-            {
-               desc.ddpfPixelFormat.dwFourCC = (uint32)PIXEL_FMT_DXT5;
-               desc.ddpfPixelFormat.dwRGBBitCount = (uint32)PIXEL_FMT_DXT5_xGxR;
-               break;
-            }
-            case PIXEL_FMT_DXT5_xGBR:
-            {
-               desc.ddpfPixelFormat.dwFourCC = (uint32)PIXEL_FMT_DXT5;
-               desc.ddpfPixelFormat.dwRGBBitCount = (uint32)PIXEL_FMT_DXT5_xGBR;
-               break;
-            }
-            case PIXEL_FMT_DXT5_AGBR:
-            {
-               desc.ddpfPixelFormat.dwFourCC = (uint32)PIXEL_FMT_DXT5;
-               desc.ddpfPixelFormat.dwRGBBitCount = (uint32)PIXEL_FMT_DXT5_AGBR;
-               break;
-            }
-            default:
-            {
-               desc.ddpfPixelFormat.dwFourCC = (uint32)m_format;
-               desc.ddpfPixelFormat.dwRGBBitCount = 0;
-               break;
-            }
-         }
-
-         uint bits_per_pixel = pixel_format_helpers::get_bpp(m_format);
-         desc.lPitch = (((desc.dwWidth + 3) & ~3) * ((desc.dwHeight + 3) & ~3) * bits_per_pixel) >> 3;
-         desc.dwFlags |= DDSD_LINEARSIZE;
-      }
-      else
-      {
-         switch (m_format)
-         {
-            case PIXEL_FMT_A8R8G8B8:
-            {
-               desc.ddpfPixelFormat.dwFlags |= (DDPF_RGB | DDPF_ALPHAPIXELS);
-               desc.ddpfPixelFormat.dwRGBBitCount = 32;
-               desc.ddpfPixelFormat.dwRBitMask = 0xFF0000;
-               desc.ddpfPixelFormat.dwGBitMask = 0x00FF00;
-               desc.ddpfPixelFormat.dwBBitMask = 0x0000FF;
-               desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
-               break;
-            }
-            case PIXEL_FMT_R8G8B8:
-            {
-               desc.ddpfPixelFormat.dwFlags |= DDPF_RGB;
-               desc.ddpfPixelFormat.dwRGBBitCount = 24;
-               desc.ddpfPixelFormat.dwRBitMask = 0xFF0000;
-               desc.ddpfPixelFormat.dwGBitMask = 0x00FF00;
-               desc.ddpfPixelFormat.dwBBitMask = 0x0000FF;
-               break;
-            }
-            case PIXEL_FMT_A8:
-            {
-               desc.ddpfPixelFormat.dwFlags |= DDPF_ALPHA;
-               desc.ddpfPixelFormat.dwRGBBitCount = 8;
-               desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF;
-               break;
-            }
-            case PIXEL_FMT_L8:
-            {
-               desc.ddpfPixelFormat.dwFlags |= DDPF_LUMINANCE;
-               desc.ddpfPixelFormat.dwRGBBitCount = 8;
-               desc.ddpfPixelFormat.dwRBitMask = 0xFF;
-               break;
-            }
-            case PIXEL_FMT_A8L8:
-            {
-               desc.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS | DDPF_LUMINANCE;
-               desc.ddpfPixelFormat.dwRGBBitCount = 16;
-               desc.ddpfPixelFormat.dwRBitMask = 0xFF;
-               desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF00;
-               break;
-            }
-            default:
-            {
-               CRNLIB_ASSERT(false);
-               return false;
-            }
-         }
-
-         uint bits_per_pixel = desc.ddpfPixelFormat.dwRGBBitCount;
-         desc.lPitch = (desc.dwWidth * bits_per_pixel) >> 3;
-         desc.dwFlags |= DDSD_LINEARSIZE;
-      }
-
-      if (!c_crnlib_little_endian_platform)
-         utils::endian_switch_dwords(reinterpret_cast<uint32*>(&desc), sizeof(desc) / sizeof(uint32));
-
-      if (!serializer.write(&desc, sizeof(desc)))
-         return false;
-
-      if (!c_crnlib_little_endian_platform)
-         utils::endian_switch_dwords(reinterpret_cast<uint32*>(&desc), sizeof(desc) / sizeof(uint32));
-
-      crnlib::vector<uint8> write_buf;
-
-      const bool can_unflip_packed_texture = can_unflip_without_unpacking();
-      if ((is_packed()) && (is_flipped()) && (!can_unflip_without_unpacking()))
-      {
-         console::warning("mipmapped_texture::write_dds: One or more faces/miplevels cannot be unflipped without unpacking. Writing flipped .DDS texture.");
-      }
-
-      for (uint face = 0; face < get_num_faces(); face++)
-      {
-         for (uint level = 0; level < get_num_levels(); level++)
-         {
-            const mip_level* pLevel = get_level(face, level);
-
-            if (dxt_format)
-            {
-               const uint width = pLevel->get_width();
-               const uint height = pLevel->get_height();
-
-               CRNLIB_ASSERT(width == math::maximum<uint>(1, m_width >> level));
-               CRNLIB_ASSERT(height == math::maximum<uint>(1, m_height >> level));
-
-               const dxt_image* p = pLevel->get_dxt_image();
-               dxt_image tmp;
-               if ((can_unflip_packed_texture) && (pLevel->get_orientation_flags() & (cOrientationFlagXFlipped | cOrientationFlagYFlipped)))
-               {
-                  tmp = *p;
-                  if (pLevel->get_orientation_flags() & cOrientationFlagXFlipped) 
-                  {
-                     if (!tmp.flip_x())
-                        console::warning("mipmapped_texture::write_dds: Unable to unflip compressed texture on X axis");
-                  }
-
-                  if (pLevel->get_orientation_flags() & cOrientationFlagYFlipped) 
-                  {
-                     if (!tmp.flip_y())
-                        console::warning("mipmapped_texture::write_dds: Unable to unflip compressed texture on Y axis");
-                  }
-                  p = &tmp;
-               }
-
-               const uint num_blocks_x = (width + 3) >> 2;
-               const uint num_blocks_y = (height + 3) >> 2;
-
-               CRNLIB_ASSERT(num_blocks_x * num_blocks_y * p->get_elements_per_block() == p->get_total_elements());
-               width, height, num_blocks_x, num_blocks_y;
-
-               const uint size_in_bytes = p->get_total_elements() * sizeof(dxt_image::element);
-               if (size_in_bytes > write_buf.size())
-                  write_buf.resize(size_in_bytes);
-
-               memcpy(&write_buf[0], p->get_element_ptr(), size_in_bytes);
-
-               // DXT data is always little endian in memory, just like the DDS format.
-               // (Except for ETC1, which contains big endian 64-bit QWORD's).
-               //if (!c_crnlib_little_endian_platform)
-               //   utils::endian_switch_words(reinterpret_cast<WORD*>(&write_buf[0]), size_in_bytes / sizeof(WORD));
-
-               if (!serializer.write(&write_buf[0], size_in_bytes))
-                  return false;
-            }
-            else
-            {
-               const uint width = pLevel->get_width();
-               const uint height = pLevel->get_height();
-
-               const image_u8* p = pLevel->get_image();
-               image_u8 tmp;
-               if (pLevel->get_orientation_flags() & (cOrientationFlagXFlipped | cOrientationFlagYFlipped))
-               {
-                  p = pLevel->get_unpacked_image(tmp, cUnpackFlagUnflip);
-               }
-
-               const uint bits_per_pixel = desc.ddpfPixelFormat.dwRGBBitCount;
-               const uint bytes_per_pixel = bits_per_pixel >> 3;
-
-               const uint pitch = width * bytes_per_pixel;
-               if (pitch > write_buf.size())
-                  write_buf.resize(pitch);
-
-               for (uint y = 0; y < height; y++)
-               {
-                  const color_quad_u8* pSrc = p->get_scanline(y);
-                  const color_quad_u8* pEnd = pSrc + width;
-
-                  uint8* pDst = &write_buf[0];
-
-                  do
-                  {
-                     const color_quad_u8& c = *pSrc;
-
-                     uint x = 0;
-                     switch (m_format)
-                     {
-                        case PIXEL_FMT_A8R8G8B8:
-                        {
-                           x = (c.a << 24) | (c.r << 16) | (c.g << 8) | c.b;
-                           break;
-                        }
-                        case PIXEL_FMT_R8G8B8:
-                        {
-                           x = (c.r << 16) | (c.g << 8) | c.b;
-                           break;
-                        }
-                        case PIXEL_FMT_A8:
-                        {
-                           x = c.a;
-                           break;
-                        }
-                        case PIXEL_FMT_A8L8:
-                        {
-                           x = (c.a << 8) | c.get_luma();
-                           break;
-                        }
-                        case PIXEL_FMT_L8:
-                        {
-                           x = c.get_luma();
-                           break;
-                        }
-                        default: break;
-                     }
-
-                     pDst[0] = static_cast<uint8>(x);
-                     if (bytes_per_pixel > 1)
-                     {
-                        pDst[1] = static_cast<uint8>(x >> 8);
-
-                        if (bytes_per_pixel > 2)
-                        {
-                           pDst[2] = static_cast<uint8>(x >> 16);
-
-                           if (bytes_per_pixel > 3)
-                              pDst[3] = static_cast<uint8>(x >> 24);
-                        }
-                     }
-
-                     pSrc++;
-                     pDst += bytes_per_pixel;
-
-                  } while (pSrc != pEnd);
-
-                  if (!serializer.write(&write_buf[0], pitch))
-                     return false;
-               }
-            }
-         }
-      }
-
-      clear_last_error();
-
-      return true;
-   }
-
-   bool mipmapped_texture::read_ktx(data_stream_serializer& serializer)
-   {
-      clear();
-
-      set_last_error("Unable to read KTX file");
-
-      ktx_texture kt;
-      if (!kt.read_from_stream(serializer))
-         return false;
-
-      if ((kt.get_depth() > 1) || (kt.get_array_size() > 1))
-      {
-         set_last_error("read_ktx: Depth and array textures are not supported");
-         return false;
-      }
-
-      // Must be 1D, 2D, or a cubemap, with or without mipmaps.
-      m_width = kt.get_width();
-      m_height = kt.get_height();
-
-      uint num_mip_levels = kt.get_num_mips();
-      uint num_faces = kt.get_num_faces();
-
-      uint32 crnlib_fourcc = 0;
-      dynamic_string crnlib_fourcc_str;
-      if (kt.get_key_value_as_string("CRNLIB_FOURCC", crnlib_fourcc_str))
-      {
-         if (crnlib_fourcc_str.get_len() == 4)
-         {
-            for (int i = 3; i >= 0; i--)
-               crnlib_fourcc = (crnlib_fourcc << 8) | crnlib_fourcc_str[i];
-         }
-      }
-
-      const bool is_compressed_texture = kt.is_compressed();
-      dxt_format dxt_fmt = cDXTInvalid;
-      
-      pixel_packer unpacker;
-      if (is_compressed_texture)
-      {
-         switch (kt.get_ogl_internal_fmt())
-         {
-            case KTX_ETC1_RGB8_OES:
-               dxt_fmt = cETC1;
-               break;
-            case KTX_RGB_S3TC:
-            case KTX_RGB4_S3TC:
-            case KTX_COMPRESSED_RGB_S3TC_DXT1_EXT:
-            case KTX_COMPRESSED_SRGB_S3TC_DXT1_EXT:
-               dxt_fmt = cDXT1;
-               break;
-            case KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-            case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
-               dxt_fmt = cDXT1A;
-               break;
-            case KTX_RGBA_S3TC:
-            case KTX_RGBA4_S3TC:
-            case KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-            case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
-               dxt_fmt = cDXT3;
-               break;
-            case KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-            case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
-            case KTX_RGBA_DXT5_S3TC:
-            case KTX_RGBA4_DXT5_S3TC:
-               dxt_fmt = cDXT5;
-               break;
-            case KTX_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
-               dxt_fmt = cDXN_YX;
-               if (crnlib_fourcc == PIXEL_FMT_DXN)
-               {
-                  dxt_fmt = cDXN_XY;
-               }
-               break;
-            case KTX_COMPRESSED_LUMINANCE_LATC1_EXT:
-               dxt_fmt = cDXT5A;
-               break;
-            default:
-               set_last_error("Unsupported KTX internal format");
-               return false;
-         }
-
-         m_format = pixel_format_helpers::from_dxt_format(dxt_fmt);
-         if (m_format == PIXEL_FMT_INVALID)
-         {
-            set_last_error("Unsupported KTX internal compressed format");
-            return false;
-         }
-
-         if (crnlib_fourcc != 0)
-         {
-            switch (crnlib_fourcc)
-            {
-               case PIXEL_FMT_DXT5_CCxY:
-               case PIXEL_FMT_DXT5_xGxR:
-               case PIXEL_FMT_DXT5_xGBR:
-               case PIXEL_FMT_DXT5_AGBR:
-               {
-                  if (dxt_fmt == cDXT5)
-                  {
-                     m_format = static_cast<pixel_format>(crnlib_fourcc);
-                  }
-                  break;
-               }
-            }
-         }
-      }
-      else
-      {
-         m_format = PIXEL_FMT_A8R8G8B8; 
-         const uint type_size = get_ogl_type_size(kt.get_ogl_type());
-         const uint type_bits = type_size * 8;
-
-         // Normal component order:   1,2,3,4 (*last* component packed into LSB of output type)
-         // Reversed component order: 4,3,2,1 (*first* component packed into LSB of output type)
-
-         if (is_packed_pixel_ogl_type(kt.get_ogl_type()))
-         {
-            switch (kt.get_ogl_type())
-            {
-               // 24bpp packed formats
-               case KTX_UNSIGNED_BYTE_3_3_2:          unpacker.init("B2G3R3"); m_format = PIXEL_FMT_R8G8B8; break;
-               case KTX_UNSIGNED_BYTE_2_3_3_REV:      unpacker.init("R3G3B2"); m_format = PIXEL_FMT_R8G8B8; break;
-               case KTX_UNSIGNED_SHORT_5_6_5:         unpacker.init("B5G6R5"); m_format = PIXEL_FMT_R8G8B8; break;
-               case KTX_UNSIGNED_SHORT_5_6_5_REV:     unpacker.init("R5G6B5"); m_format = PIXEL_FMT_R8G8B8; break;
-               // 32bpp packed formats
-               case KTX_UNSIGNED_SHORT_4_4_4_4:       unpacker.init("A4B4G4R4"); break;
-               case KTX_UNSIGNED_SHORT_4_4_4_4_REV:   unpacker.init("R4G4B4A4"); break;
-               case KTX_UNSIGNED_SHORT_5_5_5_1:       unpacker.init("A1B5G5R5"); break;
-               case KTX_UNSIGNED_SHORT_1_5_5_5_REV:   unpacker.init("R5G5B5A1"); break;
-               case KTX_UNSIGNED_INT_8_8_8_8:         unpacker.init("A8B8G8R8"); break;
-               case KTX_UNSIGNED_INT_8_8_8_8_REV:     unpacker.init("R8G8B8A8"); break;
-               case KTX_UNSIGNED_INT_10_10_10_2:      unpacker.init("A2B10G10R10"); break;
-               case KTX_UNSIGNED_INT_2_10_10_10_REV:  unpacker.init("R10G10B10A2"); break;
-               case KTX_UNSIGNED_INT_5_9_9_9_REV:     unpacker.init("R9G9B9A5"); break;
-               default:
-                  set_last_error("Unsupported KTX packed pixel type");
-                  return false;
-            }
-
-            unpacker.set_pixel_stride(get_ogl_type_size(kt.get_ogl_type()));
-         }
-         else
-         {
-            switch (kt.get_ogl_fmt())
-            {
-               case 1:
-               case KTX_RED:
-               case KTX_RED_INTEGER:
-               case KTX_R8:
-               case KTX_R8UI: 
-               {
-                  unpacker.init("R", -1, type_bits);
-                  m_format = PIXEL_FMT_R8G8B8;
-                  break;
-               }
-               case KTX_GREEN:
-               case KTX_GREEN_INTEGER:
-               {
-                  unpacker.init("G", -1, type_bits);
-                  m_format = PIXEL_FMT_R8G8B8;
-                  break;
-               }
-               case KTX_BLUE:
-               case KTX_BLUE_INTEGER:
-               {
-                  unpacker.init("B", -1, type_bits);
-                  m_format = PIXEL_FMT_R8G8B8;
-                  break;
-               }
-               case KTX_ALPHA:
-               {
-                  unpacker.init("A", -1, type_bits);
-                  m_format = PIXEL_FMT_A8;
-                  break;
-               }
-               case KTX_LUMINANCE:
-               {
-                  unpacker.init("Y", -1, type_bits);
-                  m_format = PIXEL_FMT_L8;
-                  break;
-               }
-               case 2:
-               case KTX_RG:
-               case KTX_RG8:
-               case KTX_RG_INTEGER:
-               {
-                  unpacker.init("RG", -1, type_bits);
-                  m_format = PIXEL_FMT_A8L8;
-                  break;
-               }
-               case KTX_LUMINANCE_ALPHA:
-               {
-                  unpacker.init("YA", -1, type_bits);
-                  m_format = PIXEL_FMT_A8L8;
-                  break;
-               }  
-               case 3:
-               case KTX_SRGB: 
-               case KTX_RGB: 
-               case KTX_RGB_INTEGER: 
-               case KTX_RGB8: 
-               case KTX_SRGB8: 
-               {
-                  unpacker.init("RGB", -1, type_bits);
-                  m_format = PIXEL_FMT_R8G8B8;
-                  break;
-               }  
-               case KTX_BGR:
-               case KTX_BGR_INTEGER: 
-               {
-                  unpacker.init("BGR", -1, type_bits);
-                  m_format = PIXEL_FMT_R8G8B8;
-                  break;
-               }  
-               case 4:
-               case KTX_RGBA_INTEGER: 
-               case KTX_RGBA: 
-               case KTX_SRGB_ALPHA: 
-               case KTX_SRGB8_ALPHA8: 
-               case KTX_RGBA8: 
-               {
-                  unpacker.init("RGBA", -1, type_bits);
-                  break;
-               }  
-               case KTX_BGRA:
-               case KTX_BGRA_INTEGER:
-               {
-                  unpacker.init("BGRA", -1, type_bits);
-                  break;
-               }  
-               default:
-                  set_last_error("Unsupported KTX pixel format");
-                  return false;
-            }
-            
-            unpacker.set_pixel_stride(unpacker.get_num_comps() * get_ogl_type_size(kt.get_ogl_type()));
-         }
-
-         CRNLIB_ASSERT(unpacker.is_valid());
-      }
-
-      m_comp_flags = pixel_format_helpers::get_component_flags(m_format);
-
-      m_faces.resize(num_faces);
-
-      bool x_flipped = false;
-      bool y_flipped = true;
-
-      dynamic_string orient;
-      if ((kt.get_key_value_as_string("KTXorientation", orient)) && (orient.get_len() >= 7))
-      {
-         //  0123456
-         // "S=r,T=d"
-         if ((orient[0] == 'S') && (orient[1] == '=') && (orient[3] == ',') && 
-             (orient[4] == 'T') && (orient[5] == '='))
-         {
-            if (tolower(orient[2]) == 'l')
-               x_flipped = true;
-            else if (tolower(orient[2]) == 'r')
-               x_flipped = false;
-            
-            if (tolower(orient[6]) == 'u')
-               y_flipped = true;
-            else if (tolower(orient[6]) == 'd')
-               y_flipped = false;
-         }
-      }
-
-      orientation_flags_t orient_flags = cDefaultOrientationFlags;
-      if (x_flipped) orient_flags = static_cast<orientation_flags_t>(orient_flags | cOrientationFlagXFlipped);
-      if (y_flipped) orient_flags = static_cast<orientation_flags_t>(orient_flags | cOrientationFlagYFlipped);
-      
-      bool dxt1_alpha = false;
-
-      for (uint face_index = 0; face_index < num_faces; face_index++)
-      {
-         m_faces[face_index].resize(num_mip_levels);
-
-         for (uint level_index = 0; level_index < num_mip_levels; level_index++)
-         {
-            const uint width = math::maximum<uint>(m_width >> level_index, 1U);
-            const uint height = math::maximum<uint>(m_height >> level_index, 1U);
-
-            mip_level* pMip = crnlib_new<mip_level>();
-            m_faces[face_index][level_index] = pMip;
-
-            const crnlib::vector<uint8>& image_data = kt.get_image_data(level_index, 0, face_index, 0);
-            
-            if (is_compressed_texture)
-            {
-               const uint bytes_per_block = pixel_format_helpers::get_dxt_bytes_per_block(m_format);
-
-               const uint num_blocks_x = (width + 3) >> 2;
-               const uint num_blocks_y = (height + 3) >> 2;
-
-               const uint level_pitch = num_blocks_x * num_blocks_y * bytes_per_block;
-               if (image_data.size() != level_pitch)
-                  return false;
-
-               dxt_image* pDXTImage = crnlib_new<dxt_image>();
-               if (!pDXTImage->init(dxt_fmt, width, height, false))
-               {
-                  crnlib_delete(pDXTImage);
-
-                  CRNLIB_ASSERT(0);
-                  return false;
-               }
-
-               CRNLIB_ASSERT(pDXTImage->get_element_vec().size() * sizeof(dxt_image::element) == level_pitch);
-               
-               memcpy(&pDXTImage->get_element_vec()[0], image_data.get_ptr(), image_data.size());
-
-               if ((m_format == PIXEL_FMT_DXT1) && (!dxt1_alpha))
-                  dxt1_alpha = pDXTImage->has_alpha();
-
-               pMip->assign(pDXTImage, m_format, orient_flags);
-            }
-            else
-            {
-               if (image_data.size() != (width * height * unpacker.get_pixel_stride()))
-                  return false;
-
-               image_u8* pImage = crnlib_new<image_u8>(width, height);
-
-               pImage->set_comp_flags(m_comp_flags);
-
-               const uint8* pSrc = image_data.get_ptr();
-                                             
-               color_quad_u8 q(0, 0, 0, 255);
-
-               for (uint y = 0; y < height; y++)
-               {
-                  for (uint x = 0; x < width; x++)
-                  {
-                     color_quad_u8 c;
-                     pSrc = static_cast<const uint8*>(unpacker.unpack(pSrc, c));
-                     pImage->set_pixel_unclipped(x, y, c);
-                  }
-               }
-
-               pMip->assign(pImage, m_format, orient_flags);
-
-               CRNLIB_ASSERT(pMip->get_comp_flags() == m_comp_flags);
-            }
-         }
-      }
-
-      clear_last_error();
-
-      if (dxt1_alpha)
-         change_dxt1_to_dxt1a();
-      
-      return true;
-   }
-
-   bool mipmapped_texture::write_ktx(data_stream_serializer& serializer) const
-   {
-      if (!m_width)
-      {
-         set_last_error("Nothing to write");
-         return false;
-      }
-
-      set_last_error("write_ktx() failed");
-
-      uint32 ogl_internal_fmt = 0, ogl_fmt = 0, ogl_type = 0;
-
-      pixel_packer packer;
-            
-      if (is_packed())
-      {
-         switch (get_format())
-         {
-            case PIXEL_FMT_DXT1: 
-            {
-               ogl_internal_fmt = KTX_COMPRESSED_RGB_S3TC_DXT1_EXT;
-               break;
-            }
-            case PIXEL_FMT_DXT1A:
-            {
-               ogl_internal_fmt = KTX_COMPRESSED_RGBA_S3TC_DXT1_EXT;
-               break;
-            }
-            case PIXEL_FMT_DXT2:
-            case PIXEL_FMT_DXT3:
-            {
-               ogl_internal_fmt = KTX_COMPRESSED_RGBA_S3TC_DXT3_EXT;
-               break;
-            }
-            case PIXEL_FMT_DXT4:
-            case PIXEL_FMT_DXT5:
-            case PIXEL_FMT_DXT5_CCxY:
-            case PIXEL_FMT_DXT5_xGxR:
-            case PIXEL_FMT_DXT5_xGBR:
-            case PIXEL_FMT_DXT5_AGBR:
-            {
-               ogl_internal_fmt = KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT;
-               break;
-            }
-            case PIXEL_FMT_3DC:
-            case PIXEL_FMT_DXN:
-            {
-               ogl_internal_fmt = KTX_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
-               break;
-            }
-            case PIXEL_FMT_DXT5A:
-            {
-               ogl_internal_fmt = KTX_COMPRESSED_LUMINANCE_LATC1_EXT;
-               break;
-            }
-            case PIXEL_FMT_ETC1:
-            {
-               ogl_internal_fmt = KTX_ETC1_RGB8_OES;
-               break;
-            }
-            default:
-            {
-               CRNLIB_ASSERT(0);
-               return false;
-            }
-         }
-      }
-      else
-      {
-         ogl_type = KTX_UNSIGNED_BYTE;
-
-         switch (get_format())
-         {
-            case PIXEL_FMT_R8G8B8:     ogl_internal_fmt = KTX_RGB8;              ogl_fmt = KTX_RGB;               packer.init("R8G8B8"); break;
-            case PIXEL_FMT_L8:         ogl_internal_fmt = KTX_LUMINANCE8;        ogl_fmt = KTX_LUMINANCE;         packer.init("G8"); break;
-            case PIXEL_FMT_A8:         ogl_internal_fmt = KTX_ALPHA8;            ogl_fmt = KTX_ALPHA;             packer.init("A8"); break;
-            case PIXEL_FMT_A8L8:       ogl_internal_fmt = KTX_LUMINANCE8_ALPHA8; ogl_fmt = KTX_LUMINANCE_ALPHA;   packer.init("Y8A8"); break;
-            case PIXEL_FMT_A8R8G8B8:   ogl_internal_fmt = KTX_RGBA8;             ogl_fmt = KTX_RGBA;              packer.init("R8G8B8A8"); break;
-            default:
-            {
-               CRNLIB_ASSERT(0);
-               return false;
-            }
-         }
-      }
-      
-      ktx_texture kt;      
-      bool success;
-      if (determine_texture_type() == cTextureTypeCubemap)
-         success = kt.init_cubemap(get_width(), get_num_levels(), ogl_internal_fmt, ogl_fmt, ogl_type);
-      else
-         success = kt.init_2D(get_width(), get_height(), get_num_levels(), ogl_internal_fmt, ogl_fmt, ogl_type);
-      if (!success)
-         return false;
-            
-      dynamic_string fourcc_str(cVarArg, "%c%c%c%c", m_format & 0xFF, (m_format >> 8) & 0xFF, (m_format >> 16) & 0xFF, (m_format >> 24) & 0xFF);
-      kt.add_key_value("CRNLIB_FOURCC", fourcc_str.get_ptr());
-
-      const mip_level* pLevel0 = get_level(0, 0);
-      dynamic_string ktx_orient_str(cVarArg, "S=%c,T=%c", (pLevel0->get_orientation_flags() & cOrientationFlagXFlipped) ? 'l' : 'r', (pLevel0->get_orientation_flags() & cOrientationFlagYFlipped) ? 'u' : 'd');
-      kt.add_key_value("KTXorientation", ktx_orient_str.get_ptr());
-      
-      for (uint face_index = 0; face_index < get_num_faces(); face_index++)
-      {
-         for (uint level_index = 0; level_index < get_num_levels(); level_index++)
-         {
-            const mip_level* pLevel = get_level(face_index, level_index);
-            
-            const uint mip_width = pLevel->get_width();
-            const uint mip_height = pLevel->get_height();
-
-            if (is_packed())
-            {
-               const dxt_image* p = pLevel->get_dxt_image();
-
-               kt.add_image(face_index, level_index, p->get_element_ptr(), p->get_size_in_bytes());
-            }
-            else
-            {
-               const image_u8* p = pLevel->get_image();
-
-               crnlib::vector<uint8> tmp(mip_width * mip_height * packer.get_pixel_stride());
-
-               uint8* pDst = tmp.get_ptr();
-               for (uint y = 0; y < mip_height; y++)
-                  for (uint x = 0; x < mip_width; x++)
-                     pDst = (uint8*)packer.pack(p->get_unclamped(x, y), pDst);
-               
-               kt.add_image(face_index, level_index, tmp.get_ptr(), tmp.size_in_bytes());
-            }
-         }
-      }
-
-      if (!kt.write_to_stream(serializer))
-         return false;
-
-      clear_last_error();
-      return true;
-   }
-
-   void mipmapped_texture::assign(face_vec& faces)
-   {
-      CRNLIB_ASSERT(!faces.empty());
-      if (faces.empty())
-         return;
-
-      free_all_mips();
-
-#ifdef CRNLIB_BUILD_DEBUG
-      for (uint i = 1; i < faces.size(); i++)
-         CRNLIB_ASSERT(faces[i].size() == faces[0].size());
-#endif
-
-      mip_level* p = faces[0][0];
-      m_width = p->get_width();
-      m_height = p->get_height();
-      m_comp_flags = p->get_comp_flags();
-      m_format = p->get_format();
-
-      m_faces.swap(faces);
-
-      CRNLIB_ASSERT(check());
-   }
-
-   void mipmapped_texture::assign(mip_level* pLevel)
-   {
-      face_vec faces(1, mip_ptr_vec(1, pLevel));
-      assign(faces);
-   }
-
-   void mipmapped_texture::assign(image_u8* p, pixel_format fmt, orientation_flags_t orient_flags)
-   {
-      mip_level* pLevel = crnlib_new<mip_level>();
-      pLevel->assign(p, fmt, orient_flags);
-      assign(pLevel);
-   }
-
-   void mipmapped_texture::assign(dxt_image* p, pixel_format fmt, orientation_flags_t orient_flags)
-   {
-      mip_level* pLevel = crnlib_new<mip_level>();
-      pLevel->assign(p, fmt, orient_flags);
-      assign(pLevel);
-   }
-
-   void mipmapped_texture::set(texture_file_types::format source_file_type, const mipmapped_texture& mipmapped_texture)
-   {
-      clear();
-
-      *this = mipmapped_texture;
-      m_source_file_type = source_file_type;
-   }
-
-   image_u8* mipmapped_texture::get_level_image(uint face, uint level, image_u8& img, uint unpack_flags) const
-   {
-      if (!is_valid())
-         return NULL;
-
-      const mip_level* pLevel = get_level(face, level);
-
-      return pLevel->get_unpacked_image(img, unpack_flags);
-   }
-
-   void mipmapped_texture::swap(mipmapped_texture& img)
-   {
-      utils::swap(m_width, img.m_width);
-      utils::swap(m_height, img.m_height);
-      utils::swap(m_comp_flags, img.m_comp_flags);
-      utils::swap(m_format, img.m_format);
-      m_faces.swap(img.m_faces);
-      m_last_error.swap(img.m_last_error);
-      utils::swap(m_source_file_type, img.m_source_file_type);
-
-      CRNLIB_ASSERT(check());
-   }
-
-   texture_type mipmapped_texture::determine_texture_type() const
-   {
-      if (!is_valid())
-         return cTextureTypeUnknown;
-
-      if (get_num_faces() == 6)
-         return cTextureTypeCubemap;
-      else if (is_vertical_cross())
-         return cTextureTypeVerticalCrossCubemap;
-      else if (is_normal_map())
-         return cTextureTypeNormalMap;
-
-      return cTextureTypeRegularMap;
-   }
-
-   void mipmapped_texture::discard_mips()
-   {
-      for (uint f = 0; f < m_faces.size(); f++)
-      {
-         if (m_faces[f].size() > 1)
-         {
-            for (uint l = 1; l < m_faces[f].size(); l++)
-               crnlib_delete(m_faces[f][l]);
-
-            m_faces[f].resize(1);
-         }
-      }
-
-      CRNLIB_ASSERT(check());
-   }
-
-   void mipmapped_texture::init(uint width, uint height, uint levels, uint faces, pixel_format fmt, const char* pName, orientation_flags_t orient_flags)
-   {
-      clear();
-
-      CRNLIB_ASSERT((width > 0) && (height > 0) && (levels > 0));
-      CRNLIB_ASSERT((faces == 1) || (faces == 6));
-
-      m_width = width;
-      m_height = height;
-      m_comp_flags = pixel_format_helpers::get_component_flags(fmt);
-      m_format = fmt;
-      if (pName)
-         m_name.set(pName);
-      
-      m_faces.resize(faces);
-      for (uint f = 0; f < faces; f++)
-      {
-         m_faces[f].resize(levels);
-         for (uint l = 0; l < levels; l++)
-         {
-            m_faces[f][l] = crnlib_new<mip_level>();
-
-            const uint mip_width = math::maximum(1U, width >> l);
-            const uint mip_height = math::maximum(1U, height >> l);
-            if (pixel_format_helpers::is_dxt(fmt))
-            {
-               dxt_image* p = crnlib_new<dxt_image>();
-               p->init(pixel_format_helpers::get_dxt_format(fmt), mip_width, mip_height, true);
-               m_faces[f][l]->assign(p, m_format, orient_flags);
-            }
-            else
-            {
-               image_u8* p = crnlib_new<image_u8>(mip_width, mip_height);
-               p->set_comp_flags(m_comp_flags);
-               m_faces[f][l]->assign(p, m_format, orient_flags);
-            }
-         }
-      }
-
-      CRNLIB_ASSERT(check());
-   }
-
-   void mipmapped_texture::discard_mipmaps()
-   {
-      if (!is_valid())
-         return;
-
-      discard_mips();
-   }
-
-   bool mipmapped_texture::convert(pixel_format fmt, bool cook, const dxt_image::pack_params& p)
-   {
-      if (!is_valid())
-         return false;
-
-      if (fmt == get_format())
-         return true;
-
-      uint total_pixels = 0;
-      for (uint f = 0; f < m_faces.size(); f++)
-         for (uint l = 0; l < m_faces[f].size(); l++)
-            total_pixels += m_faces[f][l]->get_total_pixels();
-
-      uint num_pixels_processed = 0;
-
-      uint progress_start = p.m_progress_start;
-
-      for (uint f = 0; f < m_faces.size(); f++)
-      {
-         for (uint l = 0; l < m_faces[f].size(); l++)
-         {
-            const uint num_pixels = m_faces[f][l]->get_total_pixels();
-
-            uint progress_range = (num_pixels * p.m_progress_range) / total_pixels;
-
-            dxt_image::pack_params tmp_params(p);
-            tmp_params.m_progress_start = math::clamp<uint>(progress_start, 0, p.m_progress_range);
-            tmp_params.m_progress_range = math::clamp<uint>(progress_range, 0, p.m_progress_range - tmp_params.m_progress_start);
-
-            progress_start += tmp_params.m_progress_range;
-
-            if (!m_faces[f][l]->convert(fmt, cook, tmp_params))
-            {
-               clear();
-               return false;
-            }
-
-            num_pixels_processed += num_pixels;
-         }
-      }
-
-      m_format = get_level(0, 0)->get_format();
-      m_comp_flags = get_level(0, 0)->get_comp_flags();
-
-      CRNLIB_ASSERT(check());
-
-      if (p.m_pProgress_callback)
-      {
-         if (!p.m_pProgress_callback(p.m_progress_start + p.m_progress_range, p.m_pProgress_callback_user_data_ptr))
-            return false;
-      }
-
-      return true;
-   }
-
-   bool mipmapped_texture::convert(pixel_format fmt, const dxt_image::pack_params& p)
-   {
-      return convert(fmt, true, p);
-   }
-
-   bool mipmapped_texture::convert(pixel_format fmt, bool cook, const dxt_image::pack_params& p, int qdxt_quality, bool hierarchical)
-   {
-      if ((!pixel_format_helpers::is_dxt(fmt)) || (fmt == PIXEL_FMT_DXT3) || (fmt == PIXEL_FMT_ETC1))
-      {
-         // QDXT doesn't support DXT3 or ETC1 yet.
-         return convert(fmt, cook, p);
-      }
-
-      mipmapped_texture src_tex(*this);
-
-      if (src_tex.is_packed())
-         src_tex.unpack_from_dxt(true);
-
-      if (cook)
-      {
-         mipmapped_texture cooked_tex(src_tex);
-
-         for (uint f = 0; f < m_faces.size(); f++)
-            for (uint l = 0; l < m_faces[f].size(); l++)
-               src_tex.m_faces[f][l]->cook_image(*cooked_tex.m_faces[f][l]->get_image());
-
-         src_tex.swap(cooked_tex);
-      }
-
-      qdxt1_params q1_params;
-      q1_params.init(p, qdxt_quality, hierarchical);
-
-      qdxt5_params q5_params;
-      q5_params.init(p, qdxt_quality, hierarchical);
-
-      if (pixel_format_helpers::is_pixel_format_non_srgb(fmt) || (m_comp_flags & pixel_format_helpers::cCompFlagNormalMap) || (m_comp_flags & pixel_format_helpers::cCompFlagLumaChroma))
-      {
-         // Disable perceptual colorspace metrics when packing to swizzled or non-RGB pixel formats.
-         q1_params.m_perceptual = false;
-      }
-
-      task_pool tp;
-      if (!tp.init(p.m_num_helper_threads))
-         return false;
-
-      mipmapped_texture packed_tex;
-
-      qdxt_state state(tp);
-      if (!src_tex.qdxt_pack_init(state, packed_tex, q1_params, q5_params, fmt, false))
-         return false;
-
-      if (!src_tex.qdxt_pack(state, packed_tex, q1_params, q5_params))
-         return false;
-
-      swap(packed_tex);
-
-      return true;
-   }
-
-   bool mipmapped_texture::is_packed() const
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      return get_level(0, 0)->is_packed();
-   }
-
-   bool mipmapped_texture::set_alpha_to_luma()
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      if (is_packed())
-         unpack_from_dxt(true);
-
-      for (uint f = 0; f < m_faces.size(); f++)
-         for (uint l = 0; l < get_num_levels(); l++)
-            get_level(f, l)->set_alpha_to_luma();
-
-      m_format = get_level(0, 0)->get_format();
-      m_comp_flags = get_level(0, 0)->get_comp_flags();
-
-      CRNLIB_ASSERT(check());
-
-      return true;
-   }
-
-   bool mipmapped_texture::convert(image_utils::conversion_type conv_type)
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      if (is_packed())
-         unpack_from_dxt(true);
-
-      for (uint f = 0; f < m_faces.size(); f++)
-         for (uint l = 0; l < get_num_levels(); l++)
-            get_level(f, l)->convert(conv_type);
-
-      m_format = get_level(0, 0)->get_format();
-      m_comp_flags = get_level(0, 0)->get_comp_flags();
-
-      CRNLIB_ASSERT(check());
-
-      return true;
-   }
-
-   bool mipmapped_texture::unpack_from_dxt(bool uncook)
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      CRNLIB_ASSERT(pixel_format_helpers::is_dxt(m_format));
-      if (!pixel_format_helpers::is_dxt(m_format))
-         return false;
-
-      for (uint f = 0; f < m_faces.size(); f++)
-         for (uint l = 0; l < get_num_levels(); l++)
-            if (!get_level(f, l)->unpack_from_dxt(uncook))
-               return false;
-
-      m_format = get_level(0, 0)->get_format();
-      m_comp_flags = get_level(0, 0)->get_comp_flags();
-
-      CRNLIB_ASSERT(check());
-
-      return true;
-   }
-
-   bool mipmapped_texture::has_alpha() const
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      if (pixel_format_helpers::has_alpha(m_format))
-         return true;
-
-      if ((m_format == PIXEL_FMT_DXT1) && (get_level(0, 0)->get_dxt_image()))
-      {
-         // Try scanning DXT1 mip levels to find blocks with transparent pixels.
-         for (uint f = 0; f < get_num_faces(); f++)
-            if (get_level(f, 0)->get_dxt_image()->has_alpha())
-               return true;
-      }
-
-      return false;
-   }
-
-   bool mipmapped_texture::is_normal_map() const
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      if (pixel_format_helpers::is_normal_map(get_format()))
-         return true;
-
-      const mip_level* pLevel = get_level(0, 0);
-
-      if (pLevel->get_image())
-         return image_utils::is_normal_map(*pLevel->get_image(), m_name.get_ptr());
-
-      image_u8 tmp;
-      pLevel->get_dxt_image()->unpack(tmp);
-      return image_utils::is_normal_map(tmp, m_name.get_ptr());
-   }
-
-   bool mipmapped_texture::is_vertical_cross() const
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      if (get_num_faces() > 1)
-         return false;
-
-      if (!((math::is_power_of_2(m_height)) && (!math::is_power_of_2(m_width)) && (m_height / 4U == m_width / 3U)))
-         return false;
-
-      return true;
-   }
-
-   bool mipmapped_texture::resize(uint new_width, uint new_height, const resample_params& params)
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      CRNLIB_ASSERT((new_width >= 1) && (new_height >= 1));
-
-      face_vec faces(get_num_faces());
-      for (uint f = 0; f < faces.size(); f++)
-      {
-         faces[f].resize(1);
-         faces[f][0] = crnlib_new<mip_level>();
-      }
-
-      for (uint f = 0; f < faces.size(); f++)
-      {
-         image_u8 tmp;
-         image_u8* pImg = get_level(f, 0)->get_unpacked_image(tmp, cUnpackFlagUncook);
-
-         image_u8* pMip = crnlib_new<image_u8>();
-
-         image_utils::resample_params rparams;
-         rparams.m_dst_width = new_width;
-         rparams.m_dst_height = new_height;
-         rparams.m_filter_scale = params.m_filter_scale;
-         rparams.m_first_comp = 0;
-         rparams.m_num_comps = pImg->is_component_valid(3) ? 4 : 3;
-         rparams.m_srgb = params.m_srgb;
-         rparams.m_wrapping = params.m_wrapping;
-         rparams.m_pFilter = params.m_pFilter;
-         rparams.m_multithreaded = params.m_multithreaded;
-
-         if (!image_utils::resample(*pImg, *pMip, rparams))
-         {
-            crnlib_delete(pMip);
-
-            for (uint f = 0; f < faces.size(); f++)
-               for (uint l = 0; l < faces[f].size(); l++)
-                  crnlib_delete(faces[f][l]);
-
-            return false;
-         }
-
-         if (params.m_renormalize)
-            image_utils::renorm_normal_map(*pMip);
-
-         pMip->set_comp_flags(pImg->get_comp_flags());
-
-         faces[f][0]->assign(pMip, PIXEL_FMT_INVALID, get_level(f, 0)->get_orientation_flags());
-      }
-
-      assign(faces);
-
-      CRNLIB_ASSERT(check());
-
-      return true;
-   }
-
-   bool mipmapped_texture::generate_mipmaps(const generate_mipmap_params& params, bool force)
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-
-      uint num_levels = 1;
-      {
-         uint width = get_width();
-         uint height = get_height();
-         while ((width > params.m_min_mip_size) || (height > params.m_min_mip_size))
-         {
-            width >>= 1U;
-            height >>= 1U;
-            num_levels++;
-         }
-      }
-
-      if ((params.m_max_mips > 0) && (num_levels > params.m_max_mips))
-         num_levels = params.m_max_mips;
-
-      if ((force) && (get_num_levels() > 1))
-         discard_mipmaps();
-
-      if (num_levels == get_num_levels())
-         return true;
-
-      face_vec faces(get_num_faces());
-      for (uint f = 0; f < faces.size(); f++)
-      {
-         faces[f].resize(num_levels);
-         for (uint l = 0; l < num_levels; l++)
-            faces[f][l] = crnlib_new<mip_level>();
-      }
-
-      for (uint f = 0; f < faces.size(); f++)
-      {
-         image_u8 tmp;
-         image_u8* pImg = get_level(f, 0)->get_unpacked_image(tmp, cUnpackFlagUncook);
-
-         for (uint l = 0; l < num_levels; l++)
-         {
-            const uint mip_width = math::maximum<uint>(1U, get_width() >> l);
-            const uint mip_height = math::maximum<uint>(1U, get_height() >> l);
-
-            image_u8* pMip = crnlib_new<image_u8>();
-
-            if (!l)
-               *pMip = *pImg;
-            else
-            {
-               image_utils::resample_params rparams;
-               rparams.m_dst_width = mip_width;
-               rparams.m_dst_height = mip_height;
-               rparams.m_filter_scale = params.m_filter_scale;
-               rparams.m_first_comp = 0;
-               rparams.m_num_comps = pImg->is_component_valid(3) ? 4 : 3;
-               rparams.m_srgb = params.m_srgb;
-               rparams.m_wrapping = params.m_wrapping;
-               rparams.m_pFilter = params.m_pFilter;
-               rparams.m_multithreaded = params.m_multithreaded;
-
-               if (!image_utils::resample(*pImg, *pMip, rparams))
-               {
-                  crnlib_delete(pMip);
-
-                  for (uint f = 0; f < faces.size(); f++)
-                     for (uint l = 0; l < faces[f].size(); l++)
-                        crnlib_delete(faces[f][l]);
-
-                  return false;
-               }
-
-               if (params.m_renormalize)
-                  image_utils::renorm_normal_map(*pMip);
-
-               pMip->set_comp_flags(pImg->get_comp_flags());
-            }
-
-            faces[f][l]->assign(pMip, PIXEL_FMT_INVALID, get_level(f, 0)->get_orientation_flags());
-         }
-      }
-
-      assign(faces);
-
-      CRNLIB_ASSERT(check());
-
-      return true;
-   }
-
-   bool mipmapped_texture::crop(uint x, uint y, uint width, uint height)
-   {
-      CRNLIB_ASSERT(is_valid());
-      if (!is_valid())
-         return false;
-      if (get_num_faces() > 1)
-         return false;
-
-      if ((width < 1) || (height < 1))
-         return false;
-
-      image_u8 tmp;
-      image_u8* pImg = get_level(0, 0)->get_unpacked_image(tmp, cUnpackFlagUncook | cUnpackFlagUnflip);
-
-      image_u8* pMip = crnlib_new<image_u8>(width, height);
-
-      if (!pImg->extract_block(pMip->get_ptr(), x, y, width, height))
-         return false;
-
-      face_vec faces(1);
-      faces[0].resize(1);
-      faces[0][0] = crnlib_new<mip_level>();
-
-      pMip->set_comp_flags(pImg->get_comp_flags());
-
-      faces[0][0]->assign(pMip);
-
-      assign(faces);
-
-      CRNLIB_ASSERT(check());
-
-      return true;
-   }
-
-   bool mipmapped_texture::vertical_cross_to_cubemap()
-   {
-      if (!is_vertical_cross())
-         return false;
-
-      const uint face_width = get_height() / 4;
-
-      bool alpha_is_valid = has_alpha();
-
-      mipmapped_texture cubemap;
-
-      pixel_format fmt = alpha_is_valid ? PIXEL_FMT_A8R8G8B8 : PIXEL_FMT_R8G8B8;
-
-      cubemap.init(face_width, face_width, 1, 6, fmt, m_name.get_ptr(), cDefaultOrientationFlags);
-
-      // +x -x +y -y +z -z
-      //     0  1  2
-      // 0     +y
-      // 1  -x +z +x
-      // 2     -y
-      // 3     -z
-
-      for (uint face_index = 0; face_index < 6; face_index++)
-      {
-         const mip_level* pSrc = get_level(0, 0);
-
-         image_u8 tmp_img;
-         image_u8* pSrc_image = pSrc->get_unpacked_image(tmp_img, cUnpackFlagUncook | cUnpackFlagUnflip);
-
-         const mip_level* pDst = get_level(face_index, 0);
-         image_u8* pDst_image = pDst->get_image();
-         CRNLIB_ASSERT(pDst_image);
-
-         const bool flipped = (face_index == 5);
-         const uint x_ofs = g_vertical_cross_image_offsets[face_index][0] * face_width;
-         const uint y_ofs = g_vertical_cross_image_offsets[face_index][1] * face_width;
-
-         for (uint y = 0; y < face_width; y++)
-         {
-            for (uint x = 0; x < face_width; x++)
-            {
-               const color_quad_u8& c = (*pSrc_image)(x_ofs + x, y_ofs + y);
-
-               if (!flipped)
-                  (*pDst_image)(x, y) = c;
-               else
-                  (*pDst_image)(face_width - 1 - x, face_width - 1 - y) = c;
-            }
-         }
-      }
-
-      swap(cubemap);
-
-      CRNLIB_ASSERT(check());
-
-      return true;
-   }
-
-   bool mipmapped_texture::qdxt_pack_init(qdxt_state& state, mipmapped_texture& dst_tex, const qdxt1_params& dxt1_params, const qdxt5_params& dxt5_params, pixel_format fmt, bool cook)
-   {
-      if (!is_valid())
-         return false;
-
-      state.m_qdxt1_params = dxt1_params;
-      state.m_qdxt5_params[0] = dxt5_params;
-      state.m_qdxt5_params[1] = dxt5_params;
-      utils::zero_object(state.m_has_blocks);
-
-      switch (fmt)
-      {
-         case PIXEL_FMT_DXT1:
-         {
-            state.m_has_blocks[0] = true;
-            break;
-         }
-         case PIXEL_FMT_DXT1A:
-         {
-            state.m_has_blocks[0] = true;
-            state.m_qdxt1_params.m_use_alpha_blocks = true;
-            break;
-         }
-         case PIXEL_FMT_DXT4:
-         case PIXEL_FMT_DXT5:
-         {
-            state.m_has_blocks[0] = true;
-            state.m_has_blocks[1] = true;
-            state.m_qdxt1_params.m_use_alpha_blocks = false;
-            state.m_qdxt5_params[0].m_comp_index = 3;
-            break;
-         }
-         case PIXEL_FMT_DXT5_CCxY:
-         case PIXEL_FMT_DXT5_xGxR:
-         case PIXEL_FMT_DXT5_xGBR:
-         case PIXEL_FMT_DXT5_AGBR:
-         {
-            state.m_has_blocks[0] = true;
-            state.m_has_blocks[1] = true;
-            state.m_qdxt1_params.m_use_alpha_blocks = false;
-            state.m_qdxt1_params.m_perceptual = false;
-            state.m_qdxt5_params[0].m_comp_index = 3;
-            break;
-         }
-         case PIXEL_FMT_3DC:
-         {
-            state.m_has_blocks[1] = true;
-            state.m_has_blocks[2] = true;
-            state.m_qdxt5_params[0].m_comp_index = 1;
-            state.m_qdxt5_params[1].m_comp_index = 0;
-            break;
-         }
-         case PIXEL_FMT_DXN:
-         {
-            state.m_has_blocks[1] = true;
-            state.m_has_blocks[2] = true;
-            state.m_qdxt5_params[0].m_comp_index = 0;
-            state.m_qdxt5_params[1].m_comp_index = 1;
-            break;
-         }
-         case PIXEL_FMT_DXT5A:
-         {
-            state.m_has_blocks[1] = true;
-            state.m_qdxt5_params[0].m_comp_index = 3;
-            break;
-         }
-         case PIXEL_FMT_ETC1:
-         {
-            console::warning("mipmapped_texture::qdxt_pack_init: This method does not support ETC1");
-            return false;
-         }
-         default:
-         {
-            CRNLIB_ASSERT(0);
-            return false;
-         }
-      }
-
-      const uint num_elements = state.m_has_blocks[0] + state.m_has_blocks[1] + state.m_has_blocks[2];
-
-      uint cur_progress_start = dxt1_params.m_progress_start;
-      if (state.m_has_blocks[0])
-      {
-         state.m_qdxt1_params.m_progress_start = cur_progress_start;
-         state.m_qdxt1_params.m_progress_range = dxt1_params.m_progress_range / num_elements;
-         cur_progress_start += state.m_qdxt1_params.m_progress_range;
-      }
-
-      if (state.m_has_blocks[1])
-      {
-         state.m_qdxt5_params[0].m_progress_start = cur_progress_start;
-         state.m_qdxt5_params[0].m_progress_range = dxt1_params.m_progress_range / num_elements;
-         cur_progress_start += state.m_qdxt5_params[0].m_progress_range;
-      }
-
-      if (state.m_has_blocks[2])
-      {
-         state.m_qdxt5_params[1].m_progress_start = cur_progress_start;
-         state.m_qdxt5_params[1].m_progress_range = dxt1_params.m_progress_range - cur_progress_start;
-      }
-
-      state.m_fmt = fmt;
-
-      dst_tex.init(get_width(), get_height(), get_num_levels(), get_num_faces(), fmt, get_name().get_ptr(), cDefaultOrientationFlags);
-
-      state.m_pixel_blocks.resize(0);
-
-      image_utils::conversion_type cook_conv_type = image_utils::cConversion_Invalid;
-      if (cook)
-      {
-         cook_conv_type = image_utils::get_conversion_type(true, fmt);
-         if (pixel_format_helpers::is_alpha_only(fmt) && !pixel_format_helpers::has_alpha(m_format))
-            cook_conv_type = image_utils::cConversion_Y_To_A;
-      }
-
-      state.m_qdxt1_params.m_num_mips = 0;
-      state.m_qdxt5_params[0].m_num_mips = 0;
-      state.m_qdxt5_params[1].m_num_mips = 0;
-
-      for (uint f = 0; f < get_num_faces(); f++)
-      {
-         for (uint l = 0; l < get_num_levels(); l++)
-         {
-            mip_level* pLevel = get_level(f, l);
-
-            dst_tex.get_level(f, l)->set_orientation_flags(pLevel->get_orientation_flags());
-
-            image_u8 tmp_img;
-            image_u8 img(*pLevel->get_unpacked_image(tmp_img, cUnpackFlagUncook));
-
-            if (cook_conv_type != image_utils::cConversion_Invalid)
-               image_utils::convert_image(img, cook_conv_type);
-
-            const uint num_blocks_x = (img.get_width() + 3) / 4;
-            const uint num_blocks_y = (img.get_height() + 3) / 4;
-            const uint total_blocks = num_blocks_x * num_blocks_y;
-
-            const uint cur_size = state.m_pixel_blocks.size();
-            state.m_pixel_blocks.resize(cur_size + total_blocks);
-            dxt_pixel_block* pDst_blocks = &state.m_pixel_blocks[cur_size];
-
-            {
-               CRNLIB_ASSERT(state.m_qdxt1_params.m_num_mips < qdxt1_params::cMaxMips);
-               qdxt1_params::mip_desc& mip_desc = state.m_qdxt1_params.m_mip_desc[state.m_qdxt1_params.m_num_mips];
-               mip_desc.m_first_block = cur_size;
-               mip_desc.m_block_width = num_blocks_x;
-               mip_desc.m_block_height = num_blocks_y;
-               state.m_qdxt1_params.m_num_mips++;
-            }
-
-            for (uint i = 0; i < 2; i++)
-            {
-               CRNLIB_ASSERT(state.m_qdxt5_params[i].m_num_mips < qdxt5_params::cMaxMips);
-               qdxt5_params::mip_desc& mip_desc = state.m_qdxt5_params[i].m_mip_desc[state.m_qdxt5_params[i].m_num_mips];
-               mip_desc.m_first_block = cur_size;
-               mip_desc.m_block_width = num_blocks_x;
-               mip_desc.m_block_height = num_blocks_y;
-               state.m_qdxt5_params[i].m_num_mips++;
-            }
-
-            for (uint block_y = 0; block_y < num_blocks_y; block_y++)
-            {
-               const uint img_y = block_y << 2;
-
-               for (uint block_x = 0; block_x < num_blocks_x; block_x++)
-               {
-                  const uint img_x = block_x << 2;
-
-                  color_quad_u8* pDst_pixel = &pDst_blocks->m_pixels[0][0];
-
-                  pDst_blocks++;
-
-                  for (uint by = 0; by < 4; by++)
-                     for (uint bx = 0; bx < 4; bx++)
-                        *pDst_pixel++ = img.get_clamped(img_x + bx, img_y + by);
-               } // block_x
-            } // block_y
-         } // l
-      } // f
-
-      if (state.m_has_blocks[0])
-      {
-         if (!state.m_qdxt1.init(state.m_pixel_blocks.size(), &state.m_pixel_blocks[0], state.m_qdxt1_params))
-            return false;
-      }
-
-      if (state.m_has_blocks[1])
-      {
-         if (!state.m_qdxt5a.init(state.m_pixel_blocks.size(), &state.m_pixel_blocks[0], state.m_qdxt5_params[0]))
-            return false;
-      }
-
-      if (state.m_has_blocks[2])
-      {
-         if (!state.m_qdxt5b.init(state.m_pixel_blocks.size(), &state.m_pixel_blocks[0], state.m_qdxt5_params[1]))
-            return false;
-      }
-
-      return true;
-   }
-
-   bool mipmapped_texture::qdxt_pack(qdxt_state& state, mipmapped_texture& dst_tex, const qdxt1_params& dxt1_params, const qdxt5_params& dxt5_params)
-   {
-      if (!is_valid())
-         return false;
-
-      CRNLIB_ASSERT(dxt1_params.m_quality_level <= qdxt1_params::cMaxQuality);
-      CRNLIB_ASSERT(dxt5_params.m_quality_level <= qdxt5_params::cMaxQuality);
-
-      state.m_qdxt1_params.m_quality_level = dxt1_params.m_quality_level;
-      state.m_qdxt1_params.m_pProgress_func = dxt1_params.m_pProgress_func;
-      state.m_qdxt1_params.m_pProgress_data = dxt1_params.m_pProgress_data;
-
-      state.m_qdxt5_params[0].m_quality_level = dxt5_params.m_quality_level;
-      state.m_qdxt5_params[0].m_pProgress_func = dxt5_params.m_pProgress_func;
-      state.m_qdxt5_params[0].m_pProgress_data = dxt5_params.m_pProgress_data;
-
-      state.m_qdxt5_params[1].m_quality_level = dxt5_params.m_quality_level;
-      state.m_qdxt5_params[1].m_pProgress_func = dxt5_params.m_pProgress_func;
-      state.m_qdxt5_params[1].m_pProgress_data = dxt5_params.m_pProgress_data;
-
-      const uint num_elements = state.m_has_blocks[0] + state.m_has_blocks[1] + state.m_has_blocks[2];
-
-      uint cur_progress_start = dxt1_params.m_progress_start;
-      if (state.m_has_blocks[0])
-      {
-         state.m_qdxt1_params.m_progress_start = cur_progress_start;
-         state.m_qdxt1_params.m_progress_range = dxt1_params.m_progress_range / num_elements;
-         cur_progress_start += state.m_qdxt1_params.m_progress_range;
-      }
-
-      if (state.m_has_blocks[1])
-      {
-         state.m_qdxt5_params[0].m_progress_start = cur_progress_start;
-         state.m_qdxt5_params[0].m_progress_range = dxt1_params.m_progress_range / num_elements;
-         cur_progress_start += state.m_qdxt5_params[0].m_progress_range;
-      }
-
-      if (state.m_has_blocks[2])
-      {
-         state.m_qdxt5_params[1].m_progress_start = cur_progress_start;
-         state.m_qdxt5_params[1].m_progress_range = dxt1_params.m_progress_range - cur_progress_start;
-      }
-
-      crnlib::vector<dxt1_block> dxt1_blocks;
-      if (state.m_has_blocks[0])
-      {
-         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
-            pow_mul = 1.5f;
-         }
-         else if (state.m_fmt == PIXEL_FMT_DXT5)
-         {
-            // favor color more than alpha
-            pow_mul = .75f;
-         }
-
-         if (!state.m_qdxt1.pack(&dxt1_blocks[0], 1, state.m_qdxt1_params, pow_mul))
-            return false;
-      }
-
-      crnlib::vector<dxt5_block> dxt5_blocks[2];
-      for (uint i = 0; i < 2; i++)
-      {
-         if (state.m_has_blocks[i + 1])
-         {
-            dxt5_blocks[i].resize(state.m_pixel_blocks.size());
-
-            if (!(i ? state.m_qdxt5b : state.m_qdxt5a).pack(&dxt5_blocks[i][0], 1, state.m_qdxt5_params[i]))
-               return false;
-         }
-      }
-
-      uint cur_block_ofs = 0;
-
-      for (uint f = 0; f < dst_tex.get_num_faces(); f++)
-      {
-         for (uint l = 0; l < dst_tex.get_num_levels(); l++)
-         {
-            mip_level* pDst_level = dst_tex.get_level(f, l);
-
-            const uint num_blocks_x = (pDst_level->get_width() + 3) / 4;
-            const uint num_blocks_y = (pDst_level->get_height() + 3) / 4;
-            const uint total_blocks = num_blocks_x * num_blocks_y;
-
-            dxt_image* pDst_dxt_image = pDst_level->get_dxt_image();
-
-            dxt_image::element* pDst = pDst_dxt_image->get_element_ptr();
-            for (uint block_index = 0; block_index < total_blocks; block_index++)
-            {
-               if (state.m_has_blocks[1])
-                  memcpy(pDst, &dxt5_blocks[0][cur_block_ofs + block_index], 8);
-
-               if (state.m_has_blocks[2])
-                  memcpy(pDst + 1, &dxt5_blocks[1][cur_block_ofs + block_index], 8);
-
-               if (state.m_has_blocks[0])
-                  memcpy(pDst + state.m_has_blocks[1], &dxt1_blocks[cur_block_ofs + block_index], 8);
-
-               pDst += pDst_dxt_image->get_elements_per_block();
-            }
-
-            cur_block_ofs += total_blocks;
-         }
-      }
-
-      if (dxt1_params.m_pProgress_func)
-      {
-         if (!dxt1_params.m_pProgress_func(dxt1_params.m_progress_start + dxt1_params.m_progress_range, dxt1_params.m_pProgress_data))
-            return false;
-      }
-
-      CRNLIB_ASSERT(dst_tex.check());
-
-      return true;
-   }
-   
-   bool mipmapped_texture::read_from_file(const char* pFilename, texture_file_types::format file_format)
-   {
-      clear();
-      
-      set_last_error("Can't open file");
-
-      bool success = false;
-
-      cfile_stream in_stream;
-      if (in_stream.open(pFilename))
-      {
-         data_stream_serializer serializer(in_stream);
-         success = read_from_stream(serializer, file_format);
-      }
-            
-      return success;
-   }
-
-   bool mipmapped_texture::read_from_stream(data_stream_serializer& serializer, texture_file_types::format file_format)
-   {
-      clear();
-      
-      if (!serializer.get_stream())
-      {
-         set_last_error("Invalid stream");
-         return false;
-      }
-      
-      if (file_format == texture_file_types::cFormatInvalid)
-         file_format = texture_file_types::determine_file_format(serializer.get_name().get_ptr());
-
-      if (file_format == texture_file_types::cFormatInvalid)
-      {
-         set_last_error("Unsupported file format");
-         return false;
-      }
-      
-      set_last_error("Image file load failed");
-
-      bool success = false;
-
-      if (!texture_file_types::supports_mipmaps(file_format))
-      {
-         success = read_regular_image(serializer, file_format);
-      }
-      else
-      {
-         switch (file_format)
-         {
-            case texture_file_types::cFormatDDS:
-            {
-               success = read_dds(serializer);
-               break;
-            }
-            case texture_file_types::cFormatCRN:
-            {
-               success = read_crn(serializer);
-               break;
-            }
-            case texture_file_types::cFormatKTX:
-            {
-               success = read_ktx(serializer);
-               break;
-            }
-            default:
-            {
-               CRNLIB_ASSERT(0);
-               break;
-            }
-         }
-      }
-
-      if (success)
-      {
-         CRNLIB_ASSERT(check());
-
-         m_source_file_type = file_format;
-         set_name(serializer.get_name());
-         clear_last_error();
-      }
-
-      return success;
-   }
-   
-   bool mipmapped_texture::read_regular_image(data_stream_serializer &serializer, texture_file_types::format file_format)
-   {
-      file_format;
-
-      image_u8* pImg = crnlib_new<image_u8>();
-      bool status = image_utils::read_from_stream(*pImg, serializer, 0);
-      if (!status)
-      {
-         crnlib_delete(pImg);
-
-         set_last_error("Failed loading image file");
-         return false;
-      }
-
-      mip_level* pLevel = crnlib_new<mip_level>();
-      pLevel->assign(pImg);
-
-      assign(pLevel);
-      set_name(serializer.get_name());
-
-      return true;
-
-   }
-
-   bool mipmapped_texture::read_crn_from_memory(const void *pData, uint data_size, const char* pFilename)
-   {
-      clear();
-
-      set_last_error("Image file load failed");
-
-      if ((!pData) || (data_size < 1)) return false;
-
-      crnd::crn_texture_info tex_info;
-      tex_info.m_struct_size = sizeof(crnd::crn_texture_info);
-      if (!crnd_get_texture_info(pData, data_size, &tex_info))
-      {
-         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("Unsupported DXT format");
-         return false;
-      }
-
-      const dxt_format dxt_fmt = pixel_format_helpers::get_dxt_format(dds_fmt);
-
-      face_vec faces(tex_info.m_faces);
-      for (uint f = 0; f < tex_info.m_faces; f++)
-      {
-         faces[f].resize(tex_info.m_levels);
-
-         for (uint l = 0; l < tex_info.m_levels; l++)
-            faces[f][l] = crnlib_new<mip_level>();
-      }
-
-      const uint tex_num_blocks_x = (tex_info.m_width + 3) >> 2;
-      const uint tex_num_blocks_y = (tex_info.m_height + 3) >> 2;
-
-      vector<uint8> dxt_data;
-      // 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("CRN unpack failed");
-
-#if 0
-      timer t;
-      double total_time = 0.0f;
-      t.start();
-#endif
-
-      crnd::crnd_unpack_context pContext = crnd::crnd_unpack_begin(pData, data_size);
-
-#if 0
-      total_time += t.get_elapsed_secs();
-#endif
-
-      if (!pContext)
-      {
-         for (uint f = 0; f < faces.size(); f++)
-            for (uint l = 0; l < faces[f].size(); l++)
-               crnlib_delete(faces[f][l]);
-         return false;
-      }
-
-      uint total_pixels = 0;
-
-      void* pFaces[cCRNMaxFaces];
-      for (uint f = tex_info.m_faces; f < cCRNMaxFaces; f++)
-         pFaces[f] = NULL;
-
-      for (uint l = 0; l < tex_info.m_levels; l++)
-      {
-         const uint level_width = math::maximum<uint>(1U, tex_info.m_width >> l);
-         const uint level_height = math::maximum<uint>(1U, tex_info.m_height >> l);
-         const uint num_blocks_x = (level_width + 3U) >> 2U;
-         const uint num_blocks_y = (level_height + 3U) >> 2U;
-
-         const uint row_pitch = num_blocks_x * tex_info.m_bytes_per_block;
-         const uint size_of_face = num_blocks_y * row_pitch;
-
-         total_pixels += num_blocks_x * num_blocks_y * 4 * 4 * tex_info.m_faces;
-
-#if 0
-         t.start();
-#endif
-
-         for (uint f = 0; f < tex_info.m_faces; f++)
-            pFaces[f] = &dxt_data[f * size_of_face];
-
-         if (!crnd::crnd_unpack_level(pContext, pFaces, dxt_data.size(), row_pitch, l))
-         {
-            crnd::crnd_unpack_end(pContext);
-            for (uint f = 0; f < faces.size(); f++)
-               for (uint l = 0; l < faces[f].size(); l++)
-                  crnlib_delete(faces[f][l]);
-            return false;
-         }
-
-#if 0
-         total_time += t.get_elapsed_secs();
-#endif
-
-         for (uint f = 0; f < tex_info.m_faces; f++)
-         {
-            dxt_image* pDXT_image = crnlib_new<dxt_image>();
-
-            if (!pDXT_image->init(
-               dxt_fmt, level_width, level_height,
-               num_blocks_x * num_blocks_y * (tex_info.m_bytes_per_block / sizeof(dxt_image::element)),
-               reinterpret_cast<dxt_image::element*>(pFaces[f]), true))
-            {
-               crnlib_delete(pDXT_image);
-
-               crnd::crnd_unpack_end(pContext);
-               for (uint f = 0; f < faces.size(); f++)
-                  for (uint l = 0; l < faces[f].size(); l++)
-                     crnlib_delete(faces[f][l]);
-
-               return false;
-            }
-
-            faces[f][l]->assign(pDXT_image, dds_fmt);
-         }
-      }
-
-#if 0
-      if (total_pixels)
-      {
-         console::info("read_crn_from_memory: Total pixels: %u, ms: %3.3fms, megapixels/sec: %3.3f",
-            total_pixels, total_time * 1000.0f, total_pixels / total_time);
-      }
-#endif
-
-      crnd::crnd_unpack_end(pContext);
-
-      assign(faces);
-      set_name(pFilename);
-
-      m_source_file_type = texture_file_types::cFormatCRN;
-      clear_last_error();
-
-      return true;
-   }
-
-   bool mipmapped_texture::read_crn(data_stream_serializer& serializer)
-   {
-      crnlib::vector<uint8> crn_data;
-      if (!serializer.read_entire_file(crn_data))
-      {
-         set_last_error("Failed reading CRN file");
-         return false;
-      }
-      return read_crn_from_memory(crn_data.get_ptr(), crn_data.size(), serializer.get_name().get_ptr());
-   }
-
-   bool mipmapped_texture::write_to_file(
-      const char* pFilename,
-      texture_file_types::format file_format,
-      crn_comp_params* pComp_params,
-      uint32 *pActual_quality_level, float *pActual_bitrate,
-      uint32 image_write_flags)
-   {
-      if (pActual_quality_level) *pActual_quality_level = 0;
-      if (pActual_bitrate) *pActual_bitrate = 0.0f;
-
-      if (!is_valid())
-      {
-         set_last_error("Unable to write empty texture");
-         return false;
-      }
-
-      if (file_format == texture_file_types::cFormatInvalid)
-         file_format = texture_file_types::determine_file_format(pFilename);
-      
-      if (file_format == texture_file_types::cFormatInvalid)
-      {
-         set_last_error("Unknown file format");
-         return false;
-      }
-
-      bool success = false;
-
-      if ( ((pComp_params) && (file_format == texture_file_types::cFormatDDS)) || 
-           (file_format == texture_file_types::cFormatCRN) )
-      {
-         if (!pComp_params)
-            return false;
-         success = write_comp_texture(pFilename, *pComp_params, pActual_quality_level, pActual_bitrate);
-      }
-      else if (!texture_file_types::supports_mipmaps(file_format))
-      {
-         success = write_regular_image(pFilename, image_write_flags);
-      }
-      else
-      {
-         if (pComp_params)
-         {
-            console::warning("mipmapped_texture::write_to_file: Ignoring CRN compression parameters (currently unsupported for this file type).");
-         }
-
-         cfile_stream write_stream;
-         if (!write_stream.open(pFilename, cDataStreamWritable | cDataStreamSeekable))
-         {
-            set_last_error(dynamic_string(cVarArg, "Failed creating output file \"%s\"", pFilename).get_ptr());
-            return false;
-         }
-         data_stream_serializer serializer(write_stream);
-
-         switch (file_format)
-         {
-            case texture_file_types::cFormatDDS:
-            {
-               success = write_dds(serializer);
-               break;
-            }
-            case texture_file_types::cFormatKTX:
-            {
-               success = write_ktx(serializer);
-               break;
-            }
-            default:
-            {
-               break;
-            }
-         }
-      }
-
-      return success;
-   }
-
-   bool mipmapped_texture::write_regular_image(const char* pFilename, uint32 image_write_flags)
-   {
-      image_u8 tmp;
-      image_u8* pLevel_image = get_level_image(0, 0, tmp);
-
-      if (!image_utils::write_to_file(pFilename, *pLevel_image, image_write_flags))
-      {
-         set_last_error("File write failed");
-         return false;
-      }
-
-      return true;
-   }
-   
-   void mipmapped_texture::print_crn_comp_params(const crn_comp_params& p)
-   {
-      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 mipmapped_texture::write_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);
-
-      if (pActual_quality_level) *pActual_quality_level = 0;
-      if (pActual_bitrate) *pActual_bitrate = 0.0f;
-
-      if (math::maximum(get_height(), get_width()) > cCRNMaxLevelResolution)
-      {
-         set_last_error("Texture resolution is too big!");
-         return false;
-      }
-
-      comp_params.m_faces = get_num_faces();
-      comp_params.m_levels = get_num_levels();
-      comp_params.m_width = get_width();
-      comp_params.m_height = get_height();
-
-      image_u8 temp_images[cCRNMaxFaces][cCRNMaxLevels];
-      for (uint f = 0; f < get_num_faces(); f++)
-      {
-         for (uint l = 0; l < get_num_levels(); l++)
-         {
-            image_u8* p = get_level_image(f, l, temp_images[f][l]);
-
-            comp_params.m_pImages[f][l] = (crn_uint32*)p->get_ptr();
-         }
-      }
-
-      if (comp_params.get_flag(cCRNCompFlagDebugging))
-         print_crn_comp_params(comp_params);
-
-      timer t;
-      t.start();
-
-      crnlib::vector<uint8> comp_data;
-      if (!create_compressed_texture(comp_params, comp_data, pActual_quality_level, pActual_bitrate))
-      {
-         set_last_error("CRN compression failed");
-         return false;
-      }
-
-      double total_time = t.get_elapsed_secs();
-      if (comp_params.get_flag(cCRNCompFlagDebugging))
-      {
-         console::debug("\nTotal compression time: %3.3fs", total_time);
-      }
-
-      cfile_stream out_stream;
-      if (!out_stream.open(pFilename, cDataStreamWritable | cDataStreamSeekable))
-      {
-         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("Failed writing to file");
-         return false;
-      }
-
-      if (!out_stream.close())
-      {
-         set_last_error("Failed writing to file");
-         return false;
-      }
-
-      return true;
-   }
-
-   uint mipmapped_texture::get_total_pixels_in_all_faces_and_mips() const
-   {
-      uint total_pixels = 0;
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++)
-            total_pixels += m_faces[l][m]->get_total_pixels();
-
-      return total_pixels;
-   }
-
-   void mipmapped_texture::set_orientation_flags(orientation_flags_t flags)
-   {
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++) 
-            m_faces[l][m]->set_orientation_flags(flags);
-   }
-
-   bool mipmapped_texture::is_flipped() const
-   {
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++) 
-            if (m_faces[l][m]->is_flipped())
-               return true;
-
-      return false;
-   }
-
-   bool mipmapped_texture::is_x_flipped() const
-   {
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++) 
-            if (m_faces[l][m]->is_x_flipped())
-               return true;
-
-      return false;
-   }
-
-   bool mipmapped_texture::is_y_flipped() const
-   {
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++) 
-            if (m_faces[l][m]->is_y_flipped())
-               return true;
-
-      return false;
-   }
-
-   bool mipmapped_texture::can_unflip_without_unpacking() const
-   {
-      if (!is_valid())
-         return false;
-
-      if (!is_packed())
-         return true;
-
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++) 
-            if (!m_faces[l][m]->can_unflip_without_unpacking())
-               return false;
-
-      return true;
-   }
-
-   bool mipmapped_texture::unflip(bool allow_unpacking_to_flip, bool uncook_if_necessary_to_unpack)
-   {
-      if (!is_valid())
-         return false;
-
-      if (is_packed())
-      {
-         // The texture is packed - make sure all faces/miplevels can be consistently unflipped.
-         bool can_do_packed_unflip = can_unflip_without_unpacking();
-         
-         if ((!can_do_packed_unflip) && (!allow_unpacking_to_flip))
-            return false;
-
-         // If any face/miplevel can't unflip the packed bits, then just unpack the whole texture.
-         if (!can_do_packed_unflip)
-            unpack_from_dxt(uncook_if_necessary_to_unpack);
-      }
-
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++) 
-            if (!m_faces[l][m]->unflip(true, false))
-               return false;
-
-      CRNLIB_VERIFY(check());
-
-      return true;
-   }
-
-#if 0
-   bool mipmapped_texture::flip_x()
-   {
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++) 
-            if (!m_faces[l][m]->flip_x())
-               return false;
-
-      return true;
-   }
-#endif
-
-   bool mipmapped_texture::flip_y_helper()
-   {
-      for (uint l = 0; l < m_faces.size(); l++)
-         for (uint m = 0; m < m_faces[l].size(); m++) 
-            if (!m_faces[l][m]->flip_y())
-               return false;
-
-      return true;
-   }
-
-   bool mipmapped_texture::flip_y(bool update_orientation_flags)
-   {
-      mipmapped_texture temp_tex(*this);
-      if (!temp_tex.flip_y_helper())
-      {
-         temp_tex = *this;
-         temp_tex.unpack_from_dxt(true);
-         if (!temp_tex.flip_y_helper())
-            return false;
-      }
-      swap(temp_tex);
-      
-      if (update_orientation_flags)
-      {
-         for (uint f = 0; f < get_num_faces(); f++)
-         {
-            for (uint m = 0; m < get_face(f).size(); m++)
-            {
-               uint orient_flags = get_face(f)[m]->get_orientation_flags();
-               orient_flags ^= cOrientationFlagYFlipped;
-               get_face(f)[m]->set_orientation_flags(static_cast<orientation_flags_t>(orient_flags));
-            }
-         }
-      }
-      
-      CRNLIB_ASSERT(check());
-      
-      return true;
-   }
-
-} // namespace crnlib
-

+ 0 - 339
Source/ThirdParty/crunch/crnlib/crn_mipmapped_texture.h

@@ -1,339 +0,0 @@
-// File: crn_mipmapped_texture.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dxt_image.h"
-#include "../inc/dds_defs.h"
-#include "crn_pixel_format.h"
-#include "crn_image.h"
-#include "crn_resampler.h"
-#include "crn_data_stream_serializer.h"
-#include "crn_qdxt1.h"
-#include "crn_qdxt5.h"
-#include "crn_texture_file_types.h"
-#include "crn_image_utils.h"
-
-namespace crnlib
-{
-   extern const vec2I g_vertical_cross_image_offsets[6];
-
-   enum orientation_flags_t
-   {
-      cOrientationFlagXFlipped = 1,
-      cOrientationFlagYFlipped = 2,
-
-      cDefaultOrientationFlags = 0
-   };
-
-   enum unpack_flags_t
-   {
-      cUnpackFlagUncook = 1,
-      cUnpackFlagUnflip = 2
-   };
-
-   class mip_level
-   {
-      friend class mipmapped_texture;
-
-   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, orientation_flags_t orient_flags = cDefaultOrientationFlags);
-      void assign(dxt_image* p, pixel_format fmt = PIXEL_FMT_INVALID, orientation_flags_t orient_flags = cDefaultOrientationFlags);
-
-      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; }
-      
-      orientation_flags_t get_orientation_flags() const { return m_orient_flags; }
-      void set_orientation_flags(orientation_flags_t flags) { m_orient_flags = flags; }
-
-      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, uint unpack_flags) 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; }
-
-      inline pixel_format get_format() const { return m_format; }
-      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, orientation_flags_t orient_flags = cDefaultOrientationFlags);
-      bool pack_to_dxt(pixel_format fmt, bool cook, const dxt_image::pack_params& p);
-
-      bool unpack_from_dxt(bool uncook = true);
-
-      // Returns true if flipped on either axis.
-      bool is_flipped() const;
-      
-      bool is_x_flipped() const;
-      bool is_y_flipped() const;
-      
-      bool can_unflip_without_unpacking() const;
-      
-      // Returns true if unflipped on either axis.
-      // Will try to flip packed (DXT/ETC) data in-place, if this isn't possible it'll unpack/uncook the mip level then unflip.
-      bool unflip(bool allow_unpacking_to_flip, bool uncook_during_unpack);
-      
-      bool set_alpha_to_luma();
-      bool convert(image_utils::conversion_type conv_type);
-
-      bool flip_x();
-      bool flip_y();
-
-   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;
-
-      orientation_flags_t                    m_orient_flags;
-
-      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_level*> mip_ptr_vec;
-
-   // And an array of one, six, or N faces make up a texture.
-   typedef crnlib::vector<mip_ptr_vec> face_vec;
-
-   class mipmapped_texture
-   {
-   public:
-      // Construction/destruction
-      mipmapped_texture();
-      ~mipmapped_texture();
-
-      mipmapped_texture(const mipmapped_texture& other);
-      mipmapped_texture& operator= (const mipmapped_texture& rhs);
-
-      void clear();
-
-      void init(uint width, uint height, uint levels, uint faces, pixel_format fmt, const char* pName, orientation_flags_t orient_flags);
-
-      // Assumes ownership.
-      void assign(face_vec& faces);
-      void assign(mip_level* pLevel);
-      void assign(image_u8* p, pixel_format fmt = PIXEL_FMT_INVALID, orientation_flags_t orient_flags = cDefaultOrientationFlags);
-      void assign(dxt_image* p, pixel_format fmt = PIXEL_FMT_INVALID, orientation_flags_t orient_flags = cDefaultOrientationFlags);
-
-      void set(texture_file_types::format source_file_type, const mipmapped_texture& mipmapped_texture);
-
-      // Accessors
-      image_u8* get_level_image(uint face, uint level, image_u8& img, uint unpack_flags = cUnpackFlagUncook | cUnpackFlagUnflip) const;
-
-      inline bool is_valid() const { return m_faces.size() > 0; }
-
-      const dynamic_string& get_name() const { return m_name; }
-      void set_name(const dynamic_string& name) { m_name = 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; }
-      inline uint get_height() const { return m_height; }
-      inline uint get_total_pixels() const { return m_width * m_height; }
-      uint get_total_pixels_in_all_faces_and_mips() const;
-
-      inline uint get_num_faces() const { return m_faces.size(); }
-      inline uint get_num_levels() const { if (m_faces.empty()) return 0; else return m_faces[0].size(); }
-
-      inline pixel_format_helpers::component_flags get_comp_flags() const { return m_comp_flags; }
-      inline pixel_format get_format() const { return m_format; }
-
-      inline bool is_unpacked() const { if (get_num_faces()) { return get_level(0, 0)->get_image() != NULL; } return false; }
-
-      inline const   mip_ptr_vec& get_face(uint face) const { return m_faces[face]; }
-      inline         mip_ptr_vec& get_face(uint face)       { return m_faces[face]; }
-
-      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;
-      texture_type determine_texture_type() const;
-
-      const dynamic_string& get_last_error() const { return m_last_error; }
-      void clear_last_error() { m_last_error.clear(); }
-
-      // Reading/writing
-      bool read_dds(data_stream_serializer& serializer);
-      bool write_dds(data_stream_serializer& serializer) const;
-
-      bool read_ktx(data_stream_serializer& serializer);
-      bool write_ktx(data_stream_serializer& serializer) const;
- 
-      bool read_crn(data_stream_serializer& serializer);
-      bool read_crn_from_memory(const void *pData, uint data_size, const char* pFilename);
-      
-      // If file_format is texture_file_types::cFormatInvalid, the format will be determined from the filename's extension.
-      bool read_from_file(const char* pFilename, texture_file_types::format file_format = texture_file_types::cFormatInvalid);
-      bool read_from_stream(data_stream_serializer& serializer, texture_file_types::format file_format = texture_file_types::cFormatInvalid);
-
-      bool write_to_file(
-         const char* pFilename,
-         texture_file_types::format file_format = texture_file_types::cFormatInvalid,
-         crn_comp_params* pComp_params = NULL,
-         uint32* pActual_quality_level = NULL, float* pActual_bitrate = NULL,
-         uint32 image_write_flags = 0);
-
-      // 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);
-      bool convert(pixel_format fmt, bool cook, const dxt_image::pack_params& p, int qdxt_quality, bool hierarchical = true);
-      bool convert(image_utils::conversion_type conv_type);
-
-      bool unpack_from_dxt(bool uncook = true);
-
-      bool set_alpha_to_luma();
-
-      void discard_mipmaps();
-
-      void discard_mips();
-
-      struct resample_params
-      {
-         resample_params() :
-            m_pFilter("kaiser"),
-            m_wrapping(false),
-            m_srgb(false),
-            m_renormalize(false),
-            m_filter_scale(.9f),
-            m_gamma(1.75f),    // or 2.2f
-            m_multithreaded(true)
-         {
-         }
-
-         const char* m_pFilter;
-         bool        m_wrapping;
-         bool        m_srgb;
-         bool        m_renormalize;
-         float       m_filter_scale;
-         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() :
-            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<dxt_pixel_block>     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;
-            m_qdxt1.clear();
-            m_qdxt5a.clear();
-            m_qdxt5b.clear();
-            m_pixel_blocks.clear();
-            m_qdxt1_params.clear();
-            m_qdxt5_params[0].clear();
-            m_qdxt5_params[1].clear();
-            utils::zero_object(m_has_blocks);
-         }
-      };
-      bool qdxt_pack_init(qdxt_state& state, mipmapped_texture& dst_tex, const qdxt1_params& dxt1_params, const qdxt5_params& dxt5_params, pixel_format fmt, bool cook);
-      bool qdxt_pack(qdxt_state& state, mipmapped_texture& dst_tex, const qdxt1_params& dxt1_params, const qdxt5_params& dxt5_params);
-
-      void swap(mipmapped_texture& img);
-
-      bool check() const;
-
-      void set_orientation_flags(orientation_flags_t flags);
-
-      // Returns true if any face/miplevel is flipped.
-      bool is_flipped() const;
-      bool is_x_flipped() const;
-      bool is_y_flipped() const;
-      bool can_unflip_without_unpacking() const;
-      bool unflip(bool allow_unpacking_to_flip, bool uncook_if_necessary_to_unpack);
-      
-      bool flip_y(bool update_orientation_flags);
-
-   private:
-      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_string                 m_last_error;
-
-      inline void clear_last_error() const { m_last_error.clear(); }
-      inline void set_last_error(const char* p) const { m_last_error = p; }
-
-      void free_all_mips();
-      bool read_regular_image(data_stream_serializer &serializer, texture_file_types::format file_format);
-      bool write_regular_image(const char* pFilename, uint32 image_write_flags);
-      bool read_dds_internal(data_stream_serializer& serializer);
-      void print_crn_comp_params(const crn_comp_params& p);
-      bool write_comp_texture(const char* pFilename, const crn_comp_params &comp_params, uint32 *pActual_quality_level, float *pActual_bitrate);
-      void change_dxt1_to_dxt1a();
-      bool flip_y_helper();
-   };
-
-   inline void swap(mipmapped_texture& a, mipmapped_texture& b)
-   {
-      a.swap(b);
-   }
-
-} // namespace crnlib

+ 0 - 91
Source/ThirdParty/crunch/crnlib/crn_packed_uint.h

@@ -1,91 +0,0 @@
-// File: crn_packed_uint
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   template<unsigned int N>
-   struct packed_uint
-   {
-      inline packed_uint() { }
-
-      inline packed_uint(unsigned int val) { *this = val; }
-
-      inline packed_uint(const packed_uint& other) { *this = other; }
-
-      inline packed_uint& operator= (const packed_uint& rhs)
-      {
-         if (this != &rhs)
-            memcpy(m_buf, rhs.m_buf, sizeof(m_buf));
-         return *this;
-      }
-
-      inline packed_uint& operator= (unsigned int val)
-      {
-#ifdef CRNLIB_BUILD_DEBUG
-         if (N == 1)
-         {
-            CRNLIB_ASSERT(val <= 0xFFU);
-         }
-         else if (N == 2)
-         {
-            CRNLIB_ASSERT(val <= 0xFFFFU);
-         }
-         else if (N == 3)
-         {
-            CRNLIB_ASSERT(val <= 0xFFFFFFU);
-         }
-#endif      
-         
-         val <<= (8U * (4U - N));
-
-         for (unsigned int i = 0; i < N; i++)
-         {
-            m_buf[i] = static_cast<unsigned char>(val >> 24U);
-            val <<= 8U;
-         }
-
-         return *this;
-      }
-
-      inline operator unsigned int() const
-      {
-         switch (N)
-         {
-            case 1:  return  m_buf[0];
-            case 2:  return (m_buf[0] <<  8U) |  m_buf[1];
-            case 3:  return (m_buf[0] << 16U) | (m_buf[1] <<  8U) | (m_buf[2]);
-            default: return (m_buf[0] << 24U) | (m_buf[1] << 16U) | (m_buf[2] << 8U) | (m_buf[3]);
-         }
-      }
-
-      unsigned char m_buf[N];
-   };
-   template<typename T>
-   class packed_value
-   {
-   public:
-      packed_value() { }
-      packed_value(T val) { *this = val; }
-
-      inline operator T() const
-      {
-         T result = 0;
-         for (int i = sizeof(T) - 1; i >= 0; i--)
-            result = static_cast<T>((result << 8) | m_bytes[i]);
-         return result;
-      }
-      packed_value& operator= (T val)
-      {
-         for (int i = 0; i < sizeof(T); i++)
-         {
-            m_bytes[i] = static_cast<uint8>(val);
-            val >>= 8;
-         }
-         return *this;
-      }            
-   private:
-      uint8 m_bytes[sizeof(T)];
-   };
-} // namespace crnlib
-   

+ 0 - 280
Source/ThirdParty/crunch/crnlib/crn_pixel_format.cpp

@@ -1,280 +0,0 @@
-// File: crn_pixel_format.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_pixel_format.h"
-#include "crn_image.h"
-
-namespace crnlib
-{
-   namespace pixel_format_helpers
-   {
-      const pixel_format g_all_pixel_formats[] =
-      {
-         PIXEL_FMT_DXT1,
-         PIXEL_FMT_DXT2,
-         PIXEL_FMT_DXT3,
-         PIXEL_FMT_DXT4,
-         PIXEL_FMT_DXT5,
-         PIXEL_FMT_3DC,
-         PIXEL_FMT_DXN,
-         PIXEL_FMT_DXT5A,
-         PIXEL_FMT_DXT5_CCxY,
-         PIXEL_FMT_DXT5_xGxR,
-         PIXEL_FMT_DXT5_xGBR,
-         PIXEL_FMT_DXT5_AGBR,
-         PIXEL_FMT_DXT1A,
-         PIXEL_FMT_ETC1,
-         PIXEL_FMT_R8G8B8,
-         PIXEL_FMT_L8,
-         PIXEL_FMT_A8,
-         PIXEL_FMT_A8L8,
-         PIXEL_FMT_A8R8G8B8
-      };
-
-      uint get_num_formats()
-      {
-         return sizeof(g_all_pixel_formats) / sizeof(g_all_pixel_formats[0]);
-      }
-
-      pixel_format get_pixel_format_by_index(uint index)
-      {
-         CRNLIB_ASSERT(index < get_num_formats());
-         return g_all_pixel_formats[index];
-      }
-
-      const char* get_pixel_format_string(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_INVALID:   return "INVALID";
-            case PIXEL_FMT_DXT1:      return "DXT1";
-            case PIXEL_FMT_DXT1A:     return "DXT1A";
-            case PIXEL_FMT_DXT2:      return "DXT2";
-            case PIXEL_FMT_DXT3:      return "DXT3";
-            case PIXEL_FMT_DXT4:      return "DXT4";
-            case PIXEL_FMT_DXT5:      return "DXT5";
-            case PIXEL_FMT_3DC:       return "3DC";
-            case PIXEL_FMT_DXN:       return "DXN";
-            case PIXEL_FMT_DXT5A:     return "DXT5A";
-            case PIXEL_FMT_DXT5_CCxY: return "DXT5_CCxY";
-            case PIXEL_FMT_DXT5_xGxR: return "DXT5_xGxR";
-            case PIXEL_FMT_DXT5_xGBR: return "DXT5_xGBR";
-            case PIXEL_FMT_DXT5_AGBR: return "DXT5_AGBR";
-            case PIXEL_FMT_ETC1:      return "ETC1";
-            case PIXEL_FMT_R8G8B8:    return "R8G8B8";
-            case PIXEL_FMT_A8R8G8B8:  return "A8R8G8B8";
-            case PIXEL_FMT_A8:        return "A8";
-            case PIXEL_FMT_L8:        return "L8";
-            case PIXEL_FMT_A8L8:      return "A8L8";
-            default: break;
-         }
-         CRNLIB_ASSERT(false);
-         return "?";
-      }
-
-      const char* get_crn_format_string(crn_format fmt)
-      {
-         switch (fmt)
-         {
-            case cCRNFmtDXT1:        return "DXT1";
-            case cCRNFmtDXT3:        return "DXT3";
-            case cCRNFmtDXT5:        return "DXT5";
-            case cCRNFmtDXT5_CCxY:   return "DXT5_CCxY";
-            case cCRNFmtDXT5_xGBR:   return "DXT5_xGBR";
-            case cCRNFmtDXT5_AGBR:   return "DXT5_AGBR";
-            case cCRNFmtDXT5_xGxR:   return "DXT5_xGxR";
-            case cCRNFmtDXN_XY:      return "DXN_XY";
-            case cCRNFmtDXN_YX:      return "DXN_YX";
-            case cCRNFmtDXT5A:       return "DXT5A";
-            case cCRNFmtETC1:        return "ETC1";
-            default: break;
-         }
-         CRNLIB_ASSERT(false);
-         return "?";
-      }
-
-      component_flags get_component_flags(pixel_format fmt)
-      {
-         // These flags are for *uncooked* pixels, i.e. after after adding Z to DXN maps, or converting YCC maps to RGB, etc.
-
-         uint flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid | cCompFlagGrayscale;
-         switch (fmt)
-         {
-            case PIXEL_FMT_DXT1:
-            case PIXEL_FMT_ETC1:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid;
-               break;
-            }
-            case PIXEL_FMT_DXT1A:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid;
-               break;
-            }
-            case PIXEL_FMT_DXT2:
-            case PIXEL_FMT_DXT3:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid;
-               break;
-            }
-            case PIXEL_FMT_DXT4:
-            case PIXEL_FMT_DXT5:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid;
-               break;
-            }
-            case PIXEL_FMT_DXT5A:
-            {
-               flags = cCompFlagAValid;
-               break;
-            }
-            case PIXEL_FMT_DXT5_CCxY:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagLumaChroma;
-               break;
-            }
-            case PIXEL_FMT_DXT5_xGBR:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagNormalMap;
-               break;
-            }
-            case PIXEL_FMT_DXT5_AGBR:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid | cCompFlagNormalMap;
-               break;
-            }
-            case PIXEL_FMT_DXT5_xGxR:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagNormalMap;
-               break;
-            }
-            case PIXEL_FMT_3DC:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagNormalMap;
-               break;
-            }
-            case PIXEL_FMT_DXN:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagNormalMap;
-               break;
-            }
-            case PIXEL_FMT_R8G8B8:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid;
-               break;
-            }
-            case PIXEL_FMT_A8R8G8B8:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid;
-               break;
-            }
-            case PIXEL_FMT_A8:
-            {
-               flags = cCompFlagAValid;
-               break;
-            }
-            case PIXEL_FMT_L8:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagGrayscale;
-               break;
-            }
-            case PIXEL_FMT_A8L8:
-            {
-               flags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid | cCompFlagGrayscale;
-               break;
-            }
-            default:
-            {
-               CRNLIB_ASSERT(0);
-               break;
-            }
-         }
-         return static_cast<component_flags>(flags);
-      }
-
-      crn_format convert_pixel_format_to_best_crn_format(pixel_format crn_fmt)
-      {
-         crn_format fmt = cCRNFmtDXT1;
-         switch (crn_fmt)
-         {
-            case PIXEL_FMT_DXT1:
-            case PIXEL_FMT_DXT1A:
-               fmt = cCRNFmtDXT1;
-               break;
-            case PIXEL_FMT_DXT2:
-            case PIXEL_FMT_DXT3:
-            case PIXEL_FMT_DXT4:
-            case PIXEL_FMT_DXT5:
-               fmt = cCRNFmtDXT5;
-               break;
-            case PIXEL_FMT_3DC:
-               fmt = cCRNFmtDXN_YX;
-               break;
-            case PIXEL_FMT_DXN:
-               fmt = cCRNFmtDXN_XY;
-               break;
-            case PIXEL_FMT_DXT5A:
-               fmt = cCRNFmtDXT5A;
-               break;
-            case PIXEL_FMT_R8G8B8:
-            case PIXEL_FMT_L8:
-               fmt = cCRNFmtDXT1;
-               break;
-            case PIXEL_FMT_A8R8G8B8:
-            case PIXEL_FMT_A8:
-            case PIXEL_FMT_A8L8:
-               fmt = cCRNFmtDXT5;
-               break;
-            case PIXEL_FMT_DXT5_CCxY:
-               fmt = cCRNFmtDXT5_CCxY;
-               break;
-            case PIXEL_FMT_DXT5_xGBR:
-               fmt = cCRNFmtDXT5_xGBR;
-               break;
-            case PIXEL_FMT_DXT5_AGBR:
-               fmt = cCRNFmtDXT5_AGBR;
-               break;
-            case PIXEL_FMT_DXT5_xGxR:
-               fmt = cCRNFmtDXT5_xGxR;
-               break;
-            case PIXEL_FMT_ETC1:
-               fmt = cCRNFmtETC1;
-               break;
-            default:
-            {
-               CRNLIB_ASSERT(false);
-               break;
-            }
-         }
-         return fmt;
-      }
-
-      pixel_format convert_crn_format_to_pixel_format(crn_format fmt)
-      {
-         switch (fmt)
-         {
-            case cCRNFmtDXT1:       return PIXEL_FMT_DXT1;
-            case cCRNFmtDXT3:       return PIXEL_FMT_DXT3;
-            case cCRNFmtDXT5:       return PIXEL_FMT_DXT5;
-            case cCRNFmtDXT5_CCxY:  return PIXEL_FMT_DXT5_CCxY;
-            case cCRNFmtDXT5_xGxR:  return PIXEL_FMT_DXT5_xGxR;
-            case cCRNFmtDXT5_xGBR:  return PIXEL_FMT_DXT5_xGBR;
-            case cCRNFmtDXT5_AGBR:  return PIXEL_FMT_DXT5_AGBR;
-            case cCRNFmtDXN_XY:     return PIXEL_FMT_DXN;
-            case cCRNFmtDXN_YX:     return PIXEL_FMT_3DC;
-            case cCRNFmtDXT5A:      return PIXEL_FMT_DXT5A;
-            case cCRNFmtETC1:       return PIXEL_FMT_ETC1;
-            default: 
-            {
-               CRNLIB_ASSERT(false); 
-               break;
-            }
-         }
-
-         return PIXEL_FMT_INVALID;
-      }
-
-   } // namespace pixel_format
-
-} // namespace crnlib
-

+ 0 - 284
Source/ThirdParty/crunch/crnlib/crn_pixel_format.h

@@ -1,284 +0,0 @@
-// File: crn_pixel_format.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dxt.h"
-#include "../inc/crnlib.h"
-#include "../inc/dds_defs.h"
-
-namespace crnlib
-{
-   namespace pixel_format_helpers
-   {
-      uint get_num_formats();
-      pixel_format get_pixel_format_by_index(uint index);
-
-      const char* get_pixel_format_string(pixel_format fmt);
-
-      const char* get_crn_format_string(crn_format fmt);
-
-      inline bool is_grayscale(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_L8:
-            case PIXEL_FMT_A8L8:
-               return true;
-            default: break;
-         }
-         return false;
-      }
-
-      inline bool is_dxt1(pixel_format fmt)
-      {
-         return (fmt == PIXEL_FMT_DXT1) || (fmt == PIXEL_FMT_DXT1A);
-      }
-
-      // has_alpha() should probably be called "has_opacity()" - it indicates if the format encodes opacity
-      // because some swizzled DXT5 formats do not encode opacity.
-      inline bool has_alpha(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_DXT1A:
-            case PIXEL_FMT_DXT2:
-            case PIXEL_FMT_DXT3:
-            case PIXEL_FMT_DXT4:
-            case PIXEL_FMT_DXT5:
-            case PIXEL_FMT_DXT5A:
-            case PIXEL_FMT_A8R8G8B8:
-            case PIXEL_FMT_A8:
-            case PIXEL_FMT_A8L8:
-            case PIXEL_FMT_DXT5_AGBR:
-               return true;
-            default: break;
-         }
-         return false;
-      }
-
-      inline bool is_alpha_only(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_A8:
-            case PIXEL_FMT_DXT5A:
-               return true;
-            default: break;
-         }
-         return false;
-      }
-
-      inline bool is_normal_map(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_3DC:
-            case PIXEL_FMT_DXN:
-            case PIXEL_FMT_DXT5_xGBR:
-            case PIXEL_FMT_DXT5_xGxR:
-            case PIXEL_FMT_DXT5_AGBR:
-               return true;
-            default: break;
-         }
-         return false;
-      }
-
-      inline int is_dxt(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_DXT1:
-            case PIXEL_FMT_DXT1A:
-            case PIXEL_FMT_DXT2:
-            case PIXEL_FMT_DXT3:
-            case PIXEL_FMT_DXT4:
-            case PIXEL_FMT_DXT5:
-            case PIXEL_FMT_3DC:
-            case PIXEL_FMT_DXT5A:
-            case PIXEL_FMT_DXN:
-            case PIXEL_FMT_DXT5_CCxY:
-            case PIXEL_FMT_DXT5_xGxR:
-            case PIXEL_FMT_DXT5_xGBR:
-            case PIXEL_FMT_DXT5_AGBR:
-            case PIXEL_FMT_ETC1:
-               return true;
-            default: break;
-         }
-         return false;
-      }
-
-      inline int get_fundamental_format(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_DXT1A:
-               return PIXEL_FMT_DXT1;
-            case PIXEL_FMT_DXT5_CCxY:
-            case PIXEL_FMT_DXT5_xGxR:
-            case PIXEL_FMT_DXT5_xGBR:
-            case PIXEL_FMT_DXT5_AGBR:
-               return PIXEL_FMT_DXT5;
-            default: break;
-         }
-         return fmt;
-      }
-
-      inline dxt_format get_dxt_format(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_DXT1:         return cDXT1;
-            case PIXEL_FMT_DXT1A:        return cDXT1A;
-            case PIXEL_FMT_DXT2:         return cDXT3;
-            case PIXEL_FMT_DXT3:         return cDXT3;
-            case PIXEL_FMT_DXT4:         return cDXT5;
-            case PIXEL_FMT_DXT5:         return cDXT5;
-            case PIXEL_FMT_3DC:          return cDXN_YX;
-            case PIXEL_FMT_DXT5A:        return cDXT5A;
-            case PIXEL_FMT_DXN:          return cDXN_XY;
-            case PIXEL_FMT_DXT5_CCxY:    return cDXT5;
-            case PIXEL_FMT_DXT5_xGxR:    return cDXT5;
-            case PIXEL_FMT_DXT5_xGBR:    return cDXT5;
-            case PIXEL_FMT_DXT5_AGBR:    return cDXT5;
-            case PIXEL_FMT_ETC1:         return cETC1;
-            default: break;
-         }
-         return cDXTInvalid;
-      }
-
-      inline pixel_format from_dxt_format(dxt_format dxt_fmt)
-      {
-         switch (dxt_fmt)
-         {
-            case cDXT1:
-               return PIXEL_FMT_DXT1;
-            case cDXT1A:
-               return PIXEL_FMT_DXT1A;
-            case cDXT3:
-               return PIXEL_FMT_DXT3;
-            case cDXT5:
-               return PIXEL_FMT_DXT5;
-            case cDXN_XY:
-               return PIXEL_FMT_DXN;
-            case cDXN_YX:
-               return PIXEL_FMT_3DC;
-            case cDXT5A:
-               return PIXEL_FMT_DXT5A;
-            case cETC1:
-               return PIXEL_FMT_ETC1;
-            default: break;
-         }
-         CRNLIB_ASSERT(false);
-         return PIXEL_FMT_INVALID;
-      }
-
-      inline bool is_pixel_format_non_srgb(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_3DC:
-            case PIXEL_FMT_DXN:
-            case PIXEL_FMT_DXT5A:
-            case PIXEL_FMT_DXT5_CCxY:
-            case PIXEL_FMT_DXT5_xGxR:
-            case PIXEL_FMT_DXT5_xGBR:
-            case PIXEL_FMT_DXT5_AGBR:
-               return true;
-            default: break;
-         }
-         return false;
-      }
-
-      inline bool is_crn_format_non_srgb(crn_format fmt)
-      {
-         switch (fmt)
-         {
-            case cCRNFmtDXN_XY:
-            case cCRNFmtDXN_YX:
-            case cCRNFmtDXT5A:
-            case cCRNFmtDXT5_CCxY:
-            case cCRNFmtDXT5_xGxR:
-            case cCRNFmtDXT5_xGBR:
-            case cCRNFmtDXT5_AGBR:
-               return true;
-            default: break;
-         }
-         return false;
-      }
-
-      inline uint get_bpp(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_DXT1:      return 4;
-            case PIXEL_FMT_DXT1A:     return 4;
-            case PIXEL_FMT_ETC1:      return 4;
-            case PIXEL_FMT_DXT2:      return 8;
-            case PIXEL_FMT_DXT3:      return 8;
-            case PIXEL_FMT_DXT4:      return 8;
-            case PIXEL_FMT_DXT5:      return 8;
-            case PIXEL_FMT_3DC:       return 8;
-            case PIXEL_FMT_DXT5A:     return 4;
-            case PIXEL_FMT_R8G8B8:    return 24;
-            case PIXEL_FMT_A8R8G8B8:  return 32;
-            case PIXEL_FMT_A8:        return 8;
-            case PIXEL_FMT_L8:        return 8;
-            case PIXEL_FMT_A8L8:      return 16;
-            case PIXEL_FMT_DXN:       return 8;
-            case PIXEL_FMT_DXT5_CCxY: return 8;
-            case PIXEL_FMT_DXT5_xGxR: return 8;
-            case PIXEL_FMT_DXT5_xGBR: return 8;
-            case PIXEL_FMT_DXT5_AGBR: return 8;
-            default: break;
-         }
-         CRNLIB_ASSERT(false);
-         return 0;
-      };
-
-      inline uint get_dxt_bytes_per_block(pixel_format fmt)
-      {
-         switch (fmt)
-         {
-            case PIXEL_FMT_DXT1:      return 8;
-            case PIXEL_FMT_DXT1A:     return 8;
-            case PIXEL_FMT_DXT5A:     return 8;
-            case PIXEL_FMT_ETC1:      return 8;
-            case PIXEL_FMT_DXT2:      return 16;
-            case PIXEL_FMT_DXT3:      return 16;
-            case PIXEL_FMT_DXT4:      return 16;
-            case PIXEL_FMT_DXT5:      return 16;
-            case PIXEL_FMT_3DC:       return 16;
-            case PIXEL_FMT_DXN:       return 16;
-            case PIXEL_FMT_DXT5_CCxY: return 16;
-            case PIXEL_FMT_DXT5_xGxR: return 16;
-            case PIXEL_FMT_DXT5_xGBR: return 16;
-            case PIXEL_FMT_DXT5_AGBR: return 16;
-            default: break;
-         }
-         CRNLIB_ASSERT(false);
-         return 0;
-      }
-
-      enum component_flags
-      {
-         cCompFlagRValid            = 1,
-         cCompFlagGValid            = 2,
-         cCompFlagBValid            = 4,
-         cCompFlagAValid            = 8,
-
-         cCompFlagGrayscale         = 16,
-         cCompFlagNormalMap         = 32,
-         cCompFlagLumaChroma        = 64,
-
-         cDefaultCompFlags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid
-      };
-
-      component_flags get_component_flags(pixel_format fmt);
-
-      crn_format convert_pixel_format_to_best_crn_format(pixel_format crn_fmt);
-
-      pixel_format convert_crn_format_to_pixel_format(crn_format fmt);
-
-   } // namespace pixel_format_helpers
-
-} // namespace crnlib
-

+ 0 - 92
Source/ThirdParty/crunch/crnlib/crn_platform.cpp

@@ -1,92 +0,0 @@
-// 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)
-{
-   return IsDebuggerPresent() != 0;
-}
-
-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

+ 0 - 96
Source/ThirdParty/crunch/crnlib/crn_platform.h

@@ -1,96 +0,0 @@
-// File: crn_platform.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-bool crnlib_is_debugger_present(void);
-void crnlib_debug_break(void);
-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<long>(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)))
-   #define CRNLIB_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER)
-   #define CRNLIB_ALIGNED(x) __declspec(align(x))
-   #define CRNLIB_NOINLINE __declspec(noinline) 
-#else
-   #define CRNLIB_ALIGNED(x)
-   #define CRNLIB_NOINLINE
-#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
-}

+ 0 - 356
Source/ThirdParty/crunch/crnlib/crn_prefix_coding.cpp

@@ -1,356 +0,0 @@
-// File: crn_prefix_coding.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_prefix_coding.h"
-//#include "rand.h"
-
-#ifdef CRNLIB_BUILD_DEBUG
-   //#define TEST_DECODER_TABLES
-#endif
-
-namespace crnlib
-{
-
-   namespace prefix_coding
-   {
-      bool limit_max_code_size(uint num_syms, uint8* pCodesizes, uint max_code_size)
-      {
-         const uint cMaxEverCodeSize = 34;            
-         
-         if ((!num_syms) || (num_syms > cMaxSupportedSyms) || (max_code_size < 1) || (max_code_size > cMaxEverCodeSize))
-            return false;
-         
-         uint num_codes[cMaxEverCodeSize + 1];
-         utils::zero_object(num_codes);
-
-         bool should_limit = false;
-         
-         for (uint i = 0; i < num_syms; i++)
-         {
-            uint c = pCodesizes[i];
-            if (c)
-            {
-               CRNLIB_ASSERT(c <= cMaxEverCodeSize);
-               
-               num_codes[c]++;
-               if (c > max_code_size)
-                  should_limit = true;
-            }
-         }
-         
-         if (!should_limit)
-            return true;
-         
-         uint ofs = 0;
-         uint next_sorted_ofs[cMaxEverCodeSize + 1];
-         for (uint i = 1; i <= cMaxEverCodeSize; i++)
-         {
-            next_sorted_ofs[i] = ofs;
-            ofs += num_codes[i];
-         }
-            
-         if ((ofs < 2) || (ofs > cMaxSupportedSyms))
-            return true;
-         
-         if (ofs > (1U << max_code_size))
-            return false;
-                           
-         for (uint i = max_code_size + 1; i <= cMaxEverCodeSize; i++)
-            num_codes[max_code_size] += num_codes[i];
-         
-         // Technique of adjusting tree to enforce maximum code size from LHArc.
-         
-         uint total = 0;
-         for (uint i = max_code_size; i; --i)
-            total += (num_codes[i] << (max_code_size - i));
-
-         if (total == (1U << max_code_size))  
-            return true;
-            
-         do
-         {
-            num_codes[max_code_size]--;
-
-            uint i;
-            for (i = max_code_size - 1; i; --i)
-            {
-               if (!num_codes[i])
-                  continue;
-               num_codes[i]--;          
-               num_codes[i + 1] += 2;   
-               break;
-            }
-            if (!i)
-               return false;
-
-            total--;   
-         } while (total != (1U << max_code_size));
-         
-         uint8 new_codesizes[cMaxSupportedSyms];
-         uint8* p = new_codesizes;
-         for (uint i = 1; i <= max_code_size; i++)
-         {
-            uint n = num_codes[i];
-            if (n)
-            {
-               memset(p, i, n);
-               p += n;
-            }
-         }
-                                             
-         for (uint i = 0; i < num_syms; i++)
-         {
-            const uint c = pCodesizes[i];
-            if (c)
-            {
-               uint ofs = next_sorted_ofs[c];
-               next_sorted_ofs[c] = ofs + 1;
-            
-               pCodesizes[i] = static_cast<uint8>(new_codesizes[ofs]);
-            }
-         }
-            
-         return true;
-      }
-            
-      bool generate_codes(uint num_syms, const uint8* pCodesizes, uint16* pCodes)
-      {
-         uint num_codes[cMaxExpectedCodeSize + 1];
-         utils::zero_object(num_codes);
-
-         for (uint i = 0; i < num_syms; i++)
-         {
-            uint c = pCodesizes[i];
-            if (c)
-            {
-               CRNLIB_ASSERT(c <= cMaxExpectedCodeSize);
-               num_codes[c]++;
-            }
-         }
-
-         uint code = 0;
-
-         uint next_code[cMaxExpectedCodeSize + 1];
-         next_code[0] = 0;
-         
-         for (uint i = 1; i <= cMaxExpectedCodeSize; i++)
-         {
-            next_code[i] = code;
-            
-            code = (code + num_codes[i]) << 1;
-         }
-
-         if (code != (1 << (cMaxExpectedCodeSize + 1)))
-         {
-            uint t = 0;
-            for (uint i = 1; i <= cMaxExpectedCodeSize; i++)
-            {
-               t += num_codes[i];
-               if (t > 1)
-                  return false;
-            }
-         }
-
-         for (uint i = 0; i < num_syms; i++)
-         {
-            uint c = pCodesizes[i];
-            if (c)
-            {
-               CRNLIB_ASSERT(next_code[c] <= cUINT16_MAX);
-               pCodes[i] = static_cast<uint16>(next_code[c]++);
-               
-               CRNLIB_ASSERT(math::total_bits(pCodes[i]) <= pCodesizes[i]);
-            }
-         }  
-         
-         return true;
-      }
-            
-      bool generate_decoder_tables(uint num_syms, const uint8* pCodesizes, decoder_tables* pTables, uint table_bits)
-      {
-         uint min_codes[cMaxExpectedCodeSize];
-         
-         if ((!num_syms) || (table_bits > cMaxTableBits))
-            return false;
-            
-         pTables->m_num_syms = num_syms;
-         
-         uint num_codes[cMaxExpectedCodeSize + 1];
-         utils::zero_object(num_codes);
-
-         for (uint i = 0; i < num_syms; i++)
-         {
-            uint c = pCodesizes[i];
-            if (c)
-               num_codes[c]++;
-         }
-
-         uint sorted_positions[cMaxExpectedCodeSize + 1];
-               
-         uint code = 0;
-
-         uint total_used_syms = 0;
-         uint max_code_size = 0;
-         uint min_code_size = UINT_MAX;
-         for (uint i = 1; i <= cMaxExpectedCodeSize; i++)
-         {
-            const uint n = num_codes[i];
-            
-            if (!n)
-               pTables->m_max_codes[i - 1] = 0;//UINT_MAX;
-            else
-            {
-               min_code_size = math::minimum(min_code_size, i);
-               max_code_size = math::maximum(max_code_size, i);
-                  
-               min_codes[i - 1] = code;
-               
-               pTables->m_max_codes[i - 1] = code + n - 1;
-               pTables->m_max_codes[i - 1] = 1 + ((pTables->m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1));
-               
-               pTables->m_val_ptrs[i - 1] = total_used_syms;
-               
-               sorted_positions[i] = total_used_syms;
-               
-               code += n;
-               total_used_syms += n;
-            }
-
-            code <<= 1;
-         }
-         
-         pTables->m_total_used_syms = total_used_syms;
-
-         if (total_used_syms > pTables->m_cur_sorted_symbol_order_size)
-         {
-            pTables->m_cur_sorted_symbol_order_size = total_used_syms;
-            
-            if (!math::is_power_of_2(total_used_syms))
-               pTables->m_cur_sorted_symbol_order_size = math::minimum<uint>(num_syms, math::next_pow2(total_used_syms));
-            
-            if (pTables->m_sorted_symbol_order)
-            {
-               crnlib_delete_array(pTables->m_sorted_symbol_order);
-               pTables->m_sorted_symbol_order = NULL;
-            }
-            
-            pTables->m_sorted_symbol_order = crnlib_new_array<uint16>(pTables->m_cur_sorted_symbol_order_size);
-         }
-         
-         pTables->m_min_code_size = static_cast<uint8>(min_code_size);
-         pTables->m_max_code_size = static_cast<uint8>(max_code_size);
-                  
-         for (uint i = 0; i < num_syms; i++)
-         {
-            uint c = pCodesizes[i];
-            if (c)
-            {
-               CRNLIB_ASSERT(num_codes[c]);
-               
-               uint sorted_pos = sorted_positions[c]++;
-               
-               CRNLIB_ASSERT(sorted_pos < total_used_syms);
-               
-               pTables->m_sorted_symbol_order[sorted_pos] = static_cast<uint16>(i);
-            }            
-         }
-
-         if (table_bits <= pTables->m_min_code_size)
-            table_bits = 0;                                       
-         pTables->m_table_bits = table_bits;
-                  
-         if (table_bits)
-         {
-            uint table_size = 1 << table_bits;
-            if (table_size > pTables->m_cur_lookup_size)
-            {
-               pTables->m_cur_lookup_size = table_size;
-               
-               if (pTables->m_lookup)
-               {
-                  crnlib_delete_array(pTables->m_lookup);
-                  pTables->m_lookup = NULL;
-               }
-                  
-               pTables->m_lookup = crnlib_new_array<uint32>(table_size);
-            }
-                        
-            memset(pTables->m_lookup, 0xFF, static_cast<uint>(sizeof(pTables->m_lookup[0])) * (1UL << table_bits));
-            
-            for (uint codesize = 1; codesize <= table_bits; codesize++)
-            {
-               if (!num_codes[codesize])
-                  continue;
-               
-               const uint fillsize = table_bits - codesize;
-               const uint fillnum = 1 << fillsize;
-               
-               const uint min_code = min_codes[codesize - 1];
-               const uint max_code = pTables->get_unshifted_max_code(codesize);
-               const uint val_ptr = pTables->m_val_ptrs[codesize - 1];
-                      
-               for (uint code = min_code; code <= max_code; code++)
-               {
-                  const uint sym_index = pTables->m_sorted_symbol_order[ val_ptr + code - min_code ];
-                  CRNLIB_ASSERT( pCodesizes[sym_index] == codesize );
-                  
-                  for (uint j = 0; j < fillnum; j++)
-                  {
-                     const uint t = j + (code << fillsize);
-                     
-                     CRNLIB_ASSERT(t < (1U << table_bits));
-                     
-                     CRNLIB_ASSERT(pTables->m_lookup[t] == cUINT32_MAX);
-                     
-                     pTables->m_lookup[t] = sym_index | (codesize << 16U);
-                  }
-               }
-            }
-         }         
-         
-         for (uint i = 0; i < cMaxExpectedCodeSize; i++)
-            pTables->m_val_ptrs[i] -= min_codes[i];
-         
-         pTables->m_table_max_code = 0;
-         pTables->m_decode_start_code_size = pTables->m_min_code_size;
-
-         if (table_bits)
-         {
-            uint i;
-            for (i = table_bits; i >= 1; i--)
-            {
-               if (num_codes[i])
-               {
-                  pTables->m_table_max_code = pTables->m_max_codes[i - 1];
-                  break;
-               }
-            }
-            if (i >= 1)
-            {
-               pTables->m_decode_start_code_size = table_bits + 1;
-               for (uint i = table_bits + 1; i <= max_code_size; i++)
-               {
-                  if (num_codes[i])
-                  {
-                     pTables->m_decode_start_code_size = i;
-                     break;
-                  }
-               }
-            }
-         }
-
-         // sentinels
-         pTables->m_max_codes[cMaxExpectedCodeSize] = UINT_MAX;
-         pTables->m_val_ptrs[cMaxExpectedCodeSize] = 0xFFFFF;
-
-         pTables->m_table_shift = 32 - pTables->m_table_bits;
-
-         return true;
-      }
-               
-   } // namespace prefix_codig
-
-
-} // namespace crnlib
-
-

+ 0 - 116
Source/ThirdParty/crunch/crnlib/crn_prefix_coding.h

@@ -1,116 +0,0 @@
-// File: crn_prefix_coding.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   namespace prefix_coding
-   {
-      const uint cMaxExpectedCodeSize = 16;
-      const uint cMaxSupportedSyms = 8192;
-      const uint cMaxTableBits = 11;
-
-      bool limit_max_code_size(uint num_syms, uint8* pCodesizes, uint max_code_size);
-
-      bool generate_codes(uint num_syms, const uint8* pCodesizes, uint16* pCodes);
-
-      class decoder_tables
-      {
-      public:
-         inline decoder_tables() :
-            m_table_shift(0), m_table_max_code(0), m_decode_start_code_size(0), m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL)
-         {
-         }
-
-         inline decoder_tables(const decoder_tables& other) :
-            m_table_shift(0), m_table_max_code(0), m_decode_start_code_size(0), m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL)
-         {
-            *this = other;
-         }
-
-         decoder_tables& operator= (const decoder_tables& other)
-         {
-            if (this == &other)
-               return *this;
-
-            clear();
-
-            memcpy(this, &other, sizeof(*this));
-
-            if (other.m_lookup)
-            {
-               m_lookup = crnlib_new_array<uint32>(m_cur_lookup_size);
-               memcpy(m_lookup, other.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size);
-            }
-
-            if (other.m_sorted_symbol_order)
-            {
-               m_sorted_symbol_order = crnlib_new_array<uint16>(m_cur_sorted_symbol_order_size);
-               memcpy(m_sorted_symbol_order, other.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size);
-            }
-
-            return *this;
-         }
-
-         inline void clear()
-         {
-            if (m_lookup)
-            {
-               crnlib_delete_array(m_lookup);
-               m_lookup = 0;
-               m_cur_lookup_size = 0;
-            }
-
-            if (m_sorted_symbol_order)
-            {
-               crnlib_delete_array(m_sorted_symbol_order);
-               m_sorted_symbol_order = NULL;
-               m_cur_sorted_symbol_order_size = 0;
-            }
-         }
-
-         inline ~decoder_tables()
-         {
-            if (m_lookup)
-               crnlib_delete_array(m_lookup);
-
-            if (m_sorted_symbol_order)
-               crnlib_delete_array(m_sorted_symbol_order);
-         }
-
-         // DO NOT use any complex classes here - it is bitwise copied.
-
-         uint                 m_num_syms;
-         uint                 m_total_used_syms;
-         uint                 m_table_bits;
-         uint                 m_table_shift;
-         uint                 m_table_max_code;
-         uint                 m_decode_start_code_size;
-
-         uint8                m_min_code_size;
-         uint8                m_max_code_size;
-
-         uint                 m_max_codes[cMaxExpectedCodeSize + 1];
-         int                  m_val_ptrs[cMaxExpectedCodeSize + 1];
-
-         uint                 m_cur_lookup_size;
-         uint32*              m_lookup;
-
-         uint                 m_cur_sorted_symbol_order_size;
-         uint16*              m_sorted_symbol_order;
-
-         inline uint get_unshifted_max_code(uint len) const
-         {
-            CRNLIB_ASSERT( (len >= 1) && (len <= cMaxExpectedCodeSize) );
-            uint k = m_max_codes[len - 1];
-            if (!k)
-               return UINT_MAX;
-            return (k - 1) >> (16 - len);
-         }
-      };
-
-      bool generate_decoder_tables(uint num_syms, const uint8* pCodesizes, decoder_tables* pTables, uint table_bits);
-
-   } // namespace prefix_coding
-
-} // namespace crnlib

+ 0 - 910
Source/ThirdParty/crunch/crnlib/crn_qdxt1.cpp

@@ -1,910 +0,0 @@
-// File: crn_qdxt.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_qdxt1.h"
-#include "crn_dxt1.h"
-#include "crn_dxt_fast.h"
-#include "crn_image_utils.h"
-#include "crn_dxt_hc_common.h"
-
-#define GENERATE_DEBUG_IMAGES 0
-
-namespace crnlib
-{
-   qdxt1::qdxt1(task_pool& task_pool) :
-      m_pTask_pool(&task_pool),
-      m_main_thread_id(0),
-      m_canceled(false),
-      m_progress_start(0),
-      m_progress_range(100),
-      m_num_blocks(0),
-      m_pBlocks(NULL),
-      m_pDst_elements(NULL),
-      m_elements_per_block(0),
-      m_max_selector_clusters(0),
-      m_prev_percentage_complete(-1),
-      m_selector_clusterizer(task_pool)
-   {
-   }
-
-   qdxt1::~qdxt1()
-   {
-   }
-
-   void qdxt1::clear()
-   {
-      m_main_thread_id = 0;
-      m_num_blocks = 0;
-      m_pBlocks = 0;
-      m_pDst_elements = NULL;
-      m_elements_per_block = 0;
-      m_params.clear();
-      m_endpoint_clusterizer.clear();
-      m_endpoint_cluster_indices.clear();
-      m_max_selector_clusters = 0;
-      m_canceled = false;
-      m_progress_start = 0;
-      m_progress_range = 100;
-      m_selector_clusterizer.clear();
-
-      for (uint i = 0; i <= qdxt1_params::cMaxQuality; i++)
-         m_cached_selector_cluster_indices[i].clear();
-
-      m_cluster_hash.clear();
-
-      m_prev_percentage_complete = -1;
-   }
-
-   bool qdxt1::init(uint n, const dxt_pixel_block* pBlocks, const qdxt1_params& params)
-   {
-      clear();
-
-      CRNLIB_ASSERT(n && pBlocks);
-
-      m_main_thread_id = crn_get_current_thread_id();
-
-      m_num_blocks = n;
-      m_pBlocks = pBlocks;
-      m_params = params;
-
-      m_endpoint_clusterizer.reserve_training_vecs(m_num_blocks);
-
-      m_progress_start = 0;
-      m_progress_range = 75;
-
-      const bool debugging = false;
-      image_u8 debug_img;
-
-      if ((m_params.m_hierarchical) && (m_params.m_num_mips))
-      {
-         vec6F_clusterizer::training_vec_array& training_vecs = m_endpoint_clusterizer.get_training_vecs();
-         training_vecs.resize(m_num_blocks);
-
-         uint encoding_hist[cNumChunkEncodings];
-         utils::zero_object(encoding_hist);
-
-         uint total_processed_blocks = 0;
-         uint next_progress_threshold = 512;
-
-         for (uint level = 0; level < m_params.m_num_mips; level++)
-         {
-            const qdxt1_params::mip_desc& level_desc = m_params.m_mip_desc[level];
-
-            const uint num_chunks_x = (level_desc.m_block_width + cChunkBlockWidth - 1) / cChunkBlockWidth;
-            const uint num_chunks_y = (level_desc.m_block_height + cChunkBlockHeight - 1) / cChunkBlockHeight;
-
-            const uint level_width = level_desc.m_block_width * 4;
-            const uint level_height = level_desc.m_block_height * 4;
-
-            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<float>(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++)
-               {
-                  color_quad_u8 chunk_pixels[cChunkPixelWidth * cChunkPixelHeight];
-
-                  for (uint y = 0; y < cChunkPixelHeight; y++)
-                  {
-                     const uint pix_y = math::minimum<uint>(chunk_y * cChunkPixelHeight + y, level_height - 1);
-
-                     const uint outer_block_index = level_desc.m_first_block + ((pix_y >> 2) * level_desc.m_block_width);
-
-                     for (uint x = 0; x < cChunkPixelWidth; x++)
-                     {
-                        const uint pix_x = math::minimum<uint>(chunk_x * cChunkPixelWidth + x, level_width - 1);
-
-                        const uint block_index = outer_block_index + (pix_x >> 2);
-
-                        const dxt_pixel_block& block = m_pBlocks[block_index];
-
-                        const color_quad_u8& p = block.m_pixels[pix_y & 3][pix_x & 3];
-
-                        chunk_pixels[x + y * 8] = p;
-                     }
-                  }
-
-                  struct layout_results
-                  {
-                     uint m_low_color;
-                     uint m_high_color;
-                     uint8 m_selectors[cChunkPixelWidth * cChunkPixelHeight];
-                     uint64 m_error;
-                     //float m_penalty;
-                  };
-                  layout_results layouts[cNumChunkTileLayouts];
-
-                  for (uint l = 0; l < cNumChunkTileLayouts; l++)
-                  {
-                     const uint width = g_chunk_tile_layouts[l].m_width;
-                     const uint height = g_chunk_tile_layouts[l].m_height;
-                     const uint x_ofs = g_chunk_tile_layouts[l].m_x_ofs;
-                     const uint y_ofs = g_chunk_tile_layouts[l].m_y_ofs;
-
-                     color_quad_u8 layout_pixels[cChunkPixelWidth * cChunkPixelHeight];
-                     for (uint y = 0; y < height; y++)
-                        for (uint x = 0; x < width; x++)
-                           layout_pixels[x + y * width] = chunk_pixels[(x_ofs + x) + (y_ofs + y) * cChunkPixelWidth];
-
-                     const uint n = width * height;
-                     dxt_fast::compress_color_block(n, layout_pixels, layouts[l].m_low_color, layouts[l].m_high_color, layouts[l].m_selectors);
-
-                     color_quad_u8 c[4];
-                     dxt1_block::get_block_colors(c, static_cast<uint16>(layouts[l].m_low_color), static_cast<uint16>(layouts[l].m_high_color));
-
-                     uint64 error = 0;
-                     for (uint i = 0; i < n; i++)
-                        error += color::elucidian_distance(layout_pixels[i], c[layouts[l].m_selectors[i]], false);
-
-                     layouts[l].m_error = error;
-
-#if 0
-                     if ((width > 4) || (height > 4))
-                     {
-                        const uint dist = color::elucidian_distance(
-                           dxt1_block::unpack_color(static_cast<uint16>(layouts[l].m_low_color), true),
-                           dxt1_block::unpack_color(static_cast<uint16>(layouts[l].m_high_color), true), false);
-
-                        layouts[l].m_penalty = math::clamp((sqrt((float)dist) - 75.0f) / 150.0f, 0.0f, 2.0f);
-                        if ((width == 8) && (height == 8))
-                           layouts[l].m_penalty *= 2.0f;
-                     }
-                     else
-                     {
-                        layouts[l].m_penalty = 0.0f;
-                     }
-#endif
-                  }
-
-                  double best_peak_snr = -1.0f;
-                  uint best_encoding = 0;
-
-                  for (uint e = 0; e < cNumChunkEncodings; e++)
-                  {
-                     const chunk_encoding_desc& encoding_desc = g_chunk_encodings[e];
-
-                     double total_error = 0;
-
-                     for (uint t = 0; t < encoding_desc.m_num_tiles; t++)
-                        total_error += (double)layouts[encoding_desc.m_tiles[t].m_layout_index].m_error;
-
-                     //double mean_squared = total_error * (1.0f / (16.0f * 3.0f));
-                     double mean_squared = total_error * (1.0f / (64.0f * 3.0f));
-                     double root_mean_squared = sqrt(mean_squared);
-
-                     double peak_snr = 999999.0f;
-                     if (mean_squared)
-                        peak_snr = math::clamp<double>(log10(255.0f / root_mean_squared) * 20.0f, 0.0f, 500.0f);
-
-                     //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));
-
-                     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;
-
-                     //for (uint t = 0; t < encoding_desc.m_num_tiles; t++)
-                     //   peak_snr -= (double)layouts[encoding_desc.m_tiles[t].m_layout_index].m_penalty;
-
-                     if (peak_snr > best_peak_snr)
-                     {
-                        best_peak_snr = peak_snr;
-                        best_encoding = e;
-                     }
-                  }
-
-                  encoding_hist[best_encoding]++;
-
-                  const chunk_encoding_desc& encoding_desc = g_chunk_encodings[best_encoding];
-
-                  for (uint t = 0; t < encoding_desc.m_num_tiles; t++)
-                  {
-                     const chunk_tile_desc& tile_desc = encoding_desc.m_tiles[t];
-
-                     uint layout_index = tile_desc.m_layout_index;
-                     const layout_results& layout = layouts[layout_index];
-                     color_quad_u8 c[4];
-                     if (debugging)
-                        dxt1_block::get_block_colors(c, static_cast<uint16>(layout.m_low_color), static_cast<uint16>(layout.m_high_color));
-
-                     color_quad_u8 tile_pixels[cChunkPixelWidth * cChunkPixelHeight];
-
-                     for (uint y = 0; y < tile_desc.m_height; y++)
-                     {
-                        const uint pix_y = y + tile_desc.m_y_ofs;
-
-                        for (uint x = 0; x < tile_desc.m_width; x++)
-                        {
-                           const uint pix_x = x + tile_desc.m_x_ofs;
-
-                           tile_pixels[x + y * tile_desc.m_width] = chunk_pixels[pix_x + pix_y * cChunkPixelWidth];
-
-                           if (debugging)
-                              debug_img(chunk_x * 8 + pix_x, chunk_y * 8 + pix_y) = c[layout.m_selectors[x + y * tile_desc.m_width]];
-                        }
-                     }
-
-                     color_quad_u8 l, h;
-                     dxt_fast::find_representative_colors(tile_desc.m_width * tile_desc.m_height, tile_pixels, l, h);
-
-                     //const uint dist = color::color_distance(m_params.m_perceptual, l, h, false);
-                     const uint dist = color::elucidian_distance(l, h, false);
-
-                     const uint cColorDistToWeight = 5000;
-                     const uint cMaxWeight = 8;
-                     uint weight = math::clamp<uint>(dist / cColorDistToWeight, 1, cMaxWeight);
-
-                     vec6F ev;
-
-                     ev[0] = l[0]; ev[1] = l[1]; ev[2] = l[2];
-                     ev[3] = h[0]; ev[4] = h[1]; ev[5] = h[2];
-
-                     for (uint y = 0; y < (tile_desc.m_height >> 2); y++)
-                     {
-                        uint block_y = chunk_y * cChunkBlockHeight + y + (tile_desc.m_y_ofs >> 2);
-                        if (block_y >= level_desc.m_block_height)
-                           continue;
-
-                        for (uint x = 0; x < (tile_desc.m_width >> 2); x++)
-                        {
-                           uint block_x = chunk_x * cChunkBlockWidth + x + (tile_desc.m_x_ofs >> 2);
-                           if (block_x >= level_desc.m_block_width)
-                              break;
-
-                           uint block_index = level_desc.m_first_block + block_x + block_y * level_desc.m_block_width;
-
-                           training_vecs[block_index].first = ev;
-                           training_vecs[block_index].second = weight;
-
-                           total_processed_blocks++;
-
-                           //if (debugging)
-                           //{
-                           //   debug_img(block_x, block_y) = l;
-                           //   debug_img(block_x + level_desc.m_block_width, block_y) = h;
-                           //}
-
-                        } // x
-                     } // y
-                  } //t
-
-                  if (total_processed_blocks >= next_progress_threshold)
-                  {
-                     next_progress_threshold += 512;
-
-                     if (!update_progress(total_processed_blocks, m_num_blocks - 1))
-                        return false;
-                  }
-
-               } // chunk_x
-            } // chunk_y
-
-#if GENERATE_DEBUG_IMAGES
-            if (debugging)
-               image_utils::write_to_file(dynamic_string(cVarArg, "debug_%u.tga", level).get_ptr(), debug_img, image_utils::cWriteFlagIgnoreAlpha);
-#endif
-
-         } // level
-
-#if 0
-         trace("chunk encoding hist: ");
-         for (uint i = 0; i < cNumChunkEncodings; i++)
-            trace("%u ", encoding_hist[i]);
-         trace("\n");
-#endif
-      }
-      else
-      {
-         for (uint block_index = 0; block_index < m_num_blocks; block_index++)
-         {
-            if ((block_index & 511) == 0)
-            {
-               if (!update_progress(block_index, m_num_blocks - 1))
-                  return false;
-            }
-
-            color_quad_u8 l, h;
-            dxt_fast::find_representative_colors(cDXTBlockSize * cDXTBlockSize, &m_pBlocks[block_index].m_pixels[0][0], l, h);
-
-            //const uint dist = color::color_distance(m_params.m_perceptual, l, h, false);
-            const uint dist = color::elucidian_distance(l, h, false);
-
-            const uint cColorDistToWeight = 5000;
-            const uint cMaxWeight = 8;
-            uint weight = math::clamp<uint>(dist / cColorDistToWeight, 1, cMaxWeight);
-
-            vec6F ev;
-
-            ev[0] = l[0]; ev[1] = l[1]; ev[2] = l[2];
-            ev[3] = h[0]; ev[4] = h[1]; ev[5] = h[2];
-
-            m_endpoint_clusterizer.add_training_vec(ev, weight);
-         }
-      }
-
-      const uint cMaxEndpointClusters = 65535U;
-
-      m_progress_start = 75;
-      m_progress_range = 20;
-
-      if (!m_endpoint_clusterizer.generate_codebook(cMaxEndpointClusters, generate_codebook_progress_callback, this))
-         return false;
-
-      crnlib::hash_map<uint, empty_type> selector_hash;
-
-      m_progress_start = 95;
-      m_progress_range = 5;
-
-      for (uint block_index = 0; block_index < m_num_blocks; block_index++)
-      {
-         if ((block_index & 511) == 0)
-         {
-            if (!update_progress(block_index, m_num_blocks - 1))
-               return false;
-         }
-
-         dxt1_block dxt_blk;
-         dxt_fast::compress_color_block(&dxt_blk, &m_pBlocks[block_index].m_pixels[0][0]);
-
-         uint selectors = dxt_blk.m_selectors[0] | (dxt_blk.m_selectors[1] << 8) | (dxt_blk.m_selectors[2] << 16) | (dxt_blk.m_selectors[3] << 24);
-
-         selector_hash.insert(selectors);
-      }
-
-      m_max_selector_clusters = selector_hash.size() + 128;
-
-//      trace("max endpoint clusters: %u\n", m_endpoint_clusterizer.get_codebook_size());
-//      trace("max selector clusters: %u\n", m_max_selector_clusters);
-
-      update_progress(1, 1);
-
-      return true;
-   }
-
-   bool qdxt1::update_progress(uint value, uint max_value)
-   {
-      if (!m_params.m_pProgress_func)
-         return true;
-
-      uint percentage = max_value ? (m_progress_start + (value * m_progress_range + (max_value / 2)) / max_value) : 100;
-      if ((int)percentage == m_prev_percentage_complete)
-         return true;
-      m_prev_percentage_complete = percentage;
-
-      if (!m_params.m_pProgress_func(m_params.m_progress_start + (percentage * m_params.m_progress_range) / 100U, m_params.m_pProgress_data))
-      {
-         m_canceled = true;
-         return false;
-      }
-
-      return true;
-   }
-
-   void qdxt1::pack_endpoints_task(uint64 data, void* pData_ptr)
-   {
-      pData_ptr;
-      const uint thread_index = static_cast<uint>(data);
-
-      crnlib::vector<color_quad_u8> cluster_pixels;
-      cluster_pixels.reserve(1024);
-
-      crnlib::vector<uint8> selectors;
-      selectors.reserve(1024);
-
-      dxt1_endpoint_optimizer optimizer;
-      dxt1_endpoint_optimizer::params p;
-      dxt1_endpoint_optimizer::results r;
-
-      p.m_quality = m_params.m_dxt_quality;
-      p.m_use_alpha_blocks = m_params.m_use_alpha_blocks;
-      p.m_dxt1a_alpha_threshold = m_params.m_dxt1a_alpha_threshold;
-      p.m_perceptual = m_params.m_perceptual;
-
-      uint cluster_index_progress_mask = math::next_pow2(m_endpoint_cluster_indices.size() / 100);
-      cluster_index_progress_mask /= 2;
-      cluster_index_progress_mask = math::maximum<uint>(cluster_index_progress_mask, 8);
-      cluster_index_progress_mask -= 1;
-
-      cluster_id cid;
-      const crnlib::vector<uint32>& indices = cid.m_cells;
-
-      for (uint cluster_index = 0; cluster_index < m_endpoint_cluster_indices.size(); cluster_index++)
-      {
-         if (m_canceled)
-            return;
-
-         if ((cluster_index & cluster_index_progress_mask) == 0)
-         {
-            if (crn_get_current_thread_id() == m_main_thread_id)
-            {
-               if (!update_progress(cluster_index, m_endpoint_cluster_indices.size() - 1))
-                  return;
-            }
-         }
-
-         if (m_pTask_pool->get_num_threads())
-         {
-            if ((cluster_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-               continue;
-         }
-
-         const crnlib::vector<uint>& cluster_indices = m_endpoint_cluster_indices[cluster_index];
-
-         selectors.resize(cluster_indices.size() * cDXTBlockSize * cDXTBlockSize);
-
-         bool found = false;
-         uint32 found_endpoints = 0;
-
-         cid.set(cluster_indices);
-
-         {
-            scoped_spinlock lock(m_cluster_hash_lock);
-
-            cluster_hash::const_iterator it(m_cluster_hash.find(cid));
-            if (it != m_cluster_hash.end())
-            {
-               CRNLIB_ASSERT(cid == it->first);
-
-               found = true;
-               found_endpoints = it->second;
-            }
-         }
-
-         if (found)
-         {
-            const uint16 low_color = static_cast<uint16>(found_endpoints);
-            const uint16 high_color = static_cast<uint16>((found_endpoints >> 16U));
-
-            color_quad_u8 block_colors[4];
-            dxt1_block::get_block_colors(block_colors, low_color, high_color);
-
-            const bool is_alpha_block = (low_color <= high_color);
-
-            for (uint block_iter = 0; block_iter < indices.size(); block_iter++)
-            {
-               const uint block_index = indices[block_iter];
-
-               const color_quad_u8* pSrc_pixels = &m_pBlocks[block_index].m_pixels[0][0];
-
-               for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-               {
-                  dxt1_block& dxt_block = get_block(block_index);
-
-                  dxt_block.set_low_color(static_cast<uint16>(low_color));
-                  dxt_block.set_high_color(static_cast<uint16>(high_color));
-
-                  uint mask = 0;
-                  for (int i = 15; i >= 0; i--)
-                  {
-                     mask <<= 2;
-
-                     const color_quad_u8& c = pSrc_pixels[i];
-
-                     uint dist0 = color::color_distance(m_params.m_perceptual, c, block_colors[0], false);
-                     uint dist1 = color::color_distance(m_params.m_perceptual, c, block_colors[1], false);
-                     uint dist2 = color::color_distance(m_params.m_perceptual, c, block_colors[2], false);
-
-                     uint selector = 0, best_dist = dist0;
-
-                     if (dist1 < best_dist) { selector = 1; best_dist = dist1; }
-                     if (dist2 < best_dist) { selector = 2; best_dist = dist2; }
-
-                     if (!is_alpha_block)
-                     {
-                        uint dist3 = color::color_distance(m_params.m_perceptual, c, block_colors[3], false);
-                        if (dist3 < best_dist) { selector = 3; }
-                     }
-                     else
-                     {
-                        if (c.a < m_params.m_dxt1a_alpha_threshold)
-                           selector = 3;
-                     }
-
-                     mask |= selector;
-                  }
-
-                  dxt_block.m_selectors[0] = static_cast<uint8>(mask & 0xFF);
-                  dxt_block.m_selectors[1] = static_cast<uint8>((mask >> 8) & 0xFF);
-                  dxt_block.m_selectors[2] = static_cast<uint8>((mask >> 16) & 0xFF);
-                  dxt_block.m_selectors[3] = static_cast<uint8>((mask >> 24) & 0xFF);
-               }
-            }
-         }
-         else
-         {
-            cluster_pixels.resize(indices.size() * cDXTBlockSize * cDXTBlockSize);
-
-            color_quad_u8* pDst = &cluster_pixels[0];
-
-            bool has_alpha_pixels = false;
-
-            for (uint block_iter = 0; block_iter < indices.size(); block_iter++)
-            {
-               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 = (const color_quad_u8*)m_pBlocks[block_index].m_pixels;
-
-               for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-               {
-                  const color_quad_u8& src = pSrc_pixels[i];
-
-                  if (src.a < m_params.m_dxt1a_alpha_threshold)
-                     has_alpha_pixels = true;
-
-                  *pDst++ = src;
-               }
-            }
-
-            p.m_block_index = cluster_index;
-            p.m_num_pixels = cluster_pixels.size();
-            p.m_pPixels = cluster_pixels.begin();
-
-            r.m_pSelectors = selectors.begin();
-
-            uint low_color, high_color;
-            if ((m_params.m_dxt_quality != cCRNDXTQualitySuperFast) || (has_alpha_pixels))
-            {
-               p.m_pixels_have_alpha = has_alpha_pixels;
-
-               optimizer.compute(p, r);
-               low_color = r.m_low_color;
-               high_color = r.m_high_color;
-            }
-            else
-            {
-               dxt_fast::compress_color_block(cluster_pixels.size(), cluster_pixels.begin(), low_color, high_color, selectors.begin(), true);
-            }
-
-            const uint8* pSrc_selectors = selectors.begin();
-
-            for (uint block_iter = 0; block_iter < indices.size(); block_iter++)
-            {
-               const uint block_index = indices[block_iter];
-
-               dxt1_block& dxt_block = get_block(block_index);
-
-               dxt_block.set_low_color(static_cast<uint16>(low_color));
-               dxt_block.set_high_color(static_cast<uint16>(high_color));
-
-               uint mask = 0;
-               for (int i = 15; i >= 0; i--)
-               {
-                  mask <<= 2;
-                  mask |= pSrc_selectors[i];
-               }
-               pSrc_selectors += (cDXTBlockSize * cDXTBlockSize);
-
-               dxt_block.m_selectors[0] = static_cast<uint8>(mask & 0xFF);
-               dxt_block.m_selectors[1] = static_cast<uint8>((mask >> 8) & 0xFF);
-               dxt_block.m_selectors[2] = static_cast<uint8>((mask >> 16) & 0xFF);
-               dxt_block.m_selectors[3] = static_cast<uint8>((mask >> 24) & 0xFF);
-
-            }
-
-            {
-               scoped_spinlock lock(m_cluster_hash_lock);
-
-               m_cluster_hash.insert(cid, low_color | (high_color << 16));
-            }
-         }
-
-      }
-   }
-
-   struct optimize_selectors_params
-   {
-      CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(optimize_selectors_params);
-
-      optimize_selectors_params(
-         crnlib::vector< crnlib::vector<uint> >&  selector_cluster_indices) :
-            m_selector_cluster_indices(selector_cluster_indices)
-      {
-      }
-
-      crnlib::vector< crnlib::vector<uint> >&  m_selector_cluster_indices;
-   };
-
-   void qdxt1::optimize_selectors_task(uint64 data, void* pData_ptr)
-   {
-      const uint thread_index = static_cast<uint>(data);
-
-      optimize_selectors_params& task_params = *static_cast<optimize_selectors_params*>(pData_ptr);
-
-      crnlib::vector<uint> block_categories[2];
-      block_categories[0].reserve(2048);
-      block_categories[1].reserve(2048);
-
-      for (uint cluster_index = 0; cluster_index < task_params.m_selector_cluster_indices.size(); cluster_index++)
-      {
-         if (m_canceled)
-            return;
-
-         if ((cluster_index & 255) == 0)
-         {
-            if (crn_get_current_thread_id() == m_main_thread_id)
-            {
-               if (!update_progress(cluster_index, task_params.m_selector_cluster_indices.size() - 1))
-                  return;
-            }
-         }
-
-         if (m_pTask_pool->get_num_threads())
-         {
-            if ((cluster_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-               continue;
-         }
-
-         const crnlib::vector<uint>& selector_indices = task_params.m_selector_cluster_indices[cluster_index];
-
-         if (selector_indices.size() <= 1)
-            continue;
-
-         block_categories[0].resize(0);
-         block_categories[1].resize(0);
-
-         for (uint block_iter = 0; block_iter < selector_indices.size(); block_iter++)
-         {
-            const uint block_index = selector_indices[block_iter];
-
-            const dxt1_block& src_block = get_block(block_index);
-
-            if (!src_block.is_alpha_block())
-               block_categories[0].push_back(block_index);
-            else
-            {
-               bool has_alpha_pixels = false;
-
-               if (m_params.m_dxt1a_alpha_threshold > 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++)
-                  {
-                     const color_quad_u8& src = pSrc_pixels[i];
-                     if (src.a < m_params.m_dxt1a_alpha_threshold)
-                     {
-                        has_alpha_pixels = true;
-                        break;
-                     }
-                  }
-               }
-
-               if (has_alpha_pixels)
-                  continue;
-
-               block_categories[1].push_back(block_index);
-            }
-         }
-
-         dxt1_block blk;
-         utils::zero_object(blk);
-
-         for (uint block_type = 0; block_type <= 1; block_type++)
-         {
-            const crnlib::vector<uint>& block_indices = block_categories[block_type];
-            if (block_indices.size() <= 1)
-               continue;
-
-            for (uint y = 0; y < 4; y++)
-            {
-               for (uint x = 0; x < 4; x++)
-               {
-                  uint best_s = 0;
-                  uint64 best_error = 0xFFFFFFFFFFULL;
-
-                  uint max_s = 4;
-                  if (block_type == 1)
-                     max_s = 3;
-
-                  for (uint s = 0; s < max_s; s++)
-                  {
-                     uint64 total_error = 0;
-
-                     for (uint block_iter = 0; block_iter < block_indices.size(); block_iter++)
-                     {
-                        const uint block_index = block_indices[block_iter];
-
-                        const color_quad_u8& orig_color = m_pBlocks[block_index].m_pixels[y][x];
-
-                        const dxt1_block& dst_block = get_block(block_index);
-
-                        color_quad_u8 colors[4];
-                        dxt1_block::get_block_colors(colors, static_cast<uint16>(dst_block.get_low_color()), static_cast<uint16>(dst_block.get_high_color()));
-
-                        uint error = color::color_distance(m_params.m_perceptual, orig_color, colors[s], false);
-
-                        total_error += error;
-                     }
-
-                     if (total_error < best_error)
-                     {
-                        best_error = total_error;
-                        best_s = s;
-                     }
-                  }
-
-                  blk.set_selector(x, y, best_s);
-
-               } // x
-            } // y
-
-            for (uint block_iter = 0; block_iter < block_indices.size(); block_iter++)
-            {
-               const uint block_index = block_indices[block_iter];
-
-               dxt1_block& dst_block = get_block(block_index);
-
-               memcpy(dst_block.m_selectors, blk.m_selectors, sizeof(dst_block.m_selectors));
-            }
-         }
-
-      } // cluster_index
-   }
-
-   bool qdxt1::generate_codebook_progress_callback(uint percentage_completed, void* pData)
-   {
-      return static_cast<qdxt1*>(pData)->update_progress(percentage_completed, 100U);
-   }
-
-   bool qdxt1::create_selector_clusters(uint max_selector_clusters, crnlib::vector< crnlib::vector<uint> >& selector_cluster_indices)
-   {
-      m_progress_start = m_progress_range;
-      m_progress_range = 33;
-
-      weighted_selector_vec_array selector_vecs(m_num_blocks);
-
-      for (uint block_iter = 0; block_iter < m_num_blocks; block_iter++)
-      {
-         dxt1_block& dxt1_block = get_block(block_iter);
-
-         vec16F sv;
-         float* pDst = &sv[0];
-
-         for (uint y = 0; y < 4; y++)
-            for (uint x = 0; x < 4; x++)
-               *pDst++ = g_dxt1_to_linear[dxt1_block.get_selector(x, y)];
-
-         const color_quad_u8 first_color(dxt1_block::unpack_color((uint16)dxt1_block.get_low_color(), true));
-         const color_quad_u8 second_color(dxt1_block::unpack_color((uint16)dxt1_block.get_high_color(), true));
-         const uint dist = color::color_distance(m_params.m_perceptual, first_color, second_color, false);
-
-         const uint cColorDistToWeight = 2000;
-         const uint cMaxWeight = 2048;
-         uint weight = math::clamp<uint>(dist / cColorDistToWeight, 1, cMaxWeight);
-
-         selector_vecs[block_iter].m_vec = sv;
-         selector_vecs[block_iter].m_weight = weight;
-      }
-
-      return m_selector_clusterizer.create_clusters(
-         selector_vecs, max_selector_clusters, selector_cluster_indices, generate_codebook_progress_callback, this);
-   }
-
-   bool qdxt1::pack(dxt1_block* pDst_elements, uint elements_per_block, const qdxt1_params& params, float quality_power_mul)
-   {
-      CRNLIB_ASSERT(m_num_blocks);
-
-      m_main_thread_id = crn_get_current_thread_id();
-      m_canceled = false;
-
-      m_pDst_elements = pDst_elements;
-      m_elements_per_block = elements_per_block;
-      m_params = params;
-      if (!m_params.m_use_alpha_blocks)
-         m_params.m_dxt1a_alpha_threshold = 0;
-
-      m_prev_percentage_complete = -1;
-
-      CRNLIB_ASSERT(m_params.m_quality_level <= qdxt1_params::cMaxQuality);
-      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<uint>(static_cast<uint>(m_endpoint_clusterizer.get_codebook_size() * endpoint_quality), 128U, m_endpoint_clusterizer.get_codebook_size());
-      //const uint max_selector_clusters = math::clamp<uint>(static_cast<uint>(m_max_selector_clusters * selector_quality), 150U, m_max_selector_clusters);
-      const uint max_endpoint_clusters = math::clamp<uint>(static_cast<uint>(m_endpoint_clusterizer.get_codebook_size() * endpoint_quality), 96U, m_endpoint_clusterizer.get_codebook_size());
-      const uint max_selector_clusters = math::clamp<uint>(static_cast<uint>(m_max_selector_clusters * selector_quality), 128U, m_max_selector_clusters);
-
-      if (quality >= 1.0f)
-      {
-         m_endpoint_cluster_indices.resize(m_num_blocks);
-         for (uint i = 0; i < m_num_blocks; i++)
-         {
-            m_endpoint_cluster_indices[i].resize(1);
-            m_endpoint_cluster_indices[i][0] = i;
-         }
-      }
-      else
-         m_endpoint_clusterizer.retrieve_clusters(max_endpoint_clusters, m_endpoint_cluster_indices);
-
-//      trace("endpoint clusters: %u\n", m_endpoint_cluster_indices.size());
-
-      uint total_blocks = 0;
-      uint max_blocks = 0;
-      for (uint i = 0; i < m_endpoint_cluster_indices.size(); i++)
-      {
-         uint num = m_endpoint_cluster_indices[i].size();
-         total_blocks += num;
-         max_blocks = math::maximum(max_blocks, num);
-      }
-#if 0
-      trace("Num clusters: %u, Average blocks per cluster: %u, Max blocks per cluster: %u\n",
-         m_endpoint_cluster_indices.size(),
-         total_blocks / m_endpoint_cluster_indices.size(),
-         max_blocks);
-#endif
-
-      crnlib::vector< crnlib::vector<uint> >& selector_cluster_indices = m_cached_selector_cluster_indices[params.m_quality_level];
-
-      m_progress_start = 0;
-      if (quality >= 1.0f)
-         m_progress_range = 100;
-      else if (selector_cluster_indices.empty())
-         m_progress_range = (m_params.m_dxt_quality == cCRNDXTQualitySuperFast) ? 10 : 33;
-      else
-         m_progress_range = (m_params.m_dxt_quality == cCRNDXTQualitySuperFast) ? 10 : 50;
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &qdxt1::pack_endpoints_task, i);
-      m_pTask_pool->join();
-
-      if (m_canceled)
-         return false;
-
-      if (quality >= 1.0f)
-         return true;
-
-      if (selector_cluster_indices.empty())
-      {
-         create_selector_clusters(max_selector_clusters, selector_cluster_indices);
-
-         if (m_canceled)
-         {
-            selector_cluster_indices.clear();
-
-            return false;
-         }
-      }
-
-      m_progress_start += m_progress_range;
-      m_progress_range = 100 - m_progress_start;
-
-      optimize_selectors_params optimize_selectors_task_params(selector_cluster_indices);
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &qdxt1::optimize_selectors_task, i, &optimize_selectors_task_params);
-
-      m_pTask_pool->join();
-
-      return !m_canceled;
-   }
-
-} // namespace crnlib
-
-

+ 0 - 185
Source/ThirdParty/crunch/crnlib/crn_qdxt1.h

@@ -1,185 +0,0 @@
-// File: crn_qdxt1.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_dxt.h"
-#include "crn_hash_map.h"
-#include "crn_clusterizer.h"
-#include "crn_hash.h"
-#include "crn_threaded_clusterizer.h"
-#include "crn_dxt_image.h"
-
-namespace crnlib
-{
-   struct qdxt1_params
-   {
-      qdxt1_params()
-      {
-         clear();
-      }
-
-      void clear()
-      {
-         m_quality_level = cMaxQuality;
-         m_dxt_quality = cCRNDXTQualityUber;
-         m_perceptual = true;
-         m_dxt1a_alpha_threshold = 0;
-         m_use_alpha_blocks = true;
-         m_pProgress_func = NULL;
-         m_pProgress_data = NULL;
-         m_num_mips = 0;
-         m_hierarchical = true;
-         utils::zero_object(m_mip_desc);
-         m_progress_start = 0;
-         m_progress_range = 100;
-      }
-
-      void init(const dxt_image::pack_params &pp, int quality_level, bool hierarchical)
-      {
-         m_dxt_quality = pp.m_quality;
-         m_hierarchical = hierarchical;
-         m_perceptual = pp.m_perceptual;
-         m_use_alpha_blocks = pp.m_use_both_block_types;
-         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;
-      uint m_progress_start;
-      uint m_progress_range;
-   };
-
-   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;
-      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> vec6F_clusterizer;
-      vec6F_clusterizer    m_endpoint_clusterizer;
-
-      crnlib::vector< crnlib::vector<uint> > m_endpoint_cluster_indices;
-
-      typedef vec<16, float> vec16F;
-      typedef threaded_clusterizer<vec16F> 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<uint> > m_cached_selector_cluster_indices[qdxt1_params::cMaxQuality + 1];
-
-      struct cluster_id
-      {
-         cluster_id() : m_hash(0)
-         {
-
-         }
-
-         cluster_id(const crnlib::vector<uint>& indices)
-         {
-            set(indices);
-         }
-
-         void set(const crnlib::vector<uint>& indices)
-         {
-            m_cells.resize(indices.size());
-
-            for (uint i = 0; i < indices.size(); i++)
-               m_cells[i] = static_cast<uint32>(indices[i]);
-
-            std::sort(m_cells.begin(), m_cells.end());
-
-            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)
-               return false;
-
-            return m_cells == rhs.m_cells;
-         }
-
-         crnlib::vector<uint32> m_cells;
-
-         size_t m_hash;
-
-         operator size_t() const { return m_hash; }
-      };
-
-      typedef crnlib::hash_map<cluster_id, uint> cluster_hash;
-      cluster_hash m_cluster_hash;
-      spinlock m_cluster_hash_lock;
-
-      static bool generate_codebook_dummy_progress_callback(uint percentage_completed, void* pData);
-      static bool generate_codebook_progress_callback(uint percentage_completed, void* pData);
-      bool update_progress(uint value, uint max_value);
-      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<uint> >& 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

+ 0 - 827
Source/ThirdParty/crunch/crnlib/crn_qdxt5.cpp

@@ -1,827 +0,0 @@
-// File: crn_qdxt5.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-#include "crn_core.h"
-#include "crn_qdxt5.h"
-#include "crn_dxt5a.h"
-#include "crn_image.h"
-#include "crn_image_utils.h"
-#include "crn_dxt_fast.h"
-#include "crn_dxt_hc_common.h"
-
-#define QDXT5_DEBUGGING 0
-
-namespace crnlib
-{
-    qdxt5::qdxt5(task_pool& task_pool) :
-      m_pTask_pool(&task_pool),
-      m_main_thread_id(0),
-      m_canceled(false),
-      m_progress_start(0),
-      m_progress_range(100),
-      m_num_blocks(0),
-      m_pBlocks(NULL),
-      m_pDst_elements(NULL),
-      m_elements_per_block(0),
-      m_max_selector_clusters(0),
-      m_prev_percentage_complete(-1),
-      m_selector_clusterizer(task_pool)
-   {
-   }
-
-   qdxt5::~qdxt5()
-   {
-   }
-
-   void qdxt5::clear()
-   {
-      m_main_thread_id = 0;
-      m_num_blocks = 0;
-      m_pBlocks = 0;
-      m_pDst_elements = NULL;
-      m_elements_per_block = 0;
-      m_params.clear();
-      m_endpoint_clusterizer.clear();
-      m_endpoint_cluster_indices.clear();
-      m_max_selector_clusters = 0;
-      m_canceled = false;
-      m_progress_start = 0;
-      m_progress_range = 100;
-      m_selector_clusterizer.clear();
-
-      for (uint i = 0; i <= qdxt5_params::cMaxQuality; i++)
-         m_cached_selector_cluster_indices[i].clear();
-
-      m_cluster_hash.clear();
-
-      m_prev_percentage_complete = -1;
-   }
-
-   bool qdxt5::init(uint n, const dxt_pixel_block* pBlocks, const qdxt5_params& params)
-   {
-      clear();
-
-      CRNLIB_ASSERT(n && pBlocks);
-
-      m_main_thread_id = crn_get_current_thread_id();
-
-      m_num_blocks = n;
-      m_pBlocks = pBlocks;
-      m_params = params;
-
-      m_endpoint_clusterizer.reserve_training_vecs(m_num_blocks);
-
-      m_progress_start = 0;
-      m_progress_range = 75;
-
-      image_u8 debug_img;
-
-      const bool debugging = true;
-
-      if ((m_params.m_hierarchical) && (m_params.m_num_mips))
-      {
-         vec2F_clusterizer::training_vec_array& training_vecs = m_endpoint_clusterizer.get_training_vecs();
-         training_vecs.resize(m_num_blocks);
-
-         uint encoding_hist[cNumChunkEncodings];
-         utils::zero_object(encoding_hist);
-
-         uint total_processed_blocks = 0;
-         uint next_progress_threshold = 512;
-
-         for (uint level = 0; level < m_params.m_num_mips; level++)
-         {
-            const qdxt5_params::mip_desc& level_desc = m_params.m_mip_desc[level];
-
-            const uint num_chunks_x = (level_desc.m_block_width + cChunkBlockWidth - 1) / cChunkBlockWidth;
-            const uint num_chunks_y = (level_desc.m_block_height + cChunkBlockHeight - 1) / cChunkBlockHeight;
-
-            const uint level_width = level_desc.m_block_width * 4;
-            const uint level_height = level_desc.m_block_height * 4;
-
-            if (debugging)
-               debug_img.resize(num_chunks_x * cChunkPixelWidth, num_chunks_y * cChunkPixelHeight);
-
-            for (uint chunk_y = 0; chunk_y < num_chunks_y; chunk_y++)
-            {
-               for (uint chunk_x = 0; chunk_x < num_chunks_x; chunk_x++)
-               {
-                  color_quad_u8 chunk_pixels[cChunkPixelWidth * cChunkPixelHeight];
-
-                  for (uint y = 0; y < cChunkPixelHeight; y++)
-                  {
-                     const uint pix_y = math::minimum<uint>(chunk_y * cChunkPixelHeight + y, level_height - 1);
-
-                     const uint outer_block_index = level_desc.m_first_block + ((pix_y >> 2) * level_desc.m_block_width);
-
-                     for (uint x = 0; x < cChunkPixelWidth; x++)
-                     {
-                        const uint pix_x = math::minimum<uint>(chunk_x * cChunkPixelWidth + x, level_width - 1);
-
-                        const uint block_index = outer_block_index + (pix_x >> 2);
-
-                        const dxt_pixel_block& block = m_pBlocks[block_index];
-
-                        const color_quad_u8& p = block.m_pixels[pix_y & 3][pix_x & 3];
-
-                        chunk_pixels[x + y * 8] = p;
-                     }
-                  }
-
-                  struct layout_results
-                  {
-                     uint m_low_color;
-                     uint m_high_color;
-                     uint8 m_selectors[cChunkPixelWidth * cChunkPixelHeight];
-                     uint64 m_error;
-                     //float m_penalty;
-                  };
-                  layout_results layouts[cNumChunkTileLayouts];
-
-                  for (uint l = 0; l < cNumChunkTileLayouts; l++)
-                  {
-                     const uint width = g_chunk_tile_layouts[l].m_width;
-                     const uint height = g_chunk_tile_layouts[l].m_height;
-                     const uint x_ofs = g_chunk_tile_layouts[l].m_x_ofs;
-                     const uint y_ofs = g_chunk_tile_layouts[l].m_y_ofs;
-
-                     color_quad_u8 layout_pixels[cChunkPixelWidth * cChunkPixelHeight];
-                     for (uint y = 0; y < height; y++)
-                        for (uint x = 0; x < width; x++)
-                           layout_pixels[x + y * width] = chunk_pixels[(x_ofs + x) + (y_ofs + y) * cChunkPixelWidth];
-
-                     const uint n = width * height;
-                     dxt_fast::compress_alpha_block(n, layout_pixels, layouts[l].m_low_color, layouts[l].m_high_color, layouts[l].m_selectors, m_params.m_comp_index);
-
-                     uint c[dxt5_block::cMaxSelectorValues];
-                     dxt5_block::get_block_values(c, layouts[l].m_low_color, layouts[l].m_high_color);
-
-                     uint64 error = 0;
-                     for (uint i = 0; i < n; i++)
-                        error += math::square((int)layout_pixels[i][m_params.m_comp_index] - (int)c[layouts[l].m_selectors[i]]);
-
-                     layouts[l].m_error = error;
-                  }
-
-                  double best_peak_snr = -1.0f;
-                  uint best_encoding = 0;
-
-                  for (uint e = 0; e < cNumChunkEncodings; e++)
-                  {
-                     const chunk_encoding_desc& encoding_desc = g_chunk_encodings[e];
-
-                     double total_error = 0;
-
-                     for (uint t = 0; t < encoding_desc.m_num_tiles; t++)
-                        total_error += (double)layouts[encoding_desc.m_tiles[t].m_layout_index].m_error;
-
-                     double mean_squared = total_error * (1.0f / 64.0f);
-                     double root_mean_squared = sqrt(mean_squared);
-
-                     double peak_snr = 999999.0f;
-                     if (mean_squared)
-                        peak_snr = math::clamp<double>(log10(255.0f / root_mean_squared) * 20.0f, 0.0f, 500.0f);
-
-                     float adaptive_tile_alpha_psnr_derating = 2.4f;
-                     //if (level)
-                     //   adaptive_tile_alpha_psnr_derating = math::lerp(adaptive_tile_alpha_psnr_derating * .5f, .3f, math::maximum((level - 1) / float(m_params.m_num_mips - 2), 1.0f));
-                     if ((level) && (adaptive_tile_alpha_psnr_derating > .25f))
-                     {
-                        adaptive_tile_alpha_psnr_derating = math::maximum(.25f, adaptive_tile_alpha_psnr_derating / powf(3.0f, static_cast<float>(level)));
-                     }
-
-                     float alpha_derating = math::lerp( 0.0f, adaptive_tile_alpha_psnr_derating, (g_chunk_encodings[e].m_num_tiles - 1) / 3.0f );
-                     peak_snr = peak_snr - alpha_derating;
-
-                     //for (uint t = 0; t < encoding_desc.m_num_tiles; t++)
-                     //   peak_snr -= (double)layouts[encoding_desc.m_tiles[t].m_layout_index].m_penalty;
-
-                     if (peak_snr > best_peak_snr)
-                     {
-                        best_peak_snr = peak_snr;
-                        best_encoding = e;
-                     }
-                  }
-
-                  encoding_hist[best_encoding]++;
-
-                  const chunk_encoding_desc& encoding_desc = g_chunk_encodings[best_encoding];
-
-                  for (uint t = 0; t < encoding_desc.m_num_tiles; t++)
-                  {
-                     const chunk_tile_desc& tile_desc = encoding_desc.m_tiles[t];
-
-                     uint layout_index = tile_desc.m_layout_index;
-                     const layout_results& layout = layouts[layout_index];
-
-                     uint c[dxt5_block::cMaxSelectorValues];
-                     if (debugging)
-                        dxt5_block::get_block_values(c, layout.m_low_color, layout.m_high_color);
-
-                     color_quad_u8 tile_pixels[cChunkPixelWidth * cChunkPixelHeight];
-
-                     for (uint y = 0; y < tile_desc.m_height; y++)
-                     {
-                        const uint pix_y = y + tile_desc.m_y_ofs;
-
-                        for (uint x = 0; x < tile_desc.m_width; x++)
-                        {
-                           const uint pix_x = x + tile_desc.m_x_ofs;
-
-                           uint a = chunk_pixels[pix_x + pix_y * cChunkPixelWidth][m_params.m_comp_index];
-
-                           tile_pixels[x + y * tile_desc.m_width].set(a, a, a, 255);
-
-                           if (debugging)
-                              debug_img(chunk_x * 8 + pix_x, chunk_y * 8 + pix_y) = c[layout.m_selectors[x + y * tile_desc.m_width]];
-                        }
-                     }
-
-                     color_quad_u8 l, h;
-                     dxt_fast::find_representative_colors(tile_desc.m_width * tile_desc.m_height, tile_pixels, l, h);
-
-                     const uint dist = math::square<int>((int)l[0] - (int)h[0]);
-
-                     const int cAlphaErrorToWeight = 8;
-                     const uint cMaxWeight = 8;
-                     uint weight = math::clamp<uint>(dist / cAlphaErrorToWeight, 1, cMaxWeight);
-
-                     vec2F ev;
-
-                     ev[0] = l[0];
-                     ev[1] = h[0];
-
-                     for (uint y = 0; y < (tile_desc.m_height >> 2); y++)
-                     {
-                        uint block_y = chunk_y * cChunkBlockHeight + y + (tile_desc.m_y_ofs >> 2);
-                        if (block_y >= level_desc.m_block_height)
-                           continue;
-
-                        for (uint x = 0; x < (tile_desc.m_width >> 2); x++)
-                        {
-                           uint block_x = chunk_x * cChunkBlockWidth + x + (tile_desc.m_x_ofs >> 2);
-                           if (block_x >= level_desc.m_block_width)
-                              break;
-
-                           uint block_index = level_desc.m_first_block + block_x + block_y * level_desc.m_block_width;
-
-                           training_vecs[block_index].first = ev;
-                           training_vecs[block_index].second = weight;
-
-                           total_processed_blocks++;
-
-                        } // x
-                     } // y
-                  } //t
-
-                  if (total_processed_blocks >= next_progress_threshold)
-                  {
-                     next_progress_threshold += 512;
-
-                     if (!update_progress(total_processed_blocks, m_num_blocks - 1))
-                        return false;
-                  }
-
-               } // chunk_x
-            } // chunk_y
-
-#if QDXT5_DEBUGGING
-            if (debugging)
-               image_utils::write_to_file(dynamic_wstring(cVarArg, "debug_%u.tga", level).get_ptr(), debug_img, image_utils::cWriteFlagIgnoreAlpha);
-#endif
-
-         } // level
-
-#if 0
-         trace("chunk encoding hist: ");
-         for (uint i = 0; i < cNumChunkEncodings; i++)
-            trace("%u ", encoding_hist[i]);
-         trace("\n");
-#endif
-      }
-      else
-      {
-         for (uint block_index = 0; block_index < m_num_blocks; block_index++)
-         {
-            if ((block_index & 511) == 0)
-            {
-               if (!update_progress(block_index, m_num_blocks - 1))
-                  return false;
-            }
-
-            color_quad_u8 c[16];
-            for (uint y = 0; y < cDXTBlockSize; y++)
-               for (uint x = 0; x < cDXTBlockSize; x++)
-                  c[x+y*cDXTBlockSize].set(m_pBlocks[block_index].m_pixels[y][x][m_params.m_comp_index], 255);
-
-            color_quad_u8 l, h;
-            dxt_fast::find_representative_colors(cDXTBlockSize * cDXTBlockSize, c, l, h);
-
-            const uint dist = math::square<int>((int)l[0] - (int)h[0]);
-
-            const int cAlphaErrorToWeight = 8;
-            const uint cMaxWeight = 8;
-            uint weight = math::clamp<uint>(dist / cAlphaErrorToWeight, 1, cMaxWeight);
-
-            vec2F ev;
-
-            ev[0] = l[0];
-            ev[1] = h[0];
-
-            m_endpoint_clusterizer.add_training_vec(ev, weight);
-         }
-      }
-
-      const uint cMaxEndpointClusters = 65535U;
-
-      m_progress_start = 75;
-      m_progress_range = 20;
-
-      if (!m_endpoint_clusterizer.generate_codebook(cMaxEndpointClusters, generate_codebook_progress_callback, this))
-         return false;
-
-      crnlib::hash_map<uint64, empty_type> selector_hash;
-
-      m_progress_start = 95;
-      m_progress_range = 5;
-
-      for (uint block_index = 0; block_index < m_num_blocks; block_index++)
-      {
-         if ((block_index & 511) == 0)
-         {
-            if (!update_progress(block_index, m_num_blocks - 1))
-               return false;
-         }
-
-         dxt5_block dxt_blk;
-         dxt_fast::compress_alpha_block(&dxt_blk, &m_pBlocks[block_index].m_pixels[0][0], m_params.m_comp_index);
-
-         uint64 selectors = 0;
-         for (uint i = 0; i < dxt5_block::cNumSelectorBytes; i++)
-            selectors |= static_cast<uint64>(dxt_blk.m_selectors[i]) << (i * 8U);
-
-         selector_hash.insert(selectors);
-      }
-
-      m_max_selector_clusters = selector_hash.size() + 128;
-
-      update_progress(1, 1);
-
-      return true;
-   }
-
-   bool qdxt5::update_progress(uint value, uint max_value)
-   {
-      if (!m_params.m_pProgress_func)
-         return true;
-
-      uint percentage = max_value ? (m_progress_start + (value * m_progress_range + (max_value / 2)) / max_value) : 100;
-      if ((int)percentage == m_prev_percentage_complete)
-         return true;
-      m_prev_percentage_complete = percentage;
-
-      if (!m_params.m_pProgress_func(m_params.m_progress_start + (percentage * m_params.m_progress_range) / 100U, m_params.m_pProgress_data))
-      {
-         m_canceled = true;
-         return false;
-      }
-
-      return true;
-   }
-
-   void qdxt5::pack_endpoints_task(uint64 data, void* pData_ptr)
-   {
-      pData_ptr;
-      const uint thread_index = static_cast<uint>(data);
-
-      crnlib::vector<color_quad_u8> cluster_pixels;
-      cluster_pixels.reserve(1024);
-
-      crnlib::vector<uint8> selectors;
-      selectors.reserve(1024);
-
-      dxt5_endpoint_optimizer optimizer;
-      dxt5_endpoint_optimizer::params p;
-      dxt5_endpoint_optimizer::results r;
-
-      p.m_quality = m_params.m_dxt_quality;
-      p.m_comp_index = m_params.m_comp_index;
-      p.m_use_both_block_types = m_params.m_use_both_block_types;
-
-      uint cluster_index_progress_mask = math::next_pow2(m_endpoint_cluster_indices.size() / 100);
-      cluster_index_progress_mask /= 2;
-      cluster_index_progress_mask = math::maximum<uint>(cluster_index_progress_mask, 8);
-      cluster_index_progress_mask -= 1;
-
-      for (uint cluster_index = 0; cluster_index < m_endpoint_cluster_indices.size(); cluster_index++)
-      {
-         if (m_canceled)
-            return;
-
-         if ((cluster_index & cluster_index_progress_mask) == 0)
-         {
-            if (crn_get_current_thread_id() == m_main_thread_id)
-            {
-               if (!update_progress(cluster_index, m_endpoint_cluster_indices.size() - 1))
-                  return;
-            }
-         }
-
-         if (m_pTask_pool->get_num_threads())
-         {
-            if ((cluster_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-               continue;
-         }
-
-         const crnlib::vector<uint>& cluster_indices = m_endpoint_cluster_indices[cluster_index];
-
-         selectors.resize(cluster_indices.size() * cDXTBlockSize * cDXTBlockSize);
-
-         cluster_pixels.resize(cluster_indices.size() * cDXTBlockSize * cDXTBlockSize);
-
-         color_quad_u8* pDst = &cluster_pixels[0];
-
-         for (uint block_iter = 0; block_iter < cluster_indices.size(); block_iter++)
-         {
-            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 = (const color_quad_u8*)m_pBlocks[block_index].m_pixels;
-
-            for (uint i = 0; i < cDXTBlockSize * cDXTBlockSize; i++)
-            {
-               const color_quad_u8& src = pSrc_pixels[i];
-
-               *pDst++ = src;
-            }
-         }
-
-         p.m_block_index = cluster_index;
-         p.m_num_pixels = cluster_pixels.size();
-         p.m_pPixels = cluster_pixels.begin();
-
-         r.m_pSelectors = selectors.begin();
-
-         uint low_color;
-         uint high_color;
-         if (m_params.m_dxt_quality != cCRNDXTQualitySuperFast)
-         {
-            optimizer.compute(p, r);
-            low_color = r.m_first_endpoint;
-            high_color = r.m_second_endpoint;
-         }
-         else
-         {
-            dxt_fast::compress_alpha_block(cluster_pixels.size(), cluster_pixels.begin(), low_color, high_color, selectors.begin(), m_params.m_comp_index);
-         }
-
-         const uint8* pSrc_selectors = selectors.begin();
-
-         for (uint block_iter = 0; block_iter < cluster_indices.size(); block_iter++)
-         {
-            const uint block_index = cluster_indices[block_iter];
-
-            dxt5_block& dxt_block = get_block(block_index);
-
-            dxt_block.set_low_alpha(low_color);
-            dxt_block.set_high_alpha(high_color);
-
-            for (uint y = 0; y < 4; y++)
-               for (uint x = 0; x < 4; x++)
-                  dxt_block.set_selector(x, y, *pSrc_selectors++);
-         }
-      }
-   }
-
-   struct optimize_selectors_params
-   {
-      CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(optimize_selectors_params);
-
-      optimize_selectors_params(
-         crnlib::vector< crnlib::vector<uint> >&  selector_cluster_indices) :
-         m_selector_cluster_indices(selector_cluster_indices)
-      {
-      }
-
-      crnlib::vector< crnlib::vector<uint> >&  m_selector_cluster_indices;
-   };
-
-   void qdxt5::optimize_selectors_task(uint64 data, void* pData_ptr)
-   {
-      const uint thread_index = static_cast<uint>(data);
-
-      optimize_selectors_params& task_params = *static_cast<optimize_selectors_params*>(pData_ptr);
-
-      crnlib::vector<uint> block_categories[2];
-      block_categories[0].reserve(2048);
-      block_categories[1].reserve(2048);
-
-      for (uint cluster_index = 0; cluster_index < task_params.m_selector_cluster_indices.size(); cluster_index++)
-      {
-         if (m_canceled)
-            return;
-
-         if ((cluster_index & 255) == 0)
-         {
-            if (crn_get_current_thread_id() == m_main_thread_id)
-            {
-               if (!update_progress(cluster_index, task_params.m_selector_cluster_indices.size() - 1))
-                  return;
-            }
-         }
-
-         if (m_pTask_pool->get_num_threads())
-         {
-            if ((cluster_index % (m_pTask_pool->get_num_threads() + 1)) != thread_index)
-               continue;
-         }
-
-         const crnlib::vector<uint>& selector_indices = task_params.m_selector_cluster_indices[cluster_index];
-
-         if (selector_indices.size() <= 1)
-            continue;
-
-         block_categories[0].resize(0);
-         block_categories[1].resize(0);
-
-         for (uint block_iter = 0; block_iter < selector_indices.size(); block_iter++)
-         {
-            const uint block_index = selector_indices[block_iter];
-
-            const dxt5_block& src_block = get_block(block_index);
-
-            block_categories[src_block.is_alpha6_block()].push_back(block_index);
-         }
-
-         dxt5_block blk;
-         utils::zero_object(blk);
-
-         for (uint block_type = 0; block_type <= 1; block_type++)
-         {
-            const crnlib::vector<uint>& block_indices = block_categories[block_type];
-            if (block_indices.size() <= 1)
-               continue;
-
-            for (uint y = 0; y < cDXTBlockSize; y++)
-            {
-               for (uint x = 0; x < cDXTBlockSize; x++)
-               {
-                  uint best_s = 0;
-                  uint64 best_error = 0xFFFFFFFFFFULL;
-
-                  for (uint s = 0; s < dxt5_block::cMaxSelectorValues; s++)
-                  {
-                     uint64 total_error = 0;
-
-                     for (uint block_iter = 0; block_iter < block_indices.size(); block_iter++)
-                     {
-                        const uint block_index = block_indices[block_iter];
-
-                        const color_quad_u8& orig_color = m_pBlocks[block_index].m_pixels[y][x];
-
-                        const dxt5_block& dst_block = get_block(block_index);
-
-                        uint values[dxt5_block::cMaxSelectorValues];
-                        dxt5_block::get_block_values(values, dst_block.get_low_alpha(), dst_block.get_high_alpha());
-
-                        int error = math::square((int)orig_color[m_params.m_comp_index] - (int)values[s]);
-
-                        total_error += error;
-                     }
-
-                     if (total_error < best_error)
-                     {
-                        best_error = total_error;
-                        best_s = s;
-                     }
-                  }
-
-                  blk.set_selector(x, y, best_s);
-
-               } // x
-            } // y
-
-            for (uint block_iter = 0; block_iter < block_indices.size(); block_iter++)
-            {
-               const uint block_index = block_indices[block_iter];
-
-               dxt5_block& dst_block = get_block(block_index);
-
-               memcpy(dst_block.m_selectors, blk.m_selectors, sizeof(dst_block.m_selectors));
-            }
-         }
-
-      } // cluster_index
-   }
-
-   bool qdxt5::generate_codebook_progress_callback(uint percentage_completed, void* pData)
-   {
-      return static_cast<qdxt5*>(pData)->update_progress(percentage_completed, 100U);
-   }
-
-   bool qdxt5::create_selector_clusters(uint max_selector_clusters, crnlib::vector< crnlib::vector<uint> >& selector_cluster_indices)
-   {
-      weighted_selector_vec_array selector_vecs[2];
-      crnlib::vector<uint> selector_vec_remap[2];
-
-      for (uint block_type = 0; block_type < 2; block_type++)
-      {
-         for (uint block_iter = 0; block_iter < m_num_blocks; block_iter++)
-         {
-            dxt5_block& dxt5_block = get_block(block_iter);
-            if ((uint)dxt5_block.is_alpha6_block() != block_type)
-               continue;
-
-            vec16F sv;
-            float* pDst = &sv[0];
-
-            bool uses_absolute_values = false;
-
-            for (uint y = 0; y < 4; y++)
-            {
-               for (uint x = 0; x < 4; x++)
-               {
-                  const uint s = dxt5_block.get_selector(x, y);
-
-                  float f;
-                  if (dxt5_block.is_alpha6_block())
-                  {
-                     if (s >= 6)
-                     {
-                        uses_absolute_values = true;
-                        f = 0.0f;
-                     }
-                     else
-                        f = g_dxt5_alpha6_to_linear[s];
-                  }
-                  else
-                     f = g_dxt5_to_linear[s];
-
-                  *pDst++ = f;
-               }
-            }
-
-            if (uses_absolute_values)
-               continue;
-
-            int low_alpha = dxt5_block.get_low_alpha();
-            int high_alpha = dxt5_block.get_high_alpha();
-            int dist = math::square(low_alpha - high_alpha);
-
-            const uint cAlphaDistToWeight = 8;
-            const uint cMaxWeight = 2048;
-            uint weight = math::clamp<uint>(dist / cAlphaDistToWeight, 1, cMaxWeight);
-
-            selector_vecs[block_type].resize(selector_vecs[block_type].size() + 1);
-            selector_vecs[block_type].back().m_vec = sv;
-            selector_vecs[block_type].back().m_weight = weight;
-
-            selector_vec_remap[block_type].push_back(block_iter);
-         }
-      }
-
-      selector_cluster_indices.clear();
-
-      for (uint block_type = 0; block_type < 2; block_type++)
-      {
-         if (selector_vecs[block_type].empty())
-            continue;
-
-         if ((selector_vecs[block_type].size() / (float)m_num_blocks) < .01f)
-            continue;
-         uint max_clusters = static_cast<uint>((math::emulu(selector_vecs[block_type].size(), max_selector_clusters) + (m_num_blocks - 1)) / m_num_blocks);
-         max_clusters = math::minimum(math::maximum(64U, max_clusters), selector_vecs[block_type].size());
-         if (max_clusters >= selector_vecs[block_type].size())
-            continue;
-
-#if QDXT5_DEBUGGING
-         trace("max_clusters (%u): %u\n", block_type, max_clusters);
-#endif
-
-         crnlib::vector< crnlib::vector<uint> > block_type_selector_cluster_indices;
-
-         if (!block_type)
-         {
-            m_progress_start = m_progress_range;
-            m_progress_range = 16;
-         }
-         else
-         {
-            m_progress_start = m_progress_range + 16;
-            m_progress_range = 17;
-         }
-
-         if (!m_selector_clusterizer.create_clusters(
-            selector_vecs[block_type], max_clusters, block_type_selector_cluster_indices, generate_codebook_progress_callback, this))
-         {
-            return false;
-         }
-
-         const uint first_cluster = selector_cluster_indices.size();
-         selector_cluster_indices.enlarge(block_type_selector_cluster_indices.size());
-
-         for (uint i = 0; i < block_type_selector_cluster_indices.size(); i++)
-         {
-            crnlib::vector<uint>& indices = selector_cluster_indices[first_cluster + i];
-            indices.swap(block_type_selector_cluster_indices[i]);
-
-            for (uint j = 0; j < indices.size(); j++)
-               indices.at(j) = selector_vec_remap[block_type][indices.at(j)];
-         }
-      }
-
-      return true;
-   }
-
-   bool qdxt5::pack(dxt5_block* pDst_elements, uint elements_per_block, const qdxt5_params& params)
-   {
-      CRNLIB_ASSERT(m_num_blocks);
-
-      m_main_thread_id = crn_get_current_thread_id();
-      m_canceled = false;
-
-      m_pDst_elements = pDst_elements;
-      m_elements_per_block = elements_per_block;
-      m_params = params;
-
-      m_prev_percentage_complete = -1;
-
-      CRNLIB_ASSERT(m_params.m_quality_level <= qdxt5_params::cMaxQuality);
-      const float quality = m_params.m_quality_level / (float)qdxt5_params::cMaxQuality;
-      const float endpoint_quality = powf(quality, 2.1f);
-      const float selector_quality = powf(quality, 1.65f);
-
-      const uint max_endpoint_clusters = math::clamp<uint>(static_cast<uint>(m_endpoint_clusterizer.get_codebook_size() * endpoint_quality), 16U, m_endpoint_clusterizer.get_codebook_size());
-      const uint max_selector_clusters = math::clamp<uint>(static_cast<uint>(m_max_selector_clusters * selector_quality), 32U, m_max_selector_clusters);
-
-#if QDXT5_DEBUGGING
-      trace("max endpoint clusters: %u\n", max_endpoint_clusters);
-      trace("max selector clusters: %u\n", max_selector_clusters);
-#endif
-
-      if (quality >= 1.0f)
-      {
-         m_endpoint_cluster_indices.resize(m_num_blocks);
-         for (uint i = 0; i < m_num_blocks; i++)
-         {
-            m_endpoint_cluster_indices[i].resize(1);
-            m_endpoint_cluster_indices[i][0] = i;
-         }
-      }
-      else
-         m_endpoint_clusterizer.retrieve_clusters(max_endpoint_clusters, m_endpoint_cluster_indices);
-
-      uint total_blocks = 0;
-      uint max_blocks = 0;
-      for (uint i = 0; i < m_endpoint_cluster_indices.size(); i++)
-      {
-         uint num = m_endpoint_cluster_indices[i].size();
-         total_blocks += num;
-         max_blocks = math::maximum(max_blocks, num);
-      }
-
-      crnlib::vector< crnlib::vector<uint> >& selector_cluster_indices = m_cached_selector_cluster_indices[params.m_quality_level];
-
-      m_progress_start = 0;
-      if (quality >= 1.0f)
-         m_progress_range = 100;
-      else if (selector_cluster_indices.empty())
-         m_progress_range = (m_params.m_dxt_quality == cCRNDXTQualitySuperFast) ? 10 : 33;
-      else
-         m_progress_range = (m_params.m_dxt_quality == cCRNDXTQualitySuperFast) ? 10 : 50;
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &qdxt5::pack_endpoints_task, i);
-      m_pTask_pool->join();
-
-      if (m_canceled)
-         return false;
-
-      if (quality >= 1.0f)
-         return true;
-
-      if (selector_cluster_indices.empty())
-      {
-         create_selector_clusters(max_selector_clusters, selector_cluster_indices);
-
-         if (m_canceled)
-         {
-            selector_cluster_indices.clear();
-
-            return false;
-         }
-      }
-
-      m_progress_start += m_progress_range;
-      m_progress_range = 100 - m_progress_start;
-
-      optimize_selectors_params optimize_selectors_task_params(selector_cluster_indices);
-
-      for (uint i = 0; i <= m_pTask_pool->get_num_threads(); i++)
-         m_pTask_pool->queue_object_task(this, &qdxt5::optimize_selectors_task, i, &optimize_selectors_task_params);
-
-      m_pTask_pool->join();
-
-      return !m_canceled;
-   }
-
-} // namespace crnlib

+ 0 - 194
Source/ThirdParty/crunch/crnlib/crn_qdxt5.h

@@ -1,194 +0,0 @@
-// File: crn_qdxt5.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-#include "crn_hash_map.h"
-#include "crn_clusterizer.h"
-#include "crn_hash.h"
-#include "crn_threaded_clusterizer.h"
-#include "crn_dxt.h"
-#include "crn_dxt_image.h"
-
-namespace crnlib
-{
-   struct qdxt5_params
-   {
-      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;
-      }
-
-      void init(const dxt_image::pack_params &pp, int quality_level, bool hierarchical, int comp_index = 3)
-      {
-         m_dxt_quality = pp.m_quality;
-         m_hierarchical = hierarchical;
-         m_comp_index = comp_index;
-         m_use_both_block_types = pp.m_use_both_block_types;
-         m_quality_level = quality_level;
-      }
-
-      enum { cMaxQuality = cCRNMaxQualityLevel };
-      uint m_quality_level;
-      crn_dxt_quality m_dxt_quality;
-      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;
-      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);
-
-      uint get_num_blocks() const { return m_num_blocks; }
-      const dxt_pixel_block* get_blocks() const { return m_pBlocks; }
-
-      bool pack(dxt5_block* pDst_elements, uint elements_per_block, const qdxt5_params& params);
-
-   private:
-      task_pool*           m_pTask_pool;
-      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;
-
-      dxt5_block*          m_pDst_elements;
-      uint                 m_elements_per_block;
-      qdxt5_params         m_params;
-
-      uint                 m_max_selector_clusters;
-
-      int                  m_prev_percentage_complete;
-
-      typedef vec<2, float> vec2F;
-      typedef clusterizer<vec2F> vec2F_clusterizer;
-      vec2F_clusterizer    m_endpoint_clusterizer;
-
-      crnlib::vector< crnlib::vector<uint> > m_endpoint_cluster_indices;
-
-      typedef vec<16, float> vec16F;
-      typedef threaded_clusterizer<vec16F> 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<uint> > m_cached_selector_cluster_indices[qdxt5_params::cMaxQuality + 1];
-
-      struct cluster_id
-      {
-         cluster_id() : m_hash(0)
-         {
-
-         }
-
-         cluster_id(const crnlib::vector<uint>& indices)
-         {
-            set(indices);
-         }
-
-         void set(const crnlib::vector<uint>& indices)
-         {
-            m_cells.resize(indices.size());
-
-            for (uint i = 0; i < indices.size(); i++)
-               m_cells[i] = static_cast<uint32>(indices[i]);
-
-            std::sort(m_cells.begin(), m_cells.end());
-
-            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)
-               return false;
-
-            return m_cells == rhs.m_cells;
-         }
-
-         crnlib::vector<uint32> m_cells;
-
-         size_t m_hash;
-
-         operator size_t() const { return m_hash; }
-      };
-
-      typedef crnlib::hash_map<cluster_id, uint> cluster_hash;
-      cluster_hash m_cluster_hash;
-      spinlock m_cluster_hash_lock;
-
-      static bool generate_codebook_dummy_progress_callback(uint percentage_completed, void* pData);
-      static bool generate_codebook_progress_callback(uint percentage_completed, void* pData);
-      bool update_progress(uint value, uint max_value);
-      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<uint> >& selector_cluster_indices);
-
-      inline dxt5_block& get_block(uint index) const { return m_pDst_elements[index * m_elements_per_block]; }
-   };
-
-} // namespace crnlib
-
-
-
-
-
-
-
-
-
-

+ 0 - 345
Source/ThirdParty/crunch/crnlib/crn_radix_sort.h

@@ -1,345 +0,0 @@
-// File: crn_radix_sort.h
-// See Copyright Notice and license at the end of inc/crnlib.h
-#pragma once
-
-namespace crnlib
-{
-   // Returns pointer to sorted array.
-   template<typename T>
-   T* radix_sort(uint num_vals, T* pBuf0, T* pBuf1, uint key_ofs, uint key_size)
-   {  
-      CRNLIB_ASSERT_OPEN_RANGE(key_ofs, 0, sizeof(T));
-      CRNLIB_ASSERT_CLOSED_RANGE(key_size, 1, 4);
-
-      uint hist[256 * 4];
-
-      memset(hist, 0, sizeof(hist[0]) * 256 * key_size);
-
-#define CRNLIB_GET_KEY(p) (*(uint*)((uint8*)(p) + key_ofs))
-
-      if (key_size == 4)
-      {
-         T* p = pBuf0;
-         T* q = pBuf0 + num_vals;
-         for ( ; p != q; p++)
-         {
-            const uint key = CRNLIB_GET_KEY(p);
-
-            hist[        key        & 0xFF]++;
-            hist[256 + ((key >>  8) & 0xFF)]++;
-            hist[512 + ((key >> 16) & 0xFF)]++;
-            hist[768 + ((key >> 24) & 0xFF)]++;
-         }
-      }
-      else if (key_size == 3)
-      {
-         T* p = pBuf0;
-         T* q = pBuf0 + num_vals;
-         for ( ; p != q; p++)
-         {
-            const uint key = CRNLIB_GET_KEY(p);
-
-            hist[        key        & 0xFF]++;
-            hist[256 + ((key >>  8) & 0xFF)]++;
-            hist[512 + ((key >> 16) & 0xFF)]++;
-         }
-      }   
-      else if (key_size == 2)
-      {
-         T* p = pBuf0;
-         T* q = pBuf0 + (num_vals >> 1) * 2;
-
-         for ( ; p != q; p += 2)
-         {
-            const uint key0 = CRNLIB_GET_KEY(p);
-            const uint key1 = CRNLIB_GET_KEY(p+1);
-
-            hist[        key0         & 0xFF]++;
-            hist[256 + ((key0 >>  8) & 0xFF)]++;
-
-            hist[        key1        & 0xFF]++;
-            hist[256 + ((key1 >>  8) & 0xFF)]++;
-         }
-
-         if (num_vals & 1)
-         {
-            const uint key = CRNLIB_GET_KEY(p);
-
-            hist[        key        & 0xFF]++;
-            hist[256 + ((key >>  8) & 0xFF)]++;
-         }
-      }      
-      else
-      {
-         CRNLIB_ASSERT(key_size == 1);
-         if (key_size != 1)
-            return NULL;
-
-         T* p = pBuf0;
-         T* q = pBuf0 + (num_vals >> 1) * 2;
-
-         for ( ; p != q; p += 2)
-         {
-            const uint key0 = CRNLIB_GET_KEY(p);
-            const uint key1 = CRNLIB_GET_KEY(p+1);
-
-            hist[key0 & 0xFF]++;
-            hist[key1 & 0xFF]++;
-         }
-
-         if (num_vals & 1)
-         {
-            const uint key = CRNLIB_GET_KEY(p);
-            hist[key & 0xFF]++;
-         }
-      }
-
-      T* pCur = pBuf0;
-      T* pNew = pBuf1;
-
-      for (uint pass = 0; pass < key_size; pass++)
-      {
-         const uint* pHist = &hist[pass << 8];
-
-         uint offsets[256];
-
-         uint cur_ofs = 0;
-         for (uint i = 0; i < 256; i += 2)
-         {
-            offsets[i] = cur_ofs;
-            cur_ofs += pHist[i];
-
-            offsets[i+1] = cur_ofs;
-            cur_ofs += pHist[i+1];
-         }
-
-         const uint pass_shift = pass << 3;
-
-         T* p = pCur;
-         T* q = pCur + (num_vals >> 1) * 2;
-
-         for ( ; p != q; p += 2)
-         {
-            uint c0 = (CRNLIB_GET_KEY(p) >> pass_shift) & 0xFF;
-            uint c1 = (CRNLIB_GET_KEY(p+1) >> pass_shift) & 0xFF;
-
-            if (c0 == c1)
-            {
-               uint dst_offset0 = offsets[c0];
-
-               offsets[c0] = dst_offset0 + 2;
-
-               pNew[dst_offset0] = p[0];
-               pNew[dst_offset0 + 1] = p[1];
-            }
-            else
-            {
-               uint dst_offset0 = offsets[c0]++;
-               uint dst_offset1 = offsets[c1]++;
-
-               pNew[dst_offset0] = p[0];
-               pNew[dst_offset1] = p[1];
-            }
-         }
-
-         if (num_vals & 1)
-         {
-            uint c = (CRNLIB_GET_KEY(p) >> pass_shift) & 0xFF;
-
-            uint dst_offset = offsets[c];
-            offsets[c] = dst_offset + 1;
-
-            pNew[dst_offset] = *p;
-         }
-
-         T* t = pCur;
-         pCur = pNew;
-         pNew = t;
-      }            
-
-      return pCur;
-   }
-
-#undef CRNLIB_GET_KEY
-
-   // Returns pointer to sorted array.
-   template<typename T, typename Q>
-   T* indirect_radix_sort(uint num_indices, T* pIndices0, T* pIndices1, const Q* pKeys, uint key_ofs, uint key_size, bool init_indices)
-   {  
-      CRNLIB_ASSERT_OPEN_RANGE(key_ofs, 0, sizeof(T));
-      CRNLIB_ASSERT_CLOSED_RANGE(key_size, 1, 4);
-
-      if (init_indices)
-      {
-         T* p = pIndices0;
-         T* q = pIndices0 + (num_indices >> 1) * 2;
-         uint i;
-         for (i = 0; p != q; p += 2, i += 2)
-         {
-            p[0] = static_cast<T>(i);
-            p[1] = static_cast<T>(i + 1); 
-         }
-
-         if (num_indices & 1)
-            *p = static_cast<T>(i);
-      }
-
-      uint hist[256 * 4];
-
-      memset(hist, 0, sizeof(hist[0]) * 256 * key_size);
-
-#define CRNLIB_GET_KEY(p) (*(const uint*)((const uint8*)(pKeys + *(p)) + key_ofs))
-#define CRNLIB_GET_KEY_FROM_INDEX(i) (*(const uint*)((const uint8*)(pKeys + (i)) + key_ofs))
-
-      if (key_size == 4)
-      {
-         T* p = pIndices0;
-         T* q = pIndices0 + num_indices;
-         for ( ; p != q; p++)
-         {
-            const uint key = CRNLIB_GET_KEY(p);
-
-            hist[        key        & 0xFF]++;
-            hist[256 + ((key >>  8) & 0xFF)]++;
-            hist[512 + ((key >> 16) & 0xFF)]++;
-            hist[768 + ((key >> 24) & 0xFF)]++;
-         }
-      }
-      else if (key_size == 3)
-      {
-         T* p = pIndices0;
-         T* q = pIndices0 + num_indices;
-         for ( ; p != q; p++)
-         {
-            const uint key = CRNLIB_GET_KEY(p);
-
-            hist[        key        & 0xFF]++;
-            hist[256 + ((key >>  8) & 0xFF)]++;
-            hist[512 + ((key >> 16) & 0xFF)]++;
-         }
-      }   
-      else if (key_size == 2)
-      {
-         T* p = pIndices0;
-         T* q = pIndices0 + (num_indices >> 1) * 2;
-
-         for ( ; p != q; p += 2)
-         {
-            const uint key0 = CRNLIB_GET_KEY(p);
-            const uint key1 = CRNLIB_GET_KEY(p+1);
-
-            hist[        key0         & 0xFF]++;
-            hist[256 + ((key0 >>  8) & 0xFF)]++;
-
-            hist[        key1        & 0xFF]++;
-            hist[256 + ((key1 >>  8) & 0xFF)]++;
-         }
-
-         if (num_indices & 1)
-         {
-            const uint key = CRNLIB_GET_KEY(p);
-
-            hist[        key        & 0xFF]++;
-            hist[256 + ((key >>  8) & 0xFF)]++;
-         }
-      }      
-      else
-      {
-         CRNLIB_ASSERT(key_size == 1);
-         if (key_size != 1)
-            return NULL;
-
-         T* p = pIndices0;
-         T* q = pIndices0 + (num_indices >> 1) * 2;
-
-         for ( ; p != q; p += 2)
-         {
-            const uint key0 = CRNLIB_GET_KEY(p);
-            const uint key1 = CRNLIB_GET_KEY(p+1);
-
-            hist[key0 & 0xFF]++;
-            hist[key1 & 0xFF]++;
-         }
-
-         if (num_indices & 1)
-         {
-            const uint key = CRNLIB_GET_KEY(p);
-
-            hist[key & 0xFF]++;
-         }
-      }      
-
-      T* pCur = pIndices0;
-      T* pNew = pIndices1;
-
-      for (uint pass = 0; pass < key_size; pass++)
-      {
-         const uint* pHist = &hist[pass << 8];
-
-         uint offsets[256];
-
-         uint cur_ofs = 0;
-         for (uint i = 0; i < 256; i += 2)
-         {
-            offsets[i] = cur_ofs;
-            cur_ofs += pHist[i];
-
-            offsets[i+1] = cur_ofs;
-            cur_ofs += pHist[i+1];
-         }
-
-         const uint pass_shift = pass << 3;
-
-         T* p = pCur;
-         T* q = pCur + (num_indices >> 1) * 2;
-
-         for ( ; p != q; p += 2)
-         {
-            uint index0 = p[0];
-            uint index1 = p[1];
-
-            uint c0 = (CRNLIB_GET_KEY_FROM_INDEX(index0) >> pass_shift) & 0xFF;
-            uint c1 = (CRNLIB_GET_KEY_FROM_INDEX(index1) >> pass_shift) & 0xFF;
-
-            if (c0 == c1)
-            {
-               uint dst_offset0 = offsets[c0];
-
-               offsets[c0] = dst_offset0 + 2;
-
-               pNew[dst_offset0] = static_cast<T>(index0);
-               pNew[dst_offset0 + 1] = static_cast<T>(index1);
-            }
-            else
-            {
-               uint dst_offset0 = offsets[c0]++;
-               uint dst_offset1 = offsets[c1]++;
-
-               pNew[dst_offset0] = static_cast<T>(index0);
-               pNew[dst_offset1] = static_cast<T>(index1);
-            }
-         }
-
-         if (num_indices & 1)
-         {
-            uint index = *p;
-            uint c = (CRNLIB_GET_KEY_FROM_INDEX(index) >> pass_shift) & 0xFF;
-
-            uint dst_offset = offsets[c];
-            offsets[c] = dst_offset + 1;
-
-            pNew[dst_offset] = static_cast<T>(index);
-         }
-
-         T* t = pCur;
-         pCur = pNew;
-         pNew = t;
-      }            
-
-      return pCur;
-   }
-
-#undef CRNLIB_GET_KEY
-#undef CRNLIB_GET_KEY_FROM_INDEX
-
-} // namespace crnlib

+ 0 - 385
Source/ThirdParty/crunch/crnlib/crn_rand.cpp

@@ -1,385 +0,0 @@
-// File: crn_rand.cpp
-// See Copyright Notice and license at the end of inc/crnlib.h
-// See:
-// http://www.ciphersbyritter.com/NEWS4/RANDC.HTM
-// http://burtleburtle.net/bob/rand/smallprng.html
-// http://www.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf
-// See GPG7, page 120, or http://www.lomont.org/Math/Papers/2008/Lomont_PRNG_2008.pdf
-#include "crn_core.h"
-#include "crn_rand.h"
-#include "crn_hash.h"
-
-#define znew   (z=36969*(z&65535)+(z>>16))
-#define wnew   (w=18000*(w&65535)+(w>>16))
-#define MWC    ((znew<<16)+wnew )
-#define SHR3  (jsr^=(jsr<<17), jsr^=(jsr>>13), jsr^=(jsr<<5))
-#define CONG  (jcong=69069*jcong+1234567)
-#define FIB   ((b=a+b),(a=b-a))
-#define KISS  ((MWC^CONG)+SHR3)
-#define LFIB4 (c++,t[c]=t[c]+t[UC(c+58)]+t[UC(c+119)]+t[UC(c+178)])
-#define SWB   (c++,bro=(x<y),t[c]=(x=t[UC(c+34)])-(y=t[UC(c+19)]+bro))
-#define UNI   (KISS*2.328306e-10)
-#define VNI   ((long) KISS)*4.656613e-10
-#define UC    (unsigned char)  /*a cast operation*/
-
-//#define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))
-#define rot(x,k) CRNLIB_ROTATE_LEFT(x,k)
-
-namespace crnlib
-{
-   static const double cNorm = 1.0 / (double)0x100000000ULL;
-
-   kiss99::kiss99()
-   {
-      x = 123456789;
-      y = 362436000;
-      z = 521288629;
-      c = 7654321;
-   }
-
-   void kiss99::seed(uint32 i, uint32 j, uint32 k)
-   {
-      x = i;
-      y = j;
-      z = k;
-      c = 7654321;
-   }
-
-   inline uint32 kiss99::next()
-   {
-      x = 69069*x+12345;
-
-      y ^= (y<<13);
-      y ^= (y>>17);
-      y ^= (y<<5);
-
-      uint64 t = c;
-      t += (698769069ULL*z);
-      c = static_cast<uint32>(t >> 32);
-      z = static_cast<uint32>(t);
-
-      return (x+y+z);
-   }
-
-   inline uint32 ranctx::next()
-   {
-      uint32 e = a - rot(b, 27);
-      a = b ^ rot(c, 17);
-      b = c + d;
-      c = d + e;
-      d = e + a;
-      return d;
-   }
-
-   void ranctx::seed(uint32 seed)
-   {
-      a = 0xf1ea5eed, b = c = d = seed;
-      for (uint32 i=0; i<20; ++i)
-         next();
-   }
-
-   well512::well512()
-   {
-      seed(0xDEADBE3F);
-   }
-
-   void well512::seed(uint32 seed[well512::cStateSize])
-   {
-      memcpy(m_state, seed, sizeof(m_state));
-      m_index = 0;
-   }
-
-   void well512::seed(uint32 seed)
-   {
-      uint32 jsr = utils::swap32(seed) ^ 0xAAC29377;
-
-      for (uint i = 0; i < cStateSize; i++)
-      {
-         SHR3;
-         seed = bitmix32c(seed);
-
-         m_state[i] = seed ^ jsr;
-      }
-      m_index = 0;
-   }
-
-   void well512::seed(uint32 seed1, uint32 seed2, uint32 seed3)
-   {
-      uint32 jsr = seed2;
-      uint32 jcong = seed3;
-
-      for (uint i = 0; i < cStateSize; i++)
-      {
-         SHR3;
-         seed1 = bitmix32c(seed1);
-         CONG;
-
-         m_state[i] = seed1 ^ jsr ^ jcong;
-      }
-      m_index = 0;
-   }
-
-   inline uint32 well512::next()
-   {
-      uint32 a, b, c, d;
-      a = m_state[m_index];
-      c = m_state[(m_index+13)&15];
-      b = a^c^(a<<16)^(c<<15);
-      c = m_state[(m_index+9)&15];
-      c ^= (c>>11);
-      a = m_state[m_index] = b^c;
-      d = a^((a<<5)&0xDA442D20UL);
-      m_index = (m_index + 15)&15;
-      a = m_state[m_index];
-      m_state[m_index] = a^b^d^(a<<2)^(b<<18)^(c<<28);
-      return m_state[m_index];
-   }
-
-   random::random()
-   {
-      seed(12345,65435,34221);
-   }
-
-   random::random(uint32 i)
-   {
-      seed(i);
-   }
-
-   void random::seed(uint32 i1, uint32 i2, uint32 i3)
-   {
-      m_ranctx.seed(i1^i2^i3);
-
-      m_kiss99.seed(i1, i2, i3);
-
-      m_well512.seed(i1, i2, i3);
-
-      for (uint i = 0; i < 100; i++)
-         urand32();
-   }
-
-   void random::seed(uint32 i)
-   {
-      uint32 jsr = i;
-      SHR3; SHR3;
-      uint32 jcong = utils::swap32(~jsr);
-      CONG; CONG;
-      uint32 i1 = SHR3 ^ CONG;
-      uint32 i2 = SHR3 ^ CONG;
-      uint32 i3 = SHR3 + CONG;
-      seed(i1, i2, i3);
-   }
-
-   uint32 random::urand32()
-   {
-      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();
-   }
-
-   uint32 random::bit()
-   {
-      uint32 k = urand32();
-      return (k ^ (k >> 6) ^ (k >> 10) ^ (k >> 30)) & 1;
-   }
-
-   double random::drand(double l, double h)
-   {
-      CRNLIB_ASSERT(l <= h);
-      if (l >= h)
-         return l;
-
-      return math::clamp(l + (h - l) * (urand32() * cNorm), l, h);
-   }
-
-   float random::frand(float l, float h)
-   {
-      CRNLIB_ASSERT(l <= h);
-      if (l >= h)
-         return l;
-
-      float r = static_cast<float>(l + (h - l) * (urand32() * cNorm));
-
-      return math::clamp<float>(r, l, h);
-   }
-   
-   int random::irand(int l, int h)
-   {
-      CRNLIB_ASSERT(l < h);
-      if (l >= h)
-         return l;
-
-      uint32 range = static_cast<uint32>(h - l);
-
-      uint32 rnd = urand32();
-
-#if defined(_M_IX86) && defined(_MSC_VER)
-      //uint32 rnd_range = static_cast<uint32>(__emulu(range, rnd) >> 32U);
-      uint32 x[2];
-      *reinterpret_cast<uint64*>(x) = __emulu(range, rnd);
-      uint32 rnd_range = x[1];
-#else
-      uint32 rnd_range = static_cast<uint32>((((uint64)range) * ((uint64)rnd)) >> 32U);
-#endif
-
-      int result = l + rnd_range;
-      CRNLIB_ASSERT((result >= l) && (result < h));
-      return result;
-   }
-
-   int random::irand_inclusive(int l, int h)
-   {
-      CRNLIB_ASSERT(h < cINT32_MAX);
-      return irand(l, h + 1);
-   }
-
-   /*
-      ALGORITHM 712, COLLECTED ALGORITHMS FROM ACM.
-      THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE,
-      VOL. 18, NO. 4, DECEMBER, 1992, PP. 434-435.
-      The function returns a normally distributed pseudo-random number
-      with a given mean and standard devaiation.  Calls are made to a
-      function subprogram which must return independent random
-      numbers uniform in the interval (0,1).
-      The algorithm uses the ratio of uniforms method of A.J. Kinderman
-      and J.F. Monahan augmented with quadratic bounding curves.
-      */
-   double random::gaussian(double mean, double stddev)
-   {
-      double  q,u,v,x,y;
-
-      /*
-      Generate P = (u,v) uniform in rect. enclosing acceptance region
-      Make sure that any random numbers <= 0 are rejected, since
-      gaussian() requires uniforms > 0, but RandomUniform() delivers >= 0.
-      */
-      do {
-         u = drand(0, 1);
-         v = drand(0, 1);
-         if (u <= 0.0 || v <= 0.0) {
-            u = 1.0;
-            v = 1.0;
-         }
-         v = 1.7156 * (v - 0.5);
-
-         /*  Evaluate the quadratic form */
-         x = u - 0.449871;
-         y = fabs(v) + 0.386595;
-         q = x * x + y * (0.19600 * y - 0.25472 * x);
-
-         /* Accept P if inside inner ellipse */
-         if (q < 0.27597)
-            break;
-
-         /*  Reject P if outside outer ellipse, or outside acceptance region */
-      } while ((q > 0.27846) || (v * v > -4.0 * log(u) * u * u));
-
-      /*  Return ratio of P's coordinates as the normal deviate */
-      return (mean + stddev * v / u);
-   }
-
-   void random::test()
-   {
-   }
-
-   fast_random::fast_random() :
-      jsr(0xABCD917A),
-      jcong(0x17F3DEAD)
-   {
-   }
-
-   fast_random::fast_random(const fast_random& other) :
-      jsr(other.jsr), jcong(other.jcong)
-   {
-   }
-
-   fast_random::fast_random(uint32 i)
-   {
-      seed(i);
-   }
-
-   fast_random& fast_random::operator=(const fast_random& other)
-   {
-      jsr = other.jsr;
-      jcong = other.jcong;
-      return *this;
-   }
-
-   void fast_random::seed(uint32 i)
-   {
-      jsr = i;
-      SHR3;
-      SHR3;
-      jcong = (~i) ^ 0xDEADBEEF;
-
-      SHR3;
-      CONG;
-   }
-
-   uint32 fast_random::urand32()
-   {
-      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);
-      if (l >= h)
-         return l;
-
-      uint32 range = static_cast<uint32>(h - l);
-
-      uint32 rnd = urand32();
-
-#if defined(_M_IX86) && defined(_MSC_VER)
-      //uint32 rnd_range = static_cast<uint32>(__emulu(range, rnd) >> 32U);
-      uint32 x[2];
-      *reinterpret_cast<uint64*>(x) = __emulu(range, rnd);
-      uint32 rnd_range = x[1];
-#else
-      uint32 rnd_range = static_cast<uint32>((((uint64)range) * ((uint64)rnd)) >> 32U);
-#endif
-
-      int result = l + rnd_range;
-      CRNLIB_ASSERT((result >= l) && (result < h));
-      return result;
-   }
-
-   double fast_random::drand(double l, double h)
-   {
-      CRNLIB_ASSERT(l <= h);
-      if (l >= h)
-         return l;
-
-      return math::clamp(l + (h - l) * (urand32() * cNorm), l, h);
-   }
-
-   float fast_random::frand(float l, float h)
-   {
-      CRNLIB_ASSERT(l <= h);
-      if (l >= h)
-         return l;
-
-      float r = static_cast<float>(l + (h - l) * (urand32() * cNorm));
-
-      return math::clamp<float>(r, l, h);
-   }
-
-} // namespace crnlib
-

Some files were not shown because too many files changed in this diff