www.pudn.com > Bmp2Txt Source Code.rar > JDib.cpp


//***************************************************************************** 
// 
// JDib.cpp 
// 
//============================================================================= 
// 
// Copyright:	 
// 
// Author:      老魏 
// 
// Date:        1999.04.06 
// 
// Description: CJDib 类实现文件 
// 
// Side Effects: 
// 
// Class: 
// 
// Function: 
// 
// Notes: 
// 
// Update: 
// 
// Date     Name     Description 
// 
// ======== =================================================================== 
// Known restrictions: 
// 
// Known bugs: 
// 
//***************************************************************************** 
#include "stdafx.h" 
#include "JDib.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CJDib 
 
//************************************************************** 
// Name:        CJDib() 
// 
// Author:      老魏 
// 
// Date:        1999.04.06 
// 
// Description: 构造函数, 初始化成员变量 
// 
// Arguments:   无 
// 
// Return:      无 
// 
// Side Effects: no 
//                
// Notes:        
// 
// Known restrictions:   
// 
// Err NO. Date     Name         Description 
// 
// Update: 
// Date     Name         Description 
// ======== ============ ============================= 
// 
//**************************************************** 
CJDib::CJDib() 
{ 
    m_bSetPalette = TRUE; 
    m_lpBMFileHeader = NULL; 
    m_lpBMInfoHeader = NULL; 
    m_lpLogPalette = NULL; 
    m_nBytesPerLine = 0; 
    m_pData = NULL; 
    m_pFileBuffer = NULL; 
} 
 
//************************************************************** 
// Name:        ~CJDib() 
// 
// Author:      老魏 
// 
// Date:        1999.04.06 
// 
// Description: 析构函数, 释放不为空的数据和调色盘内存空间 
// 
// Arguments:   无 
// 
// Return:      无 
// 
// Side Effects: no 
//                
// Notes:        
// 
// Known restrictions:   
// 
// Err NO. Date     Name         Description 
// 
// Update: 
// Date     Name         Description 
// ======== ============ ============================= 
// 
//**************************************************** 
CJDib::~CJDib() 
{ 
    if (m_lpLogPalette) 
    { 
        LocalFree(m_lpLogPalette); 
    } 
 
    if (m_pFileBuffer) 
    { 
        LocalFree(m_pFileBuffer); 
    } 
} 
 
//************************************************************** 
// Name:        Read(CString strBMPName) 
// 
// Author:      老魏 
// 
// Date:        1999.04.06 
// 
// Description: 读取 BMP文件数据, 各种指针赋值和计算逻辑调色盘 
//              不支持 JPEG 或 PNG格式 
// 
// Arguments: 
//              CString strBMPName: BMP文件名 
// 
// Return:       
//              TRUE: 成功 
//              FALSE: 失败 
// 
// Side Effects: no 
//                
// Notes:        
// 
// Known restrictions:   
// 
// Err NO. Date     Name         Description 
// 
// Update: 
// Date     Name         Description 
// ======== ============ ============================= 
// 
//**************************************************** 
BOOL CJDib::Read(CString strBMPName) 
{ 
    CFile File; 
    //按只读方式打开文件 
    BOOL bResult = File.Open(strBMPName, CFile::modeRead); 
	if (!bResult) 
	{ 
		CString strErrorMessage; 
		strErrorMessage = "打开文件:" + strBMPName + "失败 !"; 
		AfxMessageBox(strErrorMessage); 
		return FALSE; 
	} 
	 
    //取得文件长度 
    int nFileLength = File.GetLength(); 
	 
    //按文件长度申请空间 
    m_pFileBuffer = (char *)LocalAlloc(LPTR, nFileLength); 
    if (!m_pFileBuffer) 
    { 
		AfxMessageBox("申请必须的内存空间失败 !"); 
        return FALSE; 
    } 
	 
    //读取文件所有数据 
    int nBytesRead = File.Read(m_pFileBuffer, nFileLength); 
    if (nBytesRead != nFileLength) 
    { 
		AfxMessageBox("读取文件内容失败 !"); 
        return FALSE; 
    } 
	 
    //文件头指针赋值 
    m_lpBMFileHeader = (LPBITMAPFILEHEADER)m_pFileBuffer; 
	 
    //判断文件类型 
    if (m_lpBMFileHeader->bfType != 0x4d42) // 'BM' 
    { 
		CString strErrorMessage; 
		strErrorMessage = "文件:" + strBMPName + "不是有效的 BMP文件 !"; 
		AfxMessageBox(strErrorMessage); 
        return FALSE; 
    } 
	 
    //信息头指针赋值 
    m_lpBMInfoHeader = (LPBITMAPINFOHEADER)(m_pFileBuffer + sizeof(BITMAPFILEHEADER)); 
     
    //计算每行占用的字节数 (m_lpBMInfoHeader的biSizeImage成员有时为空不可用) 
    //m_nBytesPerLine = m_lpBMInfoHeader->biSizeImage / m_lpBMInfoHeader->biHeight; 
    m_nBytesPerLine = m_lpBMInfoHeader->biWidth * m_lpBMInfoHeader->biBitCount / 8; 
    if (m_nBytesPerLine % 4 != 0) 
        m_nBytesPerLine = (m_nBytesPerLine / 4 + 1) * 4; 
	 
    //数据指针赋值 
    m_pData = m_pFileBuffer + m_lpBMFileHeader->bfOffBits; 
	 
    //为调色盘申请空间 
    m_lpLogPalette = (LPLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)); 
    m_lpLogPalette->palVersion = 0x300; 
	 
    //判断是否需使用调色盘 
    switch (m_lpBMInfoHeader->biBitCount) 
    { 
    case 0: //JPEG 或 PNG 格式 
        m_bSetPalette = FALSE; 
        break; 
         
    case 1: 
        m_lpLogPalette->palNumEntries = 2; 
        m_bSetPalette = TRUE; 
        break; 
         
    case 4: 
        m_lpLogPalette->palNumEntries = 16; 
        m_bSetPalette = TRUE; 
        break; 
         
    case 8: 
        m_lpLogPalette->palNumEntries = 256; 
        m_bSetPalette = TRUE; 
        break; 
         
    case 16: 
    case 24: 
    case 32: 
        m_bSetPalette = FALSE; 
        break; 
         
    default: 
		AfxMessageBox("文件色彩数不可识别 !"); 
        return FALSE; 
    } 
	 
    //申请临时空间以处理调色盘 
    char *pPalette = m_pFileBuffer + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 
    if (!pPalette) 
	{ 
		AfxMessageBox("申请必须的内存空间失败 !"); 
        return FALSE; 
	} 
	 
    RGBQUAD rgbQuad[256]; 
    //调色盘赋值 
    memcpy(rgbQuad, pPalette, sizeof(PALETTEENTRY) * m_lpLogPalette->palNumEntries); 
    for (int i = 0; i < m_lpLogPalette->palNumEntries; i ++) 
    {                                                
        m_lpLogPalette->palPalEntry[i].peBlue = rgbQuad[i].rgbBlue; 
        m_lpLogPalette->palPalEntry[i].peGreen = rgbQuad[i].rgbGreen; 
        m_lpLogPalette->palPalEntry[i].peRed = rgbQuad[i].rgbRed; 
        m_lpLogPalette->palPalEntry[i].peFlags = rgbQuad[i].rgbReserved; 
    } 
	 
    return TRUE; 
} 
 
//************************************************************** 
// Name:        ConvertToText(CString strBMPName) 
// 
// Author:      老魏 
// 
// Date:        1999.04.06 
// 
// Description: 将给定 BMP文件转换为文本文件, 仅支持 256色格式和真彩格式 
// 
// Arguments: 
//              CString strBMPName: BMP文件名 
// 
// Return: 
//              TRUE: 成功 
//              FALSE: 失败 
// 
// Side Effects: no 
//                
// Notes:        
// 
// Known restrictions:   
// 
// Err NO. Date     Name         Description 
// 
// Update: 
// Date     Name         Description 
// ======== ============ ============================= 
// 
//**************************************************** 
BOOL CJDib::ConvertToText(CString strBMPName) 
{ 
    //字符调色盘 
	//后面将会根据像素的不同 
	//灰度选择相应的字符 
    BYTE CharPalette[16]; 
    CharPalette[0] = '#'; 
    CharPalette[1] = 'M'; 
    CharPalette[2] = '@'; 
    CharPalette[3] = 'H'; 
    CharPalette[4] = 'X'; 
    CharPalette[5] = '$'; 
    CharPalette[6] = '%'; 
    CharPalette[7] = '+'; 
    CharPalette[8] = '/'; 
    CharPalette[9] = ';'; 
    CharPalette[10] = ':'; 
    CharPalette[11] = '='; 
    CharPalette[12] = '-'; 
    CharPalette[13] = ','; 
    CharPalette[14] = '.'; 
    CharPalette[15] = ' '; 
     
    CString strTxtName = strBMPName; 
    //计算文本文件名 
    strTxtName = strTxtName.Left(strTxtName.Find('.')); 
    strTxtName += ".txt"; 
	 
    CStdioFile TxtFile; 
    //创建文本文件 
    if (!TxtFile.Open(strTxtName, CFile::modeCreate | CFile::modeWrite | CFile::typeText)) 
    { 
		CString strErrorMessage; 
		strErrorMessage = "创建文本文件:" + strTxtName + "失败 !"; 
		AfxMessageBox(strErrorMessage); 
        return FALSE; 
    } 
	 
    //读取 BMP文件数据 
    if (!Read(strBMPName)) 
    { 
        return FALSE; 
    } 
	 
    TxtFile.WriteString("Generated by 老魏!\n"); 
	 
    //取得 BMP数据指针 
    BYTE *pData = (BYTE *)m_pData; 
    BYTE *pLine = pData; 
	 
    for (int i = m_lpBMInfoHeader->biHeight - 1; i >= 0; i--) 
    { 
        //计算每行的数据指针 
        pLine = pData + i * m_nBytesPerLine; 
        CString strLineText; 
        for (int j = 0; j < m_lpBMInfoHeader->biWidth; j++) 
        { 
            int nRed, nGreen, nBlue, nValue; 
			 
            //计算当前象素的 RGB三分量的值 
            switch (m_lpBMInfoHeader->biBitCount) 
            { 
            case 24: 
                nRed = *pLine++; 
                nGreen = *pLine++; 
                nBlue = *pLine++; 
                break; 
				 
            case 8: 
                nRed = m_lpLogPalette->palPalEntry[*pLine].peRed; 
                nGreen = m_lpLogPalette->palPalEntry[*pLine].peGreen; 
                nBlue = m_lpLogPalette->palPalEntry[*pLine].peBlue; 
                pLine++; 
                break; 
				 
            default: 
				AfxMessageBox("抱歉, 当前版本仅支持 8bit和24bit文件 !"); 
                return FALSE; 
            } 
			 
            //计算灰度值 
            nValue = (nRed * 30 + nGreen * 59 + nBlue * 11) / 100; 
			 
            //转换到文本 
            strLineText += CharPalette[nValue / 16]; 
        } 
		 
        //写入文本文件 
        TxtFile.WriteString(strLineText); 
        TxtFile.WriteString("\n"); 
    } 
	 
    TxtFile.Close(); 
	 
    return TRUE; 
}