也不知道为什么,一个简单的直方图统计在8位下没有问题,在24位下面老是通不过,发现原因是数组越界,于是我就找为什么数组越界
,发现一个比较奇怪的问题,nByteWidth居然变了,看了半天没看出来,麻烦大家帮我看一下// 直方图统计.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <afx.h>
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <string.h>#pragma warning(disable : 4996)//global variables
int nWidth;
int nHeight;
int nColorBits; //每个像素所占的位数
int nColor; //图像的颜色数
int nLen; //图像文件的大小,以字节数计
int nByteWidth; //图像每行的字节数
BYTE * lpBitmap; //指向图像首字节的指针
BYTE * lpBits; //指向图像实际数据的指针
unsigned long r[255], g[255], b[255]; //直方图统计
unsigned long datalength;
/**************************************************
//函数名称: OpenFile()
//参数: CString FileName 图像的路径和文件名
//返回值: 无
//功能: 读取一幅BMP图像
***************************************************/
void OpenFile(CString FileName)
{
//创建文件句柄
HANDLE hFile = ::CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == 0)
{
std::cerr<<"建立文件不成功"<<std::endl;
return;
} //读取图像文件
DWORD WriteNum;
BITMAPFILEHEADER BFH; //文件头
::ReadFile(hFile, &BFH, 14, &WriteNum, NULL); //读取文件头,共14个字节
if((BFH.bfType != 'MB') || (WriteNum != sizeof(BITMAPFILEHEADER)))
{
std::cerr<<"不是BMP位图文件或数据有误!"<<std::endl;
return;
} nLen = GetFileSize(hFile, NULL) - sizeof(BITMAPFILEHEADER); //获取文件的长度
lpBitmap = new BYTE[nLen]; //存放图像,包括图像的信息头、调色板和像素数据
ReadFile(hFile, lpBitmap, nLen, &WriteNum, NULL); //设置全局变量的值
BITMAPINFOHEADER *BIH = ((BITMAPINFOHEADER *)lpBitmap); //图像文件的信息头
nWidth = BIH->biWidth; //图像的宽度
nHeight = BIH->biHeight; //图像的高度
nColorBits = BIH->biBitCount; //图像的颜色数
nByteWidth = (nWidth * nColorBits + 31)/32*4; //图像的扫描宽度
nColor = (nColorBits > 8)? 0 : (1 << nColorBits); //调色板中的颜色数
lpBits = lpBitmap + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColor; //指向图像数据的实际位置
datalength = nLen - sizeof(BITMAPINFOHEADER) - sizeof(RGBQUAD) * nColor;
CloseHandle(hFile);
}
void SaveFile(CString FileName)
{
//创建一个文件来保存图像文件
HANDLE hFile = ::CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == 0)
{
std::cerr<<"不能创建文件,请重新选择!"<<std::endl;
return;
} //创建一个文件头,并保存到创建的文件中
unsigned long WriteNum;
BITMAPFILEHEADER BFH;
BFH.bfType = 'MB';
BFH.bfSize = nLen + sizeof(BITMAPFILEHEADER);
BFH.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nColor * sizeof(RGBQUAD); BFH.bfReserved1 = BFH.bfReserved2 = 0; ::WriteFile(hFile, &BFH, sizeof(BITMAPFILEHEADER), &WriteNum, NULL); //保存改变的位图文件数据
::WriteFile(hFile, (BITMAPINFOHEADER *)lpBitmap, nLen, &WriteNum, NULL);
CloseHandle(hFile);
}
/********************************************************************************
//函数名称: HistogramStat()
//参数: long bCount[]
long gCount[]
long rCount[]//返回值: 无
//功能: 统计图像各级灰度的像素的个数,当是256色图像,返回值放在bCount[]中。
真彩色图像蓝色、绿色、红色分量依次放在三个参数变量中
*********************************************************************************/
void HistogramStat(unsigned long *bCount, unsigned long *gCount, unsigned long *rCount)
{
int i;
//赋初值
/*for(i = 0; i < 255; i++)
{
rCount[i] = 0;
gCount[i] = 0;
bCount[i] = 0;
}*/
memset(rCount, 0, 255);
memset(gCount, 0, 255);
memset(bCount, 0, 255);
int temp = 0; //统计各个灰度级像素的个数
for(i = 0; i < nHeight; i++)
{
for(int j = 0; j < nWidth; j++)
{
if(nColorBits == 8)
{
unsigned char * pData = lpBits + i * nByteWidth + j;
bCount[*pData]++;
}
else if(nColorBits == 24)
{
unsigned long offset = i * nByteWidth + j * 3;
unsigned char *pData = lpBits + offset;
temp = *(lpBits + offset);
bCount [temp - 1]++;
temp = *(lpBits + offset + 1);
gCount [temp - 1]++;
temp = *(lpBits + offset + 2);
rCount [temp - 1]++;
/*unsigned char * pData = lpBits + i*nWidth*3+j*3;
temp = *pData;
bCount[*(pData+1)]++;
temp = *(pData + 1);
gCount[*(pData)]++;
temp = *(pData + 2);
rCount[*(pData + 2)]++;*/
}
}
}
}int _tmain(int argc, _TCHAR* argv[])
{
char OpenFileName[100];
memset(OpenFileName, '\0', sizeof(OpenFileName));
sprintf_s(OpenFileName, "%s", "..\\..\\images\\test.bmp"); char SaveFileName[100];
memset(SaveFileName, '\0', sizeof(SaveFileName));
sprintf(SaveFileName, "%s", "..\\..\\images\\result.bmp"); //输入图像
OpenFile(OpenFileName);
HistogramStat(b, g, r); SaveFile(SaveFileName); delete [] lpBitmap; return 0;
}
,发现一个比较奇怪的问题,nByteWidth居然变了,看了半天没看出来,麻烦大家帮我看一下// 直方图统计.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <afx.h>
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <string.h>#pragma warning(disable : 4996)//global variables
int nWidth;
int nHeight;
int nColorBits; //每个像素所占的位数
int nColor; //图像的颜色数
int nLen; //图像文件的大小,以字节数计
int nByteWidth; //图像每行的字节数
BYTE * lpBitmap; //指向图像首字节的指针
BYTE * lpBits; //指向图像实际数据的指针
unsigned long r[255], g[255], b[255]; //直方图统计
unsigned long datalength;
/**************************************************
//函数名称: OpenFile()
//参数: CString FileName 图像的路径和文件名
//返回值: 无
//功能: 读取一幅BMP图像
***************************************************/
void OpenFile(CString FileName)
{
//创建文件句柄
HANDLE hFile = ::CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == 0)
{
std::cerr<<"建立文件不成功"<<std::endl;
return;
} //读取图像文件
DWORD WriteNum;
BITMAPFILEHEADER BFH; //文件头
::ReadFile(hFile, &BFH, 14, &WriteNum, NULL); //读取文件头,共14个字节
if((BFH.bfType != 'MB') || (WriteNum != sizeof(BITMAPFILEHEADER)))
{
std::cerr<<"不是BMP位图文件或数据有误!"<<std::endl;
return;
} nLen = GetFileSize(hFile, NULL) - sizeof(BITMAPFILEHEADER); //获取文件的长度
lpBitmap = new BYTE[nLen]; //存放图像,包括图像的信息头、调色板和像素数据
ReadFile(hFile, lpBitmap, nLen, &WriteNum, NULL); //设置全局变量的值
BITMAPINFOHEADER *BIH = ((BITMAPINFOHEADER *)lpBitmap); //图像文件的信息头
nWidth = BIH->biWidth; //图像的宽度
nHeight = BIH->biHeight; //图像的高度
nColorBits = BIH->biBitCount; //图像的颜色数
nByteWidth = (nWidth * nColorBits + 31)/32*4; //图像的扫描宽度
nColor = (nColorBits > 8)? 0 : (1 << nColorBits); //调色板中的颜色数
lpBits = lpBitmap + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColor; //指向图像数据的实际位置
datalength = nLen - sizeof(BITMAPINFOHEADER) - sizeof(RGBQUAD) * nColor;
CloseHandle(hFile);
}
void SaveFile(CString FileName)
{
//创建一个文件来保存图像文件
HANDLE hFile = ::CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == 0)
{
std::cerr<<"不能创建文件,请重新选择!"<<std::endl;
return;
} //创建一个文件头,并保存到创建的文件中
unsigned long WriteNum;
BITMAPFILEHEADER BFH;
BFH.bfType = 'MB';
BFH.bfSize = nLen + sizeof(BITMAPFILEHEADER);
BFH.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nColor * sizeof(RGBQUAD); BFH.bfReserved1 = BFH.bfReserved2 = 0; ::WriteFile(hFile, &BFH, sizeof(BITMAPFILEHEADER), &WriteNum, NULL); //保存改变的位图文件数据
::WriteFile(hFile, (BITMAPINFOHEADER *)lpBitmap, nLen, &WriteNum, NULL);
CloseHandle(hFile);
}
/********************************************************************************
//函数名称: HistogramStat()
//参数: long bCount[]
long gCount[]
long rCount[]//返回值: 无
//功能: 统计图像各级灰度的像素的个数,当是256色图像,返回值放在bCount[]中。
真彩色图像蓝色、绿色、红色分量依次放在三个参数变量中
*********************************************************************************/
void HistogramStat(unsigned long *bCount, unsigned long *gCount, unsigned long *rCount)
{
int i;
//赋初值
/*for(i = 0; i < 255; i++)
{
rCount[i] = 0;
gCount[i] = 0;
bCount[i] = 0;
}*/
memset(rCount, 0, 255);
memset(gCount, 0, 255);
memset(bCount, 0, 255);
int temp = 0; //统计各个灰度级像素的个数
for(i = 0; i < nHeight; i++)
{
for(int j = 0; j < nWidth; j++)
{
if(nColorBits == 8)
{
unsigned char * pData = lpBits + i * nByteWidth + j;
bCount[*pData]++;
}
else if(nColorBits == 24)
{
unsigned long offset = i * nByteWidth + j * 3;
unsigned char *pData = lpBits + offset;
temp = *(lpBits + offset);
bCount [temp - 1]++;
temp = *(lpBits + offset + 1);
gCount [temp - 1]++;
temp = *(lpBits + offset + 2);
rCount [temp - 1]++;
/*unsigned char * pData = lpBits + i*nWidth*3+j*3;
temp = *pData;
bCount[*(pData+1)]++;
temp = *(pData + 1);
gCount[*(pData)]++;
temp = *(pData + 2);
rCount[*(pData + 2)]++;*/
}
}
}
}int _tmain(int argc, _TCHAR* argv[])
{
char OpenFileName[100];
memset(OpenFileName, '\0', sizeof(OpenFileName));
sprintf_s(OpenFileName, "%s", "..\\..\\images\\test.bmp"); char SaveFileName[100];
memset(SaveFileName, '\0', sizeof(SaveFileName));
sprintf(SaveFileName, "%s", "..\\..\\images\\result.bmp"); //输入图像
OpenFile(OpenFileName);
HistogramStat(b, g, r); SaveFile(SaveFileName); delete [] lpBitmap; return 0;
}
unsigned long r[256], g[256], b[256]; //直方图统计2、初始化错误,unsigned long是4个字节的所以应该改为
memset(rCount, 0, sizeof(rCount));
memset(gCount, 0, sizeof(gCount));
memset(bCount, 0, sizeof(bCount)); memset(rCount, 0, 256 * sizeof(unsigned long));
memset(gCount, 0, 256 * sizeof(unsigned long));
memset(bCount, 0, 256 * sizeof(unsigned long));3、越界错误,因为每个颜色分量是0~255,当temp为0时,你的数组变成bCount[-1]++;,应该改为
bCount[temp]++;
修改为 lpBits = lpBitmap + BFH.bfOffBits;
8位24位直方图统计也没必要那么麻烦
DataLen 为数据长度
if(biBitCount == 8)
{
while(DataLen > 0)
{
bCount[*lpBits++]++;
DataLen--;
}
}
else if(biBitCount == 24)
{
while(DataLen > 0)
{
bCount[*lpBits++]++;
gCount[*lpBits++]++;
rCount[*lpBits++]++;
DataLen-=3;
}
}
*lpBits取到的都是灰度,都是1-256,取到的灰度作为数组下标不是应该减1吗?