SkCodec::Result SkIcoCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options& options, SkPMColor colorTable[], int* colorCount) { if (!ico_conversion_possible(dstInfo)) { return kInvalidConversion; } int index = 0; SkCodec::Result result = kInvalidScale; while (true) { index = this->chooseCodec(dstInfo.dimensions(), index); if (index < 0) { break; } SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index); SkImageInfo decodeInfo = fix_embedded_alpha(dstInfo, embeddedCodec->getInfo().alphaType()); result = embeddedCodec->startScanlineDecode(decodeInfo, &options, colorTable, colorCount); if (kSuccess == result) { fCurrScanlineCodec = embeddedCodec; return result; } index++; } SkCodecPrintf("Error: No matching candidate image in ico.\n"); return result; }
// FIXME: We should expose information about the encoded format on the // SkImageGenerator, so the client can interpret the encoded // format and request an output format. For now, as a workaround, // we guess what output format the client wants. static SkImageInfo fix_info(const SkCodec& codec) { const SkImageInfo& info = codec.getInfo(); SkAlphaType alphaType = (kUnpremul_SkAlphaType == info.alphaType()) ? kPremul_SkAlphaType : info.alphaType(); // Crudely guess that the presence of a color space means sRGB. SkColorProfileType profileType = (codec.getColorSpace()) ? kSRGB_SkColorProfileType : kLinear_SkColorProfileType; return SkImageInfo::Make(info.width(), info.height(), info.colorType(), alphaType, profileType); }
SkCodec::Result SkIcoCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes, const SkCodec::Options& options, SkPMColor* colorTable, int* colorCount) { int index = 0; while (true) { index = this->chooseCodec(dstInfo.dimensions(), index); if (index < 0) { break; } SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index); switch (embeddedCodec->startIncrementalDecode(dstInfo, pixels, rowBytes, &options, colorTable, colorCount)) { case kSuccess: fCurrIncrementalCodec = embeddedCodec; fCurrScanlineCodec = nullptr; return kSuccess; case kUnimplemented: // FIXME: embeddedCodec is a BMP. If scanline decoding would work, // return kUnimplemented so that SkSampledCodec will fall through // to use the scanline decoder. // Note that calling startScanlineDecode will require an extra // rewind. The embedded codec has an SkMemoryStream, which is // cheap to rewind, though it will do extra work re-reading the // header. // Also note that we pass nullptr for Options. This is because // Options that are valid for incremental decoding may not be // valid for scanline decoding. // Once BMP supports incremental decoding this workaround can go // away. if (embeddedCodec->startScanlineDecode(dstInfo, nullptr, colorTable, colorCount) == kSuccess) { return kUnimplemented; } // Move on to the next embedded codec. break; default: break; } index++; } SkCodecPrintf("Error: No matching candidate image in ico.\n"); return kInvalidScale; }
/* * Initiates the Ico decode */ SkCodec::Result SkIcoCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts, SkPMColor* colorTable, int* colorCount, int* rowsDecoded) { if (opts.fSubset) { // Subsets are not supported. return kUnimplemented; } if (!ico_conversion_possible(dstInfo)) { return kInvalidConversion; } int index = 0; SkCodec::Result result = kInvalidScale; while (true) { index = this->chooseCodec(dstInfo.dimensions(), index); if (index < 0) { break; } SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index); SkImageInfo decodeInfo = fix_embedded_alpha(dstInfo, embeddedCodec->getInfo().alphaType()); SkASSERT(decodeInfo.colorType() == kN32_SkColorType); result = embeddedCodec->getPixels(decodeInfo, dst, dstRowBytes, &opts, colorTable, colorCount); switch (result) { case kSuccess: case kIncompleteInput: // The embedded codec will handle filling incomplete images, so we will indicate // that all of the rows are initialized. *rowsDecoded = decodeInfo.height(); return result; default: // Continue trying to find a valid embedded codec on a failed decode. break; } index++; } SkCodecPrintf("Error: No matching candidate image in ico.\n"); return result; }
SkCodec::Result SkIcoCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options& options) { int index = 0; SkCodec::Result result = kInvalidScale; while (true) { index = this->chooseCodec(dstInfo.dimensions(), index); if (index < 0) { break; } SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index).get(); result = embeddedCodec->startScanlineDecode(dstInfo, &options); if (kSuccess == result) { fCurrCodec = embeddedCodec; return result; } index++; } SkCodecPrintf("Error: No matching candidate image in ico.\n"); return result; }
/* * Initiates the Ico decode */ SkCodec::Result SkIcoCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts, int* rowsDecoded) { if (opts.fSubset) { // Subsets are not supported. return kUnimplemented; } int index = 0; SkCodec::Result result = kInvalidScale; while (true) { index = this->chooseCodec(dstInfo.dimensions(), index); if (index < 0) { break; } SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index).get(); result = embeddedCodec->getPixels(dstInfo, dst, dstRowBytes, &opts); switch (result) { case kSuccess: case kIncompleteInput: // The embedded codec will handle filling incomplete images, so we will indicate // that all of the rows are initialized. *rowsDecoded = dstInfo.height(); return result; default: // Continue trying to find a valid embedded codec on a failed decode. break; } index++; } SkCodecPrintf("Error: No matching candidate image in ico.\n"); return result; }