This is my function, I am using the headers BMP according to wikipedia BITMAPINFOHEADER. But, I am getting a file without any image...when putting padding, the process stops.
// 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(n<1){
//cleanup
}
//Read the data of the image:
data = (char*)malloc(sizeof(char)*hp->bitmapsize);
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(n<1){
//cleanup
}
//Again going to position after header
fseek(out,sizeof(char)*hp->fileheader.dataoffset,SEEK_SET);
for (i=0; i<hp->height; i++){
for (j=0; j<hp->width; 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;
}
In the grey output file, I get nothing...moreover, I wonder if there is a way to reduce from 24 to 8 bits.
ps. My code came from reading/writing bmp files in c
The formula came from Create greyscale BMP from RGB BMP
Thanks,
You are essentially turning a 32-bit color bitmap into a 32-bit grey bitmap by changing the color values in a way that they appear grey (you are not saving any space in this way; the bitmap stays as large as it was). Anayway, it explains why you do not need to adapt the bitmap header.
But when you read every three bytes and change every three bytes, you do not take scanlines into account.
An image consists of scanlines and a scanline consits of pixels. Scanlines are alligned on even word boundaries so the last few bytes of a scanline are unused (and the scanline is thus a bit longer than all the pixels on it).
To properly process the input and create the output, your loop must be:
(EDIT: updated to use 1 byte per pixel output):
#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; i<hp->height; i++)
{
if (fread(scanlineIn, iScanlineSizeIn, 1, fp) != 1) return(0);
pIn = scanlineIn;
pOut= scanlineOut;
for (j=0; j<hp->width; j++)
{
*pOut++ = (unsigned char) ((0.1 * *pIn++) + (0.6 * *pIn++) + (0.3 * *pIn++));
}
fwrite(scanlineOut, iScanlineSizeOut, 1, grey);
}
free(scanlineIn);
free(scanlineOut);
return(1);
}
来源:https://stackoverflow.com/questions/31844871/what-is-wrong-with-this-code-for-writing-grey-scale-bmp-from-an-image-rgb-bmp-pu