Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

this C program manipulates an image from a 24-bit uncompressed bmp file by enlarging, rotating and flipping would like the program to take ALL of

this C program manipulates an image from a 24-bit uncompressed bmp file by enlarging, rotating and flipping

would like the program to take ALL of the following command line test cases:

Test 1: bbmptool f o 1.bmp example.bmp

Test 2: bmptool r 90 o 2.bmp example.bmp

Test 3: bmptool r -180 o 3.bmp example.bmp

Test 4: bmptool s 2 o 4.bmp example.bmp

Test 5: bmptool r -90 -f o 5.bmp example.bmp

Test 6: bmptool r -90 s 3 o 6.bmp example.bmp

Test 7: bmptool f r 90 s 2 o 7.bmp example.bmp

Test 8: bmptool s 2 example.bmp | bmptool r 90 | bmptool f o 8.bmp

Test 9: bmptool f example.bmp | bmptool f o 9.bmp

===============================================================================================================

//main.c

#include #include #include #include "bmplib.h"

/* * This method prints out usage of the bmptool. */ void usage(){ fprintf(stderr, "usage: bmptool [-s scale | -r degree | -f ] [-o output_file] [input_file] "); exit(1); }

/* * This method enlarges a 24-bit, uncompressed .bmp file * that has been read in using readFile() * * original - an array containing the original PIXELs, 3 bytes per each * rows - the original number of rows * cols - the original number of columns * * scale - the multiplier applied to EACH OF the rows and columns, e.g. * if scale=2, then 2* rows and 2*cols * * new - the new array containing the PIXELs, allocated within * newrows - the new number of rows (scale*rows) * newcols - the new number of cols (scale*cols) */ int enlarge(PIXEL* original, int rows, int cols, int scale, PIXEL** new, int* newrows, int* newcols) { int row, col, i, j;

if ((rows <= 0) || (cols <= 0)) return -1;

*newrows = scale*rows; *newcols = scale*cols; *new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));

for (row=0; row < rows; row++) { for(i=0; i

return 0; }

/* * This method rotates a 24-bit, uncompressed .bmp file that has been read * in using readFile(). The rotation is expressed in degrees and can be * positive, negative, or 0 -- but it must be a multiple of 90 degrees * * original - an array containing the original PIXELs, 3 bytes per each * rows - the number of rows * cols - the number of columns * rotation - a positive or negative rotation, * * new - the new array containing the PIXELs, allocated within * newrows - the new number of rows * newcols - the new number of cols */ int rotate(PIXEL* original, int rows, int cols, int rotation, PIXEL** new, int* newrows, int* newcols) { int row, col;

if(rotation % 360 == 0){ *newrows = rows; *newcols = cols; *new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL)); for (row=0; row < rows; row++){ for (col=0; col < cols; col++) { PIXEL* o = original + row*cols + col; PIXEL* n = (*new) + row*cols + col; *n = *o; } } } else if((rotation > 0 && rotation % 270 == 0) || (rotation < 0 && rotation % 90 == 0 && rotation % 180 != 0 && rotation % 270 != 0)){ *newrows = cols; *newcols = rows; *new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));

for (row=0; row < rows; row++){ for (col=0; col < cols; col++) { PIXEL* o = original + row*cols + col; PIXEL* n = (*new) + (cols-col-1)*rows + row; *n = *o; } } } else if((rotation > 0 && rotation % 180 == 0) || (rotation < 0 && rotation % 180 == 0)){ *newrows = rows; *newcols = cols; *new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));

for (row=0; row < rows; row++){ for (col=0; col < cols; col++) { PIXEL* o = original + row*cols + col; PIXEL* n = (*new) + (rows-row)*cols - (col+1); *n = *o; } } } else if((rotation > 0 && rotation % 90 == 0) || (rotation < 0 && rotation % 270 == 0)){ *newrows = cols; *newcols = rows; *new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));

for (row=0; row < rows; row++){ for (col=0; col < cols; col++) { PIXEL* o = original + row*cols + col; PIXEL* n = (*new) + col*rows + (rows-row-1); *n = *o; } } }

return 0; }

/* * This method horizontally flips a 24-bit, uncompressed bmp file * that has been read in using readFile(). * * THIS IS GIVEN TO YOU SOLELY TO LOOK AT AS AN EXAMPLE * TRY TO UNDERSTAND HOW IT WORKS * * original - an array containing the original PIXELs, 3 bytes per each * rows - the number of rows * cols - the number of columns * * new - the new array containing the PIXELs, allocated within */ int flip (PIXEL *original, PIXEL **new, int rows, int cols) { int row, col;

if ((rows <= 0) || (cols <= 0)) return -1;

*new = (PIXEL*)malloc(rows*cols*sizeof(PIXEL));

for (row=0; row < rows; row++) for (col=0; col < cols; col++) { PIXEL* o = original + row*cols + col; PIXEL* n = (*new) + row*cols + (cols-1-col); *n = *o; }

return 0; }

int main(int argc, char *argv[]) { int r, c, nr, nc; PIXEL *b, *nb; char* infile; char* outfile; int fl, ro, sc, ou, nro; /* getopt flags */ int argindex; int val_scale, val_rotate, tmp;

outfile = NULL; infile = NULL; argindex = 0; val_scale = val_rotate = 0; fl = ro = sc = ou = nro = 0; while((c = getopt(argc, argv, "srfo")) != -1){ switch(c) { case 's': if(sc){ fprintf(stderr, "Duplicate options "); exit(-1); } sc = 1; break; case 'r': if(ro){ fprintf(stderr, "Duplicate options "); exit(-1); } ro = 1; break; case 'f': if(fl){ fprintf(stderr, "Duplicate options "); exit(-1); } fl = 1; break; case 'o': if(ou){ fprintf(stderr, "Duplicate options "); exit(-1); } ou = 1; break; case '?': tmp = atoi(argv[optind]); if((tmp == 0 || tmp % 90 == 0) && !nro && ro){ nro = 1; val_rotate = tmp; } break; default: usage(); printf("default"); } } argc -= optind; argv += optind;

if(argc < 1 && !nro && !fl){ fprintf(stderr, "Too few arguments"); exit(-1); }

/* assume if argument are true, they are in order */ if(sc){ val_scale = atoi(argv[argindex++]); } if(ro && !nro){ val_rotate = atoi(argv[argindex++]); } if(ou){ outfile = argv[argindex++]; } if(argc - 1 == argindex){ infile = argv[argindex]; }

//read input file readFile(infile, &r, &c, &b);

//execute function calls based on command line flags if(fl){ flip(b, &nb, r, c); } if(sc){ enlarge(b, r, c, val_scale, &nb, &nr, &nc); r = nr; c = nc; } if(ro){ rotate(b, r, c, val_rotate, &nb, &nr, &nc); r = nr; c = nc; }

//write results to file writeFile(outfile, r, c, nb);

free(b); free(nb); return 0; }

===============================================================================================================

//bmplib.c

#include #include #include #include #include #include #include "bmplib.h"

static int myread(int fd, char* buf, unsigned int size) { int r = 0; while(r < size) { int x = read(fd, &buf[r], size-r); if(x < 0) return x; else r += x; } return size; }

static int mywrite(int fd, char* buf, unsigned int size) { int w = 0; while(w < size) { int x = write(fd, &buf[w], size-w); if(x < 0) return x; else w += x; } return size; }

int readFile (char *filename, int *rows, int *cols, PIXEL** bitmap) { int fd, ret; unsigned int start;

if(filename) { if((fd = open(filename, O_RDONLY)) < 0) { perror("Can't open bmp file to read"); return -1; } } else fd = STDIN_FILENO;

ret = readHeader (fd, rows, cols, &start); if(ret) return ret;

*bitmap = (PIXEL*)malloc(sizeof(PIXEL)*(*rows)*(*cols)); ret = readBits (fd, *bitmap, *rows, *cols, start); if(ret) return ret;

if(filename) close(fd);

return 0; }

int writeFile (char* filename, int rows, int cols, PIXEL* bitmap) { int fd, ret; unsigned int start = DEFAULT_BITMAP_OFFSET;

if(filename) { if((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) { perror("Can't open bmp file to write"); return -1; } } else fd = STDOUT_FILENO;

ret = writeHeader (fd, rows, cols, start); if(ret) return ret;

ret = writeBits(fd, rows, cols, bitmap, start); if(ret) return ret;

if(filename) close(fd);

return 0; }

int readHeader(int fd, int *rows, int *cols, unsigned int *start) { BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih;

if(myread(fd, ((char*)&bmfh)+2, sizeof(bmfh)-2) <= 0) { perror("Can't read BITMAPFILEHEADER"); return -2; } if(myread(fd, (char*)&bmih, sizeof(bmih)) <= 0) { perror("Can't read BITMAPINFOHEADER"); return -3; }

if(bmih.biCompression != 0) { fprintf(stderr, "Can't read compressed bmp"); return -4; } if(bmih.biBitCount != 24) { fprintf(stderr, "Can't handle bmp other than 24-bit"); return -5; }

*rows = bmih.biHeight; *cols = bmih.biWidth; *start = bmfh.bfOffBits;

return 0; }

int writeHeader(int fd, int rows, int cols, unsigned int start) { unsigned int fileSize; unsigned int headerSize; unsigned int paddedCols; BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih;

memset (&bmfh, 0, sizeof(bmfh)); memset (&bmih, 0, sizeof(bmih));

paddedCols = ((cols/4)*4 !=cols ? ((cols+4)/4)*4 : cols); headerSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); fileSize = rows*paddedCols*sizeof(PIXEL)+headerSize;

bmfh.bfType = 0x4D42; bmfh.bfSize = fileSize; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = start;

bmih.biSize = 40; bmih.biWidth = cols; bmih.biHeight = rows; bmih.biPlanes = 1; bmih.biBitCount = 24; bmih.biCompression = 0; bmih.biSizeImage = 0; bmih.biXPelsPerMeter = 0; bmih.biYPelsPerMeter = 0; bmih.biClrUsed = 0; bmih.biClrImportant = 0;

if(mywrite(fd, ((char*)&bmfh)+2, sizeof(bmfh)-2) < 0) { perror("Can't write BITMAPFILEHEADER"); return -2; } if(mywrite(fd, (char*)&bmih, sizeof(bmih)) < 0) { perror("Can't write BITMAPINFOHEADER"); return -3; }

return 0; }

int readBits(int fd, PIXEL* bitmap, int rows, int cols, unsigned int start) { int row; char padding[3]; int padAmount; char useless[DEFAULT_BITMAP_OFFSET];

padAmount = ((cols * sizeof(PIXEL)) % 4) ? (4 - ((cols * sizeof(PIXEL)) % 4)) : 0;

start -= sizeof(BITMAPFILEHEADER)-2+sizeof(BITMAPINFOHEADER); if(start > 0 && myread(fd, useless, start) < 0) { perror("Can't lseek to bitmap"); return -6; } /* if(lseek (fd, start, SEEK_SET) < 0) { perror("Can't lseek to bitmap"); return -6; } */

for (row=0; row < rows; row++) { if(myread(fd, (char*)(bitmap+(row*cols)), cols*sizeof(PIXEL)) < 0) { perror("Can't read bitmap"); return -7; } if(padAmount > 0) { if(myread(fd, padding, padAmount) < 0) { perror("Can't read bitmap"); return -8; } } }

return 0; }

int writeBits(int fd, int rows, int cols, PIXEL* bitmap, unsigned int start) { int row; char padding[3]; int padAmount; char useless[DEFAULT_BITMAP_OFFSET];

padAmount = ((cols * sizeof(PIXEL)) % 4) ? (4 - ((cols * sizeof(PIXEL)) % 4)) : 0; memset(padding, 0, 3);

start -= sizeof(BITMAPFILEHEADER)-2+sizeof(BITMAPINFOHEADER); if(start > 0) { memset(useless, 0, start); if(mywrite(fd, useless, start) < 0) { perror("Can't lseek to bitmap"); return -6; } } /* if(lseek (fd, start, SEEK_SET) < 0) { perror("Can't lseek to bitmap"); return -6; } */

for (row=0; row < rows; row++) { if(mywrite(fd, (char*)(bitmap+(row*cols)), cols*sizeof(PIXEL)) < 0) { perror("Can't write bitmap"); return -7; } if(padAmount > 0) { if(mywrite(fd, padding, padAmount) < 0) { perror("Can't write bitmap"); return -8; } } }

return 0; }

===============================================================================================================

//bmplib.h

#ifndef BMPLIB_H #define BMPLIB_H

typedef struct { unsigned short padding; unsigned short bfType; unsigned int bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned int bfOffBits; } BITMAPFILEHEADER;

typedef struct { unsigned int biSize; int biWidth; int biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned int biCompression; unsigned int biSizeImage; unsigned int biXPelsPerMeter; unsigned int biYPelsPerMeter; unsigned int biClrUsed; unsigned int biClrImportant; } BITMAPINFOHEADER;

typedef struct { unsigned char r; unsigned char g; unsigned char b; } PIXEL;

#define DEFAULT_BITMAP_OFFSET 1078

/* Read an uncompressed 24-bit bmp from a file named 'filename' (if null, it's standard input); return the number of 'rows', the number of 'cols', and the 'bitmap' as an array of PIXELs. The function return 0 if successful. */ int readFile (char* filename, int* rows, int* cols, PIXEL** bitmap);

/* Write an uncompressed 24-bit bmp to a file named 'filename' (if null, it's standard output); the dimension of the bmp is the number of 'rows' by the number of 'cols', and the 'bitmap' contains an array of PIXELs. The function return 0 if successful. */ int writeFile (char* filename, int rows, int cols, PIXEL* bitmap);

/* Read bmp file header from file 'fd', return the number of 'rows', the number of 'cols', and the 'start' position of the bitmap. The function returns 0 if successful. */ int readHeader(int fd, int *rows, int *cols, unsigned int *start);

/* Write bmp file header to file 'fd'; the dimention of the bitmap is the number of 'rows' by the number of 'cols', and it starts at the 'start' position. The function returns 0 if successful. */ int writeHeader(int fd, int rows, int cols, unsigned int start);

/* Read the 'bitmap' from file 'fd'; the dimention of the bitmap is the number of 'rows' by the number of 'cols', and it starts at the 'start' position. The function returns 0 if successful. */ int readBits(int fd, PIXEL* bitmap, int rows, int cols, unsigned int start);

/* Write the 'bitmap' to file 'fd'; the dimention of the bitmap is the number of 'rows' by the number of 'cols', and it starts at the 'start' position. The function returns 0 if successful. */ int writeBits(int fd, int rows, int cols, PIXEL* bitmap, unsigned int start);

#endif /*BMPLIB_H*/

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions