Question
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
/* * 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 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
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started