测试流程就是:图片->压缩图片->base64->解压图片->图片
(注意压缩会失真的,可以不压缩,但是base64会比较大)
main.cpp
#include "stdafx.h"
#include <Windows.h>
#include "base64.h"
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
#include <cstdio>
using namespace std;
using namespace cv;
#define MAX_SIZE_BASE64 100000
int main()
long t1 = GetTickCount();
string source_data, source_data_encode;
Mat srcImage, grayImage,dstImage;
//读取图片1
srcImage = imread("image.jpg");
dstImage = srcImage.clone();
imshow("【原图】", srcImage);
//MAT转base64
int quality = 50; //压缩比率0~100
vector<int> compress_params;
compress_params.push_back(IMWRITE_JPEG_QUALITY);
compress_params.push_back(quality);
std::vector<unsigned char> buf(MAX_SIZE_BASE64, 0); //vector要分配内存,否则imencode会崩
cv::imencode(".jpg", dstImage, buf, compress_params);
source_data.insert(source_data.begin(), buf.begin(), buf.end());
Base64::Encode(source_data, &source_data_encode);
printf("len: %d \n", source_data_encode.length());
//base64写入文件
FILE * fp = NULL;
fp = fopen( "data.txt", "a+" );
if ( fp == NULL )
return -1;
int res=fprintf( fp, "%s\n" ,source_data_encode.c_str());
fclose(fp);
//base64转MAT
Base64::Decode(source_data_encode, &source_data);
std::vector<unsigned char> buf2(source_data.begin(), source_data.end());
dstImage = cv::imdecode(cv::Mat(buf2), CV_LOAD_IMAGE_COLOR);
long t2 = GetTickCount();
printf("time: %d \n", t2-t1);
//原图1
imshow("【转Base64再转MAT】", dstImage);
waitKey(0);
vector<uchar>().swap(buf); //释放vector内存
vector<uchar>().swap(buf2); //释放vector内存
return 0;
}
base64.h
#pragma once
/*****base64.h*****/
#ifndef BASE64_H
#define BASE64_H
#include <string>
#include <opencv2/opencv.hpp>
const char kBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
class Base64 {
public:
static bool Encode(const std::string &in, std::string *out) {
int i = 0, j = 0;
size_t enc_len = 0;
unsigned char a3[3];
unsigned char a4[4];
out->resize(EncodedLength(in));
int input_len = in.size();
std::string::const_iterator input = in.begin();
while (input_len--) {
a3[i++] = *(input++);
if (i == 3) {
a3_to_a4(a4, a3);
for (i = 0; i < 4; i++) {
(*out)[enc_len++] = kBase64Alphabet[a4[i]];
i = 0;
if (i) {
for (j = i; j < 3; j++) {
a3[j] = '\0';
a3_to_a4(a4, a3);
for (j = 0; j < i + 1; j++) {
(*out)[enc_len++] = kBase64Alphabet[a4[j]];
while ((i++ < 3)) {
(*out)[enc_len++] = '=';
return (enc_len == out->size());
static bool Encode(const char *input, size_t input_length, char *out, size_t out_length) {
int i = 0, j = 0;
char *out_begin = out;
unsigned char a3[3];
unsigned char a4[4];
size_t encoded_length = EncodedLength(input_length);
if (out_length < encoded_length) return false;
while (input_length--) {
a3[i++] = *input++;
if (i == 3) {
a3_to_a4(a4, a3);
for (i = 0; i < 4; i++) {
*out++ = kBase64Alphabet[a4[i]];
i = 0;
if (i) {
for (j = i; j < 3; j++) {
a3[j] = '\0';
a3_to_a4(a4, a3);
for (j = 0; j < i + 1; j++) {
*out++ = kBase64Alphabet[a4[j]];
while ((i++ < 3)) {
*out++ = '=';
return (out == (out_begin + encoded_length));
static bool Decode(const std::string &in, std::string *out) {
int i = 0, j = 0;
size_t dec_len = 0;
unsigned char a3[3];
unsigned char a4[4];
int input_len = in.size();
std::string::const_iterator input = in.begin();
out->resize(DecodedLength(in));
while (input_len--) {
if (*input == '=') {
break;
a4[i++] = *(input++);
if (i == 4) {
for (i = 0; i < 4; i++) {
a4[i] = b64_lookup(a4[i]);
a4_to_a3(a3, a4);
for (i = 0; i < 3; i++) {
(*out)[dec_len++] = a3[i];
i = 0;
if (i) {
for (j = i; j < 4; j++) {
a4[j] = '\0';
for (j = 0; j < 4; j++) {
a4[j] = b64_lookup(a4[j]);
a4_to_a3(a3, a4);
for (j = 0; j < i - 1; j++) {
(*out)[dec_len++] = a3[j];
return (dec_len == out->size());
static bool Decode(const char *input, size_t input_length, char *out, size_t out_length) {
int i = 0, j = 0;
char *out_begin = out;
unsigned char a3[3];
unsigned char a4[4];
size_t decoded_length = DecodedLength(input, input_length);
if (out_length < decoded_length) return false;
while (input_length--) {
if (*input == '=') {
break;
a4[i++] = *(input++);
if (i == 4) {
for (i = 0; i < 4; i++) {
a4[i] = b64_lookup(a4[i]);
a4_to_a3(a3, a4);
for (i = 0; i < 3; i++) {
*out++ = a3[i];
i = 0;
if (i) {
for (j = i; j < 4; j++) {
a4[j] = '\0';
for (j = 0; j < 4; j++) {
a4[j] = b64_lookup(a4[j]);
a4_to_a3(a3, a4);
for (j = 0; j < i - 1; j++) {
*out++ = a3[j];
return (out == (out_begin + decoded_length));
static int DecodedLength(const char *in, size_t in_length) {
int numEq = 0;
const char *in_end = in + in_length;
while (*--in_end == '=') ++numEq;
return ((6 * in_length) / 8) - numEq;
static int DecodedLength(const std::string &in) {
int numEq = 0;
int n = in.size();
for (std::string::const_reverse_iterator it = in.rbegin(); *it == '='; ++it) {
++numEq;
return ((6 * n) / 8) - numEq;
inline static int EncodedLength(size_t length) {
return (length + 2 - ((length + 2) % 3)) / 3 * 4;
inline static int EncodedLength(const std::string &in) {
return EncodedLength(in.length());
inline static void StripPadding(std::string *in) {
while (!in->empty() && *(in->rbegin()) == '=') in->resize(in->size() - 1);
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++;
return strDecode;
static std::string base64Encode(const unsigned char* Data, int DataByte) {
//编码表
const char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//返回值
std::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;
//imgType 包括png bmp jpg jpeg等opencv能够进行编码解码的文件
static std::string Mat2Base64(const cv::Mat &img, std::string imgType) {
//Mat转base64
std::string img_data;
std::vector<uchar> vecImg;
std::vector<int> vecCompression_params;
vecCompression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
vecCompression_params.push_back(90);
imgType = "." + imgType;
cv::imencode(imgType, img, vecImg, vecCompression_params);
img_data = base64Encode(vecImg.data(), vecImg.size());
return img_data;
static cv::Mat Base2Mat(std::string &base64_data) {
cv::Mat img;
std::string s_mat;
s_mat = base64Decode(base64_data.data(), base64_data.size());
std::vector<char> base64_img(s_mat.begin(), s_mat.end());
img = cv::imdecode(base64_img, CV_LOAD_IMAGE_COLOR);
return img;
private:
static inline void a3_to_a4(unsigned char * a4, unsigned char * a3) {
a4[0] = (a3[0] & 0xfc) >> 2;
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
a4[3] = (a3[2] & 0x3f);
static inline void a4_to_a3(unsigned char * a3, unsigned char * a4) {
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
static inline unsigned char b64_lookup(unsigned char c) {
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 71;
if (c >= '0' && c <= '9') return c + 4;
if (c == '+') return 62;
if (c == '/') return 63;
return 255;
#endif // BASE64_H