Multimedia Lab – Source Coding Algorithms The learning objective of this assignment is to apply source coding algorithms for compression in multimedia applications. The assignment will allow you to understand the use of compression in still images. The Scenario: Assuming that the wheel image shown in the above picture and as well as given as a GIF file, you are required to perform the followings in order to apply source coding compression algorithms of your choice. Minimum Requirements: Identify and assign colors for the wheel – 3 Marks Use necessary C/CPP program segments given to upload the ASCII text files of color codes assigned in the step above – 3 Marks Write a C/CPP function to implement source code algorithm of your choice; Runlength/Huffman/Arithmetic/LZW – 5 Marks Prove the compression and decompression using the wheel – 4 Marks Be creative and have fun with the assignment! – Priceless HINT: Wherever applicable, use all source program segments given in order to do this assignment unless otherwise you use your own programming language such as Java or software package such as Matlab. Handing in your Lab: The lab is due Tuesday, 15th April 2014. APPENDIX HEADER FILE #ifndef IMAGE_H #define IMAGE_H // a simple example - you would need to add more functions class ImageType { public: ImageType(); ImageType(int, int, int); ImageType(ImageType&); ~ImageType(); void getImageInfo(int&, int&, int&); void setImageInfo(int, int, int); void setPixelVal(int, int, int); void getPixelVal(int, int, int&); private: int N, M, Q; int **pixelValue; }; #endif SKELETON C/CPP FILES 1. Image.cpp #include <stdlib.h> #include "image.h" ImageType::ImageType() { N = 0; M = 0; Q = 0; pixelValue = NULL; } ImageType::ImageType(int tmpN, int tmpM, int tmpQ) { int i, j; N = tmpN; M = tmpM; Q = tmpQ; pixelValue = new int* [N]; for(i=0; i<N; i++) { pixelValue[i] = new int[M]; for(j=0; j<M; j++) pixelValue[i][j] = 0; } } ImageType::ImageType(ImageType& oldImage) { int i, j; N = oldImage.N; M = oldImage.M; Q = oldImage.Q; pixelValue = new int* [N]; for(i=0; i<N; i++) { pixelValue[i] = new int[M]; for(j=0; j<M; j++) pixelValue[i][j] = oldImage.pixelValue[i][j]; } } ImageType::~ImageType() { int i; for(i=0; i<N; i++) delete [] pixelValue[i]; delete [] pixelValue; } void ImageType::getImageInfo(int& rows, int& cols, int& levels) { rows = N; cols = M; levels = Q; } void ImageType::setImageInfo(int rows, int cols, int levels) { N= rows; M= cols; Q= levels; } void ImageType::setPixelVal(int i, int j, int val) { pixelValue[i][j] = val; } void ImageType::getPixelVal(int i, int j, int& val) { val = pixelValue[i][j]; } 2. ReadImage.cpp #include <iostream.h> #include <fstream.h> #include <stdlib.h> #include "image.h" int readImage(char fname[], ImageType& image) { int i, j; int N, M, Q; unsigned char *charImage; char header [100], *ptr; ifstream ifp; ifp.open(fname, ios::in | ios::binary); if (!ifp) { cout << "Can't read image: " << fname << endl; exit(1); } // read header ifp.getline(header,100,'\n'); if ( (header[0]!=80) || /* 'P' */ (header[1]!=53) ) { /* '5' */ cout << "Image " << fname << " is not PGM" << endl; exit(1); } ifp.getline(header,100,'\n'); while(header[0]=='#') ifp.getline(header,100,'\n'); M=strtol(header,&ptr,0); N=atoi(ptr); ifp.getline(header,100,'\n'); Q=strtol(header,&ptr,0); charImage = (unsigned char *) new unsigned char [M*N]; ifp.read( reinterpret_cast<char *>(charImage), (M*N)*sizeof(unsigned char)); if (ifp.fail()) { cout << "Image " << fname << " has wrong size" << endl; exit(1); } ifp.close(); // // Convert the unsigned characters to integers // int val; for(i=0; i<N; i++) for(j=0; j<M; j++) { val = (int)charImage[i*M+j]; image.setPixelVal(i, j, val); } delete [] charImage; return (1); } 3. Threshold.cpp #include <iostream.h> #include <fstream.h> #include <stdlib.h> #include "image.h" int readImageHeader(char[], int&, int&, int&, bool&); int readImage(char[], ImageType&); int writeImage(char[], ImageType&); int main(int argc, char *argv[]) { int i, j; int M, N, Q; bool type; int val; int thresh; // read image header readImageHeader(argv[1], N, M, Q, type); // allocate memory for the image array ImageType image(N, M, Q); // read image readImage(argv[1], image); cout << "Enter threshold: "; cin >> thresh; // threshold image for(i=0; i<N; i++) for(j=0; j<M; j++) { image.getPixelVal(i, j, val); if(val < thresh) image.setPixelVal(i, j, 255); else image.setPixelVal(i, j, 0); } // write image writeImage(argv[2], image); return (1); } 4. WriteImage.cpp #include <iostream.h> #include <fstream.h> #include <stdlib.h> #include "image.h" int writeImage(char fname[], ImageType& image) { int i, j; int N, M, Q; unsigned char *charImage; ofstream ofp; image.getImageInfo(N, M, Q); charImage = (unsigned char *) new unsigned char [M*N]; // convert the integer values to unsigned char int val; for(i=0; i<N; i++) for(j=0; j<M; j++) { image.getPixelVal(i, j, val); charImage[i*M+j]=(unsigned char)val; } ofp.open(fname, ios::out | ios::binary); if (!ofp) { cout << "Can't open file: " << fname << endl; exit(1); } ofp << "P5" << endl; ofp << M << " " << N << endl; ofp << Q << endl; ofp.write( reinterpret_cast<char *>(charImage), (M*N)*sizeof(unsigned char)); if (ofp.fail()) { cout << "Can't write image " << fname << endl; exit(0); } ofp.close(); delete [] charImage; return(1); } Algorithm 1: Huffman Coding Input: Array f [1...n] of numerical frequencies or probabilities. Output: Binary coding tree with n leaves that has minimum expected code length for f . huffman(f [1...n]) T = empty binary tree Q = priority queue of pairs (i, f [i]), i = 1...n, with f as comparison key For each k = 1...n − 1 i = extractMin(Q) j = extractMin(Q) f [n + k] = f [i] + f [j] insertNode(T, n + k) with children i, j insertRear(Q, (n + k, f [n + k])) return T