rle.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #include <stdio.h>
  2. #include <grass/raster3d.h>
  3. #define G_254_SQUARE 64516
  4. #define G_254_TIMES_2 508
  5. #define G_RLE_OUTPUT_CODE(code) (*((unsigned char *) dst++) = (code))
  6. #define G_RLE_INPUT_CODE(codeP) (*(codeP) = *((unsigned char *) src++))
  7. /*---------------------------------------------------------------------------*/
  8. static int G_rle_codeLength(int length)
  9. {
  10. register int lPrime;
  11. int codeLength;
  12. if (length == -1)
  13. return 2;
  14. if (length < 254)
  15. return 1;
  16. if (length < G_254_TIMES_2)
  17. return 2;
  18. if (length < G_254_SQUARE)
  19. return 3;
  20. codeLength = 0;
  21. lPrime = length;
  22. while ((lPrime = lPrime / 254) != 0)
  23. codeLength++;
  24. return codeLength + 2;
  25. }
  26. /*---------------------------------------------------------------------------*/
  27. static char *rle_length2code(int length, char *dst)
  28. {
  29. register int lPrime;
  30. if (length == -1) { /* stop code */
  31. G_RLE_OUTPUT_CODE(255);
  32. G_RLE_OUTPUT_CODE(255);
  33. return dst;
  34. }
  35. if (length < 254) {
  36. G_RLE_OUTPUT_CODE(length);
  37. return dst;
  38. }
  39. if (length < G_254_TIMES_2) { /* length == 254 + a; a < 254 */
  40. G_RLE_OUTPUT_CODE(255);
  41. G_RLE_OUTPUT_CODE(length % 254);
  42. return dst;
  43. }
  44. if (length < G_254_SQUARE) { /* length = 254 * b + a; b, a < 254 */
  45. G_RLE_OUTPUT_CODE(254); /* this if-clause included for efficiency only */
  46. G_RLE_OUTPUT_CODE(length / 254);
  47. G_RLE_OUTPUT_CODE(length % 254);
  48. return dst;
  49. }
  50. /* TODO implement a corrected version for larger strings */
  51. /* This code is simply wrong, it works only for c == 2, critical number for wrong computation is 254*254*2 = 129032 */
  52. /* CORRECT: length = 254 ^ 2 + 254 * b + a; b, a < 254 */
  53. /* WRONG: length = 254 ^ c + 254 * b + a; b, a < 254 */
  54. lPrime = length;
  55. while ((lPrime = lPrime / 254) != 0)
  56. G_RLE_OUTPUT_CODE(254);
  57. length %= G_254_SQUARE;
  58. G_RLE_OUTPUT_CODE(length / 254);
  59. G_RLE_OUTPUT_CODE(length % 254);
  60. /* Next should be: length = 254 ^ 3 + 254 ^ 2 * c + 254 * b + a; c, b, a < 254 */
  61. return dst;
  62. }
  63. /*---------------------------------------------------------------------------*/
  64. static char *rle_code2length(char *src, int *length)
  65. {
  66. int code;
  67. if (G_RLE_INPUT_CODE(length) < 254)
  68. return src; /* length < 254 */
  69. if (*length == 255) { /* length == 254 + a; a < 254 */
  70. if (G_RLE_INPUT_CODE(length) == 255) {
  71. *length = -1;
  72. return src;
  73. }
  74. *length += 254;
  75. return src;
  76. }
  77. G_RLE_INPUT_CODE(&code);
  78. if (code < 254) { /* length = 254 * b + a; b, a < 254 */
  79. G_RLE_INPUT_CODE(length); /* this if-clause included for efficiency only */
  80. *length += 254 * code;
  81. return src;
  82. }
  83. /* TODO implement a corrected version for larger strings */
  84. /* This code is simply wrong, it works only for c == 2, critical number for wrong computation is 254*254*2 = 129032 */
  85. /* CORRECT: length = 254 ^ 2 + 254 * b + a; b, a < 254 */
  86. /* WRONG: length = 254 ^ c + 254 * b + a; b, a < 254 */
  87. *length = G_254_SQUARE;
  88. while (G_RLE_INPUT_CODE(&code) == 254)
  89. *length *= 254;
  90. *length += 254 * code;
  91. G_RLE_INPUT_CODE(&code);
  92. *length += code;
  93. /* Next should be: length = 254 ^ 3 + 254 ^ 2 * c + 254 * b + a; c, b, a < 254 */
  94. return src;
  95. }
  96. /*---------------------------------------------------------------------------*/
  97. int Rast3d_rle_count_only(char *src, int nofElts, int eltLength)
  98. {
  99. int length, nofEqual;
  100. char *head, *tail, *headStop, *headStop2;
  101. if (nofElts <= 0)
  102. Rast3d_fatal_error("trying to encode 0-length list");
  103. length = 0;
  104. nofEqual = 1;
  105. head = src + eltLength;
  106. tail = src;
  107. headStop = src + nofElts * eltLength;
  108. while (head != headStop) {
  109. headStop2 = head + eltLength;
  110. while (head != headStop2) {
  111. if (*head != *tail) {
  112. length += G_rle_codeLength(nofEqual) + eltLength;
  113. nofEqual = 1;
  114. tail = headStop2 - eltLength;
  115. break;
  116. }
  117. head++;
  118. tail++;
  119. }
  120. if (head == headStop2) {
  121. nofEqual++;
  122. continue;
  123. }
  124. head = headStop2;
  125. }
  126. length += G_rle_codeLength(nofEqual) + eltLength;
  127. return length + G_rle_codeLength(-1);
  128. }
  129. /*---------------------------------------------------------------------------*/
  130. void Rast3d_rle_encode(char *src, char *dst, int nofElts, int eltLength)
  131. {
  132. int length, nofEqual;
  133. char *head, *tail, *headStop, *headStop2;
  134. if (nofElts <= 0)
  135. Rast3d_fatal_error("trying to encode 0-length list");
  136. length = 0;
  137. nofEqual = 1;
  138. head = src + eltLength;
  139. tail = src;
  140. headStop = src + nofElts * eltLength;
  141. while (head != headStop) {
  142. headStop2 = head + eltLength;
  143. while (head != headStop2) {
  144. if (*head != *tail) {
  145. dst = rle_length2code(nofEqual, dst);
  146. tail = headStop2 - eltLength * (nofEqual + 1);
  147. head = tail + eltLength;
  148. /* printf ("equal %d char %d\n", nofEqual, *tail); */
  149. while (tail != head)
  150. *dst++ = *tail++;
  151. length += G_rle_codeLength(nofEqual) + eltLength;
  152. nofEqual = 1;
  153. tail = headStop2 - eltLength;
  154. break;
  155. }
  156. head++;
  157. tail++;
  158. }
  159. if (head == headStop2) {
  160. nofEqual++;
  161. continue;
  162. }
  163. head = headStop2;
  164. }
  165. dst = rle_length2code(nofEqual, dst);
  166. tail = headStop - eltLength * nofEqual;
  167. head = tail + eltLength;
  168. while (tail != head)
  169. *dst++ = *tail++;
  170. length += G_rle_codeLength(nofEqual) + eltLength;
  171. dst = rle_length2code(-1, dst);
  172. length += G_rle_codeLength(-1);
  173. rle_code2length(dst - 2, &nofEqual);
  174. }
  175. /*---------------------------------------------------------------------------*/
  176. void
  177. Rast3d_rle_decode(char *src, char *dst, int nofElts, int eltLength,
  178. int *lengthEncode, int *lengthDecode)
  179. {
  180. int nofEqual;
  181. char *src2, *srcStop, *src2Stop, *dstFirst;
  182. srcStop = src + nofElts * eltLength;
  183. dstFirst = dst;
  184. while (src != srcStop) {
  185. src = rle_code2length(src, &nofEqual);
  186. if (nofEqual == -1) {
  187. *lengthEncode = src - (srcStop - nofElts * eltLength);
  188. *lengthDecode = dst - dstFirst;
  189. return;
  190. }
  191. while (nofEqual--) {
  192. src2 = src;
  193. src2Stop = src2 + eltLength;
  194. while (src2 != src2Stop)
  195. *dst++ = *src2++;
  196. }
  197. src += eltLength;
  198. }
  199. Rast3d_fatal_error("Rast3d_rle_decode: string ends prematurely");
  200. }
  201. /*---------------------------------------------------------------------------*/
  202. /* TODO: Find out if this function used at all.
  203. * Seems to be some leftover from the early pre-SVN days of GRASS GIS.
  204. * Maris, 2018.
  205. */
  206. void test_rle()
  207. {
  208. char c[100];
  209. int length;
  210. do {
  211. printf("length? ");
  212. if (scanf("%d", &length) != 1)
  213. Rast3d_fatal_error("Error reading length");
  214. printf("length = %d\n", length);
  215. printf("codeLength %d ", G_rle_codeLength(length));
  216. (void)rle_length2code(length, c);
  217. length = 0;
  218. (void)rle_code2length(c, &length);
  219. printf("output length %d\n\n", length);
  220. } while (1);
  221. }