What is wrong with this code for writing grey-scale bmp from an image RGB bmp pure C - Windows OS

前端 未结 1 1463
萌比男神i
萌比男神i 2021-01-29 06:30

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.

1条回答
  •  花落未央
    2021-01-29 06:43

    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; 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);
    }   
    

    0 讨论(0)
提交回复
热议问题