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

What logical condition can I use to skip lines in the logic for f = .8 and f = .4?

首先,这个问题可能需要你15-20分钟的时间来理解。我正在编写一个名为 resize 的程序,它可以调整给定图像的大小。假设下面的table是一张6x6px的24bit 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.8f = 0.5 和 [= 生成以下输出图像 (staff.bmp) 18=] 分别.

$ ~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;
}

对于 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 部分中的代码是不够的。您的大小调整算法似乎仅适用于整数,但您作为挑战者想要采用 'more comfortable' 方式。所以我真的建议你重做你的调整算法,只关注 float 实现,因为它是这里更广泛的情况。

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