MultiGrid.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. //////////////////////////////////////////////////////////////////////
  19. //
  20. // MULTIGRID.H
  21. //
  22. // Created on 03/23/97 JRD
  23. // Implemented 03/23/97 JRD
  24. //
  25. // History:
  26. //
  27. // 04/08/97 BRH Fixed problems with include files
  28. //
  29. // 04/09/97 BRH Added GetValueUncompressed for the utility which
  30. // added attributes from each layer. It needed to
  31. // get the value fromt the previous layer and OR
  32. // them together.
  33. //
  34. //////////////////////////////////////////////////////////////////////
  35. #ifndef MULTIGRID_H
  36. #define MULTIGRID_H
  37. #include "System.h"
  38. #ifdef PATHS_IN_INCLUDES
  39. #include "BLUE/Blue.h"
  40. #include "ORANGE/File/file.h"
  41. #include "GREEN/Image/Image.h" // For Debugging only
  42. #else
  43. #include "Blue.h"
  44. #include "file.h"
  45. #include "Image.h"
  46. #endif // PATHS_IN_INCLUDES
  47. #define MULTIGRID_COOKIE "_MultiGrid_"
  48. #define MULTIGRID_CURRENT_VERSION 1
  49. //////////////////////////////////////////////////////////////////////
  50. //
  51. // CURRENT CONSTRAINTS (03/23/97)
  52. //
  53. // - Only one level of grid hierarchy
  54. // - Supports only 15-bit data
  55. // - Coarse Grid scale must be in powers of two from (2 - 16384)
  56. //
  57. // BACKWARDS COMPATIBILITY (03/23/97)
  58. //
  59. // - Supports loading RAttribute Files up to version 4
  60. //
  61. // PLANNED ENHANCEMENTS
  62. //
  63. // - Template support for data of any type
  64. // - Multiple hierarchical levels
  65. // - Disjoint grids (hierarchy only where detail is needed)
  66. //
  67. //////////////////////////////////////////////////////////////////////
  68. //
  69. // TUNING PARAMETERS
  70. //
  71. // By turning off clipping, access speed is greatly enhanced
  72. //
  73. #define MULTIGRID_CLIP TRUE // undefine to turn off clip to world...
  74. //
  75. //////////////////////////////////////////////////////////////////////
  76. //////////////////////////////////////////////////////////////////////
  77. //
  78. // RMultiGrid class
  79. //
  80. // This class provides efficient, high speed compression of a 2d data
  81. // field in a way that is transparent to the user. It supports load,
  82. // save, compress, and decompress within the class to facilitate
  83. // utilities.
  84. //
  85. // It compresses by breaking a 2d data field into a coarse grid, and
  86. // attempts to compress the data by 1) replicating tiles wherever
  87. // possible, and 2) describing blocks which are all one value by a
  88. // single value, like a 2d run length encoding.
  89. //
  90. //////////////////////////////////////////////////////////////////////
  91. class RMultiGrid
  92. {
  93. public:
  94. //////////////////////////////////////////////////////////////////////
  95. // User members:
  96. //////////////////////////////////////////////////////////////////////
  97. short m_sWidth; // With compression, you might get huge objects!
  98. short m_sHeight;
  99. //////////////////////////////////////////////////////////////////////
  100. // User methods:
  101. //////////////////////////////////////////////////////////////////////
  102. // This inline does a high speed lookup into the compressed data.
  103. // It ONLY works AFTER the data has been compressed!
  104. //
  105. short GetVal(short sX, short sY,short sClipVal = -1)
  106. {
  107. //-----------------------------------------------------------------
  108. ASSERT(m_sIsCompressed);
  109. #ifdef MULTIGRID_CLIP
  110. if ( (sX < 0) || (sY < 0) || (sX >= m_sWidth) || (sY >= m_sHeight) )
  111. return sClipVal;
  112. #endif
  113. //-----------------------------------------------------------------
  114. short sVal = *( m_ppsGridLines[sY] + (sX >> m_sShiftX) );
  115. if (sVal >=0) return sVal;
  116. // Cache miss -> must look into a stored tile:
  117. //return -sVal; // For debugging
  118. return *( m_ppsTileList[-sVal] + m_psTileLine[ sY & m_sMaskY ]
  119. + (sX & m_sMaskX) );
  120. }
  121. // If you wish to know the scale, you can get it from
  122. // the mask members:
  123. //
  124. long GetScale(short sMask) // decode the mask
  125. {
  126. return ++sMask;
  127. }
  128. // If you wish to know the coarse grid dimensions:
  129. void GetGridDimensions(short *psW,short *psH)
  130. {
  131. *psW = m_sWidth >> m_sShiftX;
  132. *psH = m_sHeight >> m_sShiftY;
  133. if ( m_sWidth & m_sMaskX ) *psW = *psW + 1; // Partial tiles
  134. if ( m_sHeight & m_sMaskY ) *psH = *psH + 1; // Partial tiles
  135. }
  136. // If you wish to know the enumber of unique blocks:
  137. short GetNumTiles()
  138. {
  139. ASSERT(m_sIsCompressed);
  140. short sNumTiles = 0 ;// scan for the number of tiles:
  141. short i,j;
  142. short sGridW,sGridH;
  143. GetGridDimensions(&sGridW,&sGridH);
  144. for (j=0;j < sGridH;j++)
  145. {
  146. for (i=0;i < sGridW;i++)
  147. {
  148. short sValue = *(m_ppsGridLines[j * (m_sMaskY + 1)] + i);
  149. if (sValue < 0) sNumTiles = MAX(sNumTiles,short(-sValue));
  150. }
  151. }
  152. return sNumTiles + 1;
  153. }
  154. // Load a compressed data set from disk
  155. //
  156. short Load(RFile* prFile);
  157. //////////////////////////////////////////////////////////////////////
  158. // Save a compressed data set to disk
  159. //
  160. short Save(RFile* prFile);
  161. //////////////////////////////////////////////////////////////////////
  162. // These user methods are for initially creating the 2d data
  163. //////////////////////////////////////////////////////////////////////
  164. // Returns SUCCESS or FAILURE
  165. // Sets up the UNCOMPRESSED data
  166. //
  167. short Alloc(short sW, short sH);
  168. // UNCOMPRESSED ACCESS:
  169. //
  170. void SetValueUncompressed(short sVal,short sX,short sY)
  171. {
  172. ASSERT(m_psGrid);
  173. ASSERT(sVal >= 0);
  174. ASSERT(!m_sIsCompressed);
  175. ASSERT( (sX >=0) && (sY >= 0) && (sX < m_sWidth) && (sY < m_sHeight));
  176. *(m_psGrid + sX + long(sY) * m_sWidth) = sVal;
  177. }
  178. // UNCOMPRESSED READ ACCESS
  179. //
  180. short GetValueUncompressed(short sX, short sY)
  181. {
  182. ASSERT(m_psGrid);
  183. ASSERT(!m_sIsCompressed);
  184. ASSERT( (sX >= 0) && (sY >= 0) && (sX < m_sWidth) && (sY < m_sHeight));
  185. return *(m_psGrid + sX + long(sY) * m_sWidth);
  186. }
  187. // A visual Debug View: (Uncompressed)
  188. //
  189. void Dump(RImage* pimDst,short sSrcX,short sSrcY,short sDstX,short sDstY,
  190. short sW,short sH);
  191. // A visual Debug View: (Compressed)
  192. //
  193. void DumpGrid(RImage* pimDst);
  194. // For Debugging:
  195. void DumpData(RImage* pimDst);
  196. // For Debugging:
  197. void DumpTiles(RImage* pimDst);
  198. //////////////////////////////////////////////////////////////////////
  199. // Performs Multigrid compression on the data in place
  200. // Optionally returns the compression statics:
  201. //
  202. // Returns FAILURE if memory could not be allocated,
  203. // or if compression did not succeed ( > 32k blocks were needed)
  204. //
  205. //////////////////////////////////////////////////////////////////////
  206. short Compress(
  207. short sTileW, // Size of tiles to try on this data
  208. short sTileH,
  209. long* plSize = NULL, // New Data Size (BYTES)
  210. long* lNumBlocks = NULL,// Number of unique tiles needed
  211. short sMatchSame = TRUE // If false, NO TILE WILL BE REUSED
  212. // which increases the speed of compresion
  213. );
  214. //////////////////////////////////////////////////////////////////////
  215. // Returns the Data to an uncompressed state to try another
  216. // compression tile size.
  217. //////////////////////////////////////////////////////////////////////
  218. short Decompress();
  219. //////////////////////////////////////////////////////////////////////
  220. // Internal members:
  221. //////////////////////////////////////////////////////////////////////
  222. short m_sIsCompressed;
  223. short m_sMaskX; // Encodes the scale of the tiles
  224. short m_sMaskY;
  225. short m_sShiftX;
  226. short m_sShiftY; // For user convenience ONLY
  227. //////////////////////////////////////////////////////////////////////
  228. // Internal methods:
  229. //////////////////////////////////////////////////////////////////////
  230. void ClearUncompressed()
  231. {
  232. m_sWidth = m_sHeight = 0;
  233. m_psGrid = NULL;
  234. }
  235. void ClearCompressed()
  236. {
  237. m_sIsCompressed = m_sMaskX = m_sMaskY = m_sShiftX = m_sShiftY = 0;
  238. m_psTiles = m_psTileLine = NULL;
  239. m_ppsGridLines = m_ppsTileList = NULL;
  240. }
  241. void FreeCompressed()
  242. {
  243. if (m_psTiles) free(m_psTiles); // This should be freed!
  244. if (m_psTileLine) free(m_psTileLine);
  245. if (m_ppsGridLines) free(m_ppsGridLines);
  246. if (m_ppsTileList) free(m_ppsTileList);
  247. ClearCompressed();
  248. }
  249. void FreeUncompressed()
  250. {
  251. if (m_psGrid) free(m_psGrid);
  252. ClearUncompressed();
  253. }
  254. void Free()
  255. {
  256. FreeCompressed();
  257. FreeUncompressed();
  258. }
  259. RMultiGrid()
  260. {
  261. ClearCompressed();
  262. ClearUncompressed();
  263. }
  264. ~RMultiGrid()
  265. {
  266. Free();
  267. }
  268. short AllocGrid(short sScaleW, short sScaleH);
  269. long MaskToShift(short sMask)
  270. {
  271. long lShift = 0;
  272. long lValue = 1;
  273. long lMask = long(sMask);
  274. while (lValue < lMask)
  275. {
  276. lShift++;
  277. lValue <<= 1;
  278. }
  279. return lShift;
  280. }
  281. public:
  282. //////////////////////////////////////////////////////////////////////
  283. // Data Structures
  284. //////////////////////////////////////////////////////////////////////
  285. short* m_psGrid; // Stores the grid data, compressed or uncompressed
  286. short** m_ppsGridLines; // fast access into the grid lines
  287. short* m_psTiles; // Stores the array of tiles
  288. short** m_ppsTileList; // fast access into the tile array
  289. short* m_psTileLine; // fast access into each tile line
  290. //////////////////////////////////////////////////////////////////////
  291. // Statics:
  292. //////////////////////////////////////////////////////////////////////
  293. static short ms_sShiftToMask[16]; // general conversion
  294. };
  295. #endif //MULTIGRID_H
  296. //////////////////////////////////////////////////////////////////////
  297. // EOF
  298. //////////////////////////////////////////////////////////////////////