生成图片的base64编码(纯C语言实现)

2024-09-02 14:04

本文主要是介绍生成图片的base64编码(纯C语言实现),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、前言

Base64编码是一种广泛使用的编码方案,将任意二进制数据转换为可打印的ASCII字符字符串。这种编码方式之所以重要,是因为许多通信协议和存储介质对数据的可传输性和可存储性有特定的要求,它们可能无法直接处理或有效传输二进制数据。Base64编码通过使用64个字符的标准字符集——包括大写字母A-Z、小写字母a-z、数字0-9以及符号“+”和“/”,来表示二进制数据中的每一个6位组。为了标识编码的结束,Base64还使用了=作为填充字符。

image-20240716143247390

在实际应用中,Base64编码常见于电子邮件附件、在URLs中嵌入二进制数据、在网页中内联图像和字体文件、以及在配置文件和数据库中存储非文本数据等多种场景。例如,在HTML或CSS文件中,可以使用Base64编码的图像数据直接作为背景图像,而无需额外的HTTP请求,这在某些情况下可以提高页面加载速度,尽管这样做可能会增加文件大小,因为Base64编码通常会使原始数据膨胀约33%左右。

在C语言中,Base64编码的实现主要涉及几个关键步骤:首先,输入的二进制数据被分成6位的区块;然后,每个6位区块被映射到Base64字符集中相应的字符;接下来,如果最后一个区块不足6位,使用0进行填充,并添加等于号作为填充字符以保持输出的长度一致。

编码过程可以分解为以下步骤:

  1. 将输入的二进制数据读入内存缓冲区。
  2. 遍历缓冲区,每次取出24位数据(即3个字节),这足以生成4个Base64字符。
  3. 将这24位分为4个6位组。
  4. 使用6位组索引Base64字符集,找到对应的字符并输出。
  5. 如果到达缓冲区末尾时剩余不足24位,使用0填充剩余位数,并输出相应的Base64字符,同时在输出字符串末尾添加等于号作为填充。

在C语言中实现Base64编码时,可以定义一个包含64个字符的数组,存储Base64字符集,通过循环和位操作来处理数据。由于C语言提供了对内存和位操作的直接访问,因此在性能敏感的应用中,使用C语言实现的Base64编码可以非常高效。

二、代码实操

2.1 将二进制数据转为Base64编码

下面是C语言程序示例,将给定的一串二进制数据转换成Base64编码并打印出来。程序使用了标准库函数,并且没有依赖任何外部库。程序中包含了创建Base64编码所需的所有步骤,如初始化字符集、读取输入数据、编码数据并打印结果。

#include <stdio.h>
#include <stdlib.h>#define BASE64_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
#define CHUNK_SIZE 3
#define BASE64_CHUNK_SIZE 4void 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 数组包含了要被编码的数据。base64_encode 函数接受这些数据,并将其转换为Base64编码。编码后的字符串被存储在 encoded_data 数组中。注意,encoded_data 数组的大小应该足够容纳编码后的字符串,因为Base64编码后的字符串长度通常是原始数据长度的4/3倍。

这个程序将打印出原始数据和编码后的Base64字符串。可以根据需要修改 data 数组的内容,以便测试不同的输入。

image-20240716142913231

2.2 实现图片的base64编码和解码

下面是一个完整的C语言程序,实现了将图片文件编码为Base64字符串,并且可以将Base64字符串解码为图片并保存到本地磁盘。这个示例程序使用标准C库,不依赖于任何第三方库。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 函数:将二进制数据编码为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++; // 结尾的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;
}// 函数:将Base64字符串解码为二进制数据
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,  // +100xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff,  // +200xff, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,  // +300x3c, 0x3d, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x3f,  // +400xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03,  // +500x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,  // +600x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,  // +700x18, 0x19, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  // +800xff, 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,  // +900x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,  // +1000x2b, 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);// 将图片数据编码为Base64字符串base64_data = base64_encode(image_data, base64_len);free(image_data);if (!base64_data) {fprintf(stderr, "Base64 编码失败\n");return 1;}// 输出Base64编码后的数据printf("Base64 编码结果:\n%s\n", base64_data);// 解码Base64字符串为图片数据decoded_data = base64_decode(base64_data, &decoded_len);free(base64_data);if (!decoded_data) {fprintf(stderr, "Base64 解码失败\n");return 1;}// 将解码后的图片数据保存为文件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;
}

这篇关于生成图片的base64编码(纯C语言实现)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1130160

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n