0

I implemented resize using recopy method as bellow but I think there are still some mistakes in my code that why it didn't yield the correct result. The thing is I'm not really sure how to implement "send infile cursor back". Please give me advice and thank you in advance.

Here is psuedocode: "recopy" method from Resize's Walkthrough

for each row

    for n-1 times

        write pixels, padding to outfile

        send infile cursor back

    write pixels, padding to outfile

    skip over infile padding

Code:

// Resize a BMP file

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "bmp.h"

int main(int argc, char *argv[])
{
    // ensure proper usage
    if (argc != 4)
    {
        fprintf(stderr, "Usage: %s n infile outfile\n", argv[0]);
        return 1;
    }

    // remember filenames
    int n = atoi(argv[1]);
    if ( n < 0 )
    {
        fprintf(stderr, "Usage: %s n infile outfile\n", argv[0]);
        return 2;
    }

    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 3;
    }

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

    // 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 5;
    }
    // determine padding for scanlines
    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    int new_padding = (4 - (n * bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // Update BITMAPINFOHEADER
    BITMAPINFOHEADER new_bi;
    new_bi.biWidth = n * bi.biWidth;
    new_bi.biHeight = n * bi.biHeight;
    new_bi.biSizeImage = ((sizeof(RGBTRIPLE) * new_bi.biWidth) + new_padding) + abs(new_bi.biHeight);

    // Update BITMAPFILEHEADER
    BITMAPFILEHEADER new_bf;
    new_bf.bfSize = new_bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    //printf("%lu\n",sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));



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

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

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        for (int l = 0; l < n - 1 ; l++)
        {
            // iterate over pixels 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 outfile
                for (int a = 0; a < n; a++)
                {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }

            }
            // then add it back (to demonstrate how)
            for (int k = 0; k < new_padding; k++)
            {
                fputc(0x00, outptr);
            }

            // send infile cursor back
            fseek(inptr, padding, SEEK_CUR);
        }

        // iterate over pixels 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 outfile
            for (int a = 0; a < n; a++)
            {
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }

        }
        // then add it back (to demonstrate how)
        for (int k = 0; k < new_padding; k++)
        {
            fputc(0x00, outptr);
        }

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

    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}
0

The main problem is that the code doesn't copy the struct data from the original header structs bi and bf to the new ones, new_bi or new_bf. That means that the headers that are written to the output file contain garbage data. Structs can be copied simply by using this method:

       newstruct = oldstruct;

This will copy every element from the old to the new.

After this, there are still some issues, but they should be easily handled.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

1
  • I really appreciate your help. Thankfully, I am able to find those issues.
    – Optimus
    May 6 '19 at 8:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .