CS50 pset 4调整大小垂直拉伸产生奇怪的输出

时间:2017-04-26 16:43:38

标签: c resize logic cs50

#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 scale infile outfile\n");
        return 1;
    }

    // remember filenames
    int n = atoi(argv[1]);
    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;
    }

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


    //Changes the Width and Height of the final image
    bi.biWidth *= n;
    bi.biHeight *= n;

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

    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // iterate over infile's scanlines
    for (int i = 1, biHeight = abs(bi.biHeight) + 1; i < biHeight; i++) {
        //array where the last line will be stored
        for (int curn = 0; curn < n; curn++) {
            long int temp = sizeof(RGBTRIPLE);
            // iterate over pixels in scanline
            for (int j = 0; j < bi.biWidth; j++) {

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

                // write RGB triple to outfile
                for (int k = 0; k < n; k++) {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }
            } 
            fseek(inptr, -temp * bi.biWidth, SEEK_CUR);
        }

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

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

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

这是我正在使用的长段代码。我试图了解同一主题的其他问题,但我无法将答案与我自己的代码相关联。我个人认为n次逻辑存在问题,因为没有它会打印出水平拉伸的图像,但我无法确定解决方案的内容。我的伪代码很简单:

    for each row
        for n times
            for each pixel in the row
                read from inptr
                for n times (second time)
                    write into outptr
                end of n times (second time)
            end of each pixel in the row
    skip over padding
    put the padding back
end of each row

这应该被拉伸Image1

这就是我使用时的样子./resize 4 smiley.bmp final.bmp Image3

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

在撰写biSizeImage之前,您尚未更新bfSizeBITMAPFILEHEADER BITMAPINFOHEADER

此外,新文件的填充将更改。

因此,使用

计算新的填充biSizeImagebfSize
padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth + padding) * abs(bi.biHeight);
bi.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

fseek()填充&#39; intptr&#39;将与'outptr&#39;的不同。因此,将两个填充存储在不同的变量中。