base64和图片转换
Base64是一种8Bit字节数据的编码方式。
在参数传输的过程中经常遇到的一种情况:使用全英文的没问题,但一旦涉及到中文就会出现乱码情况。与此类似,网络上传输的字符并不全是可打印的字符,比如二进制文件、图片等。Base64的出现就是为了解决此问题,它是基于64个可打印的字符来表示二进制的数据的一种方法。
编码原理
Base64的原理比较简单,每当我们使用Base64时都会先定义一个类似这样的数组:
char EncodeTable[] = {'A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/'};
//下标0-25对应'A'-'Z',26-51对应'a'-'z',52-61对应'0'-'9',62对应'+',63对应'/'
这就是Base64编码的索引表,字符选用了"A-Z、a-z、0-9、+、/" 64个可打印字符,这是标准的Base64协议规定。在日常使用中我们还会看到“=”或“==”号出现在Base64的编码结果中,“=”在此是作为填充字符出现,后面会讲到。
具体转换步骤
第一步:将待转换的字符串每三个字节分为一组,每个字节占8bit,那么共有24个二进制位。
第二步:将上面的24个二进制位每6个一组,共分为4组。
第三步:在每组前面添加两个0,每组由6个变为8个二进制位,总共32个二进制位,即四个字节。
第四步:根据Base64编码索引表EncodeTable获得对应的值。
在上面的步骤中,将三个字节编码后会生成四个字节,内存空间增大了三分之一。为什么使用3个字节一组呢?因为6和8的最小公倍数为24,三个字节正好24个二进制位,每6个bit位一组,恰好能够分为4组。
示例
const char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
具体分析:
第一步:'‰','P','N'对应的ASCII码值分别为137,80,78,对应的二进制值是10001001、01010000、01001110。如图第二三行所示,由此组成一个24位的二进制字符串。
第二步:如图红色框,将24位每6位二进制位一组分成四组。
第三步:在上面每一组前面补两个0,扩展成32个二进制位,此时变为四个字节:00100010、00010101、00000001、00001110。分别对应的值(Base64编码索引)为:34、21、1、14。
第四步:用上面的值在Base64编码表中进行查找,分别对应:i、V、B、O。因此“‰PN”Base64编码之后就变为:iVBO。
位数不足情况
上面是按照三个字节来举例说明的,如果字节数不足三个,那么该如何处理?
一个字节:一个字节共8个二进制位,依旧按照规则进行分组。此时共8个二进制位,每6个一组,则第二组缺少4位,用0补齐,得到两个Base64编码,而后面两组没有对应数据,都用“=”补上。因此,上图中“A”转换之后为“QQ==”;
两个字节:两个字节共16个二进制位,依旧按照规则进行分组。此时总共16个二进制位,每6个一组,则第三组缺少2位,用0补齐,得到三个Base64编码,第四组完全没有数据则用“=”补上。因此,上图中“BC”转换之后为“QKM=”;
注意事项
大多数编码都是由字符串转化成二进制的过程,而Base64的编码则是从二进制转换为字符串。与常规恰恰相反,
Base64编码主要用在传输、存储、表示二进制领域,不能算得上加密,只是无法直接看到明文。也可以通过打乱Base64编码来进行加密。
中文有多种编码(比如:utf-8、gb2312、gbk等),不同编码对应Base64编码结果都不一样。
延伸
上面我们已经看到了Base64就是用6位(2的6次幂就是64)表示字符,因此成为Base64。同理,Base32就是用5位,Base16就是用4位。大家可以按照上面的步骤进行演化一下。
代码实现
#include <tchar.h>
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
#define CreateFile CreateFileA std::string Encode(const char* Data, int DataByte)
{
//编码表
const char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//返回值
string strEncode;
unsigned char Tmp[4] = { 0 };
int LineLength = 0;
for (int i = 0; i < (int)(DataByte / 3); i++)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
Tmp[3] = *Data++;
strEncode += EncodeTable[Tmp[1] >> 2];
strEncode += EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
strEncode += EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
strEncode += EncodeTable[Tmp[3] & 0x3F];
if (LineLength += 4, LineLength == 76) { strEncode += "\r\n"; LineLength = 0; }
}
//对剩余数据进行编码
int Mod = DataByte % 3;
if (Mod == 1)
{
Tmp[1] = *Data++;
strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode += EncodeTable[((Tmp[1] & 0x03) << 4)];
strEncode += "==";
}
else if (Mod == 2)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode += EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
strEncode += EncodeTable[((Tmp[2] & 0x0F) << 2)];
strEncode += "=";
} return strEncode;
} std::string Decode(const char* Data, int DataByte, int& OutByte)
{
//解码表
const char DecodeTable[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62, // '+' [43]
0, 0, 0,
63, // '/' [47]
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9' [48-57]
0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z' [65-90]
0, 0, 0, 0, 0, 0,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z' [97-122]
};
//返回值
string strDecode;
int nValue;
int i = 0;
while (i < DataByte)
{
if (*Data != '\r' && *Data != '\n')
{
nValue = DecodeTable[*Data++] << 18;
nValue += DecodeTable[*Data++] << 12;
strDecode += (nValue & 0x00FF0000) >> 16;
OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++] << 6;
strDecode += (nValue & 0x0000FF00) >> 8;
OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++];
strDecode += nValue & 0x000000FF;
OutByte++;
}
}
i += 4;
}
else// 回车换行,跳过
{
Data++;
i++;
}
}
return strDecode;
} //以下是读写图片的调用代码:
bool ReadPhotoFile(std::string& strFileName, std::string &strData)
{
HANDLE hFile;
hFile = CreateFile(strFileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE)
{
return false;
} DWORD dFileSize = GetFileSize(hFile, NULL);
char * pBuffer = new char[dFileSize + 1]; if (pBuffer == NULL)
return false; memset(pBuffer, 0, dFileSize); DWORD dReadSize(0);
if (!ReadFile(hFile, pBuffer, dFileSize, &dReadSize, NULL))
{
delete[]pBuffer;
CloseHandle(hFile);
return false;
} strData = "";
strData = Encode((const char*)pBuffer, dReadSize); delete[]pBuffer;
CloseHandle(hFile);
return true;
} bool WritePhotoFile(std::string& strFileName, std::string &strData)
{
HANDLE hFile;
hFile = CreateFile(strFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE)
{
return false;
} int datalen(0);
DWORD dwritelen(0);
std::string strdcode = Decode(strData.data(), strData.size(), datalen);
if (!WriteFile(hFile, strdcode.data(), datalen, &dwritelen, NULL))
{
CloseHandle(hFile);
return false;
}
CloseHandle(hFile);
return true;
} int main()
{
//图片转base64
string path("C:\\Users\\X\\Desktop\\test\\name.png"); //图片路径
string data; //转换后的字符串
ReadPhotoFile(path, data); //base64转图片
string strfilename("C:\\Users\\X\\Desktop\\test\\123.bmp"); //转换后的的图片的路径和格式(可改为其他格式)
WritePhotoFile(strfilename, data); return 0;
}
Ascii码表:https://tool.ip138.com/ascii_code/
(参考博客:https://blog.csdn.net/my_angle2016/article/details/90371059)
base64和图片转换的更多相关文章
- Base64 图片转换工具
以前在写asp的后台的时候,有一个上传功能是必须的,那时候进行的图片预览(未上传前)其实就是获取本地的图片路径来显示图片,但是随着HTML5的出现,可以把图片通过编码来实现预览. 在雅虎的36条速度优 ...
- 图片转换base64数据上传,并且实现预览的简便方法
对于很多新手来说,实现上传图片并且预览功能,都会感到不知所可,然后开始在网站搜索各种各样的图片上传预览插件,但是有的时候我们只是想简单的实现判断格式,以及预览的功能,使用插件的话,会使得项目的资源空间 ...
- 运用C语言将图片转换成16进制的字符串(base64)
最近在写手机端的性能测试脚本的时候,发现手机在上传图片数据时,先将图片转换成一堆16进制的字符,将字符传输过去,服务器再将字符解码成图片 我们在loadrunner中测试时,就需要用C语言将图片编码. ...
- java 图片转换成base64字符串
import java.io.ByteArrayOutputStream; import java.io.FileInputStream;import java.io.FileOutputStream ...
- js绝对地址图片转换成base64的方法
//将图片转换成base64 function getBase64Image(url, callback){ var canvas = document.createElement('canvas') ...
- http://imgbase64.duoshitong.com/ 图片转换 base64
base64图片工具介绍: 1.支持 PNG.GIF.JPG.BMP.ICO 格式. 2.将图片转换为Base64编码,可以让你很方便地在没有上传文件的条件下将图片插入其它的网页.编辑器中. 这对于一 ...
- Java对网络图片/本地图片转换成Base64编码和解码
一.将本地图片转换成Base64编码字符串 /** * 将本地图片转换成Base64编码字符串 * * @param imgFile 图片目录路径 * @return */ public static ...
- delphi将图片转换成Base64编码函数
{************************************************************************** 名称: BaseImage 参数: fn: TF ...
- VUE Base64编码图片展示与转换图片
图片的 base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址,使用 base64 传输图片文件可以节省一个 http 请求,图片的 base64 编码可以算是前端优化的一 ...
随机推荐
- Java:LinkedHashMap类小记
Java:LinkedHashMap类小记 对 Java 中的 LinkedHashMap类,做一个微不足道的小小小小记 概述 public class LinkedHashMap<K,V> ...
- [对对子队]发布声明Beta
Beta版本的新功能 新增的游戏内容 循环部分关卡 Beta阶段我们制作了游戏的第4-6关,为循环部分关卡.这一部分的关卡设计以编程的循环思想为基础,在流水线中加入了新的命令--循环语句,并以此为核心 ...
- [技术博客]Django框架-后端的搭建
目录 Django框架-后端的搭建 前言 环境的部署 项目的创建 app的使用 创建app 修改配置文件 app中数据表的构建 前端接口 接口的路径 运行服务器 验证后端 Django框架-后端的搭建 ...
- 把字符串转换成整数 牛客网 剑指Offer
把字符串转换成整数 牛客网 剑指Offer 题目描述 将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串 ...
- Zabbix webhook 自定义报警媒介
场景一:使用企业微信机器人报警 图中的token是:在群组中添加机器人,机器人的webhook地址的key var Wechat = { token: null, to: null, message: ...
- js-arguments 函数参数对象详解
前言 JavaScript 函数参数不同于其他编程语言,既不需要规定参数的类型,也不需要关心参数的个数,因此 JavaScript 因函数参数而变得十分灵活,本文总结一下 arguments 参数对象 ...
- upload-labs通关攻略(全)
upload-labs通关攻略 upload-labs是练习文件上传很好的一个靶场,建议把upload-labs关卡全部练习一遍 1.下载安装 下载地址 链接:https://pan.baidu.co ...
- Linux&C ——信号以及信号处理
linux信号的简单介绍 信号的捕捉和处理 信号处理函数的返回 信号的发送 信号的屏蔽 一:linux信号的简单介绍. 信号提供给我们一种异步处理事件的方法,由于进程之间彼此的地址空间是独立的,所以进 ...
- 【接口】SpringBoot+接口开发(一)
一.接口的简单介绍 1.什么是接口:接口及服务: 2.接口的分类:(1)系统的内部接口;(2)第三方的外部接口; 3.简述接口原理图: 4.接口协议:是指客户端跟服务器之间或者接口与接口间进行的通讯时 ...
- MySQL基础学习——SQL对数据库进行操作、对数据库的表进行操作
1.SQL对数据库进行操作: 创建数据库: 语法: create database 数据库名称 [character set 字符集 collate 字符集校对规则];字符集校对规则即所用字符集的数据 ...