1

I am blocking on that problem since 1 week, I think that I am not far from the solution but struggling to implement the recopy method, an hint would be nice here !

/**
 * Copies a BMP piece by piece, just because.
 */

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

#include "bmp.h"

int main(int argc, char *argv[])
{
// ensure proper usage
int n = atoi(argv[3]);
if(n > 100 || n < 2)
{
    fprintf(stderr, "n should be between 2 and 100\n");
    return 5;
}

if (argc != 4)
{
    fprintf(stderr, "Usage: ./copy infile outfile n\n");
    return 1;
}

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

// 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 header for output file
BITMAPFILEHEADER bfo;
bfo = bf;
BITMAPINFOHEADER bio;
bio = bi;

bio.biWidth = bi.biWidth * n;
bio.biHeight = bi.biHeight * n;

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

 // determine padding for scanlines in the outfile
int padding_outfile = (4 - (bio.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

bio.biSizeImage = ((sizeof(RGBTRIPLE) * bio.biWidth) + padding_outfile) * abs(bio.biHeight); // in bytes
bfo.bfSize = bio.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // the size of the picture in bytes


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

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

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

    for(int t = 0; t < n - 1; t++)
    {
        for (int j = 0; j < bi.biWidth; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

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

            for(int h = 0; h < n; h++)
            {
                // write RGB triple to outfile

                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }
        }


        for (int k = 0; k < padding_outfile; k++)
        {
            fputc(0x00, outptr);
        }

        fseek(inptr, -(int long)sizeof(RGBTRIPLE) * bio.biWidth + padding, SEEK_CUR);
    }

    for (int j = 0; j < bi.biWidth; j++)
        {
        // temporary storage
        RGBTRIPLE triple;

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

            for(int h = 0; h < n; h++)
            {
                // write RGB triple to outfile
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }
        }


        for (int k = 0; k < padding_outfile; k++)
        {
            fputc(0x00, outptr);
        }

    fseek(inptr, padding, SEEK_CUR);

}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;

} enter code here

1

In your first for loop, where you write the read scanline n-1 times, you have at the end the following:

fseek(inptr, -(int long)sizeof(RGBTRIPLE) * bio.biWidth + padding, SEEK_CUR);

First of all you don't have to explicitly cast to long, since giving as input an int to a function that expects a long, the compiler will implicitly cast the int to a long, so there's that.

Then, notice how you go back sizeof(RGBTRIPLE) * bio.biWidth + padding bytes, but you don't want that! You go back in the infile by the width of the outfile, and that's wrong.

Also since you haven't read the padding from the scanline of the in file, you shouldn't add the + padding in this fseek. Basically you should never read the infile's padding, you should just skip it after the n-th time, as you correctly do in the next for loop with the

fseek(inptr, padding, SEEK_CUR);

Hope this helps! If you need more help, post a comment bellow.

Happy Coding!

2
  • 1
    Working ! Thank a lot, I was starting to bang my head against the wall =) Jun 9 '17 at 10:02
  • No problem! Keep going! :)
    – ChrisG
    Jun 9 '17 at 10:02

You must log in to answer this question.

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