0

I'm editing the post.

I found some code on this side that's using the same pseudocode from Zamyla, so I thought I'd try to understand it and use it in my own program, but I'm having problems. It'd be appreciated if someone on here could help me see what I'm doing wrong and help me fix my code.

/**
 * resize.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Resizes the file whose name is passed to it as a commandline argument.
 */

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

#include "bmp.h"

int main(int argc, char* argv[])
{
    // ensure proper usage
    if (argc != 4)
    {
        printf("Usage: ./resize n infile outfile\n");
        return 1;
    }

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

    // change n into a number so we can use it as such
    int n = atoi(argv[1]);

    if (n <= 0 || n > 100)
    {
        printf("The value provided as the size must be that of a positive integer less than or equal to 100!\n");
        return 2;
    }

    // open input file 
    FILE* inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        printf("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 4;
    }

    // remember the old padding
    int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // remember dimensions of original image
    int img_height = bi.biHeight;
    int img_width = bi.biWidth;

    // calculate dimensions of resized image
    bi.biHeight *= n;
    bi.biWidth *= n;
    int resized_height = bi.biHeight;
    int resized_width = bi.biWidth;

    // determine scanline padding
    int new_padding = (4 - (resized_width * sizeof(RGBTRIPLE)) % 4) % 4;

    // update header info
    bi.biSizeImage = ((resized_width * sizeof(RGBTRIPLE) + new_padding) * abs(resized_height));
    bf.bfSize = bi.biSizeImage + (sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER));

    // 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(img_height); i < biHeight; i++)
    {
        // iterate over pixels in scanline
        for (int j = 0; j < img_width; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

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

            for (int index = 0; index <= n - 1; index++)
            {
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }
        }
        for (int k = 0; k < new_padding; k++)
        {
            fputc(0x00, outptr);
        }
        fseek(inptr, padding, SEEK_CUR);

        // send cursor back by offset bytes
        // before reading the next pixel
        long offset = img_width * sizeof(RGBTRIPLE);
        fseek(inptr, -offset, SEEK_CUR);

        // vertical resize
        // for each row
        for (int l = 0; l < biHeight; l++)
        {
            // temporary storage for triples data
            RGBTRIPLE triple;

            int m;

            for (int iii = 0; iii < n - 1; iii++)
            {
                for (m = 0; m < img_width; m++)
                {
                    // read triples data from infile
                    fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

                    // for n - 1 times:
                        // write pixels and padding to outfile:
                    for (int index = 0; index < n; index++)
                    {
                        // write pixels to outfile
                        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                    }
                }
                // write padding to outfile
                for (int k = 0; k < new_padding; k++)
                {
                    fputc(0x00, outptr);
                }

                // send infile cursor back
                offset = sizeof(RGBTRIPLE) * m;
                fseek(inptr, -1 * offset, SEEK_CUR);
            }
            // write pixels and padding to outfile
            // skip over infile padding:
            for (m = 0; m < img_width; m++)
            {
                fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

                for (int index = 0; index < n; index++)
                {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }
            }
            for (int k = 0; k < new_padding; k++)
            {
                fputc(0x00, outptr);
            }
            fseek(inptr, padding, SEEK_CUR);
        }
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}

I need help to understand so I can use it as my own and I also need to know what I'm doing wrong here and why this code isn't working right.

Am I supposed to be writing padding to the outfile and skipping the infile padding in the horizontal resize part of the code? And if so, do I need to send the infile cursor back to read the RBGTRIPLES data from the beginning for the vertical resize? And if so (if I need to send the cursor back), am I currently doing it incorrectly? How about the way I'm trying to send the cursor back after writing the pixels to the outfile while trying to resize the image vertically?

As for the output that I'm getting as it is right now, that's here: output bmp image from resize program

Yeah. So please help me out.

Of course, the pseudocoe I'm trying to use is still this:

for each row
    for n - 1 times
        write pixels and padding to outfile
        send infile cursor back
    write pixels and padding to outfile
    skip over infile padding

Edit2: It'd be great if @Blauelf could see this and help me out by the way.

1

You'll need four nested loops.

  1. Outermost loop should be using the input image's height (absolute value, that's what "for each row" stands for)
  2. Second loop should be the one going from 0 to n-2 (<n-1) (output rows per input row)
  3. Third loop should be the one using input image's width
  4. Fourth loop going from 0 to n-1 (<n) (output pixels per input pixel in a line)

Loops 3 and 4 should be repated once after loop 2 (with skipping padding instead of going back). That could also be implemented by doing the second loop n instead of n-1 times and skipping a line plus padding (as you went back once too often).

| improve this answer | |
  • thanks for the reply. I've made some changes to the code, so before I make the changes you mentioned, I'll post the code as it currently is in my opening post. I also need to understand what you're saying about where I should skip padding and where I should rewind the cursor. Thanks again. – Osman Zakir Nov 2 '16 at 16:57
  • how do I rewind the cursor back correctly when I keep getting unsigned integer overflow errors? – Osman Zakir Nov 3 '16 at 1:12
  • I edited the post again just now. Made some more edits and included another BMP image. – Osman Zakir Nov 3 '16 at 17:15
  • Thank you very much! It's super helpful. Especially how many repetitions are needed and where the cursor has to move. – CTK2019 Jan 10 at 6:52

You must log in to answer this question.

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