0

i'm feeling so close to solve it but have some issues with the for loops i tried to debug it and see what's going on but yet there's some things i can't explain specifically with triple variable i'm trying to see how it works but couldn't also i have some doubts with how to skip old padding and when to put the new one, i think it works fine with scale of n but produces colorful image without padding, Any pointers would be much appreciated, here's my code

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

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

    // making argv[1] is factor number
    int n = atoi(argv[1]);

    //ensure n for valid input
    if (n <= 0 || n >= 100)
    {
        printf("n Must be between 0 and 100\n");
        return 1;

    }

    // 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;

    //coping the infile headers to new variables
    BITMAPFILEHEADER new_bf = bf;
    BITMAPINFOHEADER new_bi = bi;

    // calculating new width and height for the image
    new_bi.biWidth *= n;
    new_bi.biHeight *= n;

    //creating new padding with the new width
    int pading = (4 - (new_bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // checking if padding works
    printf("%i\n", pading);

    // calculating the new sizes for the image and the file
    new_bi.biSizeImage = ((sizeof(RGBTRIPLE) * new_bi.biWidth) + pading * abs(new_bi.biHeight));
    new_bf.bfSize = new_bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);


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

    // write new 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++)
    {
        //iterate over row to write it pixel by pixel n times
        for (int s = 0; s < n; s++)
        {
            // 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);
                //printf("%lu\n", sizeof(triple)); it prints so many 3 but idk why! was checking the value of triple to determine how it works in the loop btw

                // write RGB triple to outfile mult by n
                for (int r = 0; r < n; r++)
                {
                    //storing the value of multiplying j's value in the loop from infile to triple variable to write it to outfile
                    //triple = (triple + padding) * j;

                    // write RGB triple to outfile
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }
            }

            // skip over old padding
            fseek(inptr, padding, SEEK_CUR);

            // then add new padding if needed
            for (int k = 0; k < pading; k++)
            {
                fputc(0x00, outptr);
            }

            //move the cursor back to the begining of the row
            if(s < n-1)
            {
                fseek(inptr, -(new_bi.biWidth * sizeof(RGBTRIPLE) + pading), SEEK_CUR);
            }
        }
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
    }

Thanks in advance.

1 Answer 1

0

So close indeed!!!

I'll give you a hint. When you're working with an open file, are you sure that you're using values appropriate for the right file? In other words, input file vars when working with the input file and output file vars when working with the output file?

Side note on variable names. Use clear names for vars, like padding and newpadding, not padding and pading. When they are that similar, it's just asking for trouble. It's almost a guarantee that they'll get confused for each other at some point. Either the wrong one will be used or someone that's unaware won't recognize that they're two different vars (like I did at first.)

BTW, you also have a header issue. ;-)

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

3
  • first things first, thank you for your help it led me to a point for a thought, so i need some of explanation for this point if i may. when BITMAPFILEHEADER bf was declared it means bf variable of data type BITMAPFILEHEADER and have it's Properties but when we fread it, it contains 1 element and that size of that element to read from the inptr FILE so what the element that we read it? should i specify fread(&bf.bfSize ...)to read that specific element? and for the header issue you mentioned you mean that i should use a pointer at some point? like some variable equals &bf for instance?
    – ox0o
    Commented Sep 21, 2019 at 10:27
  • I'm not exactly clear about what you're asking, but I think the answer to all of it is no. First, you want to read the entire header in as one element of type BITMAPFILEHEADER. Understand that the data is stored as one long data chain, and all that data is read into the bf struct that way. Once it's in the struct, the data is accessed by the individual struct elements, so no, you wouldn't read in a particular element from the file. For the header issue, I meant that there is at least one header element that's not correctly calculated. It's a hint, meant for you to go out and look for errors.
    – Cliff B
    Commented Sep 21, 2019 at 11:00
  • i tried to debug the code to find some bugs as you pointed , so i modified some of the code and came across some questions i think it will be appropriate to make a new question for it
    – ox0o
    Commented Sep 21, 2019 at 15:02

You must log in to answer this question.

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