。bmp文件的大小和结果文件的大小错误

问题描述 投票:0回答:1

我一直在尝试编写一个调整位图文件大小的程序,但是我一生都无法弄清为什么输出文件中的文件大小不可用。

我尝试使用其他程序调整大小,然后将文件的大小从486字节调整为1.9kb,大小为2,而我的代码生成的文件大小为3.5kb。请看一下我的代码,希望有人能指出正确的方向,以使我的文件变得肿。

PS:生成的文件具有正确的尺寸,并且看起来也不错,只是文件大小无法正确缩放...

#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "bmp.h"

bool is_valid_count(int argc);
bool is_valid_range(int fact);
bool is_valid_file_type(char *filename);

int main(int argc, char *argv[])
{
    char *n = argv[1];
    int resize_factor = atoi(n);

    // validate
    if (!is_valid_count(argc) ||
        !is_valid_range(resize_factor) ||
        !is_valid_file_type(argv[2]) ||
        !is_valid_file_type(argv[3]))
    {
        printf("USAGE: run resize <resize-factor> <infile.bmp> <outfile.bmp>\n");
        return 1;
    }

    // remember filenames
    char *infile = argv[2];
    char *outfile = argv[3];

    // open input file
    FILE *open_in_file = fopen(infile, "r");
    if (open_in_file == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", infile);
        return 2;
    }

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

    // read infile's BITMAPFILEHEADER
    BITMAPFILEHEADER bitmap_file_header;
    fread(&bitmap_file_header, sizeof(BITMAPFILEHEADER), 1, open_in_file);

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bitmap_info_header;
    fread(&bitmap_info_header, sizeof(BITMAPINFOHEADER), 1, open_in_file);

    // ensure infile is (likely) a 24-bit uncompressed BMP 4.0
    if (bitmap_file_header.bfType != 0x4d42 ||
        bitmap_file_header.bfOffBits != 54 ||
        bitmap_info_header.biSize != 40 ||
        bitmap_info_header.biBitCount != 24 ||
        bitmap_info_header.biCompression != 0)
    {
        fclose(open_out_file);
        fclose(open_in_file);
        fprintf(stderr, "Unsupported file format.\n");
        return 4;
    }

    int padding_old = (4 - (bitmap_info_header.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    LONG old_biWidth = bitmap_info_header.biWidth;

    // resize bitmap
    bitmap_info_header.biHeight *= resize_factor;
    bitmap_info_header.biWidth *= resize_factor;
    int padding_new = (4 - (bitmap_info_header.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    bitmap_info_header.biSizeImage = ((sizeof(RGBTRIPLE) * bitmap_info_header.biWidth) + padding_new) * abs(bitmap_info_header.biHeight);

    bitmap_file_header.bfSize = bitmap_info_header.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    // write outfile's BITMAPFILEHEADER & BITMAPINFOHEADER
    fwrite(&bitmap_file_header, sizeof(BITMAPFILEHEADER), 1, open_out_file);
    fwrite(&bitmap_info_header, sizeof(BITMAPINFOHEADER), 1, open_out_file);

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

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

                for (int l = 0; l < resize_factor; l++)
                {
                    // write RGB triple to outfile
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, open_out_file);
                }
            }

            // add padding
            for (int m = 0; m < padding_new; m++)
            {
                fputc(0x00, open_out_file);
            }
            if (j < resize_factor - 1)
            {
                fseek(open_in_file, -(old_biWidth * (int)sizeof(RGBTRIPLE)), SEEK_CUR);
            }
        }
        // skip over padding, if any
        fseek(open_in_file, padding_old, SEEK_CUR);
    }

    fclose(open_in_file);
    fclose(open_out_file);

    // success
    return 0;
}

bool is_valid_count(int argc)
{
    if (argc != 4)
    {
        printf("Incorrect number of arguments provided. Must be 3!\n");
        return false;
    }

    return true;
}

bool is_valid_range(int fact)
{
    if (fact < 1 || fact > 100)
    {
        printf("Range is invalid.Resize-factor has to be between 1 and 100! Was: %i\n", fact);
        return false;
    }

    return true;
}

bool is_valid_file_type(char *filename)
{
    const char *dot = strrchr(filename, '.');
    const char *extension = ".bmp";

    if (strcmp(dot, extension) != 0)
    {
        printf("Filetype not recognized: %s!\n", dot);
        return false;
    }

    return true;
}
c filesize bmp
1个回答
0
投票
//FILE *open_in_file = fopen(infile, "r");
FILE *open_in_file = fopen(infile, "rb");

//FILE *open_out_file = fopen(outfile, "w");
FILE *open_out_file = fopen(outfile, "wb");

//for (int i = 0, biHeight = abs(bitmap_info_header.biHeight); i < biHeight; i++)
for (int i = 0, biHeight = abs(bitmap_info_header.biHeight)/resize_factor; i < biHeight; i++)
© www.soinside.com 2019 - 2024. All rights reserved.