这个代码从图像RGB bmp纯C – Windows操作系统写入灰度bmp有什么问题

这是我的function,我根据维基百科BITMAPINFOHEADER使用标题BMP。 但是,我得到的文件没有任何图像…当填充填充时,过程停止。

// Structures for header info #pragma pack(push,1) /* Windows 3.x bitmap file header */ typedef struct { char filetype[2]; /* magic - always 'B' 'M' */ unsigned int filesize; short reserved1; short reserved2; unsigned int dataoffset; /* offset in bytes to actual bitmap data */ } file_header; /* Windows 3.x bitmap full header, including file header */ typedef struct { file_header fileheader; unsigned int headersize; int width; int height; short planes; short bitsperpixel; /* we only support the value 24 here */ unsigned int compression; /* we do not support compression */ unsigned int bitmapsize; int horizontalres; int verticalres; unsigned int numcolors; unsigned int importantcolors; } bitmap_header; #pragma pack(pop) int RGB2GREY(char* input, char *greyImage) { //variable declaration: FILE *fp, *grey; bitmap_header* hp; int n; char *data; int oldBitsperpixel; //Open input file: fp = fopen(input, "rb"); if(fp==NULL){ //cleanup } //Read the input file headers: hp=(bitmap_header*)malloc(sizeof(bitmap_header)); if(hp==NULL) return 3; n=fread(hp, sizeof(bitmap_header), 1, fp); if(nbitmapsize); if(data==NULL){ //cleanup } //Put me in the position after header... fseek(fp,sizeof(char)*hp->fileheader.dataoffset,SEEK_SET); printf("Width %d and Height %d\n",hp->width,hp->height); int i, j; unsigned char BGR[3]; unsigned colorIntensity[3]; /*unsigned char bmppad[hp->width] = {0};*/ printf("New bitmapSize %d\n\n",hp->bitsperpixel); //Open greayImage file: grey = fopen(greyImage, "wb"); if(grey==NULL){ //cleanup } //Writes the header n=fwrite(hp,sizeof(char),sizeof(bitmap_header),grey); if(nfileheader.dataoffset,SEEK_SET); for (i=0; iheight; i++){ for (j=0; jwidth; j++){ //Reading pixel by pixel fread(BGR, 3, 1, fp); //1 unsigned char of 3 positions unsigned char colorGrey; colorGrey = (unsigned char) 0.3*BGR[2] + 0.6*BGR[1] + 0.1*BGR[0]; colorIntensity[2] = colorGrey; colorIntensity[1] = colorGrey; colorIntensity[0] = colorGrey; /*printf("B %d G %d R %d ",BGR[0],BGR[1],BGR[2]); printf("Gray %d ",colorIntensity);*/ fwrite(colorIntensity, 3, 1, grey); } /* // Adding pad option1 //fwrite(bmppad, sizeof(bmppad), 1, grey); //Adding pad option2 for (j=0; j>hp->width; j++){ fwrite(0, 1, 1, grey); }*/ } fclose(fp); fclose(grey); free(hp); free(data); return 0; 

}

在灰色输出文件中,我什么都没得到……而且,我想知道是否有办法将24位减少到8位。

PS。 我的代码来自于读取/写入c中的bmp文件

该公式来自RGB BMP的Create greyscale BMP

谢谢,

您实际上是通过以一种显示为灰色的方式更改颜色值来将32位颜色位图转换为32位灰色位图(您不会以这种方式保存任何空间;位图保持原样)。 Anayway,它解释了为什么你不需要调整位图头。

但是当您读取每三个字节并更改每三个字节时,您不会考虑扫描线。

图像由扫描线和像素的扫描线组成。 扫描线在偶数字边界上对齐,因此扫描线的最后几个字节未被使用(因此扫描线比其上的所有像素长一些)。

要正确处理输入并创建输出,您的循环必须是:

(编辑:更新为每像素输出使用1个字节):

 #pragma pack(push,1) typedef struct { unsigned char rgbBlue; unsigned char rgbGreen; unsigned char rgbRed; unsigned char rgbReserved; } pal_entry; #pragma pack(pop) int ToGreyScale(FILE *fp, FILE *grey, bitmap_header *hp) { int i, j; int iScanlineSizeIn = ((hp->width * hp->bitsperpixel) + 31) / 32 * 4; int iScanlineSizeOut= ((hp->width * 8 ) + 31) / 32 * 4; unsigned char *scanlineIn = malloc(iScanlineSizeIn), *pIn; unsigned char *scanlineOut= malloc(iScanlineSizeOut), *pOut; pal_entry pal[256]; for (i=0; i<256; i++) // create a gray scale palette {pal[i].rgbBlue= i; pal[i].rgbGreen= i; pal[i].rgbRed= i;} hp->bitsperpixel= 8; // set output bits-per-pixel hp->fileheader.filesize= sizeof(bitmap_header) + sizeof(pal) + hp->width*iScanlineSizeOut; fwrite(hp, sizeof(bitmap_header), 1, grey); // write the header... fwrite(pal, 256*sizeof(pal_entry), 1, grey); //..followed by palette for (i=0; iheight; i++) { if (fread(scanlineIn, iScanlineSizeIn, 1, fp) != 1) return(0); pIn = scanlineIn; pOut= scanlineOut; for (j=0; jwidth; j++) { *pOut++ = (unsigned char) ((0.1 * *pIn++) + (0.6 * *pIn++) + (0.3 * *pIn++)); } fwrite(scanlineOut, iScanlineSizeOut, 1, grey); } free(scanlineIn); free(scanlineOut); return(1); }