0

I'm not sure where the issue is here, but from the looks of debug I only store anything in my horizontal array (line) once despite seeing the debugger hitting that section of code properly. I assume I misunderstand how pointers work and i'm assigning incorrectly but I don't know how. My instincts tell me that my treating it like an array with [count] is not properly moving positions down the line but I don't know how to properly do this.

    // 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
    int n = abs(atoi(argv[1]));
    char *infile = argv[2];
    char *outfile = argv[3];

    //checks the factor size is within 0 - 100
    if (n < 0 || n > 100)
    {
        printf("Please enter a factor size 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;
    }

    //create new info and file header for outfile
    BITMAPINFOHEADER bi2;
    BITMAPFILEHEADER bf2;
    bi2 = bi;
    bf2 = bf;

    //assign new Height and Width to new header files
    bi2.biWidth = bi.biWidth * n;
    bi2.biHeight = bi.biHeight * n;

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


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

    //edit SizeImage and size in outfile headerfile
    bi2.biSizeImage = ((sizeof(RGBTRIPLE) * bi2.biWidth) + paddingOut) * abs(bi2.biHeight);
    bf2.bfSize = bi2.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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


    //create array to store scanlines in
    RGBTRIPLE *line = malloc(sizeof(RGBTRIPLE) * bi2.biWidth);

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        int count = 0;

        // iterate over pixels in scanline
        for (int j = 0; j < abs(bi.biWidth); j++)
        {
            // temporary storage
            RGBTRIPLE triple;


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

            //write pixel to array n times
            for (int k = 0; k < n; k++)
            {
                line[count] = triple;
                count++;
            }

        }

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

        // write array to outfile n times
        for (int l = 0; l < n; l++)
        {
            fwrite(line, sizeof(sizeof(RGBTRIPLE) * bi2.biWidth ) + 1, n, outptr);
        }

        //add padding
        for (int p = 0; p < paddingOut; p++)
        {
            fputc(0x00, outptr);
        }

    }
    free(line);

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

2 Answers 2

0

In the posted code, the code skips over the padding after each RGBTRIPLE! It should only do this after each row is processed. The code to skip the input padding shouldn't be inside the loop that processes each pixel.

There may be other issues. Without seeing the other header calculations, or the padding calculations, or sample output, there's no way to know.

Programming note: The code copies each individual element in the RGBTRIPLE struct triple. Instead of 3 separate lines of code to copy each element, you could just copy the entire struct at once.

            line[count]=triple;

It's a lot quicker, simpler and more efficient to do the latter.

[EDIT: after new code added.] Still has a few issues.

First, look at the following:

        // write array to outfile n times
        for (int l = 0; l < n; l++)
        {
            fwrite(line, sizeof(line), 1, outptr);
        }

line is a pointer. How large is a pointer? Here's an analogy. My finger is a pointer. It can point at a golf ball, a car, or the moon. In each case, how big is my finger? Does it ever change size? (well, only if I eat too much!) ;-)

Next, when is the padding being added to the output file?

Are you looking at the actual digital data being generated in the output file? It would make it a lot easier to spot patterns!

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

2
  • I did move that padding which was a mistake in placement. I also changed the struct copying to the one line copy which i had only moved away from trying to figure out my issue. I have edited it to include my entire code since my assumptions are wrong on where the issue must lie.
    – De1337ny
    Commented Mar 19, 2019 at 1:27
  • I appreciate your help so far, i've been getting closer and i think i've pinned my problem down to one piece of code and im just not able to think out the math on this one. I was able to replicate small and large perfectly but smiley is a hot mess. I updated my full code above but my issue i believe is with the following for (int l = 0; l < n; l++) { fwrite(line, sizeof(sizeof(RGBTRIPLE) * bi2.biWidth ) + 1, n, outptr); } i know the +1 is hacky but it was what i found to fix small. I cant figure out the math to make that work on all images though
    – De1337ny
    Commented Mar 19, 2019 at 18:00
0

For future readers, unfortunately I was unable to rectify this code and ended up going with moving the file pointer back to the start of the line which is FAR less complicated.

3
  • Hi, what do you mean, moving the pointer to the start of the line?.
    – mach2019
    Commented Apr 5, 2019 at 6:06
  • When reading into a file the system keeps a "bookmark" of where it is called a File Pointer. This basically is the system remembering where it was last time it read. If you look in copy.c the fseek function that skips over padding is actually moving that pointer with inptr as the file its moving within, padding is the variable for how much it needs to move, and SEEK_CUR means the current position of the File Pointer is the reference point to use for the move (if padding is 2 then it moves 2 spots forward from its CURrent spot.)
    – De1337ny
    Commented Apr 5, 2019 at 17:55
  • So instead of the array, i just looped it back to the start of the scanline n times to write out my n lines (had to break this answer up due to character restrictions, sorry) @mach2019
    – De1337ny
    Commented Apr 5, 2019 at 17:58

You must log in to answer this question.

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