也不知道为什么,一个简单的直方图统计在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;
}

解决方案 »

  1.   

    发现你3个错误1、灰度是256级的,所以应该
    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]++;
      

  2.   

    lpBits = lpBitmap + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColor; 
    修改为 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;
        }
      }
      

  3.   

    我是新手,有个弱问
    *lpBits取到的都是灰度,都是1-256,取到的灰度作为数组下标不是应该减1吗?