我可以使用什么逻辑条件来跳过 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.8
、f = 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.5
、1.9
和 2.1
等值
如果您尝试了它并得到了一些奇怪的结果(比如将 small.bmp
的大小调整为 2.1,导致图像为 6x7px,上边框为 3px,下边框仅为 1px),那么恐怕只是添加一些todo
部分中的代码是不够的。您的大小调整算法似乎仅适用于整数,但您作为挑战者想要采用 'more comfortable' 方式。所以我真的建议你重做你的调整算法,只关注 float
实现,因为它是这里更广泛的情况。
如果这不是您所期望的,我很抱歉,但如果您需要更多帮助,我会很乐意这样做。
首先,这个问题可能需要你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.8
、f = 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.5
、1.9
和 2.1
等值
如果您尝试了它并得到了一些奇怪的结果(比如将 small.bmp
的大小调整为 2.1,导致图像为 6x7px,上边框为 3px,下边框仅为 1px),那么恐怕只是添加一些todo
部分中的代码是不够的。您的大小调整算法似乎仅适用于整数,但您作为挑战者想要采用 'more comfortable' 方式。所以我真的建议你重做你的调整算法,只关注 float
实现,因为它是这里更广泛的情况。
如果这不是您所期望的,我很抱歉,但如果您需要更多帮助,我会很乐意这样做。