使用均值滤波转换的彩色BMP图像导致了倾斜,而其他图像则成功。

huangapple go评论61阅读模式
英文:

Color BMP image converted with mean filter results in skewing while others are successful

问题

I'll provide a translation of the code you provided without the comments. Please note that the code includes some HTML entities (e.g., ") that need to be converted to their respective characters in the code for it to work properly.

#include <stdio.h>
#include <stdlib.h>
#define getLineBytes(biWidth, biBitCount) (biWidth * biBitCount / 8 + 3) / 4 * 4;

#pragma pack(1)
typedef struct tagBITMAPFILEHEADER {
    unsigned char bfType[2];
    unsigned long bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned long bfOffBits;
} fileHeader;

typedef struct tagBITMAPINFOHEADER {
    unsigned long biSize;
    long biWidth;
    long biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned long biCompression;
    unsigned long biSizeImage;
    long biXPixPerMeter;
    long biYPixPerMeter;
    unsigned long biClrUsed;
    unsigned long biClrImportant;
} fileInfo;

typedef struct tagRGBQUAD {
    unsigned char rgbBlue;
    unsigned char rgbGreen;
    unsigned char rgbRed;
    unsigned char rgbReserved;
} rgbq;

void readBMP(FILE *fpBMP, fileHeader *fh, fileInfo *fi, rgbq *fq) {
    fread(fh, sizeof(fileHeader), 1, fpBMP);
    fread(fi, sizeof(fileInfo), 1, fpBMP);
    long oldBiWidth = getLineBytes(fi->biWidth, fi->biBitCount);
    fi->biBitCount = 8;
    long newBiWidth = getLineBytes(fi->biWidth, fi->biBitCount);
    fi->biSizeImage = newBiWidth * fi->biHeight;
    fh->bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
    fh->bfSize = fh->bfOffBits + fi->biSizeImage;
    for (int i = 0; i < 256; i++) {
        fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;
    }
}

void writeBMP(FILE *fpGray, fileHeader *fh, fileInfo *fi, rgbq *fq) {
    fwrite(fh, sizeof(fileHeader), 1, fpGray);
    fwrite(fi, sizeof(fileInfo), 1, fpGray);
    fwrite(fq, sizeof(rgbq), 256, fpGray);
}

void convertToGray(FILE *fpBMP, FILE *fpGray, fileInfo *fi) {
    unsigned char rgbImgData[3];
    unsigned int grayImgData;
    unsigned char rgbAnthor;
    long oldBiWidth = getLineBytes(fi->biWidth, fi->biBitCount);
    long newBiWidth = getLineBytes(fi->biWidth, 8);
    for (int i = 0; i < fi->biHeight; i++) {
        for (int j = 0; j < newBiWidth; j++) {
            if (j < fi->biWidth)
            {
                for (int k = 0; k < 3; k++) {
                    fread(&rgbImgData[k], 1, 1, fpBMP);
                }
                grayImgData = (int)((float)rgbImgData[0] * 0.299 + (float)rgbImgData[1] * 0.587 + (float)rgbImgData[2] * 0.114);
            }
            else {
                grayImgData = 0;
            }
            fwrite(&grayImgData,1, 1, fpGray);
        }
        for (int k = fi->biWidth * 3; k < oldBiWidth; k++) {
            fread(&rgbAnthor, 1, 1, fpBMP);
        }
    }   
}

int main() {
    unsigned char bmpRGBPath[] = "test.bmp";
    unsigned char bmpGrayPath[] = "gray.bmp";
    FILE *fpBMP, *fpGray;
    fileHeader fh;
    fileInfo fi;
    rgbq fq[256];
    fpBMP = fopen(bmpRGBPath, "rb");
    fpGray = fopen(bmpGrayPath, "wb");
    readBMP(fpBMP, &fh, &fi, fq);
    writeBMP(fpGray, &fh, &fi, fq);
    convertToGray(fpBMP, fpGray, &fi);
    fclose(fpGray);
    fclose(fpBMP);
    return 0;
}

Please ensure that you've corrected the HTML entities in the code to their actual characters for it to work correctly.

英文:

Excuse me, I'm working on my computer course assignment, which is about image filtering with mean filter. It is required not to use external libraries of C++ and C language, but now it has encountered some errors. I am processing a color BMP image with a width of 322 and a height of 315. As can be seen in the following image, the converted image is skewed, while there is no error in converting other images, and they are successfully converted. However, when I use Python to convert the image below, it can be converted normally.

使用均值滤波转换的彩色BMP图像导致了倾斜,而其他图像则成功。

使用均值滤波转换的彩色BMP图像导致了倾斜,而其他图像则成功。

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#define getLineBytes(biWidth, biBitCount) (biWidth * biBitCount / 8 + 3) / 4 * 4;
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER {
    unsigned char bfType[2];
    unsigned long bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned long bfOffBits;
} fileHeader;

typedef struct tagBITMAPINFOHEADER {
    unsigned long biSize;
    long biWidth;
    long biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned long biCompression;
    unsigned long biSizeImage;
    long biXPixPerMeter;
    long biYPixPerMeter;
    unsigned long biClrUsed;
    unsigned long biClrImportant;
} fileInfo;

typedef struct tagRGBQUAD {
    unsigned char rgbBlue;
    unsigned char rgbGreen;
    unsigned char rgbRed;
    unsigned char rgbReserved;
} rgbq;

void readBMP(FILE *fpBMP, fileHeader *fh, fileInfo *fi, rgbq *fq) {
    fread(fh, sizeof(fileHeader), 1, fpBMP);
    fread(fi, sizeof(fileInfo), 1, fpBMP);
    long oldBiWidth = getLineBytes(fi-&gt;biWidth, fi-&gt;biBitCount);
    fi-&gt;biBitCount = 8;
    long newBiWidth = getLineBytes(fi-&gt;biWidth, fi-&gt;biBitCount);
    fi-&gt;biSizeImage = newBiWidth * fi-&gt;biHeight;
    fh-&gt;bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
    fh-&gt;bfSize = fh-&gt;bfOffBits + fi-&gt;biSizeImage;
    for (int i = 0; i &lt; 256; i++) {
        fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;
    }
}

void writeBMP(FILE *fpGray, fileHeader *fh, fileInfo *fi, rgbq *fq) {
    fwrite(fh, sizeof(fileHeader), 1, fpGray);
    fwrite(fi, sizeof(fileInfo), 1, fpGray);
    fwrite(fq, sizeof(rgbq), 256, fpGray);
}

void convertToGray(FILE *fpBMP, FILE *fpGray, fileInfo *fi) {
    unsigned char rgbImgData[3];
    unsigned int grayImgData;
    unsigned char rgbAnthor;
    long oldBiWidth = getLineBytes(fi-&gt;biWidth, fi-&gt;biBitCount);
    long newBiWidth = getLineBytes(fi-&gt;biWidth, 8);
    for (int i = 0; i &lt; fi-&gt;biHeight; i++) {
        for (int j = 0; j &lt; newBiWidth; j++) {
            if (j &lt; fi-&gt;biWidth)
            {
                for (int k = 0; k &lt; 3; k++) {
                    fread(&amp;rgbImgData[k], 1, 1, fpBMP);
                }
                grayImgData = (int)((float)rgbImgData[0] * 0.299 + (float)rgbImgData[1] * 0.587 + (float)rgbImgData[2] * 0.114);
            }
            else {
                grayImgData = 0;
            }
            fwrite(&amp;grayImgData,1, 1, fpGray);
        }
        for (int k = fi-&gt;biWidth * 3; k &lt; oldBiWidth; k++) {
            fread(&amp;rgbAnthor, 1, 1, fpBMP);
        }
	}   
}

int main() {
    unsigned char bmpRGBPath[] = &quot;test.bmp&quot;;
    unsigned char bmpGrayPath[] = &quot;gray.bmp&quot;;
    FILE *fpBMP, *fpGray;
    fileHeader fh;
    fileInfo fi;
    rgbq fq[256];
	fpBMP = fopen(bmpRGBPath, &quot;rb&quot;);
    fpGray = fopen(bmpGrayPath, &quot;wb&quot;);
    readBMP(fpBMP, &amp;fh, &amp;fi, fq);
    writeBMP(fpGray, &amp;fh, &amp;fi, fq);
    convertToGray(fpBMP, fpGray, &amp;fi);
    fclose(fpGray);
    fclose(fpBMP);
    return 0;
}

答案1

得分: 0

以下是翻译好的代码部分:

// gfxdemo/bmporig.c -- BMP to grayscale demo

#include <stdio.h>

//#define MPACKED			__attribute__((packed))
#define MPACKED			/**/

#if DEBUG
#define dbgprt(_fmt...) \
    printf(_fmt)
#else
#define dbgprt(_fmt...) \
    do { } while (0)
#endif

#define xfread(_xf,_ptr,_len) \
    fread(_ptr,1,_len,_xf)
#define xfwrite(_xf,_ptr,_len) \
    fwrite(_ptr,1,_len,_xf)

// winX compatible types
typedef unsigned char BYTE, *PBYTE, *LPBYTE;
typedef short SHORT, *PSHORT, *LPSHORT;
typedef unsigned short WORD, *PWORD, *LPWORD;
typedef int LONG, *PLONG, *LPLONG;
typedef unsigned int ULONG, *PULONG, *LPULONG;
typedef unsigned int DWORD, *PDWORD, *LPDWORD;

#pragma pack(1)

typedef struct tagBITMAPFILEHEADER {
    BYTE bfType[2];
    DWORD bfSize;
    WORD bfReserved1;
    WORD bfReserved2;
    DWORD bfOffBits;
} MPACKED fileHeader;

typedef struct tagBITMAPINFOHEADER {
    DWORD biSize;
    LONG biWidth;
    LONG biHeight;
    WORD biPlanes;
    WORD biBitCount;
    DWORD biCompression;
    DWORD biSizeImage;
    LONG biXPixPerMeter;
    LONG biYPixPerMeter;
    DWORD biClrUsed;
    DWORD biClrImportant;
} MPACKED fileInfo;

typedef struct tagRGBQUAD {
    BYTE rgbBlue;
    BYTE rgbGreen;
    BYTE rgbRed;
    BYTE rgbReserved;
} MPACKED rgbq;

#define BMPOFF_HDR		0
#define BMPOFF_INFO		(BMPOFF_HDR + sizeof(fileHeader))
#define BMPOFF_CMAP		(BMPOFF_INFO + sizeof(fileInfo))
#define BMPOFF_DATA		(BMPOFF_CMAP + (sizeof(rgbq) * 256))

// bmp_line_bytes -- get number of bytes in line (i.e. the stride)
int
bmp_line_bytes(int biWidth, int biBitCount)
{

    return (biWidth * biBitCount / 8 + 3) / 4 * 4;
}

// readBMP -- read in BMP header/info/cmap
void
readBMP(FILE *fpBMP, fileHeader *fh, fileInfo *fi, rgbq *fq)
{

    xfread(fpBMP, fh, sizeof(*fh));
    xfread(fpBMP, fi, sizeof(*fi));
    xfread(fpBMP, fq, sizeof(*fq) * 256);
}

// writeBMP -- write out BMP header/info/cmap
void
writeBMP(FILE *fpGray, fileHeader *fh, fileInfo *fi, rgbq *fq)
{
    xfwrite(fpGray, fh, sizeof(*fh));
    xfwrite(fpGray, fi, sizeof(*fi));
    xfwrite(fpGray, fq, sizeof(*fq) * 256);
}

void
convertToGray(FILE *fpBMP, FILE *fpGray, fileHeader *fh, fileInfo *fi, rgbq *fq)
{
    unsigned int grayImgData;

    readBMP(fpBMP, fh, fi, fq);

    dbgprt("convertToGray: biWidth=%d biBitCount=%d\n",
        fi->biWidth,fi->biBitCount);

    // get stride of input file
    int oldBiWidth = bmp_line_bytes(fi->biWidth,fi->biBitCount);
    dbgprt("convertToGray: oldBiWidth=%d\n",oldBiWidth);
    BYTE oldbuf[oldBiWidth];

    // get stride of output file
    fi->biBitCount = 8;
    int newBiWidth = bmp_line_bytes(fi->biWidth, fi->biBitCount);
    dbgprt("convertToGray: newBiWidth=%d\n",newBiWidth);
    BYTE newbuf[newBiWidth];

    fi->biSizeImage = newBiWidth * fi->biHeight;
    fh->bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
    fh->bfSize = fh->bfOffBits + fi->biSizeImage;

    // convert colormap to grayscale
    for (int i = 0; i < 256; i++)
        fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;

    // output new headers
    writeBMP(fpGray, fh, fi, fq);

    // position streams to place for pixel data
    fseek(fpBMP, BMPOFF_DATA, SEEK_SET);
    fseek(fpGray, BMPOFF_DATA, SEEK_SET);

    for (int i = 0;  i < fi->biHeight;  i++) {
        // read in current input row
        //fseek(fpBMP, BMPOFF_DATA + (i * oldBiWidth), SEEK_SET);
        xfread(fpBMP, oldbuf, sizeof(oldbuf));

        // create output row
        BYTE *old = oldbuf;
        for (int j = 0;  j < newBiWidth;  j++, old += 3) {
            if (j < fi->biWidth) {
                grayImgData = (int) ((float) old[0] * 0.299 +
                    (float) old[1] * 0.587 +
                    (float) old[2] * 0.114);
            }
            else
                grayImgData = 0;

            newbuf[j] = grayImgData;
        }

        // write out output row
        //fseek(fpGray, BMPOFF_DATA + (i * newBiWidth), SEEK_SET);
        xfwrite(fpGray, newbuf, sizeof(newbuf));
    }
}

int
main(void)
{
    const char *bmpRGBPath = "inp.bmp";
    const char *bmpGrayPath = "out.bmp";

    FILE *fpBMP;
    FILE *fpGray;

    fileHeader fh;
    fileInfo fi;
    rgbq fq[256];

    fpBMP = fopen(bmpRGBPath, "rb");
    fpGray = fopen(bmpGrayPath, "wb");

    convertToGray(fpBMP, fpGray, &fh, &fi, fq);

    fclose(fpGray);
    fclose(fpBMP);

    return 0;
}

希望这对您有所帮助!

英文:

A few issues ...

  1. In a .bmp file, raster lines must be aligned to a multiple of 4.
  2. You're not accounting for the padding at the end of each row.
  3. Doing fread/fwrite a single pixel at a time is slow.
  4. Faster and easier to do the I/O on whole rows.
  5. Unless you're compiling for 32 bit mode, using long in the structs is incorrect.

Here is the corrected code. It is annotated.

By reading/writing a row at a time (i.e. the row stride), it accounts for the padding without seeking the file.

// gfxdemo/bmporig.c -- BMP to grayscale demo
#include &lt;stdio.h&gt;
//#define MPACKED			__attribute__((packed))
#define MPACKED			/**/
#if DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
#define xfread(_xf,_ptr,_len) \
fread(_ptr,1,_len,_xf)
#define xfwrite(_xf,_ptr,_len) \
fwrite(_ptr,1,_len,_xf)
// winX compatible types
typedef unsigned char BYTE, *PBYTE, *LPBYTE;
typedef short SHORT, *PSHORT, *LPSHORT;
typedef unsigned short WORD, *PWORD, *LPWORD;
typedef int LONG, *PLONG, *LPLONG;
typedef unsigned int ULONG, *PULONG, *LPULONG;
typedef unsigned int DWORD, *PDWORD, *LPDWORD;
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER {
BYTE bfType[2];
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} MPACKED fileHeader;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPixPerMeter;
LONG biYPixPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} MPACKED fileInfo;
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} MPACKED rgbq;
#define BMPOFF_HDR		0
#define BMPOFF_INFO		(BMPOFF_HDR + sizeof(fileHeader))
#define BMPOFF_CMAP		(BMPOFF_INFO + sizeof(fileInfo))
#define BMPOFF_DATA		(BMPOFF_CMAP + (sizeof(rgbq) * 256))
// bmp_line_bytes -- get number of bytes in line (i.e. the stride)
int
bmp_line_bytes(int biWidth, int biBitCount)
{
return (biWidth * biBitCount / 8 + 3) / 4 * 4;
}
// readBMP -- read in BMP header/info/cmap
void
readBMP(FILE *fpBMP, fileHeader *fh, fileInfo *fi, rgbq *fq)
{
xfread(fpBMP, fh, sizeof(*fh));
xfread(fpBMP, fi, sizeof(*fi));
xfread(fpBMP, fq, sizeof(*fq) * 256);
}
// writeBMP -- write out BMP header/info/cmap
void
writeBMP(FILE *fpGray, fileHeader *fh, fileInfo *fi, rgbq *fq)
{
xfwrite(fpGray, fh, sizeof(*fh));
xfwrite(fpGray, fi, sizeof(*fi));
xfwrite(fpGray, fq, sizeof(*fq) * 256);
}
void
convertToGray(FILE *fpBMP, FILE *fpGray, fileHeader *fh, fileInfo *fi, rgbq *fq)
{
unsigned int grayImgData;
readBMP(fpBMP, fh, fi, fq);
dbgprt(&quot;convertToGray: biWidth=%d biBitCount=%d\n&quot;,
fi-&gt;biWidth,fi-&gt;biBitCount);
// get stride of input file
int oldBiWidth = bmp_line_bytes(fi-&gt;biWidth,fi-&gt;biBitCount);
dbgprt(&quot;convertToGray: oldBiWidth=%d\n&quot;,oldBiWidth);
BYTE oldbuf[oldBiWidth];
// get stride of output file
fi-&gt;biBitCount = 8;
int newBiWidth = bmp_line_bytes(fi-&gt;biWidth, fi-&gt;biBitCount);
dbgprt(&quot;convertToGray: newBiWidth=%d\n&quot;,newBiWidth);
BYTE newbuf[newBiWidth];
fi-&gt;biSizeImage = newBiWidth * fi-&gt;biHeight;
fh-&gt;bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
fh-&gt;bfSize = fh-&gt;bfOffBits + fi-&gt;biSizeImage;
// convert colormap to grayscale
for (int i = 0; i &lt; 256; i++)
fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;
// output new headers
writeBMP(fpGray, fh, fi, fq);
// position streams to place for pixel data
fseek(fpBMP, BMPOFF_DATA, SEEK_SET);
fseek(fpGray, BMPOFF_DATA, SEEK_SET);
for (int i = 0;  i &lt; fi-&gt;biHeight;  i++) {
// read in current input row
//fseek(fpBMP, BMPOFF_DATA + (i * oldBiWidth), SEEK_SET);
xfread(fpBMP, oldbuf, sizeof(oldbuf));
// create output row
BYTE *old = oldbuf;
for (int j = 0;  j &lt; newBiWidth;  j++, old += 3) {
if (j &lt; fi-&gt;biWidth) {
grayImgData = (int) ((float) old[0] * 0.299 +
(float) old[1] * 0.587 +
(float) old[2] * 0.114);
}
else
grayImgData = 0;
newbuf[j] = grayImgData;
}
// write out output row
//fseek(fpGray, BMPOFF_DATA + (i * newBiWidth), SEEK_SET);
xfwrite(fpGray, newbuf, sizeof(newbuf));
}
}
int
main(void)
{
const char *bmpRGBPath = &quot;inp.bmp&quot;;
const char *bmpGrayPath = &quot;out.bmp&quot;;
FILE *fpBMP;
FILE *fpGray;
fileHeader fh;
fileInfo fi;
rgbq fq[256];
fpBMP = fopen(bmpRGBPath, &quot;rb&quot;);
fpGray = fopen(bmpGrayPath, &quot;wb&quot;);
convertToGray(fpBMP, fpGray, &amp;fh, &amp;fi, fq);
fclose(fpGray);
fclose(fpBMP);
return 0;
}

huangapple
  • 本文由 发表于 2023年5月21日 15:06:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76298690.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定