Update libavif (v1.0.0-main)

* Update libavif for improved compression and speed
* v1.0.0 deprecates usage of min and max-quantizers; we use `quality` and `qualityAlpha` instead
* Renamed `maxSpeed` to `MAX_EFFORT` for better readability
This commit is contained in:
robo-mop
2023-09-15 01:48:24 +05:30
parent ecc715fe55
commit 47f874677e
14 changed files with 32 additions and 32 deletions

View File

@@ -1,6 +1,6 @@
# libavif and libaom versions are from # libavif and libaom versions are from
# google3/third_party/libavif/METADATA # google3/third_party/libavif/METADATA
CODEC_URL = https://github.com/AOMediaCodec/libavif/archive/647c3c208cf152395d777c1bf7240d2ecf7df5a9.tar.gz CODEC_URL = https://github.com/AOMediaCodec/libavif/archive/bc41fc5b22786976ca23664905875ccd104f55c4.tar.gz
CODEC_PACKAGE = node_modules/libavif.tar.gz CODEC_PACKAGE = node_modules/libavif.tar.gz
LIBAOM_URL = https://aomedia.googlesource.com/aom/+archive/v3.6.0.tar.gz LIBAOM_URL = https://aomedia.googlesource.com/aom/+archive/v3.6.0.tar.gz

Binary file not shown.

Binary file not shown.

View File

@@ -6,9 +6,9 @@
using namespace emscripten; using namespace emscripten;
struct AvifOptions { struct AvifOptions {
// [0 - 63] // [0 - 100]
// 0 = lossless // 0 = worst quality
// 63 = worst quality // 100 = lossless
int cqLevel; int cqLevel;
// As above, but -1 means 'use cqLevel' // As above, but -1 means 'use cqLevel'
int cqAlphaLevel; int cqAlphaLevel;
@@ -81,23 +81,16 @@ val encode(std::string buffer, int width, int height, AvifOptions options) {
avifEncoder* encoder = avifEncoderCreate(); avifEncoder* encoder = avifEncoderCreate();
if (lossless) { if (lossless) {
encoder->minQuantizer = AVIF_QUANTIZER_LOSSLESS; encoder->quality = AVIF_QUALITY_LOSSLESS;
encoder->maxQuantizer = AVIF_QUANTIZER_LOSSLESS; encoder->qualityAlpha = AVIF_QUALITY_LOSSLESS;
encoder->minQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
encoder->maxQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
} else { } else {
encoder->minQuantizer = AVIF_QUANTIZER_BEST_QUALITY;
encoder->maxQuantizer = AVIF_QUANTIZER_WORST_QUALITY;
encoder->minQuantizerAlpha = AVIF_QUANTIZER_BEST_QUALITY;
encoder->maxQuantizerAlpha = AVIF_QUANTIZER_WORST_QUALITY;
avifEncoderSetCodecSpecificOption(encoder, "end-usage", "q"); avifEncoderSetCodecSpecificOption(encoder, "end-usage", "q");
avifEncoderSetCodecSpecificOption(encoder, "cq-level", std::to_string(options.cqLevel).c_str());
avifEncoderSetCodecSpecificOption(encoder, "sharpness", avifEncoderSetCodecSpecificOption(encoder, "sharpness",
std::to_string(options.sharpness).c_str()); std::to_string(options.sharpness).c_str());
encoder->quality = options.cqLevel;
if (options.cqAlphaLevel != -1) { if (options.cqAlphaLevel != -1) {
avifEncoderSetCodecSpecificOption(encoder, "alpha:cq-level", encoder->qualityAlpha = options.cqAlphaLevel;
std::to_string(options.cqAlphaLevel).c_str());
} }
if (options.tune == 2 || (options.tune == 0 && options.cqLevel <= 32)) { if (options.tune == 2 || (options.tune == 0 && options.cqLevel <= 32)) {

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -40,8 +40,15 @@ interface State {
tune: AVIFTune; tune: AVIFTune;
} }
const maxQuant = 63; /**
const maxSpeed = 10; * AVIF quality ranges from 0 (worst) to 100 (lossless).
* Since lossless is a separate checkbox, we cap user-inputted quality at 99
*
* AVIF speed ranges from 0 (slowest) to 10 (fastest).
* We display it as 'effort' to the user since it conveys the speed-size tradeoff
* much better: speed = 10 - effort
*/
const MAX_EFFORT = 10;
export class Options extends Component<Props, State> { export class Options extends Component<Props, State> {
static getDerivedStateFromProps( static getDerivedStateFromProps(
@@ -67,18 +74,18 @@ export class Options extends Component<Props, State> {
return { return {
options, options,
lossless, lossless,
quality: maxQuant - cqLevel, quality: cqLevel,
separateAlpha, separateAlpha,
alphaQuality: alphaQuality: separateAlpha
maxQuant - ? options.cqAlphaLevel
(separateAlpha ? options.cqAlphaLevel : defaultOptions.cqLevel), : defaultOptions.cqLevel,
subsample: subsample:
options.subsample === 0 || lossless options.subsample === 0 || lossless
? defaultOptions.subsample ? defaultOptions.subsample
: options.subsample, : options.subsample,
tileRows: options.tileRowsLog2, tileRows: options.tileRowsLog2,
tileCols: options.tileColsLog2, tileCols: options.tileColsLog2,
effort: maxSpeed - options.speed, effort: MAX_EFFORT - options.speed,
chromaDeltaQ: options.chromaDeltaQ, chromaDeltaQ: options.chromaDeltaQ,
sharpness: options.sharpness, sharpness: options.sharpness,
denoiseLevel: options.denoiseLevel, denoiseLevel: options.denoiseLevel,
@@ -120,16 +127,16 @@ export class Options extends Component<Props, State> {
}; };
const newOptions: EncodeOptions = { const newOptions: EncodeOptions = {
cqLevel: optionState.lossless ? 0 : maxQuant - optionState.quality, cqLevel: optionState.lossless ? 100 : optionState.quality,
cqAlphaLevel: cqAlphaLevel:
optionState.lossless || !optionState.separateAlpha optionState.lossless || !optionState.separateAlpha
? -1 ? -1
: maxQuant - optionState.alphaQuality, : optionState.alphaQuality,
// Always set to 4:4:4 if lossless // Always set to 4:4:4 if lossless
subsample: optionState.lossless ? 3 : optionState.subsample, subsample: optionState.lossless ? 3 : optionState.subsample,
tileColsLog2: optionState.tileCols, tileColsLog2: optionState.tileCols,
tileRowsLog2: optionState.tileRows, tileRowsLog2: optionState.tileRows,
speed: maxSpeed - optionState.effort, speed: MAX_EFFORT - optionState.effort,
chromaDeltaQ: optionState.chromaDeltaQ, chromaDeltaQ: optionState.chromaDeltaQ,
sharpness: optionState.sharpness, sharpness: optionState.sharpness,
denoiseLevel: optionState.denoiseLevel, denoiseLevel: optionState.denoiseLevel,
@@ -183,7 +190,7 @@ export class Options extends Component<Props, State> {
<div class={style.optionOneCell}> <div class={style.optionOneCell}>
<Range <Range
min="0" min="0"
max="63" max="99"
value={quality} value={quality}
onInput={this._inputChange('quality', 'number')} onInput={this._inputChange('quality', 'number')}
> >
@@ -228,7 +235,7 @@ export class Options extends Component<Props, State> {
<div class={style.optionOneCell}> <div class={style.optionOneCell}>
<Range <Range
min="0" min="0"
max="63" max="99"
value={alphaQuality} value={alphaQuality}
onInput={this._inputChange( onInput={this._inputChange(
'alphaQuality', 'alphaQuality',

View File

@@ -18,7 +18,7 @@ export const label = 'AVIF';
export const mimeType = 'image/avif'; export const mimeType = 'image/avif';
export const extension = 'avif'; export const extension = 'avif';
export const defaultOptions: EncodeOptions = { export const defaultOptions: EncodeOptions = {
cqLevel: 33, cqLevel: 50,
cqAlphaLevel: -1, cqAlphaLevel: -1,
denoiseLevel: 0, denoiseLevel: 0,
tileColsLog2: 0, tileColsLog2: 0,