0

My code is as follows:

/**
 * resize.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Resize a BMP.
 */

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

#include "bmp.h"

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

    // remember filenames and n
    int n = atoi(argv[1]);
    char* infile = argv[2];
    char* outfile = argv[3];

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

    // write outfile's BITMAPINFOHEADER
    BITMAPINFOHEADER biout = bi;
    biout.biWidth = bi.biWidth * n; 
    biout.biHeight = bi.biHeight * n;
    biout.biSizeImage = (((4 - (biout.biWidth * sizeof(RGBTRIPLE)) % 4) % 4 ) * abs(biout.biHeight)) + (biout.biWidth * abs(biout.biHeight) * 3);
    fwrite(&biout, sizeof(BITMAPINFOHEADER), 1, outptr);

    // write outfile's BITMAPFILEHEADER
    BITMAPFILEHEADER bfout = bf;
    bfout.bfSize = biout.biSizeImage + 14 + 40;
    fwrite(&bfout, sizeof(BITMAPFILEHEADER), 1, outptr);

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

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        // Writes scanline n times
        for (int l = 0; l < n; l++)
        {
            // moves SEEK_CUR if repeating the line vertically
            if (l > 0)
            {
                fseek(inptr, ((((4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4) + bi.biWidth * 3) * -1), 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 n times

                for (int k = 0; k < n; k++)
                {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }
            }

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

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

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}

After running resize.c with ./resize 2 small.bmp large.bmp, I was unable to open the large.bmp created as there was an error. So going back to my code, I ran gdb and went line by line to find out what exactly is happening. I found out that after the second iteration of for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) (i = 1 at this point), at line 98 (for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)) executes correctly and reads triple as 00FF00. However the moment the next line executes, triple becomes 000000 instead.

Why is this so? And if there is anything I missed out, please do give me a clue! Coming here is a last resort for me but I have been stuck here for several days so thank you for reading this. :)

1 Answer 1

1

Your triple didn't change, it moved. You have two significant problems. Your headers are wrong and your padding is wrong. You need to get the headers right before moving on to the images. I recommend that you get everything working for n=1 before moving on to n=2. When n=1, the input and output files should be identical. xxd and peek will be your best friends. ;-)

The header problem is an easy fix. There are two headers - in what order do they appear in the file?

Padding: The padding for the output file is not necessarily the same as the padding for the input file. Both paddings need to be calculated, based on the header data for that file.

This will get you going towards solving most of your problems. You might also consider calculating the inpadding and the outpadding only once each, storing the values in those vars and then use the vars to calculate the headers and to process the image.

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

1
  • Thank you very much :) The advice for creating two padding made my code much neater too!
    – Wet Feet
    Commented Feb 8, 2016 at 7:34

You must log in to answer this question.

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