cv::Mat与Base64转换(含图片压缩解压等流程)

测试流程就是:图片->压缩图片->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++;
				i++;
			}
		}
		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

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2022年5月27日 下午4:46
下一篇 2022年5月28日 下午3:13

相关推荐