-1

I have a JPEG image, which is represented as a base64 encoded string. I want to save it as a decoded byte array using the Win32 API WriteFile() function.

Because I will use WriteFile(), I need a C string, and I need to know its length, strlen() is bad, because, as I understand, it counts to \0 which could not be the exact end of file. So, I need a function that decodes base64 and returns a char* and outputs the exact byte count.

I have read this answer, and chose code from here (some stuff changed, I marked it):

static const unsigned char base64_table[65] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

unsigned char * base64_decode(const unsigned char *src, size_t len,
              size_t *out_len)
{
    unsigned char dtable[256], *out, *pos, block[4], tmp;
    size_t i, count, olen;
    int pad = 0;

    memset(dtable, 0x80, 256); // CHANGED
    for (i = 0; i < sizeof(base64_table) - 1; i++)
        dtable[base64_table[i]] = (unsigned char) i;
    dtable['='] = 0;

    count = 0;
    for (i = 0; i < len; i++) {
        if (dtable[src[i]] != 0x80)
            count++;
    }

    if (count == 0 || count % 4)
        return NULL;

    olen = count / 4 * 3;
    pos = out = new unsigned char[olen]; // CHANGED
    if (out == NULL)
        return NULL;

    count = 0;
    for (i = 0; i < len; i++) {
        tmp = dtable[src[i]];
        if (tmp == 0x80)
            continue;

        if (src[i] == '=')
            pad++;
        block[count] = tmp;
        count++;
        if (count == 4) {
            *pos++ = (block[0] << 2) | (block[1] >> 4);
            *pos++ = (block[1] << 4) | (block[2] >> 2);
            *pos++ = (block[2] << 6) | block[3];
            count = 0;
            if (pad) {
                if (pad == 1)
                    pos--;
                else if (pad == 2)
                    pos -= 2;
                else {
                    /* Invalid padding */
                    free(out);  // CHANGED
                    return NULL;
                }
                break;
            }
        }
    }

    *out_len = pos - out;
    return out;
}

Usage

unsigned char base[]="data:image/jpeg;base64,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";

unsigned char *g = base64_decode(base, 2568, &re); // length is appearing when you hover mouse on char[] in Visual Studio
// after call re equals 1921
HANDLE f2 = CreateFile(L"img.jpeg", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD wr2;
WriteFile(f2, g, re, &wr2, 0);
CloseHandle(f2);

The file I am getting is not viewable, the Photos app says it is corrupted. The main problem - it weights 1.87 kb, but should be 2.31 (I download this image from a browser).

What am I doing wrong?

1 Answers1

0

As @IngoLeonhardt pointed out, I should not pass the data:image/jpeg;base64, part to the function. Now it works.