0

**Relevant code is after comment: // iterate over infile's scanlines

  1. This code is able to make a new larger bmp with the correct dimensions, but the pixels are not the same color as the original bmp. After adding some printfs, I noticed the cursor in the bmp file does not move in either the infile or the outfile, and I am not sure why.

  2. The program crashes when f < 1. Not sure how to make it so it can resize to a smaller image. Would I need additional code (a conditional) to resize to a smaller image?

Thanks.

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

#include "bmp.h"

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

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

    // 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;
    }

    //change e from char to double f
    int f = atof(e);

    // change bf and bi
    bi.biWidth *= f;
    bi.biHeight *= f;

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

    if (outpadding != 0)
    {
        bf.bfSize = bi.biWidth * abs(bi.biHeight) * sizeof(RGBTRIPLE) + outpadding * abs(bi.biHeight);
    }
    else
    {
        bf.bfSize = bi.biWidth * abs(bi.biHeight) * sizeof(RGBTRIPLE);
    }

    bi.biSizeImage = bf.bfSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

    //return dimensions to infile's
    bi.biWidth /= f;
    bi.biHeight /= f;

    int inpadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    if (inpadding != 0)
    {
        bf.bfSize = bi.biWidth * abs(bi.biHeight) * sizeof(RGBTRIPLE) + inpadding * abs(bi.biHeight);
    }
    else
    {
        bf.bfSize = bi.biWidth * abs(bi.biHeight) * sizeof(RGBTRIPLE);
    }

    bi.biSizeImage = bf.bfSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    int inptrpos = ftell(inptr);
    int outptrpos = ftell(outptr);

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        //re-read scanline f times
        for (int l = 0; l < f; l++)
        {
            // iterate over pixels in scanline
            for (int j = 0; j < bi.biWidth; j++)
            {

                // temporary storage
                RGBTRIPLE triple;

                //re-copy pixel f times
                for (int m = 0; m < f; m++)
                {

                    // read RGB triple from infile
                    fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
                    printf("R: %hhu\n", triple.rgbtRed);
                    printf("G: %hhu\n", triple.rgbtGreen);
                    printf("B: %hhu\n", triple.rgbtBlue);
                    printf("inpos: %i\n", inptrpos);


                    // write RGB triple to outfile
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                    printf("outpos: %i\n", outptrpos);

                    fseek(inptr, -1*sizeof(RGBTRIPLE), SEEK_CUR);
                }
                fseek(inptr, (ftell(outptr) / f), SEEK_CUR);

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

            // then add it back (to demonstrate how)
            for (int k = 0; k < outpadding; k++)
            {
                fputc(0x00, outptr);
            }
            //move back to beginning of scanline
            fseek(inptr, -(bi.biWidth + inpadding), SEEK_CUR);
        }
        //move on to next scanline
        fseek(inptr, bi.biWidth + inpadding, SEEK_CUR);
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

1 Answer 1

1

Actually, no, the code doesn't work correctly at all.

First, the header data is incorrect. Two fields are not calculated correctly.

Second, even at resize of 1, the image output is incorrect. small.bmp is the correct output, s2.bmp is the output from your code above. Note the second line in each file.

small.bmp
00000036: 00ff00 00ff00 00ff00 000000  ............
00000042: 00ff00 ffffff 00ff00 000000  ............
0000004e: 00ff00 00ff00 00ff00 000000  ............
s2.bmp
00000036: 00ff00 00ff00 00ff00 000000  ............
00000042: 00ff00 00ff00 00ff00 000000  ............
0000004e: 00ff00 00ff00 00ff00 000000  ............

Once you've had a chance to work on the code, feel free to come back and ask a new question.

If this answers your question, please click on the check mark to accept. 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 .