0

I'm trying to resize the image using the "recopy" method Zamyla stated in the video, but I can't figure out why the colors are all messed up. I've tried looking at other questions, but it hasn't helped me to figure out why my code is wrong. I think my trouble is with the padding, but I've been stuck on this problem for a while now and have tried rewriting it several times, but I can't figure it out. Please help?

*edit2: I have the original bi.Width and bi.Height saved in a old_bi.Width/old_bi.Height variables and I'm now using those in my for loop

#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 n infile outfile\n");
        return 1;
    }

    // Convert string into int
    int n = atoi(argv[1]);
    // Get resize by number, check if valid
    if (n < 1 || n > 100)
    {
        fprintf(stderr, "Usage: ./resize n infile outfile\n");
        return 5;
    }


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

    // Determine original padding for original width
    int oldpadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    BITMAPFILEHEADER old_bf;
    BITMAPINFOHEADER old_bi;

    old_bi.biWidth = bi.biWidth;
    old_bi.biHeight = bi.biHeight;

    // Update width
    bi.biWidth *= n;

    // Update height
    bi.biHeight *= n;

    // Find new padding with updated width info
    int newpadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // Update biSizeImage with updated sizes and newpadding
    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + newpadding) * abs(bi.biHeight);

    // Update bfSize with updates sizes and newpadding
    bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

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

        // Loop to recopy each line (resize vertically)
        for (int k = 0; k < n - 1; k++)
        {

            // Iterate over pixels in scanline
            for (int j = 0; j < old_bi.biWidth; j++)
            {

                // Temporary storage
                RGBTRIPLE triple;

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

                // To copy pixels horizontally
                for (int q = 0; q < n; q++)
                {
                    // Write RGB triple to outfile
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }

                // Go back to the beginning of the line to copy again
                fseek(inptr, (old_bi.biWidth * sizeof(RGBTRIPLE)) * -1, SEEK_CUR);
            }

            // Add newpadding, if any
            for (int m = 0; m < newpadding; m++)
            {
                fputc(0x00, outptr);
            }

            // Skip over old padding
            fseek(inptr, oldpadding, SEEK_CUR);
        }

        // Iterate over pixels in scanline one more time
        for (int j = 0; j < old_bi.biWidth; j++)
        {
            // Temporary storage
            RGBTRIPLE triple;

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

            // To copy pixels horizontally
            for (int q = 0; q < n; q++)
            {
                // Write RGB triple to outfile
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }

        }

        // Add newpadding, if any
        for (int t = 0; t < newpadding; t++)
        {
            fputc(0x00, outptr);
        }

        // Skip over old padding
        fseek(inptr, oldpadding, SEEK_CUR);
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}
1

You use bi.biWidth (in your case the output width at that point) both in

for (int j = 0; j < bi.biWidth; j++)

(found twice) and

fseek(inptr, (bi.biWidth * sizeof(RGBTRIPLE)) * -1, SEEK_CUR);

In both cases, you would have to use input width, not output width.

Same is true for the height, though it would cause a larger file, but no visible distortion of the image (as the extra data written is ignored by the viewer).

Edit: Also, fseek(inptr, oldpadding, SEEK_CUR); does not belong into the n-1 loop. You want to do that only after fully processing your input row, writing all n output rows.

| improve this answer | |
  • Thanks for your comment. I made the change you suggested, but I'm still seeing the same random colors if I try to increase the size of the image (just copying the image works fine). Do you have any other suggestions? – gmj123 Oct 9 '19 at 17:40
  • I must have missed it before: fseek(inptr, oldpadding, SEEK_CUR); should not appear in the n-1 loop. You want to begin the next iteration where you began the current one. – Blauelf Oct 11 '19 at 8:45
  • thank you so much for your help!! I removed the extra fseek function and now it works -- thanks again!!! – gmj123 Oct 11 '19 at 14:48

You must log in to answer this question.

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