Проблема с CS50 Resize (меньше) - изменяет размер только по горизонтали - PullRequest
0 голосов
/ 26 сентября 2019

Я прохожу курс CS50 и застрял в этом задании уже несколько недель.Я чувствовал, что у меня было небольшое прозрение относительно кода, но я столкнулся с камнем преткновения.Мой код корректно изменяет размер изображения, но использует только верхнюю половину изображения, поэтому фактически просто изменяет размеры вбок, оставляя нижнюю половину пустой.

Мой код ниже, любые идеи будут великолепны!

Спасибо ...

// Copies a BMP file

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

    // extract resize factor, convert to float
    float factor = atof(argv[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 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;
    }

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

    //convert sizes by input factor
    int oldbiwidth = bi.biWidth;
    int oldbiheight = bi.biHeight;
    int oldpadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    int oldbisizeimage = ((sizeof(RGBTRIPLE) * bi.biWidth) + padding) * abs(bi.biHeight);
    int oldbfsize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    bi.biWidth *= factor; //convert to new image width
    bi.biHeight *= factor; //convert to new image height
    padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + padding) * abs(bi.biHeight); //convert to new file size in bytes, including pixels and padding
    bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //convert to new file size in bytes, including pixels, padding & headers

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

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

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(oldbiheight); i < biHeight; i++)
    {
        // iterate over pixels in scanline
        for (int j = 0; j < oldbiwidth; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

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

            for (int k = 0; k < factor; k++)
            {
                // write RGB triple to outfile
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }
        }

        // skip over padding, if any
        fseek(inptr, oldpadding, 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;
}

1 Ответ

0 голосов
/ 26 сентября 2019

В BITMAPINFOHEADER ширина и высота увеличены.Но вы расширяете только по горизонтали.

Чтобы развернуть по вертикали, прочитайте каждую строку один раз и запишите ее factor раз.

Вы можете удалить fseek(inptr, oldpadding, SEEK_CUR), поставить смещение в начале,так что вы можете вернуться к строке сканирования и снова прочитать ее, как показано в примере.

Обратите внимание, что в Windows для чтения файлов в двоичном режиме необходимы флаги "wb" и "rb".

if (factor < 1)
{
    return 0;//not prepared
}

for(int i = 0, biHeight = abs(oldbiheight); i < biHeight; i++)
{
    int offset = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
        (oldbiwidth * 3 + oldpadding) * i;

    for(int m = 0; m < factor; m++)//vertical resize
    {
        fseek(inptr, offset, SEEK_SET);//add this for scanline offset
        for(int j = 0; j < oldbiwidth; j++)
        {
            RGBTRIPLE triple;
            fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
            for(int k = 0; k < factor; k++)//horizontal
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
        }
        for(int k = 0; k < padding; k++)
            fputc(0x00, outptr);
    }
    //fseek(inptr, oldpadding, SEEK_CUR); <- remove this, offset is already handled
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...