mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-05-28 00:30:23 -04:00
avif: lossless support
This commit is contained in:
parent
384f78a13c
commit
84d56d00cf
@ -86,8 +86,7 @@ if (TARGET avif)
|
|||||||
kimageformats_read_tests(
|
kimageformats_read_tests(
|
||||||
avif
|
avif
|
||||||
)
|
)
|
||||||
# because the plug-ins use RGB->YUV conversion which sometimes results in 1 value difference.
|
kimageformats_write_tests(
|
||||||
kimageformats_write_tests(FUZZ 1
|
|
||||||
avif-nodatacheck-lossless
|
avif-nodatacheck-lossless
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@ -452,8 +452,13 @@ bool QAVIFHandler::write(const QImage &image)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_quality >= 100 && !avifCodecName(AVIF_CODEC_CHOICE_AOM, AVIF_CODEC_FLAG_CAN_ENCODE)) {
|
bool lossless = false;
|
||||||
qWarning("You are using %s encoder. It is recommended to enable libAOM encoder in libavif for better near-lossless compression.", encoder_name);
|
if (m_quality >= 100) {
|
||||||
|
if (avifCodecName(AVIF_CODEC_CHOICE_AOM, AVIF_CODEC_FLAG_CAN_ENCODE)) {
|
||||||
|
lossless = true;
|
||||||
|
} else {
|
||||||
|
qWarning("You are using %s encoder. It is recommended to enable libAOM encoder in libavif to use lossless compression.", encoder_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxQuantizer = AVIF_QUANTIZER_WORST_QUALITY * (100 - qBound(0, m_quality, 100)) / 100;
|
int maxQuantizer = AVIF_QUANTIZER_WORST_QUALITY * (100 - qBound(0, m_quality, 100)) / 100;
|
||||||
@ -648,43 +653,47 @@ bool QAVIFHandler::write(const QImage &image)
|
|||||||
|
|
||||||
// in case primaries or trc were not identified
|
// in case primaries or trc were not identified
|
||||||
if ((primaries_to_save == 2) || (transfer_to_save == 2)) {
|
if ((primaries_to_save == 2) || (transfer_to_save == 2)) {
|
||||||
// upgrade image to higher bit depth
|
if (lossless) {
|
||||||
if (save_depth == 8) {
|
iccprofile = tmpcolorimage.colorSpace().iccProfile();
|
||||||
save_depth = 10;
|
} else {
|
||||||
if (tmpcolorimage.hasAlphaChannel()) {
|
// upgrade image to higher bit depth
|
||||||
tmpcolorimage = tmpcolorimage.convertToFormat(QImage::Format_RGBA64);
|
if (save_depth == 8) {
|
||||||
} else {
|
save_depth = 10;
|
||||||
tmpcolorimage = tmpcolorimage.convertToFormat(QImage::Format_RGBX64);
|
if (tmpcolorimage.hasAlphaChannel()) {
|
||||||
|
tmpcolorimage = tmpcolorimage.convertToFormat(QImage::Format_RGBA64);
|
||||||
|
} else {
|
||||||
|
tmpcolorimage = tmpcolorimage.convertToFormat(QImage::Format_RGBX64);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((primaries_to_save == 2) && (transfer_to_save != 2)) { // other primaries but known trc
|
if ((primaries_to_save == 2) && (transfer_to_save != 2)) { // other primaries but known trc
|
||||||
primaries_to_save = (avifColorPrimaries)1; // AVIF_COLOR_PRIMARIES_BT709
|
primaries_to_save = (avifColorPrimaries)1; // AVIF_COLOR_PRIMARIES_BT709
|
||||||
matrix_to_save = (avifMatrixCoefficients)1; // AVIF_MATRIX_COEFFICIENTS_BT709
|
matrix_to_save = (avifMatrixCoefficients)1; // AVIF_MATRIX_COEFFICIENTS_BT709
|
||||||
|
|
||||||
switch (transfer_to_save) {
|
switch (transfer_to_save) {
|
||||||
case 8: // AVIF_TRANSFER_CHARACTERISTICS_LINEAR
|
case 8: // AVIF_TRANSFER_CHARACTERISTICS_LINEAR
|
||||||
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, QColorSpace::TransferFunction::Linear));
|
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, QColorSpace::TransferFunction::Linear));
|
||||||
break;
|
break;
|
||||||
case 4: // AVIF_TRANSFER_CHARACTERISTICS_BT470M
|
case 4: // AVIF_TRANSFER_CHARACTERISTICS_BT470M
|
||||||
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, 2.2f));
|
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, 2.2f));
|
||||||
break;
|
break;
|
||||||
case 5: // AVIF_TRANSFER_CHARACTERISTICS_BT470BG
|
case 5: // AVIF_TRANSFER_CHARACTERISTICS_BT470BG
|
||||||
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, 2.8f));
|
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, 2.8f));
|
||||||
break;
|
break;
|
||||||
default: // AVIF_TRANSFER_CHARACTERISTICS_SRGB + any other
|
default: // AVIF_TRANSFER_CHARACTERISTICS_SRGB + any other
|
||||||
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, QColorSpace::TransferFunction::SRgb));
|
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, QColorSpace::TransferFunction::SRgb));
|
||||||
|
transfer_to_save = (avifTransferCharacteristics)13;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if ((primaries_to_save != 2) && (transfer_to_save == 2)) { // recognized primaries but other trc
|
||||||
transfer_to_save = (avifTransferCharacteristics)13;
|
transfer_to_save = (avifTransferCharacteristics)13;
|
||||||
break;
|
tmpcolorimage.convertToColorSpace(tmpcolorimage.colorSpace().withTransferFunction(QColorSpace::TransferFunction::SRgb));
|
||||||
|
} else { // unrecognized profile
|
||||||
|
primaries_to_save = (avifColorPrimaries)1; // AVIF_COLOR_PRIMARIES_BT709
|
||||||
|
transfer_to_save = (avifTransferCharacteristics)13;
|
||||||
|
matrix_to_save = (avifMatrixCoefficients)1; // AVIF_MATRIX_COEFFICIENTS_BT709
|
||||||
|
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, QColorSpace::TransferFunction::SRgb));
|
||||||
}
|
}
|
||||||
} else if ((primaries_to_save != 2) && (transfer_to_save == 2)) { // recognized primaries but other trc
|
|
||||||
transfer_to_save = (avifTransferCharacteristics)13;
|
|
||||||
tmpcolorimage.convertToColorSpace(tmpcolorimage.colorSpace().withTransferFunction(QColorSpace::TransferFunction::SRgb));
|
|
||||||
} else { // unrecognized profile
|
|
||||||
primaries_to_save = (avifColorPrimaries)1; // AVIF_COLOR_PRIMARIES_BT709
|
|
||||||
transfer_to_save = (avifTransferCharacteristics)13;
|
|
||||||
matrix_to_save = (avifMatrixCoefficients)1; // AVIF_MATRIX_COEFFICIENTS_BT709
|
|
||||||
tmpcolorimage.convertToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, QColorSpace::TransferFunction::SRgb));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // profile is unsupported by Qt
|
} else { // profile is unsupported by Qt
|
||||||
@ -694,6 +703,9 @@ bool QAVIFHandler::write(const QImage &image)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lossless && pixel_format == AVIF_PIXEL_FORMAT_YUV444) {
|
||||||
|
matrix_to_save = (avifMatrixCoefficients)0;
|
||||||
|
}
|
||||||
avif = avifImageCreate(tmpcolorimage.width(), tmpcolorimage.height(), save_depth, pixel_format);
|
avif = avifImageCreate(tmpcolorimage.width(), tmpcolorimage.height(), save_depth, pixel_format);
|
||||||
avif->matrixCoefficients = matrix_to_save;
|
avif->matrixCoefficients = matrix_to_save;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user