rle.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include <stdio.h>
  2. #include <grass/G3d.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. /* length = 254 ^ c + 254 * b + a; b, a < 254 */
  51. lPrime = length;
  52. while ((lPrime = lPrime / 254) != 0)
  53. G_RLE_OUTPUT_CODE(254);
  54. length %= G_254_SQUARE;
  55. G_RLE_OUTPUT_CODE(length / 254);
  56. G_RLE_OUTPUT_CODE(length % 254);
  57. return dst;
  58. }
  59. /*---------------------------------------------------------------------------*/
  60. static char *rle_code2length(char *src, int *length)
  61. {
  62. int code;
  63. if (G_RLE_INPUT_CODE(length) < 254)
  64. return src; /* length < 254 */
  65. if (*length == 255) { /* length == 254 + a; a < 254 */
  66. if (G_RLE_INPUT_CODE(length) == 255) {
  67. *length = -1;
  68. return src;
  69. }
  70. *length += 254;
  71. return src;
  72. }
  73. G_RLE_INPUT_CODE(&code);
  74. if (code < 254) { /* length = 254 * b + a; b, a < 254 */
  75. G_RLE_INPUT_CODE(length); /* this if-clause included for efficiency only */
  76. *length += 254 * code;
  77. return src;
  78. }
  79. /* length = 254 ^ c + 254 * b + a; b, a < 254 */
  80. *length = G_254_SQUARE;
  81. while (G_RLE_INPUT_CODE(&code) == 254)
  82. *length *= 254;
  83. *length += 254 * code;
  84. G_RLE_INPUT_CODE(&code);
  85. *length += code;
  86. return src;
  87. }
  88. /*---------------------------------------------------------------------------*/
  89. int G_rle_count_only(char *src, int nofElts, int eltLength)
  90. {
  91. int length, nofEqual;
  92. char *head, *tail, *headStop, *headStop2;
  93. if (nofElts <= 0)
  94. G3d_fatalError("trying to encode 0-length list");
  95. length = 0;
  96. nofEqual = 1;
  97. head = src + eltLength;
  98. tail = src;
  99. headStop = src + nofElts * eltLength;
  100. while (head != headStop) {
  101. headStop2 = head + eltLength;
  102. while (head != headStop2) {
  103. if (*head != *tail) {
  104. length += G_rle_codeLength(nofEqual) + eltLength;
  105. nofEqual = 1;
  106. tail = headStop2 - eltLength;
  107. break;
  108. }
  109. head++;
  110. tail++;
  111. }
  112. if (head == headStop2) {
  113. nofEqual++;
  114. continue;
  115. }
  116. head = headStop2;
  117. }
  118. length += G_rle_codeLength(nofEqual) + eltLength;
  119. return length + G_rle_codeLength(-1);
  120. }
  121. /*---------------------------------------------------------------------------*/
  122. void G_rle_encode(char *src, char *dst, int nofElts, int eltLength)
  123. {
  124. int length, nofEqual;
  125. char *head, *tail, *headStop, *headStop2;
  126. if (nofElts <= 0)
  127. G3d_fatalError("trying to encode 0-length list");
  128. length = 0;
  129. nofEqual = 1;
  130. head = src + eltLength;
  131. tail = src;
  132. headStop = src + nofElts * eltLength;
  133. while (head != headStop) {
  134. headStop2 = head + eltLength;
  135. while (head != headStop2) {
  136. if (*head != *tail) {
  137. dst = rle_length2code(nofEqual, dst);
  138. tail = headStop2 - eltLength * (nofEqual + 1);
  139. head = tail + eltLength;
  140. /* printf ("equal %d char %d\n", nofEqual, *tail); */
  141. while (tail != head)
  142. *dst++ = *tail++;
  143. length += G_rle_codeLength(nofEqual) + eltLength;
  144. nofEqual = 1;
  145. tail = headStop2 - eltLength;
  146. break;
  147. }
  148. head++;
  149. tail++;
  150. }
  151. if (head == headStop2) {
  152. nofEqual++;
  153. continue;
  154. }
  155. head = headStop2;
  156. }
  157. dst = rle_length2code(nofEqual, dst);
  158. tail = headStop - eltLength * nofEqual;
  159. head = tail + eltLength;
  160. while (tail != head)
  161. *dst++ = *tail++;
  162. length += G_rle_codeLength(nofEqual) + eltLength;
  163. dst = rle_length2code(-1, dst);
  164. length += G_rle_codeLength(-1);
  165. rle_code2length(dst - 2, &nofEqual);
  166. }
  167. /*---------------------------------------------------------------------------*/
  168. void
  169. G_rle_decode(char *src, char *dst, int nofElts, int eltLength,
  170. int *lengthEncode, int *lengthDecode)
  171. {
  172. int nofEqual;
  173. char *src2, *srcStop, *src2Stop, *dstFirst;
  174. srcStop = src + nofElts * eltLength;
  175. dstFirst = dst;
  176. while (src != srcStop) {
  177. src = rle_code2length(src, &nofEqual);
  178. if (nofEqual == -1) {
  179. *lengthEncode = src - (srcStop - nofElts * eltLength);
  180. *lengthDecode = dst - dstFirst;
  181. return;
  182. }
  183. while (nofEqual--) {
  184. src2 = src;
  185. src2Stop = src2 + eltLength;
  186. while (src2 != src2Stop)
  187. *dst++ = *src2++;
  188. }
  189. src += eltLength;
  190. }
  191. G3d_fatalError("G_rle_decode: string ends prematurely");
  192. }
  193. /*---------------------------------------------------------------------------*/
  194. void test_rle()
  195. {
  196. char c[100];
  197. int length;
  198. do {
  199. printf("length? ");
  200. scanf("%d", &length);
  201. printf("length = %d\n", length);
  202. printf("codeLength %d ", G_rle_codeLength(length));
  203. (void)rle_length2code(length, c);
  204. length = 0;
  205. (void)rle_code2length(c, &length);
  206. printf("output length %d\n\n", length);
  207. } while (1);
  208. }