// We assume that `frameWidth` and `bitsPerPixel` have been already sanitized // earlier (and that the multiplication and addition below won't overflow).
SkASSERT(0 < frameWidth);
SkASSERT(frameWidth < 0xFFFFFF);
SkASSERT(encodedBitsPerPixel < 128);
size_t encodedBitsPerRow = static_cast<size_t>(frameWidth) * encodedBitsPerPixel;
fEncodedRowBytes = (encodedBitsPerRow + 7) / 8; // Round up to the next byte.
// Reset fSwizzler and this->colorXform(). We can't do this in onRewind() because the // interlaced scanline decoder may need to rewind.
fSwizzler.reset(nullptr);
// If skcms directly supports the encoded PNG format, we should skip format // conversion in the swizzler (or skip swizzling altogether). bool skipFormatConversion = false; switch (this->getEncodedInfo().color()) { case SkEncodedInfo::kRGB_Color: if (this->getEncodedInfo().bitsPerComponent() != 16) { break;
}
[[fallthrough]]; case SkEncodedInfo::kRGBA_Color: case SkEncodedInfo::kGray_Color:
skipFormatConversion = this->colorXform(); break; default: break;
}
if (skipFormatConversion && !options.fSubset) {
fXformMode = kColorOnly_XformMode;
} else { if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { if (!this->createColorTable(dstInfo)) { return kInvalidInput;
}
}
Result result =
this->initializeSwizzler(dstInfo, options, skipFormatConversion, frameWidth); if (result != kSuccess) { return result;
}
}
this->allocateStorage(dstInfo);
// We can't call `initializeXformParams` here, because `swizzleWidth` may // change *after* `onStartIncrementalDecode` // (`SkSampledCodec::sampledDecode` first [transitively] calls // `onStartIncrementalDecode` and *then* `SkSwizzler::onSetSampleX`).
void SkPngCodecBase::allocateStorage(const SkImageInfo& dstInfo) { switch (fXformMode) { case kSwizzleOnly_XformMode: break; case kColorOnly_XformMode: // Intentional fall through. A swizzler hasn't been created yet, but one will // be created later if we are sampling. We'll go ahead and allocate // enough memory to swizzle if necessary. case kSwizzleColor_XformMode: { constint bitsPerPixel = this->getEncodedInfo().bitsPerPixel();
// If we have more than 8-bits (per component) of precision, we will keep that // extra precision. Otherwise, we will swizzle to RGBA_8888 before transforming. const size_t bytesPerPixel = (bitsPerPixel > 32) ? bitsPerPixel / 8 : 4; const size_t colorXformBytes = dstInfo.width() * bytesPerPixel;
fStorage.reset(colorXformBytes); break;
}
}
}
// Here, we swizzle into temporary memory, which is not zero initialized. // FIXME (msarett): // Is this a problem?
swizzlerOptions.fZeroInitialized = kNo_ZeroInitialized;
}
// Ok to ignore `initializeSwizzler`'s result, because if it fails, then // `fSwizzler` will be `nullptr` and we want to return `nullptr` upon // failure.
std::ignore = this->initializeSwizzler(
this->dstInfo(), this->options(), true, this->dstInfo().width());
// Note: SkColorPalette claims to store SkPMColors, which is not necessarily the case here. bool SkPngCodecBase::createColorTable(const SkImageInfo& dstInfo) {
std::optional<SkSpan<const PaletteColorEntry>> maybePlteChunk = this->onTryGetPlteChunk(); if (!maybePlteChunk.has_value()) { returnfalse;
} const PaletteColorEntry* palette = maybePlteChunk->data();
size_t numColors = maybePlteChunk->size();
// Contents depend on tableColorType and our choice of if/when to premultiply: // { kPremul, kUnpremul, kOpaque } x { RGBA, BGRA }
SkPMColor colorTable[256];
SkColorType tableColorType = this->colorXform() ? kXformSrcColorType : dstInfo.colorType();
if (alphas) { bool premultiply = needs_premul(dstInfo.alphaType(), this->getEncodedInfo().alpha());
// Choose which function to use to create the color table. If the final destination's // colortype is unpremultiplied, the color table will store unpremultiplied colors.
PackColorProc proc = choose_pack_color_proc(premultiply, tableColorType);
for (size_t i = 0; i < numColorsWithAlpha; i++) { // We don't have a function in SkOpts that combines a set of alphas with a set // of RGBs. We could write one, but it's hardly worth it, given that this // is such a small fraction of the total decode time.
colorTable[i] = proc(alphas[i], palette->red, palette->green, palette->blue);
palette++;
}
}
if (numColorsWithAlpha < numColors) { // The optimized code depends on a 3-byte png_color struct with the colors // in RGB order. These checks make sure it is safe to use.
static_assert(3 == sizeof(PaletteColorEntry));
static_assert(offsetof(PaletteColorEntry, red) == 0);
static_assert(offsetof(PaletteColorEntry, green) == 1);
static_assert(offsetof(PaletteColorEntry, blue) == 2);
if (this->colorXform() && !this->xformOnDecode()) {
this->applyColorXform(colorTable, colorTable, numColors);
}
// Pad the color table with the last color in the table (or black) in the case that // invalid pixel indices exceed the number of colors in the table. const size_t maxColors = static_cast<size_t>(1) << this->getEncodedInfo().bitsPerComponent(); if (numColors < maxColors) {
SkPMColor lastColor = numColors > 0 ? colorTable[numColors - 1] : SK_ColorBLACK;
SkOpts::memset32(colorTable + numColors, lastColor, maxColors - numColors);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.