C语言 Problem with bfSize (Pset3, task resize, CS50)



任务是用因子重新调整 bmp 图像。我的代码在视觉上工作,当我检查重新调整的图片的六十进制并且大小正确时,它看起来是正确的,但 check50 说图片太大。我通过下载图片检查了大小,并通过CS50 IDE查看了十六进制。我还尝试了GitHub上的其他代码,但该代码也被Check50拒绝。错误是什么?提前感谢!

// Copies a BMP file
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: copy infile outfilen");
return 1;
}
// remember filenames
int factor = atoi(argv[1]);
char *infile = argv[2];
char *outfile = argv[3];
if(factor < 0 || factor > 100)
{
printf("facor must be between 0 and 100n");
return 15;
}
// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.n", infile);
return 2;
}
// open output file
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
printf("Could not create %s.n", outfile);
return 3;
}
// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
bi.biBitCount != 24 || bi.biCompression != 0)
{
fclose(outptr);
fclose(inptr);
printf("Unsupported file format.n");
return 4;
}
//adjust fileheader
BITMAPFILEHEADER bf_out = bf;
BITMAPINFOHEADER bi_out = bi;
//HEIGHT AND WIDTH
bi_out.biWidth = bi.biWidth * factor;
bi_out.biHeight = bi.biHeight * factor;
// determine padding for scanlines
int padding = (4 - (bi_out.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
//IMAGESIZE
bi_out.biSizeImage = bi_out.biHeight * bi_out.biWidth * sizeof(RGBTRIPLE)+ padding;
//BITMAPFILEHEADER
bf_out.bfSize = bi_out.biSizeImage - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER);

// write outfile's BITMAPFILEHEADER
fwrite(&bf_out, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi_out, sizeof(BITMAPINFOHEADER), 1, outptr);
printf("Original bfSize: %dn", bf.bfSize);
printf("Resized bfSize: %dn", bf_out.bfSize);
printf("Bitmapinfoheader: %lun", sizeof(BITMAPINFOHEADER));
printf("Bitmapfileheader: %lun", sizeof(BITMAPFILEHEADER));
printf("Original biSizeImage: %dn", bi.biSizeImage);
printf("Resized biSizeImage: %dn", bi_out.biSizeImage);
printf("Original biWidth: %dn", bi.biWidth);
printf("Original biHeight: %dn", bi.biHeight);
printf("Resized biWidth: %dn", bi_out.biWidth);
printf("Resized biHeight: %dn", bi_out.biHeight);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
// temporary storage
RGBTRIPLE triple[bi.biWidth];
// iterate over pixels in scanline
for (int j = 0; j < bi.biWidth; j++)
{
// read RGB triple from infile
fread(&triple[j], sizeof(RGBTRIPLE), 1, inptr);
}
for(int l = 0; l < factor; l++)
{
for(int o = 0; o < bi.biWidth; o++)
{
for(int g = 0; g < factor; g++)
{
fwrite(&triple[o], sizeof(RGBTRIPLE), 1, outptr);
}
}
for (int k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// success
return 0;
}

在网上寻找解决方案后,我终于设法找到了一个我也理解的工作代码。也许它会帮助有类似问题的人。该解决方案适用于 while 循环而不是 for 循环,并且填充是在内部循环之外完成的,但尽管如此,代码几乎相同。

/**
* resize.c
*
* Computer Science 50
* Problem Set 4
*
* Copies a BMP piece by piece, but also resizes it, just because.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./resize factor infile outfilen");
return 1;
}
// remember filenames and resize factor
int factor = atoi(argv[1]);
char* infile = argv[2];
char* outfile = argv[3];
// check factor
if (factor < 1 || factor > 100)
{
printf("Factor must be in the range [1-100]n");
return 1;
}
// open input file 
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.n", infile);
return 2;
}
// open output file
FILE* outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.n", outfile);
return 3;
}
// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
BITMAPFILEHEADER bf_new;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
bf_new = bf;
// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
BITMAPINFOHEADER bi_new;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
bi_new = bi;
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 || 
bi.biBitCount != 24 || bi.biCompression != 0)
{
fclose(outptr);
fclose(inptr);
fprintf(stderr, "Unsupported file format.n");
return 4;
}
// set new width and height dimensions
bi_new.biWidth = bi.biWidth * factor;
bi_new.biHeight = bi.biHeight * factor;
// determine padding for scanlines
int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int new_padding =  (4 - (bi_new.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// set new file size
bf_new.bfSize = 54 + (bi_new.biWidth * sizeof(RGBTRIPLE) + new_padding) * abs(bi_new.biHeight);
bi_new.biSizeImage = bf_new.bfSize - 54;

// write outfile's BITMAPFILEHEADER
fwrite(&bf_new, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi_new, sizeof(BITMAPINFOHEADER), 1, outptr);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
// each row will be printed out factor times
int rowcounter = 0;
while (rowcounter < factor)
{
// iterate over pixels in scanline
for (int j = 0; j < bi.biWidth; j++)
{
// temporary storage
RGBTRIPLE triple;
// each pixel will be printed out factor times
int pixelcounter = 0;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// write RGB triple to outfile
while (pixelcounter < factor)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
pixelcounter++;
}
}
// add new padding
for (int k = 0; k < new_padding; k++)
fputc(0x00, outptr);
// seek back to the beginning of row in input file, but not after iteration of printing
if (rowcounter < (factor - 1))
fseek(inptr, -(bi.biWidth * sizeof(RGBTRIPLE)), SEEK_CUR);
rowcounter++;
}
// skip over padding, if any
fseek(inptr, padding, SEEK_CUR);
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
//BITMAPFILEHEADER
bf_out.bfSize = bi_out.biSizeImage - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER);

文件大小是图像大小加上标题的大小。不减。

你可以替换这个

// temporary storage
RGBTRIPLE triple[bi.biWidth];
// iterate over pixels in scanline
for (int j = 0; j < bi.biWidth; j++)
{
// read RGB triple from infile
fread(&triple[j], sizeof(RGBTRIPLE), 1, inptr);
}

只需一个电话。无需循环。

RGBTRIPLE triple[bi.biWidth];
fread(triple, sizeof(RGBTRIPLE), bi.biWidth, inptr);

您还需要计算原始图像的填充,然后在读入缓冲区后查找过去。

相关内容

  • 没有找到相关文章

最新更新