【发布时间】:2014-07-06 16:07:06
【问题描述】:
我在 C 中创建了程序,女巫读取 .bmp 文件并对其应用模糊效果。算法很简单。读取文件,分离每个颜色通道并使用给定矩阵进行通道卷积。我的图像是每像素 24 位。这是我的程序的结果:http://imgur.com/lTNvPrX 而这是原始的http://imgur.com/IVGHCQk。我认为在单独的通道中访问数据时会出错,但我不知道该怎么做。我知道rows 和cols 包含像素数而不是字节数,但是当我将其乘以3 时,我得到channelBlur[y*cols+x] = toWrite 的分段错误。我正在用gcc -m32 ... 编译它
下面是用于读取文件和处理图像的结构和代码:
typedef struct __attribute__((__packed__))
{
WORD fType;
DWORD byteSize;
WORD reserved1;
WORD reserved2;
DWORD offsetToImage;
}BITMAPHEADER;
typedef struct __attribute__((__packed__))
{
DWORD structSize;
LONG width;
LONG height;
WORD planes;
WORD bitsPerPix;
DWORD compression;
DWORD imgSizeBytes;
LONG pixPerMeterX;
LONG pixPerMeterY;
DWORD colorUsd;
DWORD colorImp;
}BITMAPINFOHEADER;
typedef unsigned char* IMAGE;
加载函数:
IMAGE loadImg(const char* filename, BITMAPINFOHEADER* infoHeader)
{
FILE* fImg;
BITMAPHEADER header;
IMAGE bitmap;
fImg = fopen(filename,"rb");
if(fImg == NULL)
return NULL;
fread(&header,sizeof(BITMAPHEADER),1,fImg);
if(header.fType != 0x4D42)
{
fclose(fImg);
return NULL;
}
fread(infoHeader,sizeof(BITMAPINFOHEADER),1,fImg);
fseek(fImg,header.offsetToImage, SEEK_SET);
bitmap = (unsigned char*)malloc(infoHeader->imgSizeBytes);
fread(bitmap,infoHeader->imgSizeBytes,1,fImg);
fclose(fImg);
return bitmap;
}
和幼稚的分离通道和组合功能:
void separateChannels(const IMAGE src,unsigned int nPixels, unsigned char* red, unsigned char* green,unsigned char* blue)
{
PIXEL pix;
unsigned int i;
for(i=0;i<nPixels;i=i+3)
{
blue[i] = src[i];
green[i] = src[i+1];
red[i] = src[i+2];
}
}
IMAGE combineChannels(unsigned char* red, unsigned char* green,unsigned char* blue, unsigned int nPixels, BITMAPINFOHEADER infoHeader)
{
IMAGE image = createNewImage(infoHeader);
unsigned int i;
for(i=0;i<nPixels;i=i+3)
{
image[i] = blue[i];
image[i+1] = green[i];
image[i+2] = red[i];
}
return image;
}
createNewImage 工作正常
分配频道:
unsigned char* redBlur = (unsigned char*)malloc(infoHeader.imgSizeBytes);
unsigned char* greenBlur = (unsigned char*)malloc(infoHeader.imgSizeBytes);
unsigned char* blueBlur = (unsigned char*)malloc(infoHeader.imgSizeBytes);
这是有问题的函数:
void applyFilterOnChannel(const unsigned char* channel,unsigned char* channelBlur ,unsigned int cols,unsigned int rows, const float* filter)
{
unsigned int x;
unsigned int y;
for(y=0;y<cols;++y)
{
for(x=0;x<rows;++x)
{
float value = 0;
unsigned int filterX;
unsigned int filterY;
for(filterY=0;filterY<filterSize/2;++filterY)
{
for(filterX=0;filterX<filterSize/2;++filterX)
{
int pixelPosY = min(max(y+filterY,0),(int)rows-1);
int pixelPosX = min(max(x+filterX,0),(int)cols-1);
float pixelVal = (float)channel[pixelPosY*cols+pixelPosX];
float filterVal = filter[(filterY+filterSize/2)*filterSize+filterX+filterSize/2];
value += pixelVal*filterVal;
}
}
unsigned char toWrite = (unsigned char)value;
channelBlur[y*cols+x] = toWrite;
}
}
}
【问题讨论】:
-
nPixels是如何计算的? (如果这是宽度 * 高度,那么在处理过程中不应跳过 3。)另外,请仔细检查:读取文件后,立即将其写回。这会扭曲它吗? -
当您分离和合并频道时,您的索引是错误的。在你的循环中,你应该只将
i增加一并计算像image[3*i + 2] = red[i]这样的索引等等。 -
@Jongware
nPixels = BITMAPINFOHEADER.imgSizeBytes我知道这个变量名是错误的......加载功能很好,我在代码中执行图像翻转并得到正确的输出。 -
如果你不打电话给
applyFilterOnChannel,生成的图像可以吗?它应该与原始图像相同。 -
@Michael Walz 是的,如果我只是调用
CombineChannels并作为参数传递提取的颜色通道,我会得到原始图像。
标签: c image-processing memory-management bitmap