gpt4 book ai didi

c++ - 在 C 中导入 BMP 时的环绕问题

转载 作者:太空宇宙 更新时间:2023-11-04 07:37:24 24 4
gpt4 key购买 nike

现在我正在为我的视觉信息处理类(class)编写程序。我们为所有家庭作业提供了骨架模板,因为类(class)的重点不是学习 MFC。我在 Mac 上编程,无法访问使导入 BMP 变得容易的 Window 库。因此,我使用(并稍作修改)从该网站找到的代码:paulbourke.net/dataformats/bmp/

实际上我在过去一年中一直在使用此代码,它对 24 位 BMP(即像素表示为 RGB 的 BMP)运行良好。我需要对代码进行的主要调整是添加一个特殊例程,如果 BMP 的高度表示为负数,则反转图像的行。

当我将 BMP 导入到 GLubyte 类型的数组中时,图像的 biBitCount = 24,使用 GLDrawPixels 效果很好:

http://i.imgur.com/41TVo.png

但是,当我导入 biBitCount = 8 的 BMP 并使用 GLDrawPixels 显示它时,我得到以下信息(注意环绕错误以红色矩形突出显示):

http://i.imgur.com/xws5j.png

我必须为上次作业实现自动阈值算法,以便根据解释的区域分割图像。我认为这种环绕的错误源于导入 BMP,而不是源于 GLDrawPixels 调用。这是因为我制作的区域化算法识别出的区域多于应有的区域。这似乎暗示环绕的部分在 BMP 的数组表示中是真正不相交的。

我已经对我的代码进行了多次筛选,但终究还是无法找出导致问题的原因。

这是导入后显示 BMP 的代码:

void drawBMP(BITMAPINFO *bitmapInfo, GLubyte *bitmapIn, GLfloat xOffset, GLfloat yOffset) {
if (bitmapInfo) {
glRasterPos2f(xOffset, yOffset);

if (bitmapInfo->bmiHeader.biBitCount == 24) {
glDrawPixels(bitmapInfo->bmiHeader.biWidth,
bitmapInfo->bmiHeader.biHeight,
GL_BGR, GL_UNSIGNED_BYTE, bitmapIn);
} else {
glDrawPixels(bitmapInfo->bmiHeader.biWidth,
bitmapInfo->bmiHeader.biHeight,
GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmapIn);
}
}

glFinish();
}

也许是 GL_LUMINANCE 设置导致了问题?

下面是实际导入 BMP 的函数:

GLubyte *                          /* O - Bitmap data */
LoadDIBitmap(const char *filename, /* I - File to load */
BITMAPINFO **info) /* O - Bitmap information */
{
FILE *fp; /* Open file pointer */
GLubyte *bits; /* Bitmap pixel bits */
GLubyte *ptr; /* Pointer into bitmap */
GLubyte temp; /* Temporary variable to swap red and blue */
int x, y; /* X and Y position in image */
int length; /* Line length */
int bitsize; /* Size of bitmap */
int infosize; /* Size of header information */
BITMAPFILEHEADER header; /* File header */


/* Try opening the file; use "rb" mode to read this *binary* file. */
if ((fp = fopen(filename, "rb")) == NULL)
return (NULL);

/* Read the file header and any following bitmap information... */
header.bfType = read_word(fp);
header.bfSize = read_dword(fp);
header.bfReserved1 = read_word(fp);
header.bfReserved2 = read_word(fp);
header.bfOffBits = read_dword(fp);

if (header.bfType != BF_TYPE) /* Check for BM reversed... */
{
/* Not a bitmap file - return NULL... */
fclose(fp);
return (NULL);
}

infosize = header.bfOffBits - 18;
if ((*info = (BITMAPINFO *)malloc(sizeof(BITMAPINFO))) == NULL)
{
/* Couldn't allocate memory for bitmap info - return NULL... */
fclose(fp);
return (NULL);
}

(*info)->bmiHeader.biSize = read_dword(fp);
(*info)->bmiHeader.biWidth = read_long(fp);
(*info)->bmiHeader.biHeight = read_long(fp);
(*info)->bmiHeader.biPlanes = read_word(fp);
(*info)->bmiHeader.biBitCount = read_word(fp);
(*info)->bmiHeader.biCompression = read_dword(fp);
(*info)->bmiHeader.biSizeImage = read_dword(fp);
(*info)->bmiHeader.biXPelsPerMeter = read_long(fp);
(*info)->bmiHeader.biYPelsPerMeter = read_long(fp);
(*info)->bmiHeader.biClrUsed = read_dword(fp);
(*info)->bmiHeader.biClrImportant = read_dword(fp);

if (infosize > 40)
if (fread((*info)->bmiColors, infosize - 40, 1, fp) < 1)
{
/* Couldn't read the bitmap header - return NULL... */
free(*info);
fclose(fp);
return (NULL);
}

/* Now that we have all the header info read in, allocate memory for *
* the bitmap and read *it* in... */
if ((bitsize = (*info)->bmiHeader.biSizeImage) == 0)
bitsize = ((*info)->bmiHeader.biWidth *
(*info)->bmiHeader.biBitCount+7) / 8 *
abs((*info)->bmiHeader.biHeight);

if ((bits = malloc(bitsize)) == NULL)
{
/* Couldn't allocate memory - return NULL! */
free(*info);
fclose(fp);
return (NULL);
}

if (fread(bits, 1, bitsize, fp) < bitsize)
{
/* Couldn't read bitmap - free memory and return NULL! */
free(*info);
free(bits);
fclose(fp);
return (NULL);
}

//This needs to be done when the height is negative
if ((*info)->bmiHeader.biHeight < 0) {
(*info)->bmiHeader.biHeight *= -1;

int bitsPerPixel = (*info)->bmiHeader.biBitCount;
int bytesPerPixel;
if (bitsPerPixel >= 8) {
bytesPerPixel = bitsPerPixel/8;
} else {
exit(1);
}

int i; //Row
int j; //Column
for (i = 0; i < floor((*info)->bmiHeader.biHeight/2); i++) {
int inlineRowValue = i * (*info)->bmiHeader.biWidth * bytesPerPixel;
int inlineInvRowValue = ((*info)->bmiHeader.biHeight - i) * (*info)->bmiHeader.biWidth * bytesPerPixel;

for (j = 0; j < (*info)->bmiHeader.biWidth; j++) {
int inlineColumnValue = j * bytesPerPixel;
int currentPos = inlineRowValue + inlineColumnValue;
int invCurrentPos = inlineInvRowValue + inlineColumnValue;

int k;
GLubyte *temp = malloc(sizeof(GLubyte)*bytesPerPixel);
for (k = 0; k < bytesPerPixel; k++) {
temp[k] = bits[currentPos+k];
}
for (k = 0; k < bytesPerPixel; k++) {
bits[currentPos+k] = bits[invCurrentPos+k];
bits[invCurrentPos+k] = temp[k];
}

free(temp);
}
}
}

/* OK, everything went fine - return the allocated bitmap... */
fclose(fp);
return (bits);
}

我的直觉告诉我,当从 BMP 文件中读取内容时,文件指针没有正确递增。

如果你们知道这个错误的来源是什么,请分享。我将非常感激。这让我抓狂。

最佳答案

我认为您在这里减去的金额不对:

infosize = header.bfOffBits - 18;

这似乎考虑了 header 信息的大小,但 header 是 14 个字节(3 个字和 2 个双字),而不是 18 个字节。

为什么不直接使用:

fseek(fp, header.bfOffBits, SEEK_SET);

在读取图像数据之前?

关于c++ - 在 C 中导入 BMP 时的环绕问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7734946/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com