CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13

Threaded View

  1. #1
    Join Date
    Apr 2012
    Posts
    15

    Resizing BMP Files [Solved]

    Hey guys,

    I'm currently studying a CS course, and I have a problem set I can't seem to solve, we're required to make a small program that takes 3 arguments: (factor, file.bmp, file2.bmp) and resizes the first bmp by factor then stores it in the second file.

    I've supplied my code along with the output of a sample run in an attachment.

    This is a header file supplied by our instructor

    bmp.h

    Code:
    #include <stdint.h>
    /**
     * Common Data Types 
     *
     * The data types in this section are essentially aliases for C/C++ 
     * primitive data types.
     *
     * Adapted from http://msdn.microsoft.com/en-us/library/cc230309(PROT.10).aspx.
     * See http://en.wikipedia.org/wiki/Stdint.h for more on stdint.h.
     */
    typedef uint8_t  BYTE;
    typedef uint32_t DWORD;
    typedef int32_t  LONG;
    typedef uint16_t WORD;
    
    #define HEADER 54   // number of bytes offset for header
    
    /**
     * BITMAPFILEHEADER
     *
     * The BITMAPFILEHEADER structure contains information about the type, size,
     * and layout of a file that contains a DIB [device-independent bitmap].
     *
     * Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
     */
    typedef struct 
    { 
        WORD   bfType; 
        DWORD  bfSize; 
        WORD   bfReserved1; 
        WORD   bfReserved2; 
        DWORD  bfOffBits; 
    } __attribute__((__packed__)) 
    BITMAPFILEHEADER; 
    
    /**
     * BITMAPINFOHEADER
     *
     * The BITMAPINFOHEADER structure contains information about the 
     * dimensions and color format of a DIB [device-independent bitmap].
     *
     * Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
     */
    typedef struct
    {
        DWORD  biSize; 
        LONG   biWidth; 
        LONG   biHeight; 
        WORD   biPlanes; 
        WORD   biBitCount; 
        DWORD  biCompression; 
        DWORD  biSizeImage; 
        LONG   biXPelsPerMeter; 
        LONG   biYPelsPerMeter; 
        DWORD  biClrUsed; 
        DWORD  biClrImportant; 
    } __attribute__((__packed__))
    BITMAPINFOHEADER; 
    
    /**
     * RGBTRIPLE
     *
     * This structure describes a color consisting of relative intensities of
     * red, green, and blue.
     *
     * Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
     */
    typedef struct
    {
        BYTE  rgbtBlue;
        BYTE  rgbtGreen;
        BYTE  rgbtRed;
    } __attribute__((__packed__))
    RGBTRIPLE;
    Now here's my code resize.c

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "bmp.h"
    
    int main(int argc, char* argv[])
    {
        // ensure proper usage
        if (argc != 4)
        {
            printf("Usage: resize factor infile outfile\n");
            return 1;
        }
    
        // remember arguments
        int factor = atoi(argv[1]);
        char* infile = argv[2];
        char* outfile = argv[3];
    
        // open input & output files
        FILE* inptr = fopen(infile, "r");
        if (inptr == NULL)
        {
            printf("Could not open %s.\n", infile);
            return 2;
        }
    
        FILE* outptr = fopen(outfile, "w");
        if (outptr == NULL)
        {
            fclose(inptr);
            fprintf(stderr, "Could not create %s.\n", outfile);
            return 3;
        }
        
        if ((factor <= 0) || (factor > 100))
        {
            fprintf(stderr, "Factor must be in 1 - 100 range\n");
            return 4;
        }
        
        // read infile's BITMAPFILEHEADER
        BITMAPFILEHEADER bf;
        fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
    
        // read infile's BITMAPINFOHEADER
        BITMAPINFOHEADER bi;
        fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
        
        BITMAPFILEHEADER bfo = bf;
        BITMAPINFOHEADER bio = bi;
        
        if (factor == 1)
        {
            bfo = bf;
            bio = bi;
        }
        else
        {
            bfo = bf;
            bio = bi;
            
            bio.biWidth = bi.biWidth * factor;
            bio.biHeight = bi.biHeight * factor;
            int padding =  (4 - (bio.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
            bio.biSizeImage = (bio.biWidth * abs(bio.biHeight) * 3) + (padding * bio.biWidth);
            bfo.bfSize = bio.biSizeImage + HEADER;
        }
        
    
        // 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 5;
        }
    
        // write outfile's BITMAPFILEHEADER
        fwrite(&bfo, sizeof(BITMAPFILEHEADER), 1, outptr);
    
        // write outfile's BITMAPINFOHEADER
        fwrite(&bio, sizeof(BITMAPINFOHEADER), 1, outptr);
        
        // if factor == 1 just copy file
        if (factor == 1)
        {
            // determine padding for scanlines
            int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    
            // 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);
    
                    // 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);
            }
           
            fclose(inptr);
            fclose(outptr);
            return 0;
        }
        else
        {
            int paddingIn =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
            int paddingOut =  (4 - (bio.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
            
            for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
            {
                RGBTRIPLE* buffer = malloc(bi.biWidth * sizeof(RGBTRIPLE));
                RGBTRIPLE temp;
                
                for (int j = 0; j < bi.biWidth; j++)
                {
                    fread(&temp, sizeof(RGBTRIPLE), 1, inptr);
                    buffer[j] = temp;
                }
                
                for (int k = 0; k < bi.biWidth; k++)
                    for (int l = 0; l < factor; l++)
                        fwrite(&buffer[k], sizeof(RGBTRIPLE), 1, outptr);
                        
                for (int k = 0; k < paddingOut; k++)
                    fputc(0x00, outptr);
                    
                fseek(inptr, paddingIn, SEEK_CUR);    
                free(buffer);
            }
        }
    
        
        fclose(inptr);
        fclose(outptr);
        return 0;
    }
    Here's the output of a sample run with resizing factor of 2: http://www.putlocker.com/file/6919273A6F21E25D


    I'm almost sure the problem is with my looping constructs, and I've been using xxd and gdb for the last 3 hours trying to figure out what's wrong to no avail, any help will be appreciated... thanks.
    Attached Images Attached Images   
    Last edited by VeNiX; January 17th, 2013 at 09:57 AM. Reason: Algorithm Fixed

Posting Permissions

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





Click Here to Expand Forum to Full Width

Featured