You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50 Pset4 Resize程序求助:处理像素后文件大小异常波动

Troubleshooting CS50 Pset4 Resize: Unexpected Output File Sizes

Hey there, let's walk through some key areas to investigate for your Resize task issues—BMPs are tricky with their headers, padding, and file pointer management, so these are the most likely spots where things are going off the rails:

Header & Size Calculation Issues

  • You're writing the file header before updating its size! Look at your code: you call fwrite(&bf, ...) first, then modify bf.bfSize afterward. That means the output file gets the original, unmodified file size instead of the scaled one—this breaks the entire file structure right out the gate, leading to invalid sizes or corrupted data.
  • Your bf.bfSize formula is wrong. The line bf.bfSize = (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(bi.biSizeImage)); uses sizeof(bi.biSizeImage)—but bi.biSizeImage is already the total size of the pixel data (in bytes). You don't need to take its size; just use the value directly.
  • Double-check how you're calculating bi.biSizeImage: make sure you're using the scaled width to compute the new padding, and that the formula accounts for every scanline (including padding) multiplied by the scaled height.

Input File Pointer & Loop Logic

  • You're iterating over the scaled height instead of the original height. When you do for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++), bi.biHeight is already the scaled value. That means you're trying to read way more scanlines than exist in the original file—fread will start pulling garbage data once it hits the end of the input, which messes up all subsequent writes. You need to save the original width and height before modifying them, then loop over those original values when reading from the input.
  • Your pixel-reading loop uses the scaled width. The line for (int j = 0; j < bi.biWidth; j++) uses the scaled width to read pixels from the original file, which is way more than the original scanline has. Again, you need to use the original width here to read only the pixels that actually exist in each input scanline.

Padding & Scanline Writing

  • Make sure you're skipping the original padding, not the scaled one. When you call fseek(inptr, padding, SEEK_CUR), that padding variable is calculated using the scaled width—you need to compute and use the original padding value here instead, otherwise you'll skip too many (or too few) bytes in the input file.
  • Double-check that when you write the scaled scanlines n times, you're adding the new scaled padding each time. Your current code does this, but if the padding calculation is wrong (from using original width instead of scaled), this will still break things.

Here's your code for reference:

// resizes a BMP file 
#include <stdio.h> 
#include <stdlib.h> 
#include "bmp.h" 

int main(int argc, char *argv[]) { 
    // ensure proper usage 
    if (argc != 4) { 
        fprintf(stderr, "Usage: resize integer (1-100) infile outfile\n"); 
        return 1; 
    } 

    // remember filenames 
    char *infile = argv[2]; 
    char *outfile = argv[3]; 

    // open input file 
    FILE *inptr = fopen(infile, "r"); 
    if (inptr == NULL) { 
        fprintf(stderr, "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; 
    } 

    int n= atoi(argv[1]); 

    // 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); 
        fprintf(stderr, "Unsupported file format.\n"); 
        return 4; 
    } 

    // modify bitmapinfoheader for height an width 
    bi.biWidth = bi.biWidth*n; 
    bi.biHeight = bi.biHeight*n; 

    // determine padding for scanlines 
    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; 

    // modify bisizeimage 
    bi.biSizeImage = (((bi.biWidth*(sizeof(RGBTRIPLE)))+padding)*abs(bi.biHeight)); 

    // write outfile's BITMAPFILEHEADER 
    fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr); 

    // modify bfsize before writing it 
    bf.bfSize = (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(bi.biSizeImage)); 

    // write outfile's BITMAPINFOHEADER 
    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr); 

    // iterate over infile's scanlines 
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) { 
        // temporary storage for a triple 
        RGBTRIPLE triple; 

        // temporary storage for scanline 
        RGBTRIPLE scanline[bi.biWidth]; 

        //array position counter 
        int arraypos = 0; 

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

            //write to array n times 
            for (int l = 0; l < n; arraypos++, l++) { 
                scanline[arraypos] = triple; 
            } 
        } 

        for (int m = 0; m < n; m++) { 
            // write array to outfile 
            fwrite(&scanline, sizeof(scanline), 1, outptr); 

            // Add padding) 
            for (int k = 0; k < padding; k++) { 
                fputc(0x00, outptr); 
            } 
        } 

        // skip over padding, if any 
        fseek(inptr, padding, SEEK_CUR); 
    } 

    // close infile 
    fclose(inptr); 

    // close outfile 
    fclose(outptr); 

    // success 
    return 0; 
}

内容的提问来源于stack exchange,提问作者juansf111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:36:15