import java.io.*; /** * The class which performs the encoding process. * * @author Amanda Askew & Dane Barney * @version 2003.09.11 */ public class Encoder extends Endec { public BitWriter out; public int encodedBytes; /** * Initializes the output stream, creates a new arithmetic coder, initializes * all the contexts, and writes the file header (which precedes the actual encoded * data). * * @param compressedFile the file to decode */ public Encoder(Image inputImage, String outputFile, Coords[] contextCoords) throws IOException { out = new BitWriter(new DataOutputStream(new FileOutputStream(outputFile))); im = inputImage; ar = new ArithmeticCoder(); this.contextCoords = contextCoords; // create all the possible contexts and store them in an array createContextArray(); // write image header to file writeImgHeader(); // write context coordinates to file writeContextCoords(); } /** * Writes the image header data, which is the first thing stored * in the compressed file. */ public void writeImgHeader() throws IOException { out.writeByte((byte)im.type); // first send the type of image // now send the header byte-by-byte for(int i=0; i < im.header.length; i++) out.writeByte(im.header[i]); // finally, write the dominant color in this image out.write4Bytes(im.dominantColor); } /** * Writes the pixel coordinates in the context used to encode this file * (so the decoder knows). */ public void writeContextCoords() throws IOException { out.writeByte((byte)contextCoords.length); // first write total number of context coordinates to write for(int i=0; i < contextCoords.length; i++) { out.writeByte((byte)contextCoords[i].x); // 1st byte = x coord out.writeByte((byte)contextCoords[i].y); // 2nd byte = y coord } } /** * Encodes pixels from the image and writes to the output stream. */ public void encode() throws IOException { int startingBytes = out.bytesWritten; // iterate through all the pixels in the pixel matrix for(int j=0; j < im.height; j++) { for(int i=0; i < im.width; i++) { int currentPixel = im.pixels[i][j]; // locate the correct context for this particular pixel Context context = findContext(i,j); // send this pixel to the arithmetic coder ar.encodeValue(currentPixel, context, out); } } ar.finishEncode(out); out.finish(); encodedBytes = out.bytesWritten - startingBytes; out.close(); } }