欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用C語言生成圖片的base64編碼的代碼實現(xiàn)

 更新時間:2024年08月02日 08:50:43   作者:DS小龍哥  
Base64編碼是一種廣泛使用的編碼方案,將任意二進制數(shù)據(jù)轉(zhuǎn)換為可打印的ASCII字符字符串,在實際應(yīng)用中,Base64編碼常見于電子郵件附件、數(shù)據(jù)庫中存儲非文本數(shù)據(jù)等多種場景,本文將給大家介紹使用C語言生成圖片的base64編碼的代碼實現(xiàn),需要的朋友可以參考下

一、前言

Base64編碼是一種廣泛使用的編碼方案,將任意二進制數(shù)據(jù)轉(zhuǎn)換為可打印的ASCII字符字符串。這種編碼方式之所以重要,是因為許多通信協(xié)議和存儲介質(zhì)對數(shù)據(jù)的可傳輸性和可存儲性有特定的要求,它們可能無法直接處理或有效傳輸二進制數(shù)據(jù)。Base64編碼通過使用64個字符的標準字符集——包括大寫字母A-Z、小寫字母a-z、數(shù)字0-9以及符號“+”和“/”,來表示二進制數(shù)據(jù)中的每一個6位組。為了標識編碼的結(jié)束,Base64還使用了=作為填充字符。

在實際應(yīng)用中,Base64編碼常見于電子郵件附件、在URLs中嵌入二進制數(shù)據(jù)、在網(wǎng)頁中內(nèi)聯(lián)圖像和字體文件、以及在配置文件和數(shù)據(jù)庫中存儲非文本數(shù)據(jù)等多種場景。例如,在HTML或CSS文件中,可以使用Base64編碼的圖像數(shù)據(jù)直接作為背景圖像,而無需額外的HTTP請求,這在某些情況下可以提高頁面加載速度,盡管這樣做可能會增加文件大小,因為Base64編碼通常會使原始數(shù)據(jù)膨脹約33%左右。

在C語言中,Base64編碼的實現(xiàn)主要涉及幾個關(guān)鍵步驟:首先,輸入的二進制數(shù)據(jù)被分成6位的區(qū)塊;然后,每個6位區(qū)塊被映射到Base64字符集中相應(yīng)的字符;接下來,如果最后一個區(qū)塊不足6位,使用0進行填充,并添加等于號作為填充字符以保持輸出的長度一致。

編碼過程可以分解為以下步驟:

  • 將輸入的二進制數(shù)據(jù)讀入內(nèi)存緩沖區(qū)。
  • 遍歷緩沖區(qū),每次取出24位數(shù)據(jù)(即3個字節(jié)),這足以生成4個Base64字符。
  • 將這24位分為4個6位組。
  • 使用6位組索引Base64字符集,找到對應(yīng)的字符并輸出。
  • 如果到達緩沖區(qū)末尾時剩余不足24位,使用0填充剩余位數(shù),并輸出相應(yīng)的Base64字符,同時在輸出字符串末尾添加等于號作為填充。

在C語言中實現(xiàn)Base64編碼時,可以定義一個包含64個字符的數(shù)組,存儲Base64字符集,通過循環(huán)和位操作來處理數(shù)據(jù)。由于C語言提供了對內(nèi)存和位操作的直接訪問,因此在性能敏感的應(yīng)用中,使用C語言實現(xiàn)的Base64編碼可以非常高效。

二、代碼實操

2.1 將二進制數(shù)據(jù)轉(zhuǎn)為Base64編碼

下面是C語言程序示例,將給定的一串二進制數(shù)據(jù)轉(zhuǎn)換成Base64編碼并打印出來。程序使用了標準庫函數(shù),并且沒有依賴任何外部庫。程序中包含了創(chuàng)建Base64編碼所需的所有步驟,如初始化字符集、讀取輸入數(shù)據(jù)、編碼數(shù)據(jù)并打印結(jié)果。

#include <stdio.h>
#include <stdlib.h>
?
#define BASE64_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
#define CHUNK_SIZE 3
#define BASE64_CHUNK_SIZE 4
?
void base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len, char *out_text)
{
    unsigned char const *in = bytes_to_encode;
    unsigned char *out = (unsigned char*)out_text;
    unsigned int i;
    unsigned int j;
    unsigned int val;
?
    for (i = 0, j = 0; i < in_len - 2; i += CHUNK_SIZE, j += BASE64_CHUNK_SIZE) {
        val = ((in[i] & 0xFC) >> 2);
        out[j] = BASE64_CHARS[val];
?
        val = ((in[i] & 0x03) << 4) | ((in[i + 1] & 0xF0) >> 4);
        out[j + 1] = BASE64_CHARS[val];
?
        val = ((in[i + 1] & 0x0F) << 2) | ((in[i + 2] & 0xC0) >> 6);
        out[j + 2] = BASE64_CHARS[val];
?
        val = (in[i + 2] & 0x3F);
        out[j + 3] = BASE64_CHARS[val];
    }
?
    // Handle the last chunk gracefully.
    switch (in_len % CHUNK_SIZE) {
    case 1:
        out[j] = BASE64_CHARS[((in[i] & 0xFC) >> 2)];
        out[j + 1] = BASE64_CHARS[((in[i] & 0x03) << 4)];
        out[j + 2] = '=';
        out[j + 3] = '=';
        break;
?
    case 2:
        val = ((in[i] & 0xFC) >> 2);
        out[j] = BASE64_CHARS[val];
?
        val = ((in[i] & 0x03) << 4) | ((in[i + 1] & 0xF0) >> 4);
        out[j + 1] = BASE64_CHARS[val];
?
        out[j + 2] = BASE64_CHARS[((in[i + 1] & 0x0F) << 2)];
        out[j + 3] = '=';
        break;
    }
}
?
int main()
{
    unsigned char data[] = {0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x27, 0x0b, 0xcf, 0xa3, 0x57, 0x67};
    unsigned int data_len = sizeof(data);
    char encoded_data[100]; // Assuming enough space for the encoded string.
?
    base64_encode(data, data_len, encoded_data);
    encoded_data[data_len * 4 / 3] = '\0'; // Null terminate the string.
?
    printf("Original data: ");
    for (int i = 0; i < data_len; i++) {
        printf("%02x ", data[i]);
    }
    printf("\n");
?
    printf("Encoded data: %s\n", encoded_data);
?
    return 0;
}

在例子中,data 數(shù)組包含了要被編碼的數(shù)據(jù)。base64_encode 函數(shù)接受這些數(shù)據(jù),并將其轉(zhuǎn)換為Base64編碼。編碼后的字符串被存儲在 encoded_data 數(shù)組中。注意,encoded_data 數(shù)組的大小應(yīng)該足夠容納編碼后的字符串,因為Base64編碼后的字符串長度通常是原始數(shù)據(jù)長度的4/3倍。

這個程序?qū)⒋蛴〕鲈紨?shù)據(jù)和編碼后的Base64字符串。可以根據(jù)需要修改 data 數(shù)組的內(nèi)容,以便測試不同的輸入。

2.2 實現(xiàn)圖片的base64編碼和解碼

下面是一個完整的C語言程序,實現(xiàn)了將圖片文件編碼為Base64字符串,并且可以將Base64字符串解碼為圖片并保存到本地磁盤。這個示例程序使用標準C庫,不依賴于任何第三方庫。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
?
// 函數(shù):將二進制數(shù)據(jù)編碼為Base64字符串
char* base64_encode(const unsigned char* src, size_t len) {
    static const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
?
    char* out, * pos;
    const unsigned char* end, * in;
?
    size_t olen;
    int line_len;
?
    olen = len * 4 / 3 + 4; // 輸出長度
    olen += olen / 72; // 換行符
    olen++; // 結(jié)尾的NULL字符
    out = (char*)malloc(olen);
    if (out == NULL) return NULL;
?
    end = src + len;
    in = src;
    pos = out;
    line_len = 0;
    while (end - in >= 3) {
        *pos++ = base64_table[in[0] >> 2];
        *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
        *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
        *pos++ = base64_table[in[2] & 0x3f];
        in += 3;
        if (line_len += 4, line_len == 72) {
            *pos++ = '\n';
            line_len = 0;
        }
    }
?
    if (end - in) {
        *pos++ = base64_table[in[0] >> 2];
        if (end - in == 1) {
            *pos++ = base64_table[(in[0] & 0x03) << 4];
            *pos++ = '=';
        }
        else {
            *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
            *pos++ = base64_table[(in[1] & 0x0f) << 2];
        }
        *pos++ = '=';
    }
?
    *pos = '\0';
    return out;
}
?
// 函數(shù):將Base64字符串解碼為二進制數(shù)據(jù)
unsigned char* base64_decode(const char* src, size_t* out_len) {
    static const unsigned char base64_table[] = {
        0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  // +10
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff,  // +20
        0xff, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,  // +30
        0x3c, 0x3d, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x3f,  // +40
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03,  // +50
        0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,  // +60
        0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,  // +70
        0x18, 0x19, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  // +80
        0xff, 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,  // +90
        0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,  // +100
        0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33          // +110
    };
?
    unsigned char dtable[256], * out, * pos, block[4], tmp;
    size_t i, count, olen;
    int pad = 0;
?
    memset(dtable, 0x80, 256);
    for (i = 0; i < sizeof(base64_table); i++)
        dtable[base64_table[i]] = (unsigned char)i;
    dtable['='] = 0;
?
    count = 0;
    for (i = 0; i < strlen(src); i++) {
        if (dtable[src[i]] != 0x80)
            count++;
    }
?
    if (count == 0 || count % 4)
        return NULL;
?
    olen = count / 4 * 3;
    pos = out = (unsigned char*)malloc(olen);
    if (out == NULL) return NULL;
?
    for (i = 0; i < strlen(src); i++) {
        tmp = dtable[src[i]];
        if (tmp == 0x80) continue;
?
        if (src[i] == '=')
            pad++;
        block[count++] = tmp;
        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 {
                    free(out);
                    return NULL;
                }
                break;
            }
        }
    }
?
    *out_len = pos - out;
    return out;
}
?
int main() {
    FILE* fp;
    char* base64_data;
    unsigned char* decoded_data;
    size_t decoded_len, base64_len;
    char* filename = "test.png"; // 替換為你的圖片文件名
    char* output_filename = "decoded_image.png"; // 解碼后保存的文件名
?
    // 讀取圖片文件
    fp = fopen(filename, "rb");
    if (!fp) {
        fprintf(stderr, "無法打開文件 %s\n", filename);
        return 1;
    }
    fseek(fp, 0, SEEK_END);
    base64_len = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    unsigned char* image_data = (unsigned char*)malloc(base64_len);
    fread(image_data, 1, base64_len, fp);
    fclose(fp);
?
    // 將圖片數(shù)據(jù)編碼為Base64字符串
    base64_data = base64_encode(image_data, base64_len);
    free(image_data);
?
    if (!base64_data) {
        fprintf(stderr, "Base64 編碼失敗\n");
        return 1;
    }
?
    // 輸出Base64編碼后的數(shù)據(jù)
    printf("Base64 編碼結(jié)果:\n%s\n", base64_data);
?
    // 解碼Base64字符串為圖片數(shù)據(jù)
    decoded_data = base64_decode(base64_data, &decoded_len);
    free(base64_data);
?
    if (!decoded_data) {
        fprintf(stderr, "Base64 解碼失敗\n");
        return 1;
    }
?
    // 將解碼后的圖片數(shù)據(jù)保存為文件
    fp = fopen(output_filename, "wb");
    if (!fp) {
        fprintf(stderr, "無法打開文件 %s 進行寫入\n", output_filename);
        free(decoded_data);
        return 1;
    }
    fwrite(decoded_data, 1, decoded_len, fp);
    fclose(fp);
    free(decoded_data);
?
    printf("圖片已成功解碼并保存到 %s\n", output_filename);
?
    return 0;
}

到此這篇關(guān)于使用C語言生成圖片的base64編碼的代碼實現(xiàn)的文章就介紹到這了,更多相關(guān)C語言生成base64編碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文帶你了解C語言中的動態(tài)內(nèi)存管理函數(shù)

    一文帶你了解C語言中的動態(tài)內(nèi)存管理函數(shù)

    C語言中內(nèi)存管理相關(guān)的函數(shù)主要有realloc、calloc、malloc、free等,這篇文章主要為大家講解一下這四個函數(shù)的具體用法,需要的可以參考一下
    2023-03-03
  • C語言實現(xiàn)“幸運數(shù)”的實例詳解

    C語言實現(xiàn)“幸運數(shù)”的實例詳解

    這篇文章主要介紹了C語言實現(xiàn)“幸運數(shù)”的實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • 使用VScode搭建ROS開發(fā)環(huán)境的教程詳解

    使用VScode搭建ROS開發(fā)環(huán)境的教程詳解

    這篇文章主要介紹了使用VScode搭建ROS開發(fā)環(huán)境,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • C語言實現(xiàn)輸入一顆二元查找樹并將該樹轉(zhuǎn)換為它的鏡像

    C語言實現(xiàn)輸入一顆二元查找樹并將該樹轉(zhuǎn)換為它的鏡像

    這篇文章主要介紹了C語言實現(xiàn)輸入一顆二元查找樹并將該樹轉(zhuǎn)換為它的鏡像,是數(shù)據(jù)結(jié)構(gòu)中二元查找樹的一個比較經(jīng)典的算法,有不錯的借鑒價值,需要的朋友可以參考下
    2014-09-09
  • C++ static的作用解讀

    C++ static的作用解讀

    這篇文章主要介紹了C++ static的作用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C++11之std::future對象的使用以及說明

    C++11之std::future對象的使用以及說明

    這篇文章主要介紹了C++11之std::future對象的使用以及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 區(qū)分c++中的聲明與定義

    區(qū)分c++中的聲明與定義

    這篇文章主要介紹了如何區(qū)分c++中的聲明與定義,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-08-08
  • C++冒泡排序及其優(yōu)化算法

    C++冒泡排序及其優(yōu)化算法

    這篇文章主要為大家介紹了C++冒泡排序及其優(yōu)化算法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2021-11-11
  • 使用Qt實現(xiàn)文本文件的讀寫操作

    使用Qt實現(xiàn)文本文件的讀寫操作

    在現(xiàn)代應(yīng)用程序開發(fā)中,文件操作是一個不可或缺的任務(wù),無論是讀取配置文件、處理用戶輸入,還是保存日志信息,文件的讀取和寫入操作都非常重要,本文我們將展示如何通過一個簡單的圖形用戶界面(GUI),利用QFile、QTextStream和QFileDialog類來高效地進行文件操作
    2024-06-06
  • C++實現(xiàn)猜數(shù)字游戲

    C++實現(xiàn)猜數(shù)字游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)猜數(shù)字游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07

最新評論