Help with a program to resize an image
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8

Thread: Help with a program to resize an image

  1. #1
    Join Date
    Feb 2013
    Posts
    1

    Question Help with a program to resize an image

    Hi Everyone,

    I am currently working on problem set 4 for Harvard’s online CS50 course. I am working on a program that resizes a bmp image by a factor of N. N in entered along with an in-file and out-file in a command line argument. The program needs to calculate the header file for the out-file and write it to the out-file. It then needs to actually resize the image and, again, write to the out-file.

    The first question I have relates to the header file, here is my code for calculating the header file:


    bi2.biHeight = bi.biHeight *n;
    bi2.biWidth = bi.biWidth *n;
    int padding = (4 -(bi.biWidth * sizeof(RGBTRIPLE))%4)%4;
    bi2.biSizeImage = (bi2.biWidth * sizeof(RGBTRIPLE) + padding) * abs(bi2.biHeight);
    bf2.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bi2.biSizeImage;


    And here is my code for writing the new header file (bi2 and bf2) to the out-file:

    fwrite(&bf2, sizeof(BITMAPFILEHEADER), 1, outptr);
    fwrite(&bi2, sizeof(BITMAPINFOHEADER), 1, outptr);

    Does my code look “OK” or do you see any issues???

    At this point I need to actually resize the image. As far as I can tell there are 2 ways to go about this you either have to use an array to store each line you want to print repeatedly (and then you can just write it repeatedly) OR you have to move the pointer back in the input stream and repeat the read/resize/write process each time you need to print the row.

    It is this that I am stuck on, first of all, I am not sure what system would be better for resizing the image, although I am leaning towards using an array, and regardless, I don’t even know where to begin when in implementing either.

    So what I am asking for is, first of all, just a “double check” to make sure my header code makes sense. And second of all, a push in the right direction for actually resizing the image. Please keep in mind that this is for a course so I don’t simply want you to “fix” my code, I want to learn, and discover.

    Thanks,
    Joshua McDonald

    Here is my complete code, if that helps:

    Code:
    /****************************************************************************
     * resize.c
     *
     * Computer Science 50
     * Problem Set 4
     *
     * Resizes a BMP piece by piece, just because.
     ***************************************************************************/
           
    #include <stdio.h>
    #include <stdlib.h>
    #include "bmp.h"
    
    int main(int argc, char* argv[])
    {
        // ensure proper usage
        if (argc != 4)
        {
            printf("Usage: copy N infile outfile\n");
            return 1;
        }
    
        // remember filenames
        char* nchar = argv[1];
        char* infile = argv[2];
        char* outfile = argv[3];
        
        int timeswriten = 0;
        
        //convert nchar to an int
        int n = atoi (nchar);
    
        if (n < 1 || n > 100)
        {
        printf("Please try again with a positive number less then 100\n");
        return 1;
        }
    
        // open input file 
        FILE* inptr = fopen(infile, "r");
        if (inptr == NULL)
        {
            printf("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, bf2;
        fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
    
        // read infile's BITMAPINFOHEADER
        BITMAPINFOHEADER bi, bi2;
        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;
        }
        
        
        bi2.biHeight = bi.biHeight *n;
        bi2.biWidth = bi.biWidth *n;
        int padding = (4 -(bi.biWidth * sizeof(RGBTRIPLE))%4)%4;
        bi2.biSizeImage = (bi2.biWidth * sizeof(RGBTRIPLE) + padding) *        abs(bi2.biHeight);
        bf2.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bi2.biSizeImage;
    
        // write outfile's BITMAPFILEHEADER and BITMAPINFOHEADER
        fwrite(&bf2, sizeof(BITMAPFILEHEADER), 1, outptr);
        fwrite(&bi2, 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);
                
                
                // Here is where I need to actually resise the image!!!!
    
    
                // 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);
    
        // that's all folks
        return 0;
    }

  2. #2
    Join Date
    Apr 1999
    Posts
    27,431

    Re: Help with a program to resize an image

    Quote Originally Posted by Dude22 View Post
    Hi Everyone,

    I am currently working on problem set 4 for Harvard’s online CS50 course. I am working on a program that resizes a bmp image by a factor of N. N in entered along with an in-file and out-file in a command line argument. The program needs to calculate the header file for the out-file and write it to the out-file. It then needs to actually resize the image and, again, write to the out-file.
    You do know that there is code all over the internet that shows how to resize a BMP file, right? If you want to know what is right, just compare your code with one of the thousands of pieces of sample code that does the same thing.

    Also, very few, if any real-world programmers do this "off the top of their head" and not look at samples showing how it's done, even just as a reminder of the right steps to do.

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Feb 2013
    Location
    United States
    Posts
    56

    Re: Help with a program to resize an image

    Dude22 wrote:
    int padding = (4 -(bi.biWidth * sizeof(RGBTRIPLE))%4)%4;
    Since you are calculating the padding for the re-sized image, you want to use bi2.biWidth.
    A more efficient formula for calculating the padding is:
    int padding = ((bi2.biWidth + 1) * 3) & 0xFFFFFFFC;

    Since memory is abundant in this day of age, I would read the entire bitmap image into an array and create a second array to store the entire re-sized bitmap image. Why mess with streams?

    Now, there are a few methods you can use to enlarge an image:
    1. Simply repeat the pixels. This has the effect of making the pixels appear larger resulting in a crude and jagged image.
    2. Re-sample the pixels. This works well if the magnification factor is less than 2. For larger magnifications, the images end up looking like they do with the first method.
    3. Interpolate the colors. This gives the best results but requires the most computation.

    For shrinking an image, there are basically two methods.
    1. Remove some of the pixels. The resulting image may be very crude.
    2. Re-sample the pixels by averaging their colors. Each of the components (red, green, blue) need to be averaging separately and then recombined to form a new color.

  4. #4
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    3,926

    Re: Help with a program to resize an image

    There are in fact more than those 3 ways to enlarge an image and there are more than those 2 to reduce the image.

    It is ultimately about what sort of input image you have (a photo, a scanned document, a painted image with limited colors (MSPaint with say 16 or 256 colors).
    The end result will look best if you use the right kind of scaling with the right kind of image. This of course needs a bit of manual steering from a human. Which is why decent drawing programs will offer different resizing algorithms/filters because computers are notoriously bad at figuring this out on their own while the human brain needs only the blink of an eye to identify the type of input image.

    For this program, I would assume the intent is to scale up using a plain pixel copying approach. There are various approaches to this. Loading the entire source image in memory and havign the entire target in memory is probably the easiest, but it consumes memory, something that you may not have if you're dealing with a large megapixel image.

    For plain scaling, you can also quite easily work on a row by row nature. read a row, expand the input row by copying each input pixel N times in the output row, then write the output row N times.

  5. #5
    Join Date
    Feb 2013
    Location
    United States
    Posts
    56

    Re: Help with a program to resize an image

    Given that this is a college assignment, the goal may very well be to teach the student about the bitmap structure and/or reading and writing files sequentially, and not about the most efficient or accurate way to resize an image. If this is the case, then my previous post should be disregarded except for the part about calculating the padding.

    I now believe the assignment simply asks for the bitmap to be enlarged by an integer factor. Then each pixel would just need to be repeated both horizontally and vertically according to that factor. To repeat the pixels vertically, either a buffer will need to be used to store a row of the input image or the input file pointer will need to be reset each time the row is repeated. I guess Dude22 already knew this. The buffer approach may run slightly faster since the call to read each pixel needs to only be done once, but memory will need to be allocated based on the bitmap's width. The file pointer approach may run slightly slower, but no extra memory is required. Either way will work, but check if the instructor has a preference.

  6. #6
    Join Date
    Dec 2012
    Location
    England
    Posts
    2,463

    Re: Help with a program to resize an image


  7. #7
    Join Date
    Feb 2013
    Location
    United States
    Posts
    56

    Re: Help with a program to resize an image

    OK, I missed the part of this being an online course so there may not even be an instructor. I also misread the CS50 to be CS550. This is obviously an introductory programming course. I believe this assignment is an exercise in using file streams so I recommend the file pointer reset approach.

  8. #8
    Join Date
    Feb 2013
    Posts
    1
    Quote Originally Posted by Coder Dave View Post
    OK, I missed the part of this being an online course so there may not even be an instructor. I also misread the CS50 to be CS550. This is obviously an introductory programming course. I believe this assignment is an exercise in using file streams so I recommend the file pointer reset approach.
    [thông tin cu?a ba?n thu?c su? râ?t co? i?ch dô?i vo?i mi`nh. Ca?m on ba?n nhiê`u nhe?!!!!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center