英文:
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.
#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;
}
答案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 ...
- In a
.bmp
file, raster lines must be aligned to a multiple of 4. - You're not accounting for the padding at the end of each row.
- Doing
fread/fwrite
a single pixel at a time is slow. - Faster and easier to do the I/O on whole rows.
- 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 <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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论