代码之家  ›  专栏  ›  技术社区  ›  tropez

用C编写BMP文件会产生错误的结果

bmp c
  •  -1
  • tropez  · 技术社区  · 7 年前

    我正在尝试编写一个函数来读取BMP文件,然后复制它。我像往常一样将图像头读取到一个结构,并将像素值复制到rgb矩阵。

    我正在构建的用于编写BMP文件的函数提供了正确的图像宽度/高度和大小,但图像是全黑的,并且当像素值都不正确时(我通过使用 xxd )

    下面是编写BMP文件的函数:

    void writeBMP(BMPFILEHEADER *headerData,BMPINFOHEADER *headerInfo, int values[headerInfo->width*headerInfo->height]) {
    
            FILE *out;
            out = fopen("example.bmp", "wb");
            fwrite(headerData, sizeof(char), sizeof(BMPFILEHEADER), out);
            fseek(out, 14, SEEK_SET);
            fwrite(headerInfo, sizeof(char), sizeof(BMPINFOHEADER), out);
            fseek(out, 54, SEEK_SET);
            fwrite(values, sizeof(char), headerInfo->imagesize, out);
            fclose(out);
        }
    

    我查过了 values (这是我使用PrimTF存储像素数据的地方,像素值与原始图像像素匹配。但看起来像是一条线 fwrite(values, sizeof(char), headerInfo->imagesize, out) 正在将错误的数据写入文件。

    编辑:我正在添加有关代码的其他详细信息

    读取像素数据的函数:

    RGBmatrix readPixels(char *fileName, BMPFILEHEADER *header, BMPINFOHEADER *info) {
        FILE *fp;
        int **matR, **matG, **matB;
        int RGBvalues[info->width][info->height];
    
        RGBmatrix values;
    
        matR = allocateRGB(matR, info->width, info->height);
        matG = allocateRGB(matG, info->width, info->height);
        matB = allocateRGB(matB, info->width, info->height);
    
        fp = fopen(fileName, "rb");
        if(fp==NULL) {
            printf("Can't open file\n");
        }
    
        fseek(fp, header->offset, SEEK_SET);
    
        for(int i = 0; i<info->width; i++) {
            for(int j=0; j<info->height;j++) {
                fread(&RGBvalues[i][j], 3, 1, fp);
            }
        }
    
        for(int i=0; i<info->width; i++) {
            for(int j=0; j<info->height; j++) {
                matB[i][j] =  RGBvalues[i][j] & 0xff;
                matG[i][j] = (RGBvalues[i][j]>>8) & 0xff;
                matR[i][j] = (RGBvalues[i][j]>>16) & 0xff; 
            }
        }
    
        values.R = matR;
        values.G = matG;
        values.B = matB;
    
        return values;
    }
    

    保存BMP数据的结构:

    typedef struct RGBmatrix {
        int **R, **G, **B;
    }RGBmatrix;
    
    typedef struct BMPFILEHEADER {
        short int magicNumber;
        int bmpfSize;
        short int reserved1;
        short int reserverd2;
        int offset;
    }BMPFILEHEADER;
    
    typedef struct BMPINFOHEADER {
        unsigned int size;
        int width, height;
        unsigned short int planes;
        unsigned short int bits;
        unsigned int compression;
        unsigned int imagesize;
        int xresolution, yresolution;
        unsigned int ncolours;
        unsigned int importantcolours;
    }BMPINFOHEADER;
    

    我的主要功能:

    int main(int argc, char *argv[]) {
        BMPFILEHEADER headerData;
        BMPINFOHEADER headerInfo;
        FILE *fp;
        char fileName[20];
    
        strcpy(fileName, argv[1]); // command line argument to bmp file
    
        readBMPHeader(fileName, &headerData, &headerInfo); // read header data
        RGBmatrix values = readPixels(fileName, &headerData, &headerInfo); // read pixels
    
        int rgbModifiedValues[headerInfo.width*headerInfo.height];
    
        // do stuff with RGB values and store them into rgbModified Values
    
        writeBMP(&headerData, &headerInfo, rgbModifiedValues);
    
        return 0;
    }
    
    1 回复  |  直到 7 年前
        1
  •  3
  •   LSerni    7 年前

    我希望你正在写一个256色(8位)的bmp文件。

    如果是这样的话,有可能通过使用 int 值,则在文件中写入的条目不正确:

      these are not 8-bit in size
      |
      v
      int values[headerInfo->width*headerInfo->height])
    
    
      fwrite(values, sizeof(char), headerInfo->imagesize, out);
                     ^
                     |
                     but here you seem to treat them as if they are
    

    你应该用 unsigned char uint8_t 如果有的话。

    如果我是正确的,那么您现在应该看到一个图像,它大部分是黑色(或者大部分是一种颜色),带有垂直或对角线条纹,十六进制转储应该显示与一个或三个零交错的非零值;非零值本身是正确的:

    Expected pixel values
    12  17  4B
    
    Integer values in memory, read as bytes:
    
    12 0 0 0 17 0 0 0 4B 0 0 0