Bug 1555934 - Partially backout bug 1255106 part 3 to fix decoders with transparency. r=aosmond

This commit is contained in:
Andrew Osmond 2019-06-11 10:54:11 -04:00
Родитель c0011f4e0f
Коммит 008cb2a2d8
3 изменённых файлов: 62 добавлений и 40 удалений

Просмотреть файл

@ -116,7 +116,6 @@ nsPNGDecoder::nsPNGDecoder(RasterImage* aImage)
mFrameIsHidden(false),
mDisablePremultipliedAlpha(false),
mGotInfoCallback(false),
mUsePipeTransform(false),
mNumFrames(0) {}
nsPNGDecoder::~nsPNGDecoder() {
@ -213,10 +212,9 @@ nsresult nsPNGDecoder::CreateFrame(const FrameInfo& aFrameInfo) {
pipeFlags |= SurfacePipeFlags::PROGRESSIVE_DISPLAY;
}
qcms_transform* pipeTransform = mUsePipeTransform ? mTransform : nullptr;
Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
this, Size(), OutputSize(), aFrameInfo.mFrameRect, mFormat, animParams,
pipeTransform, pipeFlags);
/*aTransform*/ nullptr, pipeFlags);
if (!pipe) {
mPipe = SurfacePipe();
@ -415,7 +413,8 @@ static void PNGDoGammaCorrection(png_structp png_ptr, png_infop info_ptr) {
// Adapted from http://www.littlecms.com/pngchrm.c example code
static qcms_profile* PNGGetColorProfile(png_structp png_ptr, png_infop info_ptr,
int color_type, uint32_t* intent) {
int color_type, qcms_data_type* inType,
uint32_t* intent) {
qcms_profile* profile = nullptr;
*intent = QCMS_INTENT_PERCEPTUAL; // Our default
@ -493,6 +492,24 @@ static qcms_profile* PNGGetColorProfile(png_structp png_ptr, png_infop info_ptr,
}
}
if (profile) {
uint32_t profileSpace = qcms_profile_get_color_space(profile);
if (profileSpace == icSigGrayData) {
if (color_type & PNG_COLOR_MASK_ALPHA) {
*inType = QCMS_DATA_GRAYA_8;
} else {
*inType = QCMS_DATA_GRAY_8;
}
} else {
if (color_type & PNG_COLOR_MASK_ALPHA ||
png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
*inType = QCMS_DATA_RGBA_8;
} else {
*inType = QCMS_DATA_RGB_8;
}
}
}
return profile;
}
@ -570,41 +587,25 @@ void nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) {
png_set_scale_16(png_ptr);
}
// Let libpng expand interlaced images.
const bool isInterlaced = interlace_type == PNG_INTERLACE_ADAM7;
if (isInterlaced) {
png_set_interlace_handling(png_ptr);
}
qcms_data_type inType = QCMS_DATA_RGBA_8;
uint32_t intent = -1;
uint32_t pIntent;
if (decoder->mCMSMode != eCMSMode_Off) {
intent = gfxPlatform::GetRenderingIntent();
decoder->mInProfile =
PNGGetColorProfile(png_ptr, info_ptr, color_type, &pIntent);
PNGGetColorProfile(png_ptr, info_ptr, color_type, &inType, &pIntent);
// If we're not mandating an intent, use the one from the image.
if (intent == uint32_t(-1)) {
intent = pIntent;
}
}
if (decoder->mInProfile && gfxPlatform::GetCMSOutputProfile()) {
qcms_data_type inType;
qcms_data_type outType;
uint32_t profileSpace = qcms_profile_get_color_space(decoder->mInProfile);
decoder->mUsePipeTransform = profileSpace != icSigGrayData;
if (decoder->mUsePipeTransform) {
// If the transform happens with SurfacePipe, it will always be in BGRA.
inType = QCMS_DATA_BGRA_8;
outType = QCMS_DATA_BGRA_8;
if (color_type & PNG_COLOR_MASK_ALPHA || num_trans) {
outType = QCMS_DATA_RGBA_8;
} else {
if (color_type & PNG_COLOR_MASK_ALPHA) {
inType = QCMS_DATA_GRAYA_8;
outType = QCMS_DATA_RGBA_8;
} else {
inType = QCMS_DATA_GRAY_8;
outType = QCMS_DATA_RGB_8;
}
outType = QCMS_DATA_RGB_8;
}
decoder->mTransform = qcms_transform_create(
@ -619,11 +620,20 @@ void nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) {
}
if (decoder->mCMSMode == eCMSMode_All) {
decoder->mTransform = gfxPlatform::GetCMSBGRATransform();
decoder->mUsePipeTransform = true;
if (color_type & PNG_COLOR_MASK_ALPHA || num_trans) {
decoder->mTransform = gfxPlatform::GetCMSRGBATransform();
} else {
decoder->mTransform = gfxPlatform::GetCMSRGBTransform();
}
}
}
// Let libpng expand interlaced images.
const bool isInterlaced = interlace_type == PNG_INTERLACE_ADAM7;
if (isInterlaced) {
png_set_interlace_handling(png_ptr);
}
// now all of those things we set above are used to update various struct
// members and whatnot, after which we can get channels, rowbytes, etc.
png_read_update_info(png_ptr, info_ptr);
@ -688,8 +698,8 @@ void nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) {
}
#endif
if (decoder->mTransform && !decoder->mUsePipeTransform) {
uint32_t bpp[] = {0, 3, 4};
if (decoder->mTransform && (channels <= 2 || isInterlaced)) {
uint32_t bpp[] = {0, 3, 4, 3, 4};
decoder->mCMSLine =
static_cast<uint8_t*>(malloc(bpp[channels] * frameRect.Width()));
if (!decoder->mCMSLine) {
@ -830,11 +840,21 @@ void nsPNGDecoder::WriteRow(uint8_t* aRow) {
uint32_t width = uint32_t(mFrameRect.Width());
// Apply color management to the row, if necessary, before writing it out.
// This is only needed for grayscale images.
if (mTransform && !mUsePipeTransform) {
MOZ_ASSERT(mCMSLine);
qcms_transform_data(mTransform, rowToWrite, mCMSLine, width);
rowToWrite = mCMSLine;
if (mTransform) {
if (mCMSLine) {
qcms_transform_data(mTransform, rowToWrite, mCMSLine, width);
// Copy alpha over.
if (HasAlphaChannel()) {
for (uint32_t i = 0; i < width; ++i) {
mCMSLine[4 * i + 3] = rowToWrite[mChannels * i + mChannels - 1];
}
}
rowToWrite = mCMSLine;
} else {
qcms_transform_data(mTransform, rowToWrite, rowToWrite, width);
}
}
// Write this row to the SurfacePipe.

Просмотреть файл

@ -101,7 +101,6 @@ class nsPNGDecoder : public Decoder {
bool mFrameIsHidden;
bool mDisablePremultipliedAlpha;
bool mGotInfoCallback;
bool mUsePipeTransform;
struct AnimFrameInfo {
AnimFrameInfo();

Просмотреть файл

@ -228,8 +228,8 @@ nsresult nsWebPDecoder::CreateFrame(const nsIntRect& aFrameRect) {
}
Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
this, Size(), OutputSize(), aFrameRect, mFormat, animParams, mTransform,
pipeFlags);
this, Size(), OutputSize(), aFrameRect, mFormat, animParams,
/*aTransform*/ nullptr, pipeFlags);
if (!pipe) {
MOZ_LOG(sWebPLog, LogLevel::Error,
("[this=%p] nsWebPDecoder::CreateFrame -- no pipe\n", this));
@ -281,7 +281,7 @@ void nsWebPDecoder::ApplyColorProfile(const char* aProfile, size_t aLength) {
("[this=%p] nsWebPDecoder::ApplyColorProfile -- not tagged, use "
"sRGB transform\n",
this));
mTransform = gfxPlatform::GetCMSBGRATransform();
mTransform = gfxPlatform::GetCMSRGBATransform();
return;
}
@ -311,9 +311,9 @@ void nsWebPDecoder::ApplyColorProfile(const char* aProfile, size_t aLength) {
}
// Create the color management transform.
mTransform = qcms_transform_create(mInProfile, QCMS_DATA_BGRA_8,
mTransform = qcms_transform_create(mInProfile, QCMS_DATA_RGBA_8,
gfxPlatform::GetCMSOutputProfile(),
QCMS_DATA_BGRA_8, (qcms_intent)intent);
QCMS_DATA_RGBA_8, (qcms_intent)intent);
MOZ_LOG(sWebPLog, LogLevel::Debug,
("[this=%p] nsWebPDecoder::ApplyColorProfile -- use tagged "
"transform\n",
@ -463,6 +463,9 @@ LexerResult nsWebPDecoder::ReadSingle(const uint8_t* aData, size_t aLength,
for (int row = mLastRow; row < lastRow; row++) {
uint8_t* src = rowStart + row * stride;
if (mTransform) {
qcms_transform_data(mTransform, src, src, width);
}
WriteState result;
if (mFormat == SurfaceFormat::B8G8R8A8) {