--- deflate.c.org 2010-02-28 01:07:26.000000000 +0800 +++ deflate.c 2010-03-28 12:04:04.985125000 +0800 @@ -138,11 +138,11 @@ /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +/* 9 */ {32, 258, 258, 8192, deflate_fast}}; /* max compression */ #endif /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. @@ -1554,11 +1554,49 @@ * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ + if ((s->level == 9) && (s->match_length == MIN_MATCH) && ((s->strstart-s->match_start) > (1 << 14))){ + s->match_length = 0; /* discard a small match, if it too distant */ + } } + + /* a small HACK written in 5 minutes + TODO: write more clever implementation + */ + if (s->match_length >= MIN_MATCH && s->level == 9) { + int tmp_strstart = s->strstart; /* store global variables */ + int tmp_match_start = s->match_start; + int dist = s->strstart-s->match_start; + int next_len; + int next_dist; + unsigned hash = s->ins_h; + int i; + + /* lazy matching with 2 byte lookahead */ + for (i = 0; i < 2; i++) { + UPDATE_HASH(s, hash, s->window[(++s->strstart) + MIN_MATCH-1]); + + next_len = longest_match (s, s->head[hash]); /* get match length and distance */ + next_dist = s->strstart-s->match_start; + + /* check for a better match, + also check the distance of the followed match */ + if ((next_len > ((s->match_length + 1) + i)) + || ((next_len > (s->match_length + i)) && ((next_dist >> 3) < dist))) { + + s->match_length = 0; /* discard current match */ + break; + } + } + + s->strstart = tmp_strstart; /* restore values */ + s->match_start = tmp_match_start; + } + /* End of hack */ + if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush);