Skip to main content
4 of 5
added 5350 characters in body
sid
  • 15
  • 5

How to Resize an Image Vertically?

I'm able to resize a given .bmp horizontally, but the code for vertical resizing is not working. Here is my code for vertical expansion.

// resize vertically

//move pointer to start of scanline of outptr
fseek(outptr,  -3 * (bi2.biWidth + padding), SEEK_CUR);
    
fgetpos (outptr,&pos);
    
//an array of RGBTRIPLE to store one scanline
RGBTRIPLE triple[bi2.biWidth + padding]; 
    
//reading the already written first line    
for (int p = 0 ; p < bi2.biWidth + padding; p++)
{ 
    fread(&triple[p], sizeof(RGBTRIPLE), 1, outptr); 
}
fgetpos (outptr,&pos);           
    
//writing the copied array to outptr
for (int k = 0 ; k < n; k++)
{             
    for (int p = 0 ; p < bi2.biWidth + padding; p++)
         
        fwrite(&triple[p], sizeof(RGBTRIPLE), 1, outptr);   
                    
}
  

This is executed after reading the first scanline of the original bmp. I used gdb to see the values of triple's elements, but I found that they're all garbage values.

Also when I check the position of the file position indicator in outptr using fgetpos(), I find it not changing!


Update: here's my code after modifications

// iterate over infile's scanlines
fpos_t pos;
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{   
    // iterate over pixels in scanline
    fgetpos (outptr,&pos);
    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 n times horizontally
        for (int k = 0 ; k < n; k++)
        {       
            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);  
                       
        }
    }

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

    // then add padding to outfile
    for (int l = 0; l < padding; l++)
    {
        fputc(0x00, outptr);
    }        
   
    // resize vertically  
    //move pointer to start of scanline of outptr
    fsetpos( outptr, &pos );
    
    //an array of RGBTRIPLE to store one scanline
    RGBTRIPLE triplex[bi2.biWidth]; 
    
        
    //reading the already written first line    
    for (int m = 0 ; m < bi2.biWidth ; m++)
    {             
        fread(&triplex[m], sizeof(RGBTRIPLE), 1 , outptr); 
    }
    
    //skip padding
    fseek(outptr, padding, SEEK_CUR);
    for (int mn = 0 ; mn < n ; mn++)
    {
        //writing the copied array to outptr
        for (int o = 0 ; o < bi2.biWidth ; o++)
        {
            fwrite(&triplex[o], sizeof(RGBTRIPLE), 1 , outptr);   
        }
        for (int p = 0; p < padding; p++)
        {
            fputc(0x00, outptr);
        }   
    }               
}

complete program

/**

  • copy.c
  • Computer Science 50
  • Problem Set 5
  • Copies a BMP piece by piece, just because. */

#include <stdio.h> #include <stdlib.h> #include <cs50.h> #include <string.h> #include <ctype.h>//for isdigit

#include "bmp.h"

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

//checking if n is integer
int i=0;
string in=argv[1];
while(in[i]!='\0')
{
    if( isdigit(in[i]) )
    i++;
    
    else
    {
        printf("n, the resize factor, must be an integer.\n");
        return 5;
    }
}

int n=atoi(in);
if(n<1 || n>100)
{
    printf("n, the resize factor, must be a positive integer less than 100.\n");
    return 6;
}


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

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

// outfile's BITMAPFILEHEADER
BITMAPFILEHEADER bf2=bf;

// outfile's BITMAPINFOHEADER
BITMAPINFOHEADER bi2=bi;    
    
//multiplying width by n factor
bi2.biWidth = n*(bi.biWidth);
//multiplying height by n factor
bi2.biHeight = n*(bi.biHeight);

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

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

    
//size of the image
bi2.biSizeImage = (bi2.biWidth + padding) * (abs(bi2.biHeight)) * 3;// positive bi2.biHeight for calculation of bi2.biSizeImage  

//final size of bmp 
 bf2.bfSize = bi2.biSizeImage + 54;

// write outfile's BITMAPFILEHEADER    

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

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


// iterate over infile's scanlines
fpos_t pos;
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{   
    // iterate over pixels in scanline
    fgetpos (outptr,&pos);
    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 n times horizontally
        for (int k = 0 ; k < n; k++)
        {       
            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);             
        }
    }
    
    
    
    // skip over padding in infile, if any
    fseek(inptr, padding_in, SEEK_CUR);//padding_in is padding in inptr

    // then add padding to outfile
    for (int l = 0; l < padding; l++)//padding is padding in outptr
    {
        fputc(0x00, outptr);
    }        
    
    //flushing the buffer to outptr
    fflush(outptr);
    
    // resize vertically  
    
    //move pointer to start of scanline of outptr
    fsetpos( outptr, &pos );
    
    //an array of RGBTRIPLE to store one scanline
    RGBTRIPLE triplex[bi2.biWidth]; 
                
    //reading the already written first line from outptr    
    for (int m = 0 ; m < bi2.biWidth ; m++)
    {             
        fread(&triplex[m], sizeof(RGBTRIPLE), 1 , outptr); 
    }
    
    //skip padding
    fseek(outptr, padding, SEEK_CUR);
    
    //writing the values in array to outptr n times
    for (int mn = 0 ; mn < n ; mn++)
    {
        //writing values from the array
        for (int o = 0 ; o < bi2.biWidth ; o++)
        {
            fwrite(&triplex[o], sizeof(RGBTRIPLE), 1 , outptr);   
        }
        //adding padding to outptr's scanline
        for (int p = 0; p < padding; p++)
        {
            fputc(0x00, outptr);
        }   
    }               
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all folks
return 0;

}

sid
  • 15
  • 5