/* * aazip - compress files using a transform based compression system */ int main(int argc, char** argv) { FILE* f; bit_file_t* of; char* infile,*outfile; uint8_t* input,*lupdate,*bwt,lumode; int32_t I,osize,opt; uint32_t size; mode_t lupdate_alg; float ient,oent; uint64_t cost,tstart,tstop,elapsed; /* parse command line parameter */ opt = GETOPT_FINISHED; if (argc <= 1) { print_usage(argv[0]); exit(EXIT_FAILURE); } while ((opt = getopt(argc, argv, "m:h")) != GETOPT_FINISHED) { switch (opt) { case 'm': if (strcmp(optarg, "simple") == 0) lupdate_alg = SIMPLE; else if (strcmp(optarg, "mtf") == 0) lupdate_alg = MTF; else if (strcmp(optarg, "fc") == 0) lupdate_alg = FC; else if (strcmp(optarg, "wfc") == 0) lupdate_alg = WFC; else if (strcmp(optarg, "timestamp") == 0) lupdate_alg = TS; else fatal("ERROR: mode <%s> unknown!\n", optarg); break; case 'h': default: print_usage(argv[0]); exit(EXIT_FAILURE); } } /* read input file name */ if (optind < argc) infile = argv[optind]; else { print_usage(argv[0]); exit(EXIT_FAILURE); } /* read input file */ f = safe_fopen(infile,"r"); size = safe_filesize(f); input = (uint8_t*) safe_malloc(size+1); if (fread(input,1,size,f)!=(size_t)size) { fatal("read input file."); } safe_fclose(f); input[size] = 0; /* TODO calculate input entropy */ ient = 0.0f; /* perform bwt */ bwt = (uint8_t*) safe_malloc(size); tstart = gettime(); bwt = transform_bwt(input,size,bwt,&I); /* peform list update */ switch (lupdate_alg) { case SIMPLE: fprintf(stdout,"ALGORITHM: simple\n"); lupdate = lupdate_simple(bwt,size,input,&cost); break; case MTF: fprintf(stdout,"ALGORITHM: move to front\n"); lupdate = lupdate_movetofront(bwt,size,input,&cost); break; case FC: fprintf(stdout,"ALGORITHM: frequency count\n"); lupdate = lupdate_freqcount(bwt,size,input,&cost); break; case WFC: fprintf(stdout,"ALGORITHM: weighted frequency count\n"); lupdate = lupdate_wfc(bwt,size,input,&cost); break; case TS: fprintf(stdout,"ALGORITHM: timestamp\n"); lupdate = lupdate_timestamp(bwt,size,input,&cost); break; default: fatal("unkown list update algorithm."); } fprintf(stdout,"INPUT: %s (%d bytes)\n",infile,size); fprintf(stdout,"COST: %lu\n",cost); /* TODO calculate entropy after list update*/ oent = 0.0f; /* write output */ outfile = safe_strcat(infile,".aazip"); /* create bit file for writing */ of = BitFileOpen(outfile, BF_WRITE); /* write aa zip header */ BitFilePutChar('A', of); BitFilePutChar('A', of); /* write I */ BitFilePutBitsInt(of,&I,32,sizeof(uint32_t)); /* write lupdate mode */ lumode = lupdate_alg; BitFilePutBitsInt(of,&lumode,8,sizeof(uint8_t)); fprintf(stderr,"I %d lumode %d\n",I,lumode); /* perform huffman coding */ encode_huffman(lupdate,size,of); tstop = gettime(); elapsed = tstop - tstart; fprintf(stdout,"TIME: %.3f s\n",(float)elapsed/1000000); /* flush and get file stats */ BitFileFlushOutput(of,0); f = BitFileToFILE(of); osize = ftell(f); fprintf(stdout,"OUTPUT: %s\n",outfile); fprintf(stdout,"ENTROPY: %.2f bps / %.2f bps\n",ient,oent); fprintf(stdout,"COMPRESSION: %.2f\n",((float)osize/(float)size)*100); /* clean up*/ safe_fclose(f); free(input); free(bwt); return (EXIT_SUCCESS); }
/** * Saves a DWT file */ void DWT::save(const string &fileName) { FILE *fHan = fopen(fileName.data(), "wb"); // Header fwrite(&magic, 1, 2, fHan); #ifdef __BIG_ENDIAN__ // Correct endianness for writing bpp = swap_endian32(bpp); realWidth = swap_endian32(realWidth); realHeight = swap_endian32(realHeight); #endif fwrite(&bpp, sizeof(bpp), 1, fHan); fwrite(&realWidth, sizeof(int), 1, fHan); fwrite(&realHeight, sizeof(int), 1, fHan); #ifdef __BIG_ENDIAN__ // Revert endianness bpp = swap_endian32(bpp); realWidth = swap_endian32(realWidth); realHeight = swap_endian32(realHeight); #endif // Drops half of the padding when writing unsigned int stopHeight = height - (height - realHeight)/2; unsigned int stopWidth = width - (width - realWidth)/2; unsigned int stopPrHeight = stopHeight * PREVIEW / height; unsigned int stopPrWidth = stopWidth * PREVIEW / width; // Looking for the highest absolute value in the transformation, used for quantization float maxAbsValF = 0; for (unsigned int i = 0; i < stopHeight; i++) { for (unsigned int j = 0; j < stopWidth; j++){ if (i >= PREVIEW || j >= PREVIEW) { if (abs(coeff[i*width+j]) > maxAbsValF) maxAbsValF = abs(coeff[i*width+j]); } } } int maxAbsVal = round(maxAbsValF); cout << "maxValue: " << maxAbsVal << endl; fwrite(&maxAbsVal, sizeof(int), 1, fHan); const float C = ((1 << (bpp-1))-1)/(float)(maxAbsVal); // Range value const float M = (1 << (bpp-1)); // Added to get only positive values float W = 1, w = 1/sqrt(2); // Factor of multiplication for preview for (unsigned int i = PREVIEW; i < height; i <<= 1) W *= w; for (unsigned int i = PREVIEW; i < width; i <<= 1) W *= w; // Huffman, searching for occurrences in the quantization unsigned int *occ = new unsigned int[1 << bpp]; memset(occ, 0, (1 << bpp)*sizeof(int)); for (unsigned int i = 0; i < stopHeight; i++) { for (unsigned int j = 0; j < stopWidth; j++){ if (i >= PREVIEW || j >= PREVIEW) { float quant = coeff[i * width + j] * C; if (abs(quant) >= .5f) occ[range(round(quant + M))]++; } } } Huffman *huffman = new Huffman(bpp); huffman->buildTree(occ, 1<<bpp); delete[] occ; // Encoding of the preview for (unsigned int i = 0; i < stopPrHeight && i < PREVIEW; i++) { for (unsigned int j = 0; j < stopPrWidth && j < PREVIEW; j++) { unsigned char l = coeff[i*width + j] * W; fwrite(&l, 1, 1, fHan); } } // Encoding of the rest of the transform, using Huffman and RLE int zeros = 0; bit_file_t *bf = MakeBitFile(fHan, BF_APPEND); huffman->setFile(bf); huffman->writeTree(); for (unsigned int i = 0; i < stopHeight; i++) { for (unsigned int j = 0; j < stopWidth; j++) { if (i >= PREVIEW || j >= PREVIEW) { bool zero = abs(coeff[i*width + j]*C) < .5f; if (zero) zeros++; if (!zero || (i==stopHeight-1 && j==stopWidth-1)) { if (zeros != 0) { // RLE: a sequence of zeros has been found if (zeros <= 8) { unsigned int n = zeros-1; BitFilePutBit(1, bf); BitFilePutBit(0, bf); BitFilePutBitsInt(bf, &n, 3, sizeof(n)); } else { while (zeros > 0) { unsigned int n = zeros > 256 ? 255 : zeros-1; BitFilePutBit(1, bf); BitFilePutBit(1, bf); BitFilePutBitsInt(bf, &n, 8, sizeof(n)); zeros -= 256; } } zeros = 0; } if (i!=stopHeight-1 || j!=stopWidth-1) { // Huffman: write a quantized and then Huffman-encoded value unsigned int l = range(round(coeff[i*width + j]*C + M)); BitFilePutBit(0, bf); huffman->writeSymbol(l); } } } } } BitFileFlushOutput(bf, 0); delete huffman; fclose(fHan); }