0

I am really racking my brain over this. I'm trying to implement horizontal scaling for resize but all I'm getting are grey and white boxes.

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

// remember filenames
int n = atoi(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;
}

// updating to new headers
BITMAPINFOHEADER binew = bi;
BITMAPFILEHEADER bfnew = bf;
binew.biWidth = bi.biWidth * n;
binew.biHeight = bi.biHeight * n;

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

// update headers
binew.biSizeImage = ((binew.biWidth * sizeof(RGBTRIPLE)) + new_padding) * abs(binew.biHeight);
bfnew.bfSize = binew.biSizeImage + 54;

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

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

// iterate over infile's scanlines (row)
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 for one row
        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
    }
    // move pointer back to beginning of file
    fseek(inptr, -(sizeof(RGBTRIPLE) * bi.biWidth), SEEK_CUR);

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

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

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;
}

Does it have to do something with the headers not updating properly?

Update:

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

// remember filenames
int n = atoi(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;
}

// updating to new headers
BITMAPINFOHEADER binew = bi;
BITMAPFILEHEADER bfnew = bf;
binew.biWidth = bi.biWidth * n;
binew.biHeight = bi.biHeight * n;

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

// update headers
binew.biSizeImage = ((binew.biWidth * sizeof(RGBTRIPLE)) + new_padding) * abs(binew.biHeight);
bfnew.bfSize = binew.biSizeImage + 54;

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

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

// iterate over infile's scanlines (row)
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
    // scale width n times
    for (int p = 0; p < n; p++)
    {
        // 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 < new_padding; k++)
        {
            fputc(0x00, outptr);
        }

        // move pointer back to beginning of file
        // fseek(inptr, -(sizeof(RGBTRIPLE) + padding) * bi.biWidth, SEEK_CUR);
    }
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;
}

Update 2:

// iterate over infile's scanlines (row)
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);

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

        // move file pointer to next scanline
        fseek(inptr, sizeof(RGBTRIPLE) * bi.biWidth + padding, SEEK_CUR);
    }


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

    // then add it back (to demonstrate how)
    for (int k = 0; k < new_padding; k++)
    {
        fputc(0x00, outptr);
    }
    // move pointer back to beginning of scanline
    fseek(inptr, -sizeof(RGBTRIPLE) * bi.biWidth, SEEK_CUR);
}

1 Answer 1

0

There are a couple of issues. First, the code merely copies each pixel only once, not n times.

Next, the code is resetting to the beginning of the input line after each line is processed no matter what. At some point, it must be positioned to the next line. I'll leave it to you to figure out how to implement this.

The header processing is fine.

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

7
  • I implemented by method of horizontal and vertical scaling. I'm not sure if much progress has been made except for the fact that 1/8 of the image is green horizontally. This makes me think I'm still doing something wrong with the file header and I'm implementing the padding wrong. I just wanted to see if I'm following the right track.
    – brack30
    Aug 22, 2018 at 0:47
  • I have no idea what you have implemented, so I can't offer an opinion. Are you outputting each pixel n times before moving to the next pixel? Are you moving to the next line in the input file after outputting n copies of a line? Here's another suggestion. Implement the code for n=1 to get an exact copy of the input file, without the vertical sizing code, until you get that right. Then, move on to n=2.
    – Cliff B
    Aug 22, 2018 at 1:30
  • Thank you Cliff. My code works fine with n=1 but anything greater than that makes everything fall apart. I'm currently testing horizontal scaling but the outputted image only puts out a few green pixels and then it becomes a bunch of random colors. Is it that my output padding is being processed incorrectly? I updated the OP for the updated code.
    – brack30
    Aug 22, 2018 at 22:44
  • It still only duplicates each pixel once. It doesn't read 1 pixel and write n copies of the pixel.
    – Cliff B
    Aug 22, 2018 at 22:59
  • I think I managed to implement horizontal scaling and am now attempting vertical scaling. I forgot I had a negative sign in front of fseek so now I realize that I could use fseek to move to the next line. But now my outputted image has the bottom at the top. Am I doing something wrong with my fseek or am I missing a condition?
    – brack30
    Aug 23, 2018 at 0:24

You must log in to answer this question.

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