Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 指针文件在读取原始位图数据的过程中随机更改值_C_File_Bitmap - Fatal编程技术网

C 指针文件在读取原始位图数据的过程中随机更改值

C 指针文件在读取原始位图数据的过程中随机更改值,c,file,bitmap,C,File,Bitmap,我目前正在用C语言加载一个位图文件。我对C有点陌生,我遇到了一个问题:我有一个文件指针,可以读取rgb像素结构的无符号字符(它被称为rgb,但它的读取顺序是b、g、r和填充-这是位图格式文件的默认值)。我的文件是12x12像素,当它到达第9行时,它只在每个组件中放置值“204”,而图像是白色的(即所有组件=255)。在此之前的所有组件都等于255。 编辑:我将枚举更改为图像状态返回的三个定义值(未加载、蓝色、非蓝色)。 EDIT2:我编辑了代码,但现在im等于0xFFFFFF,无法访问。 代码如

我目前正在用C语言加载一个位图文件。我对C有点陌生,我遇到了一个问题:我有一个文件指针,可以读取rgb像素结构的无符号字符(它被称为rgb,但它的读取顺序是b、g、r和填充-这是位图格式文件的默认值)。我的文件是12x12像素,当它到达第9行时,它只在每个组件中放置值“204”,而图像是白色的(即所有组件=255)。在此之前的所有组件都等于255。 编辑:我将枚举更改为图像状态返回的三个定义值(未加载、蓝色、非蓝色)。 EDIT2:我编辑了代码,但现在im等于0xFFFFFF,无法访问。 代码如下:

int CalaculateBlueness()
 {

bih bih;
bfh bfh;
int counterblue = 0;
hsv hsv;
FILE *filePtr = fopen("C:\\Users\\mishe\\Desktop\\white.bmp", "rb");


//if the file doesn't exist in memory
if (filePtr == NULL)
{
    return IMAGE_NOT_LOADED;
}

//read the bitmap file header
fread(&bfh, sizeof(bfh), 1, filePtr);

//verify that this is a bmp file by check bitmap id
if (bfh.bitmap_type[0] != 'B' || bfh.bitmap_type[1] != 'M')
{
    fclose(filePtr);
    return IMAGE_NOT_LOADED;
}

fclose(filePtr);

//ensure that the filePtr will point at the start of the image info header
filePtr = fopen("C:\\Users\\mishe\\Desktop\\white.bmp", "rb");
fseek(filePtr, 14, SEEK_CUR);

//read the bitmap info header
fread(&bih, sizeof(bih), 1, filePtr);

if (bih.bit_count!=24)
{
    return ERROR_BPP;
}

//point the pointer file to the start of the raw data
//fseek(filePtr, bfh.file_size, SEEK_SET);

int size = bih.height * WIDTHBYTES(bih.width * 32);

unsigned char *im = calloc(1, size);
//put the raw bitmap pixel data in strcut rgb array 


fread(&im, sizeof(size), 1, filePtr);

//convert each pixel to it's hue value and check if in the range of blue
for (size_t i = 0; i < bih.height; i++)
{
    for (size_t j = 0; j < bih.width; j++)
    {
        hsv =rgbpixel_hue(im);
        if (hsv.h>190 && hsv.h<250)
        {
            counterblue++;
        }
        fseek(im, 3, SEEK_CUR);
    }

}

//check if more than 80% of the image is blue and return the defined state according to the result
if (counterblue > BLUE_THRESHOLD*(bih.height*bih.width))
{
    return  BLUE;
}
return  NOT_BLUE;
int-CalaculateBlueness()
{
波黑;
bfh-bfh;
int counterblue=0;
单纯疱疹病毒;
FILE*filePtr=fopen(“C:\\Users\\mishe\\Desktop\\white.bmp”、“rb”);
//如果文件在内存中不存在
if(filePtr==NULL)
{
返回未加载的图像;
}
//读取位图文件头
fread(&bfh,sizeof(bfh),1,文件管理器);
//通过检查位图id验证这是bmp文件
if(bfh.bitmap_type[0]!=“B”| bfh.bitmap_type[1]!=“M”)
{
fclose(文件管理器);
返回未加载的图像;
}
fclose(文件管理器);
//确保filePtr将指向图像信息头的开头
filePtr=fopen(“C:\\Users\\mishe\\Desktop\\white.bmp”、“rb”);
fseek(文件管理器,14,SEEK_CUR);
//读取位图信息标题
fread(波黑和波黑,sizeof(波黑),1号文件管理器);
if(波黑比特数!=24)
{
返回错误_BPP;
}
//将指针文件指向原始数据的开头
//fseek(filePtr,bfh.file\u size,SEEK\u SET);
int size=bih.height*WIDTHBYTES(bih.width*32);
无符号字符*im=calloc(1,大小);
//将原始位图像素数据放入STRUCT rgb数组中
fread(&im,sizeof(size),1,filePtr);
//将每个像素转换为其色调值,并检查是否在蓝色范围内
对于(尺寸i=0;i190&&hsv.h蓝色_阈值*(波黑高度*波黑宽度))
{
返回蓝色;
}
返回非蓝色;

}

再次打开文件之前,请关闭filePtr

fclose(filePtr);
filePtr = fopen("C:\\Users\\mishe\\Desktop\\white.bmp", "rb");
原始数据的偏移量为bfh

  //point the pointer file to the start of the raw data
    fseek(filePtr, bfh.offset, SEEK_SET);

在位图中阅读总是一件困难的事情

有很多需要考虑的问题。

fread(&im[i][j].res, sizeof(unsigned char), 1, filePtr);
通过此行,您可以从文件中读取
RGBQUAD
的保留字节。但是,此成员不在文件中。文件中的图像数据包含扫描线。请参阅下文

读取位图文件头后,您将再次打开该文件。但是,您没有关闭它。这可能是成功的,也可能是失败的,因为该文件已打开。但是,您没有检查
fopen
的返回值。无论如何,无需执行此操作,因为读取BFH后,文件指针位于BitMapInfo头;您只需读入即可。您需要读入,否则无法知道位图的尺寸

来自MSDN文档:

已建立的位图文件格式由BITMAPFILEHEADER结构和BitMapInfo header[…]结构组成。RGBQUAD结构数组(也称为颜色表)紧跟位图信息头结构。颜色表后面是颜色表的第二个索引数组(实际位图数据)

对于每像素24位位图,没有颜色表

现在的顺序是:

    //read the bitmap file header
    fread(&bfh, sizeof(bfh), 1, filePtr);

    //read the bitmap info header
    fread(&bih, sizeof(bih), 1, filePtr);

    int bpp= bih.biBitCount;
    if (bpp != 24) return 0;  // error: must be 24 bpp/ 3 bytes per pixel
现在我们必须计算存储图像所需的内存量。图像由高行宽像素组成。这些行称为扫描线

由于某些原因,扫描线在4字节边界上对齐。这意味着扫描线的最后一个字节可能未被使用。因此,从文件中读取位图数据的内存量是图像的高度乘以图像的扫描线数:

// WIDTHBYTES takes # of bits in a scanline and rounds up to nearest word.
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)

    int size= bih.biHeight * WIDTHBYTES(bih.biWidth*32));
    unsigned char *im= malloc(size);
最后,您可以读取数据。如果有颜色表,您应该通过查找跳过该表,但由于没有,您现在可以读取数据:

    fread(im, size, 1, filePtr);
现在,为了解决像素问题,由于扫描线的原因,您不能使用由图像的宽度和高度控制的简单二维表示法。您可以使用以下方法:

    int scanlineSize= WIDTHBYTES(bih.biWidth*bih.biBitCount);
    unsigned char *p, *scanline= im;

    for (int i=0; i<bih.biHeight; i++)
    {
        p= scanline;
        for (int j=0; j<bih.biWidth; j++)
        {
            g= *p++;
            b= *p++;
            r= *p++;
        }
        scanline += scanlineSize;
    }

bih.height
bih.width
的值是多少?它们是否可能大于
12
?您确定吗?您是否打印了它们,或者使用了调试器来找出它们?或者使用调试器来逐步检查代码,或者在任何可能改变值的变量上添加了观察点?您真的应该这样添加me错误检查!如果(filePtr==NULL){return img_state=2;}这应该是在fopenOn一个完全不相关的注释之后立即出现的,
img_state
变量的用途是什么?您需要它做什么?您不能只做例如
return 2
?正确,应该检查一下。从旧代码复制它,并且没有注意。然后返回枚举符号,而不是一个类似于
2
的整数。
2
只是一个整数,不会告诉我们(或其他代码读者)任何事情。定义枚举也会将其中的符号定义为可以使用的符号。谢谢。这正是我要找的答案,详细示例的+1小修复:
if(bpp!=32)
应该是
if(bpp!=24)
@Meowstar答案有0个向上投票…你忘记了向上投票还是有人真的否决了这个?你能解释一下存储图像所需内存计算背后的逻辑吗?哦,不,显然我没有足够的声誉
#include <winGDI.h>
// WIDTHBYTES takes # of bits in a scanline and rounds up to nearest word.
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)

unsigned char *readBitmap(char *szFilename)
{
    BITMAPFILEHEADER bfh;
    BITMAPINFOHEADER bih;
    int i, j, size, scanlineSize;
    unsigned char r, g, b, *p, *img, *scanline;
    FILE *filePtr;

    if ((filePtr=fopen(szFilename, "rb"))==0) return 0;

    //read the bitmap file header
    if (fread(&bfh, sizeof(bfh), 1, filePtr)!=1
    ||  bfh.bfType != 'MB') {fclose(filePtr); return 0;}

    //read the bitmap info header
    if (fread(&bih, sizeof(bih), 1, filePtr)!=1
    ||  bih.biSize!=sizeof(bih)) {fclose(filePtr); return 0;}

    if (bih.biBitCount != 24) {fclose(filePtr); return 0;}  // error: must be 24 bpp/ 3 bytes per pixel

    // allocate memory and read the image
    scanlineSize= WIDTHBYTES(bih.biWidth * bih.biBitCount);
    size= bih.biHeight * scanlineSize;
    if ((img= malloc(size))==0) {fclose(filePtr); return 0;}
    if (fread(img, size, 1, filePtr)!=1) {free (img); fclose(filePtr); return 0;}
    fclose(filePtr);

    scanline= img;
    for (i=0; i<bih.biHeight; i++)
    {
        p= scanline;
        for (j=0; j<bih.biWidth; j++)
        {
            g= *p++;
            b= *p++;
            r= *p++;
        }
        scanline += scanlineSize;
    }
    return img;
}