0

I have looked through many of the same questions but come up with no answers.

I am solely focusing at the moment on changing the headers and have tried to get calculations correct but something must be wrong as any image is invalid or unsupported when you try to open it. This also means I can't use peek to look at headers. I have looked at the values of the changed variables using printf and they aren't garbage values, they seem mostly correct, although I'm not sure that the padding is always right. Any help appreciated. Here's my code so far:

// remember filenames
double f = atof(argv[1]);
char *infile = argv[2];
char *outfile = argv[3];

//ensure float within range
if (f > 100.0 || f < 0.0)
{
    fprintf(stderr, "Factor must be between 0.0 and 100.0\n");
    return 2;
}

// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
    fprintf(stderr, "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;
BITMAPFILEHEADER new_bf = bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
BITMAPINFOHEADER new_bi = 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 5;
}

// change header sizes
new_bi.biWidth = (bi.biWidth * f);
new_bi.biHeight = (bi.biHeight * f);

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

// change header sizes
new_bi.biSizeImage = (new_bi.biWidth * abs(new_bi.biHeight) * sizeof(RGBTRIPLE)) + (new_padding * abs(new_bi.biHeight));
new_bf.bfSize = (new_bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));

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

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

// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
    // 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
        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);

// success
return 0;
}

1 Answer 1

0

"Ready, Fire, Aim!"

Look at the following code:

// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
BITMAPFILEHEADER new_bf = bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

The first line of code is creating the input header. The second line creates the output header structure and copies whatever garbage data is in the uninitialized input header. THEN the third line reads the actual input header into bf. The code that follows then updates a few fields in the output header, but the remaining fields still contain garbage data. Same logic was used for bi.

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

1
  • Thank You! I was so focused on the changing of variables, I completely overlooked the fact that the other data could be the problem! Commented Oct 19, 2017 at 8:40

You must log in to answer this question.

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