c - 我可以使用什么逻辑条件来跳过 f = .8 和 f = .4 的逻辑行?

标签 c logic cs50

首先,这个问题可能需要你15-20分钟才能理解。我正在编写一个名为 resize 的程序,它可以调整给定图像的大小。假设下表为 6x6px 24 位 bmp 图像,其中 0-35 代表 36 个像素。

row
 1| 0  1  2  3  4  5

 2| 6  7  8  9  10 11

 3| 12 13 14 15 16 17

 4| 18 19 20 21 22 23

 5| 24 25 26 27 28 29

 6| 30 31 32 33 34 35

现在我有一个可以使用的员工程序(不是源代码,只是二进制文件),它为 f = 0.8 生成以下输出图像 (staff.bmp) , f = 0.5f = 0.4分别。

$ ~cs50/hacker4/resize 0.8 test6x6.bmp staff.bmp
f = 0.8
----------
0-3| 12 13 14 15
1-4| 18 19 20 21
2-5| 24 25 26 27
3-6| 30 31 32 33

我对f = 0.8的逻辑的理解如下:这里6是输入文件的高度,4是输出文件的高度,如floor(6 * 0.8) = 4.8 = 4 (floored down)

Logic: 
6 in rows = 4 out rows
in/out rows = 6/4 = 1.5 
current = 0 + 1.5 = 1.5 = 1 #skip

5 in rows = 4 out rows
in/out rows = 5 / 4 = 1.25
current = 1 + 1.25 = 2.25 = 2 #skip

4 in rows = 4 out rows
in/out rows = 4/4  = 1
current = 2 + 1 = 3

3 in rows  =  3 out rows
in/out rows = 3/3 = 1
current = 3 + 1 = 4

2 in rows = 2 out rows 
in/out rows = 2/2 = 1
current = 4 + 1 = 5

1 in rows = 1 out rows 
in/out rows = 1/1 = 1
current = 5 + 1 = 6

对于 f = 0.5:

$ ~cs50/hacker4/resize 0.5 test6x6.bmp staff.bmp
f = 0.5
----------
0-2| 6  8  10

1-4| 18 20 22

2-6| 30 32 34

Logic:
6 in rows = 3 out rows
in/out rows = 6/3 = 2
current = 0 + 2 = 2

4 in rows = 2 out rows
in/out rows = 4/2 = 2
current = 2 + 2 = 4

2 in rows = 1 out row
in/out rows = 2/1  = 2
current = 4 + 2 = 6

最后,对于 f = 0.4:

$ ~cs50/hacker4/resize 0.4 test6x6.bmp staff.bmp
f = 0.4
-------
0-4| 18 20
1-6| 30 32

Logic:
6 in rows = 2 out rows
in/out rows = 6/2  =  3
current = 0  + 3  =  3 #skip

3 in rows = 2 out rows 
in/out rows = 3/2 = 1.5
current = 3 + 1.5 = 4.5 = 4

2 in rows = 1 out rows 
in/out rows = 2/1 = 2 
current = 4 + 2  = 6

我编写了这个程序,当 f 大于 1 时,它可以成功调整图像大小。例如:如果 f 为 2,它将把 6x6px 图像转换为 12x12px 图像。

/**
 * Resizes a BMP piece by piece, just because.
 */

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

    // convert string argument to float
    float f;
    sscanf(argv[1], " %f", &f);

    if(f > 100.0 || f < 0.0) {
        fprintf(stderr, "Usage: ./resize f 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 1;
    }

    // open output file
    FILE *outptr = fopen(outfile, "w");
    if (outptr == NULL)
    {
        fclose(inptr);
        fprintf(stderr, "Could not create %s.\n", outfile);
        return 1;
    }

    // read infile's BITMAPFILEHEADER
    BITMAPFILEHEADER bf, bfOut;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
    bfOut = bf;

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi, biOut;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
    biOut = 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;
    }

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

    //update BITMAPINFOHEADER for new resized file
    biOut.biWidth = floor(bi.biWidth * f);
    biOut.biHeight = floor(bi.biHeight * f);

    // determine padding for output file's scanline
    int paddingOut = (4 - biOut.biWidth * sizeof(RGBTRIPLE) % 4) % 4;

    // calculate output file image size header
    biOut.biSizeImage = ((sizeof(RGBTRIPLE) * biOut.biWidth) + paddingOut) * abs(biOut.biHeight);

    //update BITMAPFILEHEADER for new resized file
    bfOut.bfSize = biOut.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

    //create array in memory for storing scanline of inFile.width elements
    RGBTRIPLE *scanLine = (RGBTRIPLE *) malloc(sizeof(RGBTRIPLE) * bi.biWidth);


    // Iterate over inFile's scanlines one by one.
    int inRows =  abs(bi.biHeight), outRows = abs(biOut.biHeight), current = 0;

    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        // iterate over pixels and store them 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 scanline
            scanLine[j] = triple;
        }

        if(f< 1.0) {
            current += inRows/outRows;
            inRows -= floor(inRows/outRows);
            printf("%i\n", current);
            //***todo****
            //if(condition)
            //  continue;
            outRows--; 
        }

        //write scanline and padding to file n times verticlly 
        int ind;
        for(int m = 0;  m < ceil(f); m++) {

            //scanline
            for(int l = 0; l < biOut.biWidth; l++) {
                ind = l/f;
                fwrite(&scanLine[ind], sizeof(RGBTRIPLE), 1, outptr);
            }

            //padding
            for(int o = 0; o < paddingOut; o++) 
                fputc(0x00, outptr);

        }

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

    // cleanup
    free(scanLine);
    fclose(inptr);
    fclose(outptr);

    // success
    return 0;
}

第 118 行(待办事项部分下)的什么条件将成功 #skiplines(如逻辑),对于 f = 0.8(要跳过的前两行)、f = 0.5(没有要跳过的行)和 f = 0.4 (仅跳过第一行)?

如果你还是不明白问题,这里是full explanation .

最佳答案

您似乎通过首先尝试整数值来开始调试。但是,在裁剪图像之前,如果您确保该程序能够按 float 因子放大图像,这可能会更好,但看起来您没有这样做。因此,请继续为您的 6x6px 图像以及 CS50 的 3x3px small.bmp 尝试 1.51.92.1 等值>.

如果您尝试过并得到一些奇怪的结果(例如将 small.bmp 大小调整为 2.1,生成 6x7px 图像,上边框为 3px,下边框仅为 1px),那么我担心仅在 todo 部分添加一些代码是不够的。您的调整大小算法似乎仅适用于整数,但您作为挑战者,想要采用“更舒适”的方式。因此,我强烈建议您重新调整大小算法,仅关注 float 实现,因为它是这里更广泛的情况。

如果这不是您所期望的,我很抱歉,但如果您需要更多帮助,我将很乐意这样做。

关于c - 我可以使用什么逻辑条件来跳过 f = .8 和 f = .4 的逻辑行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42025377/

相关文章:

javascript - 连续数字的总和JavaScript

c - 我的代码有什么问题? (维吉尼亚密码 cs50,pset2)

c - 这应该是 int,那我们为什么要使用 %s?

c - 动态访问 C 结构

C 中函数的类型冲突

c - 月供C方案

将内容从一个文件复制到另一个文件,段错误

c - 将多维数组传递给 C 中的函数

Python:在执行过程中分析复杂的语句

谁能解释一下为什么会打印 41 吗?