123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- #include <stdio.h>
- #include <grass/raster3d.h>
- #define G_254_SQUARE 64516
- #define G_254_TIMES_2 508
- #define G_RLE_OUTPUT_CODE(code) (*((unsigned char *) dst++) = (code))
- #define G_RLE_INPUT_CODE(codeP) (*(codeP) = *((unsigned char *) src++))
- /*---------------------------------------------------------------------------*/
- static int G_rle_codeLength(int length)
- {
- register int lPrime;
- int codeLength;
- if (length == -1)
- return 2;
- if (length < 254)
- return 1;
- if (length < G_254_TIMES_2)
- return 2;
- if (length < G_254_SQUARE)
- return 3;
- codeLength = 0;
- lPrime = length;
- while ((lPrime = lPrime / 254) != 0)
- codeLength++;
- return codeLength + 2;
- }
- /*---------------------------------------------------------------------------*/
- static char *rle_length2code(int length, char *dst)
- {
- register int lPrime;
- if (length == -1) { /* stop code */
- G_RLE_OUTPUT_CODE(255);
- G_RLE_OUTPUT_CODE(255);
- return dst;
- }
- if (length < 254) {
- G_RLE_OUTPUT_CODE(length);
- return dst;
- }
- if (length < G_254_TIMES_2) { /* length == 254 + a; a < 254 */
- G_RLE_OUTPUT_CODE(255);
- G_RLE_OUTPUT_CODE(length % 254);
- return dst;
- }
- if (length < G_254_SQUARE) { /* length = 254 * b + a; b, a < 254 */
- G_RLE_OUTPUT_CODE(254); /* this if-clause included for efficiency only */
- G_RLE_OUTPUT_CODE(length / 254);
- G_RLE_OUTPUT_CODE(length % 254);
- return dst;
- }
- /* TODO implement a corrected version for larger strings */
- /* This code is simply wrong, it works only for c == 2, critical number for wrong computation is 254*254*2 = 129032 */
- /* CORRECT: length = 254 ^ 2 + 254 * b + a; b, a < 254 */
- /* WRONG: length = 254 ^ c + 254 * b + a; b, a < 254 */
- lPrime = length;
- while ((lPrime = lPrime / 254) != 0)
- G_RLE_OUTPUT_CODE(254);
- length %= G_254_SQUARE;
- G_RLE_OUTPUT_CODE(length / 254);
- G_RLE_OUTPUT_CODE(length % 254);
- /* Next should be: length = 254 ^ 3 + 254 ^ 2 * c + 254 * b + a; c, b, a < 254 */
- return dst;
- }
- /*---------------------------------------------------------------------------*/
- static char *rle_code2length(char *src, int *length)
- {
- int code;
- if (G_RLE_INPUT_CODE(length) < 254)
- return src; /* length < 254 */
- if (*length == 255) { /* length == 254 + a; a < 254 */
- if (G_RLE_INPUT_CODE(length) == 255) {
- *length = -1;
- return src;
- }
- *length += 254;
- return src;
- }
- G_RLE_INPUT_CODE(&code);
- if (code < 254) { /* length = 254 * b + a; b, a < 254 */
- G_RLE_INPUT_CODE(length); /* this if-clause included for efficiency only */
- *length += 254 * code;
- return src;
- }
- /* TODO implement a corrected version for larger strings */
- /* This code is simply wrong, it works only for c == 2, critical number for wrong computation is 254*254*2 = 129032 */
- /* CORRECT: length = 254 ^ 2 + 254 * b + a; b, a < 254 */
- /* WRONG: length = 254 ^ c + 254 * b + a; b, a < 254 */
- *length = G_254_SQUARE;
- while (G_RLE_INPUT_CODE(&code) == 254)
- *length *= 254;
- *length += 254 * code;
- G_RLE_INPUT_CODE(&code);
- *length += code;
- /* Next should be: length = 254 ^ 3 + 254 ^ 2 * c + 254 * b + a; c, b, a < 254 */
- return src;
- }
- /*---------------------------------------------------------------------------*/
- int Rast3d_rle_count_only(char *src, int nofElts, int eltLength)
- {
- int length, nofEqual;
- char *head, *tail, *headStop, *headStop2;
- if (nofElts <= 0)
- Rast3d_fatal_error("trying to encode 0-length list");
- length = 0;
- nofEqual = 1;
- head = src + eltLength;
- tail = src;
- headStop = src + nofElts * eltLength;
- while (head != headStop) {
- headStop2 = head + eltLength;
- while (head != headStop2) {
- if (*head != *tail) {
- length += G_rle_codeLength(nofEqual) + eltLength;
- nofEqual = 1;
- tail = headStop2 - eltLength;
- break;
- }
- head++;
- tail++;
- }
- if (head == headStop2) {
- nofEqual++;
- continue;
- }
- head = headStop2;
- }
- length += G_rle_codeLength(nofEqual) + eltLength;
- return length + G_rle_codeLength(-1);
- }
- /*---------------------------------------------------------------------------*/
- void Rast3d_rle_encode(char *src, char *dst, int nofElts, int eltLength)
- {
- int length, nofEqual;
- char *head, *tail, *headStop, *headStop2;
- if (nofElts <= 0)
- Rast3d_fatal_error("trying to encode 0-length list");
- length = 0;
- nofEqual = 1;
- head = src + eltLength;
- tail = src;
- headStop = src + nofElts * eltLength;
- while (head != headStop) {
- headStop2 = head + eltLength;
- while (head != headStop2) {
- if (*head != *tail) {
- dst = rle_length2code(nofEqual, dst);
- tail = headStop2 - eltLength * (nofEqual + 1);
- head = tail + eltLength;
- /* printf ("equal %d char %d\n", nofEqual, *tail); */
- while (tail != head)
- *dst++ = *tail++;
- length += G_rle_codeLength(nofEqual) + eltLength;
- nofEqual = 1;
- tail = headStop2 - eltLength;
- break;
- }
- head++;
- tail++;
- }
- if (head == headStop2) {
- nofEqual++;
- continue;
- }
- head = headStop2;
- }
- dst = rle_length2code(nofEqual, dst);
- tail = headStop - eltLength * nofEqual;
- head = tail + eltLength;
- while (tail != head)
- *dst++ = *tail++;
- length += G_rle_codeLength(nofEqual) + eltLength;
- dst = rle_length2code(-1, dst);
- length += G_rle_codeLength(-1);
- rle_code2length(dst - 2, &nofEqual);
- }
- /*---------------------------------------------------------------------------*/
- void
- Rast3d_rle_decode(char *src, char *dst, int nofElts, int eltLength,
- int *lengthEncode, int *lengthDecode)
- {
- int nofEqual;
- char *src2, *srcStop, *src2Stop, *dstFirst;
- srcStop = src + nofElts * eltLength;
- dstFirst = dst;
- while (src != srcStop) {
- src = rle_code2length(src, &nofEqual);
- if (nofEqual == -1) {
- *lengthEncode = src - (srcStop - nofElts * eltLength);
- *lengthDecode = dst - dstFirst;
- return;
- }
- while (nofEqual--) {
- src2 = src;
- src2Stop = src2 + eltLength;
- while (src2 != src2Stop)
- *dst++ = *src2++;
- }
- src += eltLength;
- }
- Rast3d_fatal_error("Rast3d_rle_decode: string ends prematurely");
- }
- /*---------------------------------------------------------------------------*/
- /* TODO: Find out if this function used at all.
- * Seems to be some leftover from the early pre-SVN days of GRASS GIS.
- * Maris, 2018.
- */
- void test_rle()
- {
- char c[100];
- int length;
- do {
- printf("length? ");
- if (scanf("%d", &length) != 1)
- Rast3d_fatal_error("Error reading length");
- printf("length = %d\n", length);
- printf("codeLength %d ", G_rle_codeLength(length));
- (void)rle_length2code(length, c);
- length = 0;
- (void)rle_code2length(c, &length);
- printf("output length %d\n\n", length);
- } while (1);
- }
|