// 24bit28bit.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "24bit28bit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// The one and only application object
CWinApp theApp;
using namespace std;
#include<stdio.h>
#include <afx.h>
#include <windows.h>
BYTE* ConvertTo8Bit(CString strFileName, DWORD *dwFileLength, BYTE *lpNewBmpData) ;
BOOL SaveFile(CString strFileName, DWORD dwFileLength);
BITMAPINFO* lpNewBmpInfo = NULL; //新8位位图信息头首指针
BYTE *lpOldBmp = NULL; //指向原来24位位图信息头
BYTE*lpNewBmpData = NULL; //指向新的8位位图的信息头指针
void main()
{
char strOpenFileName[200], strSaveFileName[200];
printf("请输入一幅24位位图的路径!/n");
gets( strOpenFileName );
printf("请输入你要保存转换后的8位位图的路径!/n");
gets( strSaveFileName );
DWORD dwFileLength;
lpNewBmpInfo = (BITMAPINFO*)ConvertTo8Bit( strOpenFileName, &dwFileLength, lpNewBmpData);
if( !lpNewBmpInfo )
{
printf( "转换出错,程序退出!/n");
return ;
}
if( !SaveFile( strSaveFileName, dwFileLength) )
{
printf( "保存文件出错!" );
return ;
}
if( lpNewBmpData != NULL)
delete []lpNewBmpData;
if( lpNewBmpInfo != NULL )
delete []lpNewBmpInfo;
if( lpOldBmp != NULL )
delete []lpOldBmp;
}
/*************************************************************************
* 功能: 将24位位图转换为8位位图
* 参数: strFileName: (in)24位位图文件所在路径
lpNewBmpData: (out)做为8位位图的实际数据的指针
*dwFileLength: (out)为原24位位图图像文件长度(从文件信息头开始,不含文件头的14个字节)
* 返回: 8位位图的信息头指针
************************************************************************/
BYTE* ConvertTo8Bit(CString strFileName, DWORD *dwFileLength, BYTE *lpNewBmpData)
{
if( lpNewBmpData != NULL )
{
delete []lpNewBmpData;
lpNewBmpData = NULL;
}
//创建文件句柄
HANDLE hFile = ::CreateFile(strFileName,GENERIC_READ,FILE_SHARE_READ,
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile == 0)
{
printf("不能打开文件,请重新选择!/n");
return NULL;
}
//读取图像文件
DWORD dwWriteNum;
BITMAPFILEHEADER Bmp_file_head; //文件头
ReadFile(hFile,&Bmp_file_head,14,&dwWriteNum,NULL);//读取文件头,共14个字节
if((Bmp_file_head.bfType != 'MB')||(dwWriteNum != sizeof(BITMAPFILEHEADER)))
{
printf("不是BMP位图文件或数据有误!/n");
return NULL;
}
*dwFileLength = GetFileSize(hFile,NULL)-sizeof(BITMAPFILEHEADER); //获取文件的长度
lpOldBmp= new BYTE[ *dwFileLength]; //存放原24位位图像,包括图像的信息头、调色板和像素数据
ReadFile(hFile,lpOldBmp,*dwFileLength,&dwWriteNum,NULL); //读取图像数据
BYTE*lpOldBmpData = lpOldBmp + sizeof(BITMAPINFOHEADER) ; //指向图像数据的实际位置,其调色板为0
BITMAPINFO*lpOldBmpInfo = (BITMAPINFO*)lpOldBmp;
if( lpOldBmpInfo->bmiHeader.biBitCount != 24)
{
printf( "此图像非24位位图!");
return NULL;
}
int nScanWidth; //转换后其每行扫描宽度
int nLineWidth; //将其转换成8位位图后每行宽度(即每行字节数)
int nSrcWidth,nSrcHeight;
nSrcHeight=lpOldBmpInfo->bmiHeader.biHeight; //原24位位图高度
nSrcWidth=lpOldBmpInfo->bmiHeader.biWidth; //原24位位图宽度
nLineWidth = nSrcWidth*3/4*4;
if(nLineWidth<nSrcWidth*3)
nLineWidth=nLineWidth+4; //保证以DWORD对齐(为4的整数倍)
nScanWidth=nSrcWidth/4*4;
if(nScanWidth<nSrcWidth)
nScanWidth=nScanWidth+4; //保证以DWORD对齐(为4的整数倍)
//申请位图的空间
// int nDataLen = nScanWidth*nSrcHeight+2;
// lpNewBmpInfo=(BITMAPINFO*)new BYTE[*dwFileLength];
// lpNewBmpData=new BYTE[nDataLen];
*dwFileLength = sizeof(BITMAPINFOHEADER) + 256* sizeof(RGBQUAD) + nScanWidth*nSrcHeight+2; //Save 的时候要使用
lpNewBmpInfo=(BITMAPINFO *)new BYTE[*dwFileLength];
//设置新的位图为8位位图,并设置其相应宽度与高度
lpNewBmpInfo->bmiHeader=lpOldBmpInfo->bmiHeader;
lpNewBmpInfo->bmiHeader.biBitCount=8;
//数据起始位置为原位图信息头起始+位图信息头大小+彩色表大小
//lpNewBmpData = (BYTE*)(lpNewBmpInfo + sizeof(BITMAPINFOHEADER)/* + 256* sizeof(RGBQUAD)*/);
lpNewBmpData = (BYTE*)lpNewBmpInfo + sizeof(BITMAPINFOHEADER) + 256* sizeof(RGBQUAD);
//指向图像数据的实际位置, 主要问题是在这里吧,看了BMP的结构...是应该加上256* sizeof(RGBQUAD)这个吧,还是不行..
int i,j;
//为其相应的彩色表赋值
for(i=0;i<256;i++)
{
lpNewBmpInfo->bmiColors[i].rgbRed=i;
lpNewBmpInfo->bmiColors[i].rgbGreen=i;
lpNewBmpInfo->bmiColors[i].rgbBlue=i;
lpNewBmpInfo->bmiColors[i].rgbReserved=0;
}
//按转换公式将其进行转换
for(i=0;i<nSrcHeight;i++)
{
for(j=0;j<nSrcWidth;j++)
{
BYTE color[3];
DWORD dwColorTemp;
for(int s=0; s<3; s++)
color[s]=lpOldBmpData[i*nLineWidth+j*3+s];
dwColorTemp=int(color[2]*0.299+color[1]*0.587+color[0]*0.114);
if(dwColorTemp>255)
dwColorTemp=255;
if( dwColorTemp< 0 )
dwColorTemp = 0;
lpNewBmpData[i*nScanWidth+j]=(unsigned char)dwColorTemp;
}
}
lpNewBmpData[nScanWidth*nSrcHeight]=0;
lpNewBmpData[nScanWidth*nSrcHeight+1]=0;
if( !CloseHandle( hFile ) )
printf("关闭文件时失败");
return (BYTE*)lpNewBmpInfo;
}
//传进文件名与文件长度,创建8位位图文件
BOOL SaveFile(CString strFileName, DWORD dwFileLength)
{
HANDLE hSaveFile = CreateFile( strFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if( !hSaveFile )
{
printf( "创建文件出错/n");
return FALSE;
}
//
DWORD dwWriteNum;
BITMAPFILEHEADER BFH;
BFH.bfType = 'MB';
BFH.bfSize = dwFileLength + sizeof(BITMAPFILEHEADER);
BFH.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256* sizeof(RGBQUAD); //256为调色表颜色数(0-255),这里没错吧
BFH.bfReserved1 = BFH.bfReserved2 = 0;
//写位图头信息
WriteFile( hSaveFile, &BFH, sizeof(BITMAPFILEHEADER), &dwWriteNum, NULL);
//写实际数据
WriteFile( hSaveFile, lpNewBmpInfo, dwFileLength, &dwWriteNum, NULL);
CloseHandle( hSaveFile );
return TRUE;
}