C++ 实现图片base64编解码

10 篇文章 0 订阅

最近使用人脸识别restfulAPI遇到了要求图片base64编码后传输问题。
借此机会了解下什么是base64编码。

部分内容参考自阮一峰blog:
http://www.ruanyifeng.com/blog/2008/06/base64.html

1 什么是base64编码

所谓Base64,就是说选出64个字符----小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是65个字符)----作为一个基本字符集。然后,其他所有符号都转换成这个字符集中的字符。

2 解决的问题

网络传送渠道(纯文本协议)并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就不能通过邮件传送。
http针对二进制数据做了特殊规定是可以支持传输二进制数据的,但如果在json内部传输二进制数据就会遇到这种问题,我们可以先进行base64编码转成字符串进行处理。

3 主要用途

证书 电子邮件数据,经常要用到Base64编码。

4 如何编码

第一步,将每三个字节作为一组,一共是24个二进制位。
第二步,将这24个二进制位分为四组,每个组有6个二进制位。
第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。
第四部, 每个字节的对应符号即为base64编码后的值。
Base64编码后的文本,会比原文本大出三分之一左右。

5 代码实现

nodejs实现:

var base64str1 = new Buffer(bitmap).toString('base64');

C++实现:

以下代码来自百度云SDK中base64编码部分。简单好用。

Bash64.h:
#ifndef __BASE64_H__
#define __BASE64_H__

#include <iostream>
#include <string>

static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

static inline bool is_base64(const char c)
{
    return (isalnum(c) || (c == '+') || (c == '/'));
}

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;
}

std::string base64_decode(std::string const & encoded_string)
{
    int in_len = (int) encoded_string.size();
    int i = 0;
    int j = 0;
    int in_ = 0;
    unsigned char char_array_4[4], char_array_3[3];
    std::string ret;
    
    while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
        char_array_4[i++] = encoded_string[in_]; in_++;
        if (i ==4) {
            for (i = 0; i <4; i++)
                char_array_4[i] = base64_chars.find(char_array_4[i]);
            
            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
            
            for (i = 0; (i < 3); i++)
                ret += char_array_3[i];
            i = 0;
        }
    }
    if (i) {
        for (j = i; j <4; j++)
            char_array_4[j] = 0;
        
        for (j = 0; j <4; j++)
            char_array_4[j] = base64_chars.find(char_array_4[j]);
        
        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);  
        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];  
        
        for (j = 0; (j < i - 1); j++) ret += char_array_3[j];  
    }  
    
    return ret;  
}
#endif
Test_main.cpp:
#include <string>
#include <iostream>
#include "base64.h"
#include <fstream>
#include <stdlib.h>

using namespace std;

int main(int argc, char** argv){
    fstream f, f2;
    f.open("test.jpg", ios::in|ios::binary);
    f.seekg(0, std::ios_base::end);
    std::streampos sp = f.tellg();
    int size = sp;
    cout << size << endl;
    char* buffer = (char*)malloc(sizeof(char)*size);
    f.seekg(0, std::ios_base::beg);//把文件指针移到到文件头位置
    f.read(buffer,size);
    cout << "file size:" << size << endl;     
    string imgBase64 = base64_encode(buffer, size);
    cout << "img base64 encode size:" << imgBase64.size() << endl;  
    string imgdecode64 = base64_decode(imgBase64);
    cout << "img decode size:" << imgdecode64.size() << endl;     
    f2.open("out.jpg", ios::out|ios::binary);
    f2 << imgdecode64;
    f2.close();
    return 0;
}
编译:
g++  -D_LINUX   -I. -std=c++11  ./test_main.cpp -o sample_X86_64
输出:
file size:23615
img base64 encode size:31488
img decode size:23615

源码

链接: https://pan.baidu.com/s/1MLJVytHqqIzurR31Y0dytw 提取码: i9h3
百度盘中的代码中test_main.cpp 请替换为文中代码。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值