Example #1
0
File: main.c Project: mpetri/aazip
/*
 * 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);
}
Example #2
0
/**
  * 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);
}