Skip to content

Instantly share code, notes, and snippets.

@Muscipular
Created October 6, 2023 14:41
Show Gist options
  • Save Muscipular/a0a3b01beb63f42039a73b828a947797 to your computer and use it in GitHub Desktop.
Save Muscipular/a0a3b01beb63f42039a73b828a947797 to your computer and use it in GitHub Desktop.
cg_compress
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;
}
@Muscipular
Copy link
Author

test code

 BYTE d[200 * 1024], d2[200 * 1024], d3[200 * 1024], d4[200 * 1024];

    HANDLE h = CreateFileW(L"Graphic.bin",
                           GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL);
    DWORD r;
    ReadFile(h, d, sizeof(d), &r, NULL);
    CloseHandle(h);
    CG_Graphic p;
    p.pointer.raw = d;
    BYTE *data = 0;
    size_t len = 0;
    if (p.pointer.head->version & CG_GraphicVersion::CG_VER_CGEX) {
        data = &p.pointer.V2->data;
        len = p.pointer.V2->head.length;
    } else {
        data = &p.pointer.V1->data;
        len = p.pointer.V1->head.length;
    }
    int n = cg_uncompress(data, len, d2, sizeof(d2));
    int rx = cg_compress(d2, n, d3, d2[0]);
    HANDLE w = CreateFileW(L"Raw", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    WriteFile(w, data, len, &r, 0);
    CloseHandle(w);
    w = CreateFileW(L"Data", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    WriteFile(w, d2, n, &r, 0);
    CloseHandle(w);
    w = CreateFileW(L"Rx", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    WriteFile(w, d3, rx, &r, 0);
    CloseHandle(w);
    int rxn = cg_uncompress(d3, rx, d4, sizeof(d4));
    w = CreateFileW(L"Rxd", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    WriteFile(w, d4, rxn, &r, 0);
    CloseHandle(w);
    int rxk = -1;
    for (int i = 0; i < len; ++i) {
        if (d2[i] != d4[i]) {
            rxk = i;
        }
    }
    printf("len %d, n %d, rx %d, rxn %d, rxk %d", len, n, rx, rxn, rxk);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment