Created
October 6, 2023 14:41
-
-
Save Muscipular/a0a3b01beb63f42039a73b828a947797 to your computer and use it in GitHub Desktop.
cg_compress
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct SEQ_VAL { | |
size_t start = 0, count = 0, mode = 0; | |
}; | |
int cg_compress(const unsigned char *src, size_t len, unsigned char *dest, unsigned char bgColor) { | |
SEQ_VAL seq1, seq2; | |
size_t dest_pos = 0; | |
for (size_t i = 0; i < len; ++i) { | |
switch (seq1.mode) { | |
case MODE_NONE: | |
seq1.mode = MODE_UNKNOWN; | |
seq1.start = i; | |
seq1.count = 1; | |
break; | |
case MODE_UNKNOWN: | |
if (src[seq1.start] == src[i]) { | |
seq1.mode = MODE_SAME; | |
} else { | |
seq1.mode = MODE_NOT_SAME; | |
seq2.mode = MODE_UNKNOWN; | |
seq2.start = i; | |
seq2.count = 1; | |
} | |
seq1.count++; | |
break; | |
case MODE_SAME: { | |
if (src[seq1.start] == src[i]) { | |
seq1.count++; | |
break; | |
} | |
int nWrite = writeCompress(dest + dest_pos, | |
seq1.count, | |
src[seq1.start] == bgColor ? 0 : src[seq1.start], | |
len - dest_pos); | |
if (nWrite < 0) { | |
return 0; | |
} | |
dest_pos += nWrite; | |
seq1.mode = MODE_UNKNOWN; | |
seq1.start = i; | |
seq1.count = 1; | |
break; | |
} | |
case MODE_NOT_SAME: | |
seq1.count++; | |
switch (seq2.mode) { | |
case MODE_NONE: | |
case MODE_NOT_SAME: | |
seq2.mode = MODE_UNKNOWN; | |
seq2.start = i; | |
seq2.count = 1; | |
break; | |
case MODE_UNKNOWN: | |
if (src[seq2.start] == src[i]) { | |
seq2.mode = MODE_SAME; | |
seq2.count++; | |
} else { | |
seq2.start = i; | |
seq2.count = 1; | |
} | |
break; | |
case MODE_SAME: | |
if (src[seq2.start] == src[i]) { | |
seq2.count++; | |
if (seq2.count >= 2) { | |
size_t nToWrite = seq1.count - seq2.count; | |
int nWrite = writeCompress(dest + dest_pos, | |
nToWrite, | |
-1, | |
len - dest_pos); | |
if (nWrite < 0) { | |
return 0; | |
} | |
dest_pos += nWrite; | |
if (dest_pos + nToWrite > len) { | |
return 0; | |
} | |
memcpy(dest + dest_pos, src + seq1.start, nToWrite); | |
dest_pos += nToWrite; | |
seq1 = seq2; | |
seq2.mode = MODE_NONE; | |
} | |
} else { | |
seq2.mode = MODE_UNKNOWN; | |
seq2.start = i; | |
seq2.count = 1; | |
} | |
break; | |
} | |
break; | |
} | |
} | |
if (seq1.mode > MODE_NONE) { | |
switch (seq1.mode) { | |
case MODE_UNKNOWN: | |
case MODE_SAME: { | |
int nWrite = writeCompress(dest + dest_pos, | |
seq1.count, | |
src[seq1.start] == bgColor ? 0 : src[seq1.start], | |
len - dest_pos); | |
if (nWrite < 0) { | |
return 0; | |
} | |
dest_pos += nWrite; | |
break; | |
} | |
case MODE_NOT_SAME: { | |
size_t nToWrite = seq1.count; | |
int nWrite = writeCompress(dest + dest_pos, | |
nToWrite, | |
-1, | |
len - dest_pos); | |
if (nWrite < 0) { | |
return 0; | |
} | |
dest_pos += nWrite; | |
if (dest_pos + nToWrite > len) { | |
return 0; | |
} | |
memcpy(dest + dest_pos, src + seq1.start, nToWrite); | |
dest_pos += nToWrite; | |
break; | |
} | |
} | |
} | |
return (int) dest_pos; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
test code