24位BMP转8位BMP

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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值