C++實現(xiàn)圖片轉(zhuǎn)base64的示例代碼
1.base64編碼的原因
網(wǎng)絡(luò)傳送渠道并不支持所有的字節(jié),例如傳統(tǒng)的郵件只支持可見字符的傳送,像ASCII碼的控制字符就不能通過郵件傳送。這樣用途就受到了很大的限制,比如圖片二進制流的每個字節(jié)不可能全部是可見字符,所以就傳送不了。最好的方法就是在不改變傳統(tǒng)協(xié)議的情 況下,做一種擴展方案來支持二進制文件的傳送。把不可打印的字符也能用可打印字符來表示,問題就解決了。Base64編碼應(yīng)運而生,Base64就是一種 基于64個可打印字符來表示二進制數(shù)據(jù)的表示方法。
2.base64編碼原理
Base64編碼的思想是是采用64個基本的ASCII碼字符對數(shù)據(jù)進行重新編碼。它將需要編碼的數(shù)據(jù)拆分成字節(jié)數(shù)組。以3個字節(jié)為一組。按順序排列24 位數(shù)據(jù),再把這24位數(shù)據(jù)分成4組,即每組6位。再在每組的的最高位前補兩個0湊足一個字節(jié)。這樣就把一個3字節(jié)為一組的數(shù)據(jù)重新編碼成了4個字節(jié)。當(dāng)所要編碼的數(shù)據(jù)的字節(jié)數(shù)不是3的整倍數(shù),也就是說在分組時最后一組不夠3個字節(jié)。這時在最后一組填充1到2個0字節(jié)。
3.實現(xiàn)代碼
ZBase64.h
#include string
using namespace std;
class ZBase64
{
public:
/*編碼
DataByte
[in]輸入的數(shù)據(jù)長度,以字節(jié)為單位
*/
string Encode(const unsigned char* Data,int DataByte);
/*解碼
DataByte
[in]輸入的數(shù)據(jù)長度,以字節(jié)為單位
OutByte
[out]輸出的數(shù)據(jù)長度,以字節(jié)為單位,請不要通過返回值計算
輸出數(shù)據(jù)的長度
*/
string Decode(const char* Data,int DataByte,int& OutByte);
};ZBase64.cpp
#include "ZBase64.h"
string ZBase64::Encode(const unsigned 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;}
}
//對剩余數(shù)據(jù)進行編碼
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;
}
string ZBase64::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, // '+'
0, 0, 0,
63, // '/'
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
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'
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'
};
//返回值
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;
}4.使用示例(結(jié)合opencv)
main.cpp
#include<opencv2/opencv.hpp>
#include<iostream>
#include"ZBase64.h"
#include<vector>
using namespace std;
using namespace cv;
void main()
{
Mat img = imread("1.bmp");
vector<uchar> vecImg; //Mat 圖片數(shù)據(jù)轉(zhuǎn)換為vector<uchar>
vector<int> vecCompression_params;
vecCompression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
vecCompression_params.push_back(90);
imencode(".jpg", img, vecImg, vecCompression_params);
ZBase64 base64;
string imgbase64 = base64.Encode(vecImg.data(), vecImg.size()); //實現(xiàn)圖片的base64編碼
cout << imgbase64 << endl;
}5.效果圖


6.方法補充
除了上文的方法,小編還為大家整理了其他C++實現(xiàn)圖片轉(zhuǎn)base64的方法,希望對大家有所幫助
方法一
//++Base64.h
#pragma once
class CBase64
{
public:
public:
CBase64();
~CBase64();
/*編碼
DataByte
[in]輸入的數(shù)據(jù)長度,以字節(jié)為單位
*/
std::string Encode(const char* Data, int DataByte);
/*解碼
DataByte
[in]輸入的數(shù)據(jù)長度,以字節(jié)為單位
OutByte
[out]輸出的數(shù)據(jù)長度,以字節(jié)為單位,請不要通過返回值計算
輸出數(shù)據(jù)的長度
*/
std::string Decode(const char* Data, int DataByte, int& OutByte);
};
//++Base64.cpp
#include"stdafx.h"
#include"Base64.h"
CBase64::CBase64()
{
}
CBase64::~CBase64()
{
}
std::string CBase64::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; }
}
//對剩余數(shù)據(jù)進行編碼
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 CBase64::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, // '+'
0, 0, 0,
63, // '/'
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
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'
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'
};
//返回值
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;
}
以下是讀寫圖片的調(diào)用代碼:
bool CBusinessDataMgr::ReadPhotoFile(std::basic_string<TCHAR> 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;
}
CBase64 base64;
strData = "";
strData = base64.Encode((const char*)pBuffer, dReadSize);
delete[]pBuffer;
CloseHandle(hFile);
return true;
}
bool CBusinessDataMgr::WritePhotoFile(std::basic_string<TCHAR> 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;
}
CBase64 base64;
int datalen(0);
DWORD dwritelen(0);
std::string strdcode = base64.Decode(strData.data(),strData.size(), datalen);
if (!WriteFile(hFile, strdcode.data(), datalen, &dwritelen, NULL))
{
CloseHandle(hFile);
return false;
}
CloseHandle(hFile);
return true;
}方法二
#include <string>
#include <iostream>
static std::string base64Decode(const char* Data, int DataByte) {
//解碼表
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, // '+'
0, 0, 0,
63, // '/'
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
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'
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'
};
std::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;
if (*Data != '=') {
nValue += DecodeTable[*Data++] << 6;
strDecode += (nValue & 0x0000FF00) >> 8;
if (*Data != '=') {
nValue += DecodeTable[*Data++];
strDecode += nValue & 0x000000FF;
}
}
i += 4;
}
else {
Data++;
i++;
}
}
return strDecode;
}
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
std::string base64_encode(const char* bytes_to_encode, unsigned int in_len)
{
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--)
{
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3)
{
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++)
{
ret += base64_chars[char_array_4[i]];
}
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
{
char_array_3[j] = '\0';
}
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
{
ret += base64_chars[char_array_4[j]];
}
while ((i++ < 3))
{
ret += '=';
}
}
return ret;
}
int main(){
std::fstream f;
f.open("2.jpeg", std::ios::in | std::ios::binary);
f.seekg(0, std::ios_base::end); //設(shè)置偏移量至文件結(jié)尾
std::streampos sp = f.tellg(); //獲取文件大小
int size = sp;
char* buffer = (char*)malloc(sizeof(char) * size);
f.seekg(0, std::ios_base::beg); //設(shè)置偏移量至文件開頭
f.read(buffer, size); //將文件內(nèi)容讀入buffer
std::string imgBase64 = base64_encode(buffer, size);
std::string s_mat = base64Decode(imgBase64.c_str(), imgBase64.size());
FILE* stream;
if ((stream = fopen("1.JPG", "wb")) != NULL)
{
int numwritten = fwrite(s_mat.data(), sizeof(char), s_mat.size(), stream);
fclose(stream);
} //編碼
}
到此這篇關(guān)于C++實現(xiàn)圖片轉(zhuǎn)base64的示例代碼的文章就介紹到這了,更多相關(guān)C++圖片轉(zhuǎn)base64內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
QT布局管理詳解QVBoxLayout與QHBoxLayout及QGridLayout的使用
在這篇文章中,你將知道水平布局、垂直布局、網(wǎng)格布局如何輕松上手,以純代碼方式展示。對齊方式,大小設(shè)置,圖片頭像匹配標(biāo)簽,布局器里面的組件大小隨意切換大小,認(rèn)真看完這篇文章,QT布局管理器熟練使用2022-06-06

