static long calculate_buffer_size (BITS *bits) { int block_nbr; /* Bitstring block number */ word comp_size; /* Size of compressed block */ BITBLOCK *block_ptr; /* Points to bitstring block */ long feedback = 0; /* Calulated value to return */ ASSERT (bits); feedback += sizeof (bits-> block_count); feedback += sizeof (bits-> free_list); /* Write bitstring blocks to file */ for (block_nbr = 0; block_nbr < bits-> block_count; block_nbr++) { block_ptr = bits-> block [block_nbr]; comp_size = compress_block (block_ptr-> block.data, compressed, (word)BIT_DATASIZE); feedback += sizeof (block_ptr-> right); feedback += sizeof (block_ptr-> size); feedback += sizeof (comp_size) + comp_size; } return (feedback); }
int bits_fput (FILE *file, const BITS *bits) { int block_nbr; /* Bitstring block number */ word comp_size; /* Size of compressed block */ BITBLOCK *block_ptr; /* Points to bitstring block */ ASSERT (bits); ASSERT (file); /* Write bitstring header to file */ fwrite (&bits-> block_count, sizeof (bits-> block_count), 1, file); fwrite (&bits-> free_list, sizeof (bits-> free_list), 1, file); /* Write bitstring blocks to file */ for (block_nbr = 0; block_nbr < bits-> block_count; block_nbr++) { block_ptr = bits-> block [block_nbr]; comp_size = compress_block ((byte *) block_ptr, compressed, (word) block_ptr-> size); fwrite (&comp_size, sizeof (comp_size), 1, file); fwrite (compressed, comp_size, 1, file); } return 0; }
static void have_end_of_block (Bool compress) { output_dbyte = htons (nbr_paras); *(dbyte *) inbuf = output_dbyte; if (compress) { outsize = compress_block (inbuf, outbuf, insize); output_dbyte = htons (outsize); ASSERT (fwrite (&output_dbyte, 2, 1, scratch)); ASSERT (fwrite (outbuf, 1, outsize, scratch)); sizes [nbr_blocks] = outsize + 2; } else { output_dbyte = htons (insize); ASSERT (fwrite (&output_dbyte, 2, 1, scratch)); ASSERT (fwrite (inbuf, 1, insize, scratch)); sizes [nbr_blocks] = insize + 2; } insize = 2; /* Clear input buffer */ nbr_paras = 0; nbr_blocks++; }
char * bits_save (BITS *bits) { int block_nbr; /* Bitstring block number */ word comp_size; /* Size of compressed block */ BITBLOCK *block_ptr; /* Points to bitstring block */ byte *buffer = NULL, /* Stream buffer */ *position; /* Current position in the stream */ long size; char *encoded = NULL; ASSERT (bits); size = calculate_buffer_size (bits); buffer = mem_alloc (size); if (buffer) { position = buffer; /* Write bitstring header to stream */ *((int *)position) = bits-> block_count; position += sizeof (bits-> block_count); *((dbyte *)position) = bits-> free_list; position += sizeof (bits-> free_list); /* Write bitstring blocks to stream */ for (block_nbr = 0; block_nbr < bits-> block_count; block_nbr++) { block_ptr = bits-> block [block_nbr]; comp_size = compress_block (block_ptr-> block.data, compressed, (word)BIT_DATASIZE); *((dbyte *)position) = block_ptr-> right; position += sizeof (block_ptr-> right); *((int *)position) = block_ptr-> size; position += sizeof (block_ptr-> size); *((word *)position) = comp_size; position += sizeof (word); memcpy (position, compressed, comp_size); position += comp_size; } /* Encode binary buffer in base64 */ encoded = mem_alloc ((long)((double) size * 1.5) + 2); if (encoded) encode_base64 (buffer, encoded, size); mem_free (buffer); } return (encoded); }
local compress_file_lz (FILE *input, FILE *output) { word in_size, out_size; qbyte signature = LZ_SIGNATURE; fseek (input, 0, SEEK_SET); /* Start from beginning of file */ ASSERT (fwrite (&signature, sizeof (signature), 1, output)); while ((in_size = fread (in_block, 1, BLOCK_SIZE, input)) > 0) { out_size = compress_block (in_block, out_block, in_size); ASSERT (fwrite (&out_size, 1, sizeof (out_size), output)); ASSERT (fwrite (out_block, 1, out_size, output)); printf ("lz compress: in=%d out=%d\n", in_size, out_size); } }
int wsq_encode_mem(unsigned char **odata, int *olen, const float r_bitrate, unsigned char *idata, const int w, const int h, const int d, const int ppi, char *comment_text) { struct wsq_data_struct * pwsq_data; int ret, num_pix; float *fdata; /* floating point pixel image */ float m_shift, r_scale; /* shift/scale parameters */ short *qdata; /* quantized image pointer */ int qsize, qsize1, qsize2, qsize3; /* quantized block sizes */ unsigned char *huffbits, *huffvalues; /* huffman code parameters */ HUFFCODE *hufftable; /* huffcode table */ unsigned char *huff_buf; /* huffman encoded buffer */ int hsize, hsize1, hsize2, hsize3; /* Huffman coded blocks sizes */ unsigned char *wsq_data; /* compressed data buffer */ int wsq_alloc, wsq_len; /* number of bytes in buffer */ int block_sizes[2]; /* Compute the total number of pixels in image. */ num_pix = w * h; /* Allocate floating point pixmap. */ if((fdata = (float *) malloc(num_pix*sizeof(float))) == NULL) { fprintf(stderr,"ERROR : wsq_encode_1 : malloc : fdata\n"); return(-10); } /* Convert image pixels to floating point. */ if(ret = conv_img_2_flt_ret(fdata, &m_shift, &r_scale, idata, num_pix)) { free(fdata); return(ret); } if(debug > 0) fprintf(stderr, "Input image pixels converted to floating point\n\n"); /* Build WSQ decomposition trees */ build_wsq_trees(pwsq_data->w_tree, W_TREELEN, pwsq_data->q_tree, Q_TREELEN, w, h); if(debug > 0) fprintf(stderr, "Tables for wavelet decomposition finished\n\n"); /* WSQ decompose the image */ if((ret = wsq_decompose(fdata, w, h, pwsq_data->w_tree, W_TREELEN, hifilt, MAX_HIFILT, lofilt, MAX_LOFILT))){ free(fdata); return(ret); } if(debug > 0) fprintf(stderr, "WSQ decomposition of image finished\n\n"); /* Set compression ratio and 'q' to zero. */ pwsq_data->quant_vals.cr = 0; pwsq_data->quant_vals.q = 0.0; /* Assign specified r-bitrate into quantization structure. */ pwsq_data->quant_vals.r = r_bitrate; /* Compute subband variances. */ variance(&(pwsq_data->quant_vals), pwsq_data->q_tree, Q_TREELEN, fdata, w, h); if(debug > 0) fprintf(stderr, "Subband variances computed\n\n"); /* Quantize the floating point pixmap. */ if((ret = quantize(&qdata, &qsize, &(pwsq_data->quant_vals), pwsq_data->q_tree, Q_TREELEN, fdata, w, h))){ free(fdata); return(ret); } /* Done with floating point wsq subband data. */ free(fdata); if(debug > 0) fprintf(stderr, "WSQ subband decomposition data quantized\n\n"); /* Compute quantized WSQ subband block sizes */ quant_block_sizes(&qsize1, &qsize2, &qsize3, &(pwsq_data->quant_vals), pwsq_data->w_tree, W_TREELEN, pwsq_data->q_tree, Q_TREELEN); if(qsize != qsize1+qsize2+qsize3){ fprintf(stderr, "ERROR : wsq_encode_1 : problem w/quantization block sizes\n"); return(-11); } /* Allocate a WSQ-encoded output buffer. Allocate this buffer */ /* to be the size of the original pixmap. If the encoded data */ /* exceeds this buffer size, then throw an error because we do */ /* not want our compressed data to be larger than the original */ /* image data. */ wsq_data = (unsigned char *)malloc(num_pix); if(wsq_data == (unsigned char *)NULL){ free(qdata); fprintf(stderr, "ERROR : wsq_encode_1 : malloc : wsq_data\n"); return(-12); } wsq_alloc = num_pix; wsq_len = 0; /* Add a Start Of Image (SOI) marker to the WSQ buffer. */ if((ret = putc_ushort(SOI_WSQ, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); return(ret); } if((ret = putc_nistcom_wsq(comment_text, w, h, d, ppi, 1 /* lossy */, r_bitrate, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); return(ret); } /* Store the Wavelet filter taps to the WSQ buffer. */ if((ret = putc_transform_table(lofilt, MAX_LOFILT, hifilt, MAX_HIFILT, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); return(ret); } /* Store the quantization parameters to the WSQ buffer. */ if((ret = putc_quantization_table(&(pwsq_data->quant_vals), wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); return(ret); } /* Store a frame header to the WSQ buffer. */ if((ret = putc_frame_header_wsq(w, h, m_shift, r_scale, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); return(ret); } if(debug > 0) fprintf(stderr, "SOI, tables, and frame header written\n\n"); /* Allocate a temporary buffer for holding compressed block data. */ /* This buffer is allocated to the size of the original input image, */ /* and it is "assumed" that the compressed blocks will not exceed */ /* this buffer size. */ huff_buf = (unsigned char *)malloc(num_pix); if(huff_buf == (unsigned char *)NULL) { free(qdata); free(wsq_data); fprintf(stderr, "ERROR : wsq_encode_1 : malloc : huff_buf\n"); return(-13); } /******************/ /* ENCODE Block 1 */ /******************/ /* Compute Huffman table for Block 1. */ if((ret = gen_hufftable_wsq(&hufftable, &huffbits, &huffvalues, qdata, &qsize1, 1))){ free(qdata); free(wsq_data); free(huff_buf); return(ret); } /* Store Huffman table for Block 1 to WSQ buffer. */ if((ret = putc_huffman_table(DHT_WSQ, 0, huffbits, huffvalues, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); free(huff_buf); free(huffbits); free(huffvalues); free(hufftable); return(ret); } free(huffbits); free(huffvalues); if(debug > 0) fprintf(stderr, "Huffman code Table 1 generated and written\n\n"); /* Compress Block 1 data. */ if((ret = compress_block(huff_buf, &hsize1, qdata, qsize1, MAX_HUFFCOEFF, MAX_HUFFZRUN, hufftable))){ free(qdata); free(wsq_data); free(huff_buf); free(hufftable); return(ret); } /* Done with current Huffman table. */ free(hufftable); /* Accumulate number of bytes compressed. */ hsize = hsize1; /* Store Block 1's header to WSQ buffer. */ if((ret = putc_block_header(0, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); free(huff_buf); return(ret); } /* Store Block 1's compressed data to WSQ buffer. */ if((ret = putc_bytes(huff_buf, hsize1, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); free(huff_buf); return(ret); } if(debug > 0) fprintf(stderr, "Block 1 compressed and written\n\n"); /******************/ /* ENCODE Block 2 */ /******************/ /* Compute Huffman table for Blocks 2 & 3. */ block_sizes[0] = qsize2; block_sizes[1] = qsize3; if((ret = gen_hufftable_wsq(&hufftable, &huffbits, &huffvalues, qdata+qsize1, block_sizes, 2))){ free(qdata); free(wsq_data); free(huff_buf); return(ret); } /* Store Huffman table for Blocks 2 & 3 to WSQ buffer. */ if((ret = putc_huffman_table(DHT_WSQ, 1, huffbits, huffvalues, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); free(huff_buf); free(huffbits); free(huffvalues); free(hufftable); return(ret); } free(huffbits); free(huffvalues); if(debug > 0) fprintf(stderr, "Huffman code Table 2 generated and written\n\n"); /* Compress Block 2 data. */ if((ret = compress_block(huff_buf, &hsize2, qdata+qsize1, qsize2, MAX_HUFFCOEFF, MAX_HUFFZRUN, hufftable))){ free(qdata); free(wsq_data); free(huff_buf); free(hufftable); return(ret); } /* Accumulate number of bytes compressed. */ hsize += hsize2; /* Store Block 2's header to WSQ buffer. */ if((ret = putc_block_header(1, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); free(huff_buf); free(hufftable); return(ret); } /* Store Block 2's compressed data to WSQ buffer. */ if((ret = putc_bytes(huff_buf, hsize2, wsq_data, wsq_alloc, &wsq_len))){ free(qdata); free(wsq_data); free(huff_buf); free(hufftable); return(ret); } if(debug > 0) fprintf(stderr, "Block 2 compressed and written\n\n"); /******************/ /* ENCODE Block 3 */ /******************/ /* Compress Block 3 data. */ if((ret = compress_block(huff_buf, &hsize3, qdata+qsize1+qsize2, qsize3, MAX_HUFFCOEFF, MAX_HUFFZRUN, hufftable))){ free(qdata); free(wsq_data); free(huff_buf); free(hufftable); return(ret); } /* Done with current Huffman table. */ free(hufftable); /* Done with quantized image buffer. */ free(qdata); /* Accumulate number of bytes compressed. */ hsize += hsize3; /* Store Block 3's header to WSQ buffer. */ if((ret = putc_block_header(1, wsq_data, wsq_alloc, &wsq_len))){ free(wsq_data); free(huff_buf); return(ret); } /* Store Block 3's compressed data to WSQ buffer. */ if((ret = putc_bytes(huff_buf, hsize3, wsq_data, wsq_alloc, &wsq_len))){ free(wsq_data); free(huff_buf); return(ret); } if(debug > 0) fprintf(stderr, "Block 3 compressed and written\n\n"); /* Done with huffman compressing blocks, so done with buffer. */ free(huff_buf); /* Add a End Of Image (EOI) marker to the WSQ buffer. */ if((ret = putc_ushort(EOI_WSQ, wsq_data, wsq_alloc, &wsq_len))){ free(wsq_data); return(ret); } if(debug >= 1) { fprintf(stderr, "hsize1 = %d :: hsize2 = %d :: hsize3 = %d\n", hsize1, hsize2, hsize3); fprintf(stderr,"@ r = %.3f :: complen = %d :: ratio = %.1f\n", r_bitrate, hsize, (float)(num_pix)/(float)hsize); } *odata = wsq_data; *olen = wsq_len; /* Return normally. */ return(0); }
/* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. This function * returns the total compressed length for the file so far. */ word32 CodeTree::flush_block(byte *buf, word32 stored_len, int eof) { word32 opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex; /* index of last bit length code of non zero freq */ flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */ /* Construct the literal and distance trees */ build_tree(&l_desc); // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len)); build_tree(&d_desc); // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(); /* Determine the best encoding. Compute first the block length in bytes */ opt_lenb = (opt_len+3+7)>>3; static_lenb = (static_len+3+7)>>3; input_len += stored_len; /* for debugging only */ // Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", // opt_lenb, opt_len, static_lenb, static_len, stored_len, // last_lit, last_dist)); if (static_lenb <= opt_lenb) opt_lenb = static_lenb; #ifdef FORCE_METHOD if (level == 2 && buf) /* force stored block */ #else if (stored_len+4 <= opt_lenb && buf) /* 4: two words for the lengths */ #endif { /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ /* send block type */ send_bits((STORED_BLOCK<<1)+eof, 3); compressed_len = (compressed_len + 3 + 7) & ~7L; compressed_len += (stored_len + 4) << 3; /* with header */ copy_block(buf, (unsigned)stored_len, 1); } #ifdef FORCE_METHOD else if (level == 3) /* force static trees */ #else else if (static_lenb == opt_lenb) #endif { send_bits((STATIC_TREES<<1)+eof, 3); compress_block(static_ltree,static_dtree); compressed_len += 3 + static_len; } else { send_bits((DYN_TREES<<1)+eof, 3); send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); compress_block(dyn_ltree,dyn_dtree); compressed_len += 3 + opt_len; } // assert (compressed_len == bits_sent); init_block(); if (eof) { // assert (input_len == isize); bi_windup(); compressed_len += 7; /* align on byte boundary */ } // Tracev((stderr,"\ncomprlen %lu(%lu) ", compressed_len>>3, // compressed_len-7*eof)); return compressed_len >> 3; }