审查视图

vendor/github.com/andybalholm/brotli/quality.go 5.3 KB
tangxvhui authored
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
package brotli

const fastOnePassCompressionQuality = 0

const fastTwoPassCompressionQuality = 1

const zopflificationQuality = 10

const hqZopflificationQuality = 11

const maxQualityForStaticEntropyCodes = 2

const minQualityForBlockSplit = 4

const minQualityForNonzeroDistanceParams = 4

const minQualityForOptimizeHistograms = 4

const minQualityForExtensiveReferenceSearch = 5

const minQualityForContextModeling = 5

const minQualityForHqContextModeling = 7

const minQualityForHqBlockSplitting = 10

/* For quality below MIN_QUALITY_FOR_BLOCK_SPLIT there is no block splitting,
   so we buffer at most this much literals and commands. */
const maxNumDelayedSymbols = 0x2FFF

/* Returns hash-table size for quality levels 0 and 1. */
func maxHashTableSize(quality int) uint {
	if quality == fastOnePassCompressionQuality {
		return 1 << 15
	} else {
		return 1 << 17
	}
}

/* The maximum length for which the zopflification uses distinct distances. */
const maxZopfliLenQuality10 = 150

const maxZopfliLenQuality11 = 325

/* Do not thoroughly search when a long copy is found. */
const longCopyQuickStep = 16384

func maxZopfliLen(params *encoderParams) uint {
	if params.quality <= 10 {
		return maxZopfliLenQuality10
	} else {
		return maxZopfliLenQuality11
	}
}

/* Number of best candidates to evaluate to expand Zopfli chain. */
func maxZopfliCandidates(params *encoderParams) uint {
	if params.quality <= 10 {
		return 1
	} else {
		return 5
	}
}

func sanitizeParams(params *encoderParams) {
	params.quality = brotli_min_int(maxQuality, brotli_max_int(minQuality, params.quality))
	if params.quality <= maxQualityForStaticEntropyCodes {
		params.large_window = false
	}

	if params.lgwin < minWindowBits {
		params.lgwin = minWindowBits
	} else {
		var max_lgwin int
		if params.large_window {
			max_lgwin = largeMaxWindowBits
		} else {
			max_lgwin = maxWindowBits
		}
		if params.lgwin > uint(max_lgwin) {
			params.lgwin = uint(max_lgwin)
		}
	}
}

/* Returns optimized lg_block value. */
func computeLgBlock(params *encoderParams) int {
	var lgblock int = params.lgblock
	if params.quality == fastOnePassCompressionQuality || params.quality == fastTwoPassCompressionQuality {
		lgblock = int(params.lgwin)
	} else if params.quality < minQualityForBlockSplit {
		lgblock = 14
	} else if lgblock == 0 {
		lgblock = 16
		if params.quality >= 9 && params.lgwin > uint(lgblock) {
			lgblock = brotli_min_int(18, int(params.lgwin))
		}
	} else {
		lgblock = brotli_min_int(maxInputBlockBits, brotli_max_int(minInputBlockBits, lgblock))
	}

	return lgblock
}

/* Returns log2 of the size of main ring buffer area.
   Allocate at least lgwin + 1 bits for the ring buffer so that the newly
   added block fits there completely and we still get lgwin bits and at least
   read_block_size_bits + 1 bits because the copy tail length needs to be
   smaller than ring-buffer size. */
func computeRbBits(params *encoderParams) int {
	return 1 + brotli_max_int(int(params.lgwin), params.lgblock)
}

func maxMetablockSize(params *encoderParams) uint {
	var bits int = brotli_min_int(computeRbBits(params), maxInputBlockBits)
	return uint(1) << uint(bits)
}

/* When searching for backward references and have not seen matches for a long
   time, we can skip some match lookups. Unsuccessful match lookups are very
   expensive and this kind of a heuristic speeds up compression quite a lot.
   At first 8 byte strides are taken and every second byte is put to hasher.
   After 4x more literals stride by 16 bytes, every put 4-th byte to hasher.
   Applied only to qualities 2 to 9. */
func literalSpreeLengthForSparseSearch(params *encoderParams) uint {
	if params.quality < 9 {
		return 64
	} else {
		return 512
	}
}

func chooseHasher(params *encoderParams, hparams *hasherParams) {
	if params.quality > 9 {
		hparams.type_ = 10
	} else if params.quality == 4 && params.size_hint >= 1<<20 {
		hparams.type_ = 54
	} else if params.quality < 5 {
		hparams.type_ = params.quality
	} else if params.lgwin <= 16 {
		if params.quality < 7 {
			hparams.type_ = 40
		} else if params.quality < 9 {
			hparams.type_ = 41
		} else {
			hparams.type_ = 42
		}
	} else if params.size_hint >= 1<<20 && params.lgwin >= 19 {
		hparams.type_ = 6
		hparams.block_bits = params.quality - 1
		hparams.bucket_bits = 15
		hparams.hash_len = 5
		if params.quality < 7 {
			hparams.num_last_distances_to_check = 4
		} else if params.quality < 9 {
			hparams.num_last_distances_to_check = 10
		} else {
			hparams.num_last_distances_to_check = 16
		}
	} else {
		hparams.type_ = 5
		hparams.block_bits = params.quality - 1
		if params.quality < 7 {
			hparams.bucket_bits = 14
		} else {
			hparams.bucket_bits = 15
		}
		if params.quality < 7 {
			hparams.num_last_distances_to_check = 4
		} else if params.quality < 9 {
			hparams.num_last_distances_to_check = 10
		} else {
			hparams.num_last_distances_to_check = 16
		}
	}

	if params.lgwin > 24 {
		/* Different hashers for large window brotli: not for qualities <= 2,
		   these are too fast for large window. Not for qualities >= 10: their
		   hasher already works well with large window. So the changes are:
		   H3 --> H35: for quality 3.
		   H54 --> H55: for quality 4 with size hint > 1MB
		   H6 --> H65: for qualities 5, 6, 7, 8, 9. */
		if hparams.type_ == 3 {
			hparams.type_ = 35
		}

		if hparams.type_ == 54 {
			hparams.type_ = 55
		}

		if hparams.type_ == 6 {
			hparams.type_ = 65
		}
	}
}