博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BASE64编码和解码(VC源代码) 并 内存加载 CImage 图像
阅读量:7071 次
发布时间:2019-06-28

本文共 9006 字,大约阅读时间需要 30 分钟。

 
BASE64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。完整的BASE64定义可见 RFC1421和 RFC2045。编码后的数据比原始数据略长,为原来的4/3。在电子邮件中,根据RFC822规定,每76个字符,还需要加上一个回车换行。

    转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的Bit用0补足。然后,每次取出6个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。如果最后剩下两个输入数据,在编码结果后加1个“=”;如果最后剩下一个输入数据,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

 

BASE64_API.h  文件内容

/* ----------------------------------------------------------文件名称:BASE64_API.h作者:秦建辉MSN:splashcn@msn.com当前版本:V1.1历史版本:    V1.1    2010年05月11日            修正BASE64解码的Bug。    V1.0    2010年05月07日            完成正式版本。功能描述:    BASE64编码和解码接口函数:    Base64_Encode    Base64_Decode说明:    1.    参考openssl-1.0.0。    2.    改进接口,以使其适应TCHAR字符串。    3.    修正EVP_DecodeBlock函数解码时未去掉填充字节的缺陷。 ------------------------------------------------------------ */#pragma once

#include "stdafx.h"

#include 
#ifdef __cplusplusextern "C" {#endif/*功能:将二进制数据转换成BASE64编码字符串参数说明: inputBuffer:要编码的二进制数据 inputCount:数据长度 outputBuffer:存储转换后的BASE64编码字符串返回值: -1:参数错误 >=0:有效编码长度(字符数),不包括字符串结束符。备注: 等效于openssl中EVP_EncodeBlock函数*/INT BASE64_Encode( const BYTE* inputBuffer, INT inputCount, TCHAR* outputBuffer );/*功能:将BASE64编码字符串转换为二进制数据参数说明: inputBuffer:BASE64编码字符串 inputCount:编码长度(字符数),应该为4的倍数。 outputBuffer:存储转换后的二进制数据返回值: -1:参数错误 -2:数据错误 >=0:转换后的字节数备注: 等效于openssl中EVP_DecodeBlock函数*/INT BASE64_Decode( const TCHAR* inputBuffer, INT inputCount, BYTE* outputBuffer );#ifdef __cplusplus}#endif

 

 

BASE64_API.cpp 文件内容

 

#pragma once

#include "stdafx.h"

#include "BASE64_API.h"static const CHAR* DATA_BIN2ASCII = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";INT BASE64_Encode( const BYTE* inputBuffer, INT inputCount, TCHAR* outputBuffer ){    INT i;    BYTE b0, b1, b2;    if( (inputBuffer == NULL) || (inputCount < 0) )    {        return -1;    // 参数错误    }    if( outputBuffer != NULL )    {        for( i = inputCount; i > 0; i -= 3 )        {            if( i >= 3 )            {    // 将3字节数据转换成4个ASCII字符                b0 = *inputBuffer++;                b1 = *inputBuffer++;                b2 = *inputBuffer++;                *outputBuffer++ = DATA_BIN2ASCII[b0 >> 2];                *outputBuffer++ = DATA_BIN2ASCII[((b0 << 4) | (b1 >> 4)) & 0x3F];                *outputBuffer++ = DATA_BIN2ASCII[((b1 << 2) | (b2 >> 6)) & 0x3F];                *outputBuffer++ = DATA_BIN2ASCII[b2 & 0x3F];            }            else            {                b0 = *inputBuffer++;                if( i == 2 )b1 = *inputBuffer++; else b1 = 0;                *outputBuffer++ = DATA_BIN2ASCII[b0 >> 2];                *outputBuffer++ = DATA_BIN2ASCII[((b0 << 4) | (b1 >> 4)) & 0x3F];                *outputBuffer++ = (i == 1) ? TEXT('=') : DATA_BIN2ASCII[(b1 << 2) & 0x3F];                *outputBuffer++ = TEXT('=');            }        } // End for i        *outputBuffer++ = TEXT('/0');    // 添加字符串结束标记    }    return ((inputCount + 2) / 3) * 4;    // 返回有效字符个数}#define B64_EOLN            0xF0    // 换行/n#define B64_CR                0xF1    // 回车/r#define B64_EOF                0xF2    // 连字符-#define B64_WS                0xE0    // 跳格或者空格(/t、space)#define B64_ERROR     0xFF    // 错误字符#define B64_NOT_BASE64(a)    (((a)|0x13) == 0xF3)static const BYTE DATA_ASCII2BIN[128] = {    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0xF0,0xFF,0xFF,0xF1,0xFF,0xFF,    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,    0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F,    0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,    0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,    0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,    0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,    0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF};INT BASE64_Decode( const TCHAR* inputBuffer, INT inputCount, BYTE* outputBuffer ){    INT i, j;    BYTE b[4];    TCHAR ch;    if( (inputBuffer == NULL) || (inputCount < 0) )    {        return -1;    // 参数错误    }    // 去除头部空白字符    while( inputCount > 0 )    {        ch = *inputBuffer;        if( (ch < 0) || (ch >= 0x80) )        {            return -2;    // 数据错误,不在ASCII字符编码范围内        }        else        {            if( DATA_ASCII2BIN[ch] == B64_WS )            {                inputBuffer++;                inputCount--;            }            else            {                break;            }        }    }    // 去除尾部的空白字符、回车换行字符、连字符    while( inputCount >= 4 )    {        ch = inputBuffer[inputCount - 1];        if( (ch < 0) || (ch >= 0x80) )        {            return -2;    // 数据错误,不在ASCII字符编码范围内        }        else        {            if( B64_NOT_BASE64(DATA_ASCII2BIN[ch]) )            {                inputCount--;            }            else            {                break;            }        }    }    // 字符串长度必须为4的倍数    if( (inputCount % 4) != 0 )    {        return -2;    // 数据错误    }    if( outputBuffer != NULL )    {        for( i = 0; i < inputCount; i += 4 )        {            for( j = 0; j < 4; j++ )            {                ch = *inputBuffer++;                if( (ch < 0) || (ch >= 0x80) )                {                    return -2;    // 数据错误,不在ASCII字符编码范围内                }                else                {                    if( ch == '=' )    // 发现BASE64编码中的填充字符                    {                        break;                    }                    else                    {                        b[j] = DATA_ASCII2BIN[ch];                        if( b[j] & 0x80 )                        {                            return -2;    // 数据错误,无效的Base64编码字符                        }                    }                                    }            } // End for j            if( j == 4 )            {                *outputBuffer++ = (b[0] << 2) | (b[1] >> 4);                *outputBuffer++ = (b[1] << 4) | (b[2] >> 2 );                *outputBuffer++ = (b[2] << 6) | b[3];            }            else if( j == 3 )            {    // 有1个填充字节                *outputBuffer++ = (b[0] << 2) | (b[1] >> 4);                *outputBuffer++ = (b[1] << 4) | (b[2] >> 2 );                return (i >> 2) * 3 + 2;            }            else if( j == 2 )            {    // 有2个填充字节                *outputBuffer++ = (b[0] << 2) | (b[1] >> 4);                return (i >> 2) * 3 + 1;            }            else            {                return -2;    // 数据错误,无效的Base64编码字符            }                    }    // End for i    }    return (inputCount >> 2) * 3;}

采用以上方法就可以将二进制数据转换成可见字符进行传递就可以了.

那么如何使用呢?举以下两个例子

第一个:将一个图片转换成 txt 文本 并保存起来

//选择一个图像文件,将它转为 文本保存至  _T("D:\\2.txt"void CTextPicDlg::OnBnClickedButton2(){    // TODO:  在此添加控件通知处理程序代码    CFileDialog file(TRUE,".jpg","");    if (file.DoModal() == IDOK)    {        CFile data(file.GetPathName(), CFile::modeReadWrite);        int len = data.GetLength();        BYTE *dv;        dv = (BYTE *)malloc(len*sizeof(BYTE));        data.Read(dv, len);        data.Close();        int slen = (len / 3) * 4;        slen += 10;        TCHAR * tc;        tc = (TCHAR *)malloc(slen);        slen = BASE64_Encode(dv, len, tc);        CFile save(_T("D:\\2.txt"), CFile::modeCreate | CFile::modeWrite);        save.Write(tc, slen);        save.Close();        free(tc);        free(dv);            }}

 

第二个例子,将一个文本文件还原为一个图像

void CTextPicDlg::OnBnClickedButton3(){    // TODO:  在此添加控件通知处理程序代码    CFileDialog file(TRUE, ".txt", "");    if (file.DoModal() == IDOK)    {        CFile data(file.GetPathName(), CFile::modeReadWrite);        int len = data.GetLength();        TCHAR *dv;        dv = (TCHAR *)malloc(len*sizeof(TCHAR));        data.Read(dv, len);        data.Close();        int slen = (len / 4) * 3;        slen += 10;        BYTE * tc;        tc = (BYTE *)malloc(slen);        BASE64_Decode(dv, len, tc);
 
 
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, slen);        void *  pData = GlobalLock(hGlobal);        memcpy(pData, tc, slen);  //  拷贝位图数据进去        GlobalUnlock(hGlobal);        //  创建IStream        IStream *  pStream = NULL;        if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) != S_OK)            return ;        //   使用CImage加载位图内存        CImage img;        if (SUCCEEDED(img.Load(pStream)) )        {            CClientDC dc(this);                           img.Draw(dc.m_hDC, 0, 0, 500, 300);                    }                 pStream->Release();        GlobalFree(hGlobal);                //CFileDialog savefile(FALSE, ".jpg", "");        //if (savefile.DoModal()==IDOK)        //{        //    CFile save(savefile.GetPathName(), CFile::modeCreate | CFile::modeWrite);        //    save.Write(tc, slen);        //    save.Close();        //}        free(tc);        free(dv);    }}

至此,利用Base64转码的方式,来显示保存显示图片的方法,就算是成功了!

转载于:https://www.cnblogs.com/lujin49/p/4957742.html

你可能感兴趣的文章
【Java集合源代码剖析】TreeMap源代码剖析
查看>>
【算法】 算法和数据结构绪论
查看>>
LeetCode OJ 之 Ugly Number II (丑数-二)
查看>>
(一)Thymeleaf用法——Thymeleaf简介
查看>>
【Python】 命名空间与LEGB规则
查看>>
巴斯卡三角形
查看>>
产品和团队
查看>>
mysql取差集、交集、并集
查看>>
Tex: The top-level auxiliary file: *.aux I couldn't open style file IEEEtran.bst 解决方法
查看>>
HDU 3080 The plan of city rebuild(prim和kruskal)
查看>>
三层架构—简析
查看>>
利用linux shell自己主动顶贴
查看>>
[转]MVC Razor模板引擎 @RenderBody、@RenderPage、@RenderSection及Html.RenderPartial、Html.RenderAction...
查看>>
bzoj 1860: [Zjoi2006]Mahjong麻将 题解
查看>>
第21章 RTX 低功耗之睡眠模式
查看>>
拉格朗日插值
查看>>
递归函数的写法笔记
查看>>
net 自定义泛型那点事
查看>>
免费「模拟面试」福利反馈连载(20180128期)
查看>>
Redis的并发竞争问题的解决方案总结
查看>>