mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1915543. Do color management on avifs on non-premultiplied alpha image data. r=gfx-reviewers,lsalzman
ConvertYCbCrToRGB32 was doing the premultiplied conversion, which happens before the surface pipe, which is where color management happens. Differential Revision: https://phabricator.services.mozilla.com/D220517
This commit is contained in:
parent
59302983cc
commit
ae74e50baf
@ -595,6 +595,9 @@ class SurfacePipeFactory {
|
||||
* B8G8R8X8.
|
||||
* @param aOrientation The orientation of the image.
|
||||
*
|
||||
* @param aFlags Note that only PREMULTIPLY_ALPHA is supported by this
|
||||
* function.
|
||||
*
|
||||
* @return A SurfacePipe if the parameters allowed one to be created
|
||||
* successfully, or Nothing() if the SurfacePipe could not be
|
||||
* initialized.
|
||||
@ -602,9 +605,15 @@ class SurfacePipeFactory {
|
||||
static Maybe<SurfacePipe> CreateReorientSurfacePipe(
|
||||
Decoder* aDecoder, const OrientedIntSize& aInputSize,
|
||||
const OrientedIntSize& aOutputSize, gfx::SurfaceFormat aFormat,
|
||||
qcms_transform* aTransform, const Orientation& aOrientation) {
|
||||
qcms_transform* aTransform, const Orientation& aOrientation,
|
||||
SurfacePipeFlags aFlags) {
|
||||
MOZ_ASSERT(aFlags == SurfacePipeFlags() ||
|
||||
aFlags == SurfacePipeFlags::PREMULTIPLY_ALPHA);
|
||||
|
||||
const bool downscale = aInputSize != aOutputSize;
|
||||
const bool colorManagement = aTransform != nullptr;
|
||||
const bool premultiplyAlpha =
|
||||
bool(aFlags & SurfacePipeFlags::PREMULTIPLY_ALPHA);
|
||||
|
||||
// Construct configurations for the SurfaceFilters. Note that the order of
|
||||
// these filters is significant. We want to deinterlace or interpolate raw
|
||||
@ -618,39 +627,78 @@ class SurfacePipeFactory {
|
||||
SurfaceConfig surfaceConfig{aDecoder, aOutputSize.ToUnknownSize(), aFormat,
|
||||
/* mFlipVertically */ false,
|
||||
/* mAnimParams */ Nothing()};
|
||||
SwizzleConfig premultiplyConfig{aFormat, aFormat, premultiplyAlpha};
|
||||
ReorientSurfaceConfig reorientSurfaceConfig{aDecoder, aOutputSize, aFormat,
|
||||
aOrientation};
|
||||
|
||||
Maybe<SurfacePipe> pipe;
|
||||
|
||||
if (aOrientation.IsIdentity()) {
|
||||
if (colorManagement) {
|
||||
if (downscale) {
|
||||
pipe =
|
||||
MakePipe(downscalingConfig, colorManagementConfig, surfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(colorManagementConfig, surfaceConfig);
|
||||
if (premultiplyAlpha) {
|
||||
if (aOrientation.IsIdentity()) {
|
||||
if (colorManagement) {
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, colorManagementConfig,
|
||||
premultiplyConfig, surfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(colorManagementConfig, premultiplyConfig,
|
||||
surfaceConfig);
|
||||
}
|
||||
} else { // (colorManagement is false)
|
||||
if (downscale) {
|
||||
pipe =
|
||||
MakePipe(downscalingConfig, premultiplyConfig, surfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(premultiplyConfig, surfaceConfig);
|
||||
}
|
||||
}
|
||||
} else { // (colorManagement is false)
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, surfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(surfaceConfig);
|
||||
} else { // (orientation is not identity)
|
||||
if (colorManagement) {
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, colorManagementConfig,
|
||||
premultiplyConfig, reorientSurfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(colorManagementConfig, premultiplyConfig,
|
||||
reorientSurfaceConfig);
|
||||
}
|
||||
} else { // (colorManagement is false)
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, premultiplyConfig,
|
||||
reorientSurfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(premultiplyConfig, reorientSurfaceConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // (orientation is not identity)
|
||||
if (colorManagement) {
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, colorManagementConfig,
|
||||
reorientSurfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(colorManagementConfig, reorientSurfaceConfig);
|
||||
} else { // (premultiplyAlpha is false)
|
||||
if (aOrientation.IsIdentity()) {
|
||||
if (colorManagement) {
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, colorManagementConfig,
|
||||
surfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(colorManagementConfig, surfaceConfig);
|
||||
}
|
||||
} else { // (colorManagement is false)
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, surfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(surfaceConfig);
|
||||
}
|
||||
}
|
||||
} else { // (colorManagement is false)
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, reorientSurfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(reorientSurfaceConfig);
|
||||
} else { // (orientation is not identity)
|
||||
if (colorManagement) {
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, colorManagementConfig,
|
||||
reorientSurfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(colorManagementConfig, reorientSurfaceConfig);
|
||||
}
|
||||
} else { // (colorManagement is false)
|
||||
if (downscale) {
|
||||
pipe = MakePipe(downscalingConfig, reorientSurfaceConfig);
|
||||
} else { // (downscale is false)
|
||||
pipe = MakePipe(reorientSurfaceConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1907,15 +1907,26 @@ nsAVIFDecoder::DecodeResult nsAVIFDecoder::DoDecodeInternal(
|
||||
}
|
||||
|
||||
PremultFunc premultOp = nullptr;
|
||||
const auto wantPremultiply =
|
||||
!bool(GetSurfaceFlags() & SurfaceFlags::NO_PREMULTIPLY_ALPHA);
|
||||
if (decodedData->mAlpha) {
|
||||
const auto wantPremultiply =
|
||||
!bool(GetSurfaceFlags() & SurfaceFlags::NO_PREMULTIPLY_ALPHA);
|
||||
const bool& hasPremultiply = decodedData->mAlpha->mPremultiplied;
|
||||
|
||||
if (wantPremultiply && !hasPremultiply) {
|
||||
premultOp = libyuv::ARGBAttenuate;
|
||||
} else if (!wantPremultiply && hasPremultiply) {
|
||||
premultOp = libyuv::ARGBUnattenuate;
|
||||
if (mTransform) {
|
||||
// Color management needs to be done on non-premult data, so
|
||||
// ConvertYCbCrToRGB32 needs to produce non-premult data, then color
|
||||
// management can happen and then later in the surface pipe we will
|
||||
// convert to premult if needed.
|
||||
if (hasPremultiply) {
|
||||
premultOp = libyuv::ARGBUnattenuate;
|
||||
}
|
||||
} else {
|
||||
// no color management, so premult conversion (if needed) can be done by
|
||||
// ConvertYCbCrToRGB32 before surface pipe
|
||||
if (wantPremultiply && !hasPremultiply) {
|
||||
premultOp = libyuv::ARGBAttenuate;
|
||||
} else if (!wantPremultiply && hasPremultiply) {
|
||||
premultOp = libyuv::ARGBUnattenuate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1935,6 +1946,15 @@ nsAVIFDecoder::DecodeResult nsAVIFDecoder::DoDecodeInternal(
|
||||
|
||||
Maybe<SurfacePipe> pipe = Nothing();
|
||||
|
||||
SurfacePipeFlags pipeFlags = SurfacePipeFlags();
|
||||
if (decodedData->mAlpha && mTransform) {
|
||||
// we know data is non-premult in this case, see above, so if we
|
||||
// wantPremultiply then we have to ask the surface pipe to convert for us
|
||||
if (wantPremultiply) {
|
||||
pipeFlags |= SurfacePipeFlags::PREMULTIPLY_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
if (mIsAnimated) {
|
||||
SurfaceFormat outFormat =
|
||||
decodedData->mAlpha ? SurfaceFormat::OS_RGBA : SurfaceFormat::OS_RGBX;
|
||||
@ -1946,10 +1966,11 @@ nsAVIFDecoder::DecodeResult nsAVIFDecoder::DoDecodeInternal(
|
||||
}
|
||||
pipe = SurfacePipeFactory::CreateSurfacePipe(
|
||||
this, Size(), OutputSize(), FullFrame(), format, outFormat, animParams,
|
||||
mTransform, SurfacePipeFlags());
|
||||
mTransform, pipeFlags);
|
||||
} else {
|
||||
pipe = SurfacePipeFactory::CreateReorientSurfacePipe(
|
||||
this, Size(), OutputSize(), format, mTransform, GetOrientation());
|
||||
this, Size(), OutputSize(), format, mTransform, GetOrientation(),
|
||||
pipeFlags);
|
||||
}
|
||||
|
||||
if (pipe.isNothing()) {
|
||||
|
@ -401,7 +401,7 @@ LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::ReadJPEGData(
|
||||
|
||||
Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateReorientSurfacePipe(
|
||||
this, Size(), OutputSize(), SurfaceFormat::OS_RGBX, pipeTransform,
|
||||
GetOrientation());
|
||||
GetOrientation(), SurfacePipeFlags());
|
||||
if (!pipe) {
|
||||
mState = JPEG_ERROR;
|
||||
MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
|
||||
|
Loading…
Reference in New Issue
Block a user