前段时间无所事事,看了几天的数学,提不起兴趣来,忽然在网上看到了一个软件,能把图像转换成文本的字符画,兴趣大增,做了一个。
此程序只能处理真彩色的bmp格式文件,如果没有bmp格式的图片可以使用windows自带的画图工具转换一下。
Image.h
#pragma once
#include "resource.h"
class CBitMapFile
{
protected:
//位图文件信息头
BITMAPFILEHEADER m_file_header;
//位图信息头
BITMAPINFOHEADER m_info_header;
CFile m_hFile;
//存储位图数据
BYTE* m_imageArray;
//去掉填充的无用字节,存储剩下的纯数据
BYTE* m_realImageArray;
public:
//整个文件大小
DWORD m_sizeFile;
//位图数据的大小
DWORD m_sizeImage;
//文件头所占字节数
DWORD m_offBits;
//图像的宽,即行
LONG m_width;
//图像的高,即列
LONG m_height;
//一个像素有多少比特表示
WORD m_bitCount;
//每个像素的所占字节数
int m_bytePixel;
//文件的填充字节
int m_addByte;
//文件名
CString m_fileName;
public:
CBitMapFile():m_imageArray(NULL),m_realImageArray(NULL),m_sizeFile(0),m_sizeImage(0),
m_offBits(0),m_width(0),m_height(0),m_bitCount(0),m_bytePixel(0),m_addByte(0)
,m_fileName(""){}
~CBitMapFile()
{
delete m_realImageArray;
delete m_imageArray;
}
int openfile(CString& str,int fileMode);
int turn2Gray();
int turn2Txt(CString txt_name);
};
Image.cpp
#include "stdafx.h"
#include "Image.h"
/**********************************
*打开bmp格式文件,并初始化数据成员*
**********************************/
int CBitMapFile::openfile(CString& str,int fileMode)
{
if(!m_hFile.Open(str,fileMode))
{
return -1;
}
m_fileName = m_hFile.GetFileName();
m_hFile.Read(&m_file_header,sizeof(BITMAPFILEHEADER));
m_sizeFile = m_file_header.bfSize;
m_offBits = m_file_header.bfOffBits;
m_hFile.Read(&m_info_header,sizeof(BITMAPINFOHEADER));
m_width = m_info_header.biWidth;
m_height = m_info_header.biHeight;
m_bitCount = m_info_header.biBitCount;
m_bytePixel = m_bitCount>>3;
m_sizeImage =((((m_width * m_bitCount) + 31) & ~31) / 8) * m_height;
m_addByte = (4-(m_width*m_bytePixel)%4)%4;
m_imageArray = new BYTE[m_sizeImage];
memset(m_imageArray,0,m_sizeImage);
m_hFile.Read(m_imageArray,m_sizeImage*sizeof(BYTE));
m_realImageArray = new BYTE[m_width*m_height];
memset(m_realImageArray,0,m_width*m_height);
return 1;
}
/********************************************
*将文件转换成灰度图像,再对图像做归一化处理*
********************************************/
int CBitMapFile::turn2Gray()
{
if (m_imageArray == NULL)
{
return -2;
}
for (int i =0,j= 0;i<m_sizeImage;)
{
//转换为灰度图像,注意填充的字节
BYTE blue,green,red,gray;
blue = m_imageArray[i];
green = m_imageArray[i+1];
red = m_imageArray[i+2];
gray = (BYTE)(0.3*red+0.59*green+0.11*blue);
m_imageArray[i] = gray;
m_imageArray[i+1] = gray;
m_imageArray[i+2] = gray;
m_realImageArray[j] = m_imageArray[i]>>5;
i += 3;
j++;
跳过填充字节
if (j % m_width == 0)
{
i += m_addByte;
}
}
return 1;
}
/******************************************
*对图像的每个像素做文本映射,最终写入文件*
******************************************/
int CBitMapFile::turn2Txt(CString txt_name)
{
char* _txtBuf = new char[m_width*m_height+2*m_height];
memset(_txtBuf,0,m_width*m_height+2*m_height);
//文本映射
char txtMap[8] = {'@','$','#','%','!','~','^','`'};
char* _buf = new char[m_width+2];
memset(_buf,0,m_width+2);
TRACE(_T("\'\\r\'=%x,\'\\n\'=%x"),'\r','\n');
for (int i = m_height-1;i>=0;i--)
{
for (int j = 0;j<m_width;j++)
{
_buf[j] = txtMap[m_realImageArray[i*m_width+j]];
}
_buf[m_width] = '\r';
_buf[m_width+1] = '\n';
for (int k=0;k<m_width+2;k++)
{
_txtBuf[(m_height-1-i)*m_width+k+(m_height-1-i)*2] = _buf[k];
}
}
CFile txtFile;
if (txtFile.Open(txt_name,CFile::modeCreate|CFile::modeNoInherit|CFile::modeWrite)==FALSE)
{
return -1;
}
txtFile.Write(_txtBuf,sizeof(char)*(m_width*m_height+2*m_height));
txtFile.Close();
delete _txtBuf;
delete _buf;
return 1;
}
main.cpp
// Image.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Image.h"
#include <iostream>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
if (argc<3)
{
std::cout<<"you should input like this:Image.exe (c:\\sourceFile.bmp) (c:\\goalFile.txt)\n"<<std::endl;
return -1;
}
CBitMapFile bitFile;
CString arg1 = argv[1];
CString str = argv[2];
if (bitFile.openfile(arg1,CFile::modeRead) != 1)
{
std::cout<<"ERROR:sourceFile.bmp open failed."<<std::endl;
return -1;
}
if(bitFile.turn2Gray() != 1)
{
std::cout<<"ERROR:turn2Gray function failed."<<std::endl;
return -1;
}
if (bitFile.turn2Txt(str) != 1)
{
std::cout<<"ERROR:turn2Txt function failed."<<std::endl;
return -1;
}
}
return nRetCode;
}