/* ip4.cpp - test code for ASM homework 4 - Matt Mahoney, mmahoney@cs.fit.edu This program creates a pretty picture (ip4.bmp), tests all operations, and reports the number of red, green, and blue pixels over 100. To compile: g++ ip4.cpp -o ip4.exe bcc32 ip4.cpp To run: ip4 Output: 165051 red, 91184 green, 467104 blue pixels >= 100 Created ip4.bmp You can view ip4.bmp in a web browser. */ #include #include #include #include typedef unsigned char U8; // You should provide implementations for the following functions in // MMX assembler. They should behave identically to the equivalent C++ // implementations after main(). // add val to each pixel extern "C" void brightness(U8 *image, int width, int height, int val); // multiply each pixel by val/64 extern "C" void contrast(U8 *image, int width, int height, int val); // average image with image2, rounding up extern "C" void average(U8 *image, U8 *image2, int width, int height); // produce new image with twice the width and height extern "C" void grow(U8 *image, U8 *newimage, int width, int height); // produce newimage with half the width and height extern "C" void shrink(U8 *image, U8 *newimage, int width, int height); // replace each 2x2 block with the average of those 4 pixels extern "C" void blur(U8 *image, int width, int height); // replace each pixel with 255-pixel extern "C" void invert(U8 *image, int width, int height); // make pixels white if brighter than the one above it, else black extern "C" void edge(U8 *image, int width, int height); // return number of pixels >= val extern "C" int atleast(U8 *image, int width, int height, int val); // set all pixels to val extern "C" void clear(U8 *image, int width, int height, int val); // Test code follows // For savebmp(), write x as an n-byte little endian number to file f. // f should be open for writing in binary mode. void writeint(FILE *f, unsigned int x, int n) { while (n-- > 0) putc(x, f), x >>= 8; } // Save filename as a 24-bit color .bmp file with dimensions width*height. // red, green, and blue are 1-D arrays of width*height pixels scanning // left to right starting in the lower left corner. void savebmp(const char* filename, U8* red, U8* green, U8* blue, int width, int height) { // width must be a multiple of 4 if (width & 3) printf("width %d not multiple of 4\n", width), exit(1); // Open .bmp file for writing in binary mode FILE *f = fopen(filename, "wb"); if (!f) perror(filename), exit(1); // can't create // Write 54 byte header for 24-bit color uncompressed image // see http://astronomy.swin.edu.au/~pbourke/dataformats/bmp/ putc('B', f); // magic number putc('M', f); writeint(f, width*height*3+54, 4); // file size writeint(f, 0, 4); // reserved writeint(f, 54, 4); // offset to data writeint(f, 40, 4); // size of rest of header writeint(f, width, 4); // width writeint(f, height, 4); // height writeint(f, 1, 2); // color planes writeint(f, 24, 2); // bits per pixel (1, 4, 8, or 24) writeint(f, 0, 4); // 0 = no compression writeint(f, width*height*3, 4); // image size in bytes writeint(f, 0, 4); // X pixels per meter writeint(f, 0, 4); // Y pixels per meter writeint(f, 0, 4); // palette size (0 for 24 bit) writeint(f, 0, 4); // number of important palette colors // Write data const int size = width*height; for (int i=0; i=0 && j>=0 && i=4; --i) { int x = (i*1621^i*1723)%width; // pseudo-random location int y = (i*1831^i*1907)%height; sphere(red, width, height, x, y, 500/i); } // Try inserting savebmp() after each operation to see what it does. shrink(red, green, width, height); edge(green, width/2, height/2); blur(green, width/2, height/2); invert(green, width/2, height/2); grow(green, blue, width/2, height/2); clear(green, width, height, 64); average(green, red, width, height); brightness(blue, width, height, -100); contrast(red, width, height, 120); printf("%d red, %d green, %d blue pixels >= 100\n", atleast(red, width, height, 100), // 165051 atleast(green, width, height, 100), // 91184 atleast(blue, width, height, 100)); // 467104 // Save image to bitmap file ip4.bmp savebmp("ip4.bmp", red, green, blue, width, height); return 0; } // Replace the code below with your own equivalent MMX assembler // Bound x to range 0-255. This does not need to be a separate function inline int saturate(int x) { return x < 0 ? 0 : (x > 255 ? 255 : x); } void brightness(U8 *image, int width, int height, int val) { const int size=width*height; for (int i=0; i> 6); } void average(U8 *image, U8 *image2, int width, int height) { const int size=width*height; for (int i=0; i> 1; } void grow(U8 *image, U8 *newimage, int width, int height) { for (int i=0; i> 2; *p1 = *p2 = *p3 = *p4 = avg; } } } void invert(U8 *image, int width, int height) { const int size=width*height; for (int i=0; iimage[i+width] ? 255 : 0; for (int i=size-width; i= val) ++count; return count; } void clear(U8 *image, int width, int height, int val) { memset(image, val, width*height); }