Do not allow parameter overrides in lossless.
This patch fixes:
- the fact that the order of parameters matters for lossless
- the fact that we allow a mix of -l and parameters contradictory with lossless
diff --git a/apps/avifenc.c b/apps/avifenc.c
index 848bad9..d834d5a 100644
--- a/apps/avifenc.c
+++ b/apps/avifenc.c
@@ -446,10 +446,10 @@
int returnCode = 0;
int jobs = 1;
- int minQuantizer = 24;
- int maxQuantizer = 26;
- int minQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
- int maxQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
+ int minQuantizer = -1;
+ int maxQuantizer = -1;
+ int minQuantizerAlpha = -1;
+ int maxQuantizerAlpha = -1;
int tileRowsLog2 = -1;
int tileColsLog2 = -1;
avifBool autoTiling = AVIF_FALSE;
@@ -786,19 +786,6 @@
}
} else if (!strcmp(arg, "-l") || !strcmp(arg, "--lossless")) {
lossless = AVIF_TRUE;
-
- // Set defaults, and warn later on if anything looks incorrect
- input.requestedFormat = AVIF_PIXEL_FORMAT_YUV444; // don't subsample when using AVIF_MATRIX_COEFFICIENTS_IDENTITY
- minQuantizer = AVIF_QUANTIZER_LOSSLESS; // lossless
- maxQuantizer = AVIF_QUANTIZER_LOSSLESS; // lossless
- minQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS; // lossless
- maxQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS; // lossless
- codecChoice = AVIF_CODEC_CHOICE_AOM; // rav1e doesn't support lossless transform yet:
- // https://github.com/xiph/rav1e/issues/151
- // SVT-AV1 doesn't support lossless encoding yet:
- // https://gitlab.com/AOMediaCodec/SVT-AV1/-/issues/1636
- requestedRange = AVIF_RANGE_FULL; // avoid limited range
- matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_IDENTITY; // this is key for lossless
} else if (!strcmp(arg, "-p") || !strcmp(arg, "--premultiply")) {
premultiplyAlpha = AVIF_TRUE;
} else if (!strcmp(arg, "--sharpyuv")) {
@@ -818,6 +805,62 @@
++argIndex;
}
+ // Check lossy/lossless parameters and set to default if needed.
+ if (lossless) {
+ // Pixel format.
+ if (input.requestedFormat != AVIF_PIXEL_FORMAT_NONE && input.requestedFormat != AVIF_PIXEL_FORMAT_YUV444) {
+ fprintf(stderr,
+ "When set, the pixel format can only be 444 in lossless "
+ "mode.\n");
+ returnCode = 1;
+ }
+ // Don't subsample when using AVIF_MATRIX_COEFFICIENTS_IDENTITY.
+ input.requestedFormat = AVIF_PIXEL_FORMAT_YUV444;
+ // Quantizers.
+ if (minQuantizer > 0 || maxQuantizer > 0 || minQuantizerAlpha > 0 || maxQuantizerAlpha > 0) {
+ fprintf(stderr, "Quantizers cannot be set in lossless mode, except to 0.\n");
+ returnCode = 1;
+ }
+ minQuantizer = maxQuantizer = minQuantizerAlpha = maxQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
+ // Codec.
+ if (codecChoice != AVIF_CODEC_CHOICE_AUTO && codecChoice != AVIF_CODEC_CHOICE_AOM) {
+ fprintf(stderr, "Codec can only be AOM in lossless mode.\n");
+ returnCode = 1;
+ }
+ // rav1e doesn't support lossless transform yet:
+ // https://github.com/xiph/rav1e/issues/151
+ // SVT-AV1 doesn't support lossless encoding yet:
+ // https://gitlab.com/AOMediaCodec/SVT-AV1/-/issues/1636
+ codecChoice = AVIF_CODEC_CHOICE_AOM;
+ // Range.
+ if (requestedRange != AVIF_RANGE_FULL) {
+ fprintf(stderr, "Range has to be full in lossless mode.\n");
+ returnCode = 1;
+ }
+ // Matrix coefficients.
+ if (cicpExplicitlySet && matrixCoefficients != AVIF_MATRIX_COEFFICIENTS_IDENTITY) {
+ fprintf(stderr, "Matrix coefficients have to be identity in lossless mode.\n");
+ returnCode = 1;
+ }
+ matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_IDENTITY;
+ if (returnCode == 1)
+ goto cleanup;
+ } else {
+ // Set lossy defaults.
+ if (minQuantizer == -1) {
+ minQuantizer = 24;
+ }
+ if (maxQuantizer == -1) {
+ maxQuantizer = 26;
+ }
+ if (minQuantizerAlpha == -1) {
+ minQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
+ }
+ if (maxQuantizerAlpha == -1) {
+ maxQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
+ }
+ }
+
stdinFile.filename = "(stdin)";
stdinFile.duration = outputTiming.duration;
diff --git a/tests/test_cmd_lossless.sh b/tests/test_cmd_lossless.sh
index bf0aa5d..a4bfd92 100755
--- a/tests/test_cmd_lossless.sh
+++ b/tests/test_cmd_lossless.sh
@@ -61,6 +61,16 @@
"${AVIFENC}" -s 8 "${INPUT_PNG}" -o "${ENCODED_FILE}"
"${AVIFDEC}" "${ENCODED_FILE}" "${DECODED_FILE}"
+ # Combining some arguments with lossless should fail.
+ for option in "-y 400" "--min 1" "-r limited" "--cicp 2/2/8"; do
+ "${AVIFENC}" $option -s 10 -l "${DECODED_FILE}" -o "${ENCODED_FILE}" && exit 1
+ done
+
+ # Combining some arguments with lossless should work.
+ for option in "-y 444" "--min 0" "-r full"; do
+ "${AVIFENC}" $option -s 10 -l "${DECODED_FILE}" -o "${ENCODED_FILE}"
+ done
+
# Lossless test. The decoded pixels should be the same as the original image.
echo "Testing basic lossless"
# TODO(yguyon): Make this test pass with INPUT_PNG instead of DECODED_FILE.