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

以下是C++中将cv::Mat转换base64编码的示例代码: ```c++ #include <opencv2/opencv.hpp> #include <iostream> #include <fstream> #include <sstream> #include <string> #include <cstring> #include <openssl/bio.h> #include <openssl/evp.h> #include <openssl/buffer.h> using namespace std; using namespace cv; string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { BIO *bio, *b64; BUF_MEM *bptr = BUF_MEM_new(); b64 = BIO_new(BIO_f_base64()); bio = BIO_new(BIO_s_mem()); bio = BIO_push(b64, bio); BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); BIO_write(bio, bytes_to_encode, in_len); BIO_flush(bio); BIO_get_mem_ptr(bio, &bptr); string encoded_string(bptr->data, bptr->length); BIO_free_all(bio); BUF_MEM_free(bptr); return encoded_string; } int main() { Mat image = imread("test.jpg"); if (image.empty()) { cerr << "Failed to load image" << endl; return -1; } vector<uchar> buffer; imencode(".jpg", image, buffer); string base64_image = base64_encode(buffer.data(), buffer.size()); cout << "Base64 encoded image: " << base64_image << endl; return 0; } ``` 在这个示例中,我们首先加载图像,然后将其压缩为JPEG格式,并将压缩的字节转换base64编码的字符串。我们使用OpenSSL库中的函数来执行实际的base64编码。 请注意,此示例使用C++11,并且需要OpenSSL库。在Ubuntu系统中,您可以通过以下命令安装OpenSSL: ```bash sudo apt-get install libssl-dev ``` 此外,您需要在编译时链接OpenSSL库。在Ubuntu系统中,您可以使用以下命令来编译代码: ```bash g++ -o main main.cpp -lopencv_core -lopencv_imgcodecs -lssl -lcrypto ``` 请注意,我们还需要链接OpenCV库(`opencv_core`和`opencv_imgcodecs`),这些库是用于图像处理的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值