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

蓝咒 提交于 2019-12-02 13:05:36

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);
}   
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!