0

I am stuck at this problem for a long time now. I understand the logic as : the width, padding and length of the image are different. so calculate them differently.

Read each pixel from the input file, repeat it for n times and move to next pixel doing the same for the entire line. At the same time capture this in some kind of buffer. Print the line for n number of times and then move on to the next line.

Please let me know what is wrong in this code.

Thanks, Aniket

/**
 * resize.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Copies a BMP piece by piece, at the same time resizing it as per requested input.
 */

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

#include "bmp.h"

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

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

    //remember the factor
    int scale=atoi(argv[1]);

    // 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_in;
    fread(&bf_in, sizeof(BITMAPFILEHEADER), 1, inptr);

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi_in;
    fread(&bi_in, sizeof(BITMAPINFOHEADER), 1, inptr);

    // determine outfile's BITMAPFILEHEADER
    BITMAPFILEHEADER bf_out;
    bf_out=bf_in;

    // determine outfile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi_out;
    bi_out=bi_in;

    bi_out.biWidth=bi_in.biWidth*scale;
    bi_out.biHeight=bi_in.biHeight*scale;

    // determine padding for scanlines
    int padding_in =  (4 - (bi_in.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    // calculate output file padding for printlines
    // each pixel is repeated n times in each line.
    int padding_out =  (4 - (bi_out.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    bi_out.biSizeImage=bi_out.biWidth * sizeof(RGBTRIPLE) + padding_out;
    bf_out.bfSize=(bf_in.bfSize - bi_in.biSizeImage) + bi_out.biSizeImage;             // calculate file size

    // ensure infile is (likely) a 24-bit uncompressed BMP 4.0
    if (bf_in.bfType != 0x4d42 || bf_in.bfOffBits != 54 || bi_in.biSize != 40 || 
        bi_in.biBitCount != 24 || bi_in.biCompression != 0)
    {
        fclose(outptr);
        fclose(inptr);
        fprintf(stderr, "Unsupported file format.\n");
        return 4;
    }

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

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

    // iterate over infile's scanlines

    //create a buffer to store the entire line of pixels you want to print
    //declare an array of RGBTIPLE
    RGBTRIPLE *out_scanline = malloc(sizeof(RGBTRIPLE) * bi_out.biWidth);

    //get the height of the input image    
    for (int i = 0, biHeight = abs(bi_in.biHeight); i < (biHeight); i++){

        //start at the 0th pixel of each line
        int ptr=0;

        // for every COLOR PIXEL (i.e. excluding padding)
        for (int j = 0; j < bi_in.biWidth; j++){
            RGBTRIPLE buffer;
            // read one RGB triple from infile
            fread(&buffer, sizeof(RGBTRIPLE), 1, inptr);

            //repeat the pixel 'scale' times to enlarge the image horizontally and store/append to the 'output line' array of bits
            for(int pix_rep=0; pix_rep<scale; pix_rep++){
                *(out_scanline+(ptr)) = buffer;
                ptr++;
            }

        }

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

        //print the entire horizontally expanded line (including the padding) 'scale' number of times
        //to expand the image vertically
        for (int line_rep=0;line_rep<scale;line_rep++){
            fwrite(&out_scanline, sizeof(out_scanline), 1, outptr);

            // add the padding back to the line
            for (int m = 0; m < padding_out; m++){
                fputc(0x00, outptr);

            }

        }
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);
    // that's all folks! Have fun!
    return 0;
}
2
  • It would certainly help if you could give us a hint, what error you are getting: is the code compiling? how does the output look? It would also help if you posted your entire code. – mor3dr3ad Aug 5 '16 at 8:49
  • Thanks for your response on this. The code does compile successfully. In the output the image does not seem to expand vertically. I have edited the post to include full code. COuld you please have a look? Thanks. – Aniket Pathak Aug 5 '16 at 16:36
0

Your logic is in the right direction. Let me document your code a little more with comments:

// get the height of the image, and for each line of the image, do the following
for (int i = 0, biHeight = abs(bi.biHeight); i < (biHeight); i++)
{
    // start at the 0th pixel on this line
    int ptr = 0;

    // for every COLOR PIXEL (i.e. excluding padding)
    for (int j = 0; j < bi.biWidth; j++)
    {
        // create a buffer to store the value of the pixel
        RGBTRIPLE buffer;
        // read RGB triple from infile
        fread(&buffer, sizeof(RGBTRIPLE), 1, inptr);

        // now paste the same pixel, n times, to the outfile (to resize horizontally)
        for(int pix_rep = 0; pix_rep < n; pix_rep++)
        {
            // here I assume you have declared `RGBTRIPLE triple[]` somewhere
            // above this code, and you have allocated the necessary memory
            // needed, and you assign to `triple[ptr]` the buffered pixel n
            // times. I don't think `triple` is a good name in this case,
            // because `triple` holds the whole line for your outfile. Maybe
            // something like out_scanline or something would be better
            *(triple + ptr) = buffer;
            ptr++;
        }

    }

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

    // now paste the same `out_scanline` n times to outfile (to resize vertically)
    for (int line_rep = 0; line_rep < n; line_rep++)
    {
        fwrite(&triple, sizeof(triple), 1, outptr);

        // also paste the out_padding at the end of every out_scanline
        for (int m = 0; m < padding_o; m++)
        {
            fputc(0x00, outptr);
        }

    }
}

If I had to guess, I would say that you either don't compute correctly the padding_o or triple[] isn't allocated enough memory.

If you need more help, please give as a complete example, so that we can run it. See How to create a Minimal, Complete, and Verifiable example

1
  • Thanks @ChrisG for your edit and help on this. I believe, I am calculating the padding correctly and allocating enough space for triple[] as well. I have edited the post to include my full code. Could you please check and let me know if you find any error. I have spent almost 3 days now on this but still stuck. Thanks again! – Aniket Pathak Aug 5 '16 at 16:33
0

thank you for amending the code. I think your control loops are okay; however, I think your problem is in the last part, specifically with:

fwrite(&out_scanline, sizeof(out_scanline), 1, outptr);

What you want to do here is write the actual content of out_scanline.

Try:

fwrite(out_scanline, sizeof(RGBTRIPLE), bi_out.biWidth,outptr);

instead.

Please click accept if this answered your question - let's keep up on forum maintenance.

You must log in to answer this question.

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