CS50 Resize Less:奇怪的bmp输出

时间:2018-04-12 19:59:35

标签: c image-resizing cs50

我已经完成了几十次逻辑并且看起来是正确的,我不知道为什么输出是这样的...有人可以帮助解释为什么这个逻辑输出是错误的吗?

我无法进行调试,因为我不知道如何查看RGBTRIPLE* out_row的内容。我不能用%i,%s,%c,%d来打印它...我真的很无能...... 非常感谢你...

输入
input

比例因子4的输出
output with scale factor 4

笑脸输入
smiley input

带有比例因子1的笑脸输出
smiley output with scale factor 1

以下是代码,我将BITMAPFILEHEADERBITMAPINFOHEADER的输出与样本进行了比较,看起来是正确的。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "bmp.h"

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

    // get n factor
    int n = atoi(argv[1]);

    if (n > (pow(2,23)) - 1 )
    {
        fprintf(stderr, "Error: n is too big\n");
        fprintf(stderr, "Usage: ./resize n infile outfile\n");
        return 5;
    }
    else if (n <= 0)
    {
        fprintf(stderr, "Error: n is too small\n");
        fprintf(stderr, "Usage: ./resize n infile outfile\n");
        return 6;
    }

    // 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;
    }

    // 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;
    }
    printf("biSizeImage: %i, bfSize: %i\n", bi.biSizeImage, bf.bfSize);
    printf("inputheight:%i\n", bi.biHeight);

    // save input data to variable
    int in_width = bi.biWidth;
    int in_height = bi.biHeight;
    printf("temp inheight:%i\n", in_height);
    int in_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // update outfile's HEADER
    bi.biWidth *= n;
    bi.biHeight *= n;
    int out_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + out_padding) * abs(bi.biHeight);
    bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    printf("new_biSizeImage: %i, new_bfSize: %i\n", bi.biSizeImage, bf.bfSize);

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

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

    // allocate memory to store output row
    RGBTRIPLE* out_row = malloc(bi.biWidth * sizeof(RGBTRIPLE));

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(in_height); i < biHeight; i++)
    {
        // initialize counter to write out_row
        int counter = 0;

        // iterate over pixels in scanline
        for (int j = 0; j < in_width; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

            // read RGB triple from infile
            fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

            // write the triple to out_row times n factor
            for (int o = 0; o < n ; o++)
            {
                out_row[counter] = triple;
                counter++;
            }

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

            // write the out_row result and repeat vertically
            for (int m = 0; m < n; m++)
            {
                // write RGB triple to outfile
                fwrite(out_row, sizeof(RGBTRIPLE), bi.biWidth, outptr);

                // then add it back (to demonstrate how)
                for (int k = 0; k < out_padding; k++)
                {
                    fputc(0x00, outptr);
                }
            }
        }
    }

    // release malloc
    free(out_row);

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

2 个答案:

答案 0 :(得分:0)

我从未使用CS50,但就调试而言,尝试使用像gdb这样的调试器。虽然您可能不知道printf的类型,但我相信您可以使用gdb的print语句将其打印出来。如果它是RGB值,我猜它是一个元组(R,G,B)。看到它是一个RGBTRIPLE *,它可能是一个指向元组的指针。希望这很有帮助。这是gdb指南的链接。 https://beej.us/guide/bggdb/

答案 1 :(得分:0)

我很抱歉,我发现了这个错误...我只是意识到,这是一个非常愚蠢的问题。这只是for循环中错误括号的问题。具体而言,// iterate over pixels in scanline缺少}

的部分

这是我第一次使用堆栈溢出,所以我不确定是否需要回答此问题或删除此问题。