0

So my small image is resizing vertically but I get all the wrong colors. Can someone take a quick peek at my rewrite method to see where I've gone wrong? I've attached a pic of my large.bmp passing in n=4, my code is below.

// Copies a BMP file

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

#include "bmp.h"

int main(int argc, char *argv[])
{
    // ensure proper usage
    if (argc != 4)
    {
        // TODO: REMOVE - Only for Testing Purposes
        for (int i = 0; i < strlen(*argv); i++)
        {
            printf("this is arg %i - argv[%s]\n", i, argv[i]);
        }
        fprintf(stderr, "Usage: ./resize n infile outfile\n");
        return 1;
    }
    else
    {

        // check if first argument is a digit
        //char *number = argv[1];
        // for each character in the number
        for (int i = 0; i < strlen(argv[1]);i++)
        {
            // if the character is not a digit
            if (!isdigit(argv[1][i]))
            {
                fprintf(stderr, "Usage: ./resize n infile outfile\n");
                return 1;;
            }



        }
    }


    // get the first argument (digit)
    int n = atoi(argv[1]);
    //printf("this is n:%i\n", n);

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

    // open input file (inptr now points to infile)
    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);
    //printf("this is INFILE bf....\n");
    //printf("this is bf type: %hu\n", bf.bfType); // will be 'BM' or 19778
    //printf("this is bf size: %d\n", bf.bfSize); //size in bytes of the bitmap file (includes: pixels, padding, headers)
    //printf("this is size of bf: %lu\n", sizeof(BITMAPFILEHEADER)); // should print 14 bytes

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
    //printf("this is INFILE bi....\n");
    //printf("this is bi width: %d\n", bi.biWidth); // width of image in pixels, does not include padding
    //printf("this is bi height: %d\n", bi.biHeight); // height of image in pixels
    //printf("this is bi image size: %d\n", bi.biSizeImage); // total size of image in bytes, includes pixels and padding (negative because it's top down)

    //printf("this is biWidth before resize: %i\n", bi.biWidth);
    // get the bytes for the small image (width of pixels * 3)
    int smallBytes = bi.biWidth * 3;
    int paddingOriginal = 0;
    // check if smallBytes is divisible by 4, if it's not then calculate the padding
    if (smallBytes % 4 != 0)
    {
        paddingOriginal = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
        //printf("this is pading before resize: %i\n", paddingOriginal);
    }



    // change height and width of the bitmap file (OUTFILE)
    bi.biWidth *= n;
    bi.biHeight *= n;

    // get the padding for the infile
    int paddingInfile = 0;


    // get the bytes of the small image (width in pixels x 3)
    int bytes = bi.biWidth * 3;
    // holds the result of padding from below calculation
    int padding = 0;
    // if bytes are not a multiple of 4 then
    if (bytes % 4 != 0)
    {
        // calculate the padding
        padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
        //printf("this is padding after Resize: %i\n", padding);

    }

    //printf("this is padding after Resize: %i\n", padding);

    // calcuate the new biSizeImage for Outfile using the formula
    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + padding * abs(bi.biHeight));
    //printf("this is new biSizeImage: %i\n", bi.biSizeImage);

    // calcuate the new bfSize for Outfile using the formula
    bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    //printf("this is new bfSize: %i\n", bf.bfSize);

    // 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 image size of OUTFILE
    //printf(">>>this is size of RGBTriple:%lu\n", sizeof(RGBTRIPLE));


    // write outfile's BITMAPFILEHEADER
    fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
    //printf("this is OUTFILE bf....\n");
    //printf("this is bf type: %hu\n", bf.bfType); // will be 'BM' or 19778
    //printf("this is bf size: %d\n", bf.bfSize); //size in bytes of the bitmap file (includes: pixels, padding, headers)
    //printf("this is size of bf: %lu\n", sizeof(BITMAPFILEHEADER)); // should print 14 bytes

    // write outfile's BITMAPINFOHEADER
    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
    //printf("this is OUTFILE bi....\n");
    //printf("this is bi width: %d\n", bi.biWidth); // width of image in pixels, does not include padding
    //printf("this is bi height: %d\n", bi.biHeight); // height of image in pixels
    //printf("this is bi image size: %d\n", bi.biSizeImage); // total size of image in bytes, includes pixels and padding (negative because it's top down)


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


    // iterate over infile's scanlines (row or height)
    for (int i = 0, biHeight = abs(bi.biHeight)/n; i < biHeight; i++)
    {
        //printf("this is biWidth in loop: %i\n", bi.biWidth);
        // for each row make a copy of array
        // declare new struct for vertical resizing, make size equal to biWidth
        RGBTRIPLE vertical[bi.biWidth];

        //printf("this is i: %i\n", i);
        // iterate over infile's pixels in scanline (column or width)
        for (int j = 0, biWidth = bi.biWidth/n; j < biWidth; j++)
        {

            //printf("this is biWidth: %i\n", biWidth);
            //printf("this is j: %i\n", j);
            // temporary storage
            RGBTRIPLE triple;

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


            // Resize Horizontally here
            for (int resizeHor = 0; resizeHor < n; resizeHor++)
            {
                 //printf("this is resizeHor: %i\n", resizeHor);
                 // write RGB triple to outfile
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }


            fread(&vertical, bi.biWidth, 1, inptr);
            // Resize Veritcally

           for (int writeArray = 0; writeArray < n; writeArray++)
           {
                printf("this is size of veritcal: %lu\n", sizeof(vertical));
                 // write RGB triple to outfile
                fwrite(&vertical, sizeof(vertical), 1, outptr);

                // write outile's padding to end of row

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

           }



            }


        // skip over infile's padding, if any, from the current position of the pointer
        fseek(inptr, paddingOriginal, SEEK_CUR);




    }



    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

large.bmp

1 Answer 1

1

First, there are errors in calculating header data. That should be easy to fix.

The design logic for vertical scaling is totally flawed. Understand that images are not stored in two dimensions. The data is stored in the image file linearly. Each row follows the previous row. There is no direct way to read the data vertically.

In order to scale vertically, each row needs to be scaled up horizontally first. THEN, to scale vertically, each scaled up row must be replicated the appropriate number of times. There is no way to directly scale both horizontally and vertically at the same time.

Looks like you need to rethink the logic and redesign the program section that handles the scaling process. Also, it will help you to look at the raw data of the image and not just look at the displayed image. The raw data gives a lot more clues about what's going on! Finally, start with a scaling factor of 1 and get that working before going on to 2 or larger.

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

6
  • Hi Cliff, thank you for your feedback. What are the errors in calculating the headers?
    – wolfbagel
    Commented May 1, 2019 at 23:36
  • Well, I could tell you, but how would you learn? Start by running your code with a scale of 1 and then compare the data in your file to the input file. They should be identical.
    – Cliff B
    Commented May 1, 2019 at 23:37
  • Also, what if I did something like this: 1. calculate the horizontal row 2. write that row n times, vertically I think that's what I was trying to do but don't have the code right
    – wolfbagel
    Commented May 1, 2019 at 23:38
  • That's exactly what you should be doing.
    – Cliff B
    Commented May 1, 2019 at 23:38
  • Ok, thanks I'll try it out. When I get I'll mark your answer as correct.
    – wolfbagel
    Commented May 1, 2019 at 23:39

You must log in to answer this question.

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