Example #1
0
static void do_uncompress_24(deark *c, lctx *d, struct page_ctx *pg, dbuf *unc_pixels,
	de_int64 skip)
{
	de_int64 pos;
	de_byte b;
	de_int64 count;
	de_byte n;

	pos = pg->image_pos;
	if(skip) pos+=4;

	while(1) {
		if(pos >= pg->image_pos + pg->image_len) break;

		b = de_getbyte(pos);
		pos++;
		if(b>=128) {
			// Compressed run
			count = (de_int64)b - 125;
			n = de_getbyte(pos);
			pos++;
			dbuf_write_run(unc_pixels, n, count);
		}
		else {
			// An uncompressed run
			count = 1 + (de_int64)b;
			dbuf_copy(c->infile, pos, count, unc_pixels);
			pos += count;
		}
	}
}
Example #2
0
// RLE algorithm occasionally called "RLE90". Variants of this are used by
// BinHex, ARC, StuffIt, and others.
int de_fmtutil_decompress_rle90(dbuf *inf, i64 pos1, i64 len,
	dbuf *outf, unsigned int has_maxlen, i64 max_out_len, unsigned int flags)
{
	i64 pos = pos1;
	u8 b;
	u8 lastbyte = 0x00;
	u8 countcode;
	i64 count;
	i64 nbytes_written = 0;

	while(pos < pos1+len) {
		if(has_maxlen && nbytes_written>=max_out_len) break;

		b = dbuf_getbyte(inf, pos);
		pos++;
		if(b!=0x90) {
			dbuf_writebyte(outf, b);
			nbytes_written++;
			lastbyte = b;
			continue;
		}

		// b = 0x90, which is a special code.
		countcode = dbuf_getbyte(inf, pos);
		pos++;

		if(countcode==0x00) {
			// Not RLE, just an escaped 0x90 byte.
			dbuf_writebyte(outf, 0x90);
			nbytes_written++;

			// Here there is an inconsistency between different RLE90
			// implementations.
			// Some of them can compress a run of 0x90 bytes, because the byte
			// to repeat is defined to be the "last byte emitted".
			// Others do not allow this. If the "0x90 0x00 0x90 0xNN" sequence
			// (with 0xNN>0) is encountered, they may (by accident?) repeat the
			// last non-0x90 byte emitted, or do something else.
			// Hopefully, valid files in such formats never contain this byte
			// sequence, so it shouldn't matter what we do here. But maybe not.
			// We might need to add an option to do something else.
			lastbyte = 0x90;
			continue;
		}

		// RLE. We already emitted one byte (because the byte to repeat
		// comes before the repeat count), so write countcode-1 bytes.
		count = (i64)(countcode-1);
		if(has_maxlen && (nbytes_written+count > max_out_len)) {
			count = max_out_len - nbytes_written;
		}
		dbuf_write_run(outf, lastbyte, count);
		nbytes_written += count;
	}

	return 1;
}
Example #3
0
// Returns 0 on failure (currently impossible).
int de_fmtutil_uncompress_packbits(dbuf *f, i64 pos1, i64 len,
	dbuf *unc_pixels, i64 *cmpr_bytes_consumed)
{
	i64 pos;
	u8 b, b2;
	i64 count;
	i64 endpos;

	pos = pos1;
	endpos = pos1+len;

	while(1) {
		if(unc_pixels->has_len_limit && unc_pixels->len>=unc_pixels->len_limit) {
			break; // Decompressed the requested amount of dst data.
		}

		if(pos>=endpos) {
			break; // Reached the end of source data
		}
		b = dbuf_getbyte(f, pos++);

		if(b>128) { // A compressed run
			count = 257 - (i64)b;
			b2 = dbuf_getbyte(f, pos++);
			dbuf_write_run(unc_pixels, b2, count);
		}
		else if(b<128) { // An uncompressed run
			count = 1 + (i64)b;
			dbuf_copy(f, pos, count, unc_pixels);
			pos += count;
		}
		// Else b==128. No-op.
		// TODO: Some (but not most) ILBM specs say that code 128 is used to
		// mark the end of compressed data, so maybe there should be options to
		// tell us what to do when code 128 is encountered.
	}

	if(cmpr_bytes_consumed) *cmpr_bytes_consumed = pos - pos1;
	return 1;
}
Example #4
0
// Caller must initialize *repeat_count.
static void uncompress_line(deark *c, lctx *d, dbuf *unc_line,
	i64 pos1, i64 rownum,
	i64 *bytes_consumed, i64 *repeat_count)
{
	i64 pos;
	u8 b0, b1;
	u8 val;
	i64 count;
	i64 k;
	i64 tmp_repeat_count;
	i64 unc_line_len_orig;

	*bytes_consumed = 0;
	pos = pos1;
	unc_line_len_orig = unc_line->len;

	while(1) {
		if(pos >= c->infile->len) break;
		if(unc_line->len - unc_line_len_orig >= d->rowspan_per_plane) break;

		b0 = de_getbyte(pos++);

		if(b0==0) { // Pattern run or scanline run
			b1 = de_getbyte(pos++);
			if(b1>0) { // pattern run
				de_read(d->pattern_buf, pos, d->patlen);
				pos += d->patlen;
				count = (i64)b1;
				for(k=0; k<count; k++) {
					dbuf_write(unc_line, d->pattern_buf, d->patlen);
				}
			}
			else { // (b1==0) scanline run
				u8 flagbyte;
				flagbyte = de_getbyte(pos);
				if(flagbyte==0xff) {
					pos++;
					tmp_repeat_count = (i64)de_getbyte(pos++);
					if(tmp_repeat_count == 0) {
						de_dbg(c, "row %d: bad repeat count", (int)rownum);
					}
					else {
						*repeat_count = tmp_repeat_count;
					}
				}
				else {
					de_dbg(c, "row %d: bad scanline run marker: 0x%02x",
						(int)rownum, (unsigned int)flagbyte);
				}
			}
		}
		else if(b0==0x80) { // "Uncompressed bit string"
			count = (i64)de_getbyte(pos++);
			dbuf_copy(c->infile, pos, count, unc_line);
			pos += count;
		}
		else { // "solid run"
			val = (b0&0x80) ? 0xff : 0x00;
			count = (i64)(b0 & 0x7f);
			dbuf_write_run(unc_line, val, count);
		}
	}

	*bytes_consumed = pos - pos1;
}
Example #5
0
void dbuf_write_zeroes(dbuf *f, i64 len)
{
	dbuf_write_run(f, 0, len);
}