SkCodec::Result SkBmpRLECodec::prepareToDecode(const SkImageInfo& dstInfo, const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) { // FIXME: Support subsets for scanline decodes. if (options.fSubset) { // Subsets are not supported. return kUnimplemented; } // Reset fSampleX. If it needs to be a value other than 1, it will get modified by // the sampler. fSampleX = 1; fLinesToSkip = 0; // Create the color table if necessary and prepare the stream for decode // Note that if it is non-NULL, inputColorCount will be modified if (!this->createColorTable(dstInfo.colorType(), inputColorCount)) { SkCodecPrintf("Error: could not create color table.\n"); return SkCodec::kInvalidInput; } // Copy the color table to the client if necessary copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount); // Initialize a buffer for encoded RLE data fRLEBytes = fOrigRLEBytes; if (!this->initializeStreamBuffer()) { SkCodecPrintf("Error: cannot initialize stream buffer.\n"); return SkCodec::kInvalidInput; } return SkCodec::kSuccess; }
bool SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, const Options& options, SkPMColor ctable[], int* ctableCount) { if (setjmp(png_jmpbuf(fPng_ptr))) { return false; } png_read_update_info(fPng_ptr, fInfo_ptr); if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { if (!this->createColorTable(requestedInfo.colorType(), kPremul_SkAlphaType == requestedInfo.alphaType(), ctableCount)) { return false; } } // Copy the color table to the client if they request kIndex8 mode copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); // Create the swizzler. SkPngCodec retains ownership of the color table. const SkPMColor* colors = get_color_ptr(fColorTable.get()); fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, requestedInfo, options)); SkASSERT(fSwizzler); return true; }
SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, const Options& options, SkPMColor ctable[], int* ctableCount) { // FIXME: Could we use the return value of setjmp to specify the type of // error? if (setjmp(png_jmpbuf(fPng_ptr))) { SkCodecPrintf("setjmp long jump!\n"); return kInvalidInput; } png_read_update_info(fPng_ptr, fInfo_ptr); if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { if (!this->createColorTable(requestedInfo.colorType(), kPremul_SkAlphaType == requestedInfo.alphaType(), ctableCount)) { return kInvalidInput; } } // Copy the color table to the client if they request kIndex8 mode copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); // Create the swizzler. SkPngCodec retains ownership of the color table. const SkPMColor* colors = get_color_ptr(fColorTable.get()); fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, requestedInfo, options)); SkASSERT(fSwizzler); return kSuccess; }
void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr, int* inputColorCount) { // Set up our own color table const uint32_t maxColors = 256; SkPMColor colorPtr[256]; if (NULL != inputColorCount) { // We set the number of colors to maxColors in order to ensure // safe memory accesses. Otherwise, an invalid pixel could // access memory outside of our color table array. *inputColorCount = maxColors; } // Get local color table ColorMapObject* colorMap = fGif->Image.ColorMap; // If there is no local color table, use the global color table if (NULL == colorMap) { colorMap = fGif->SColorMap; } uint32_t colorCount = 0; if (NULL != colorMap) { colorCount = colorMap->ColorCount; // giflib guarantees these properties SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel))); SkASSERT(colorCount <= 256); for (uint32_t i = 0; i < colorCount; i++) { colorPtr[i] = SkPackARGB32(0xFF, colorMap->Colors[i].Red, colorMap->Colors[i].Green, colorMap->Colors[i].Blue); } } // Gifs have the option to specify the color at a single index of the color // table as transparent. If the transparent index is greater than the // colorCount, we know that there is no valid transparent color in the color // table. If there is not valid transparent index, we will try to use the // backgroundIndex as the fill index. If the backgroundIndex is also not // valid, we will let fFillIndex default to 0 (it is set to zero in the // constructor). This behavior is not specified but matches // SkImageDecoder_libgif. uint32_t backgroundIndex = fGif->SBackGroundColor; if (fTransIndex < colorCount) { colorPtr[fTransIndex] = SK_ColorTRANSPARENT; fFillIndex = fTransIndex; } else if (backgroundIndex < colorCount) { fFillIndex = backgroundIndex; } // Fill in the color table for indices greater than color count. // This allows for predictable, safe behavior. for (uint32_t i = colorCount; i < maxColors; i++) { colorPtr[i] = colorPtr[fFillIndex]; } fColorTable.reset(new SkColorTable(colorPtr, maxColors)); copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount); }
bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& options, SkPMColor ctable[], int* ctableCount) { if (setjmp(png_jmpbuf(fPng_ptr))) { SkCodecPrintf("Failed on png_read_update_info.\n"); return false; } png_read_update_info(fPng_ptr, fInfo_ptr); // It's important to reset fColorXform to nullptr. We don't do this on rewinding // because the interlaced scanline decoder may need to rewind. fColorXform = nullptr; SkImageInfo swizzlerInfo = dstInfo; bool needsColorXform = needs_color_xform(dstInfo, this->getInfo()); if (needsColorXform) { switch (dstInfo.colorType()) { case kRGBA_8888_SkColorType: case kBGRA_8888_SkColorType: case kRGBA_F16_SkColorType: swizzlerInfo = swizzlerInfo.makeColorType(kRGBA_8888_SkColorType); if (kPremul_SkAlphaType == dstInfo.alphaType()) { swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType); } break; case kIndex_8_SkColorType: break; default: return false; } fColorXform = SkColorSpaceXform::New(sk_ref_sp(this->getInfo().colorSpace()), sk_ref_sp(dstInfo.colorSpace())); if (!fColorXform && kRGBA_F16_SkColorType == dstInfo.colorType()) { return false; } } if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { if (!this->createColorTable(dstInfo, ctableCount)) { return false; } } // Copy the color table to the client if they request kIndex8 mode copy_color_table(swizzlerInfo, fColorTable, ctable, ctableCount); // Create the swizzler. SkPngCodec retains ownership of the color table. const SkPMColor* colors = get_color_ptr(fColorTable.get()); fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, swizzlerInfo, options)); SkASSERT(fSwizzler); return true; }
/* * Initiates the bitmap decode */ SkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts, SkPMColor* inputColorPtr, int* inputColorCount) { if (!this->rewindIfNeeded()) { return kCouldNotRewind; } if (opts.fSubset) { // Subsets are not supported. return kUnimplemented; } if (dstInfo.dimensions() != this->getInfo().dimensions()) { SkCodecPrintf("Error: scaling not supported.\n"); return kInvalidScale; } if (!conversion_possible(dstInfo, this->getInfo())) { SkCodecPrintf("Error: cannot convert input type to output type.\n"); return kInvalidConversion; } // Create the color table if necessary and prepare the stream for decode // Note that if it is non-NULL, inputColorCount will be modified if (!this->createColorTable(inputColorCount)) { SkCodecPrintf("Error: could not create color table.\n"); return kInvalidInput; } // Copy the color table to the client if necessary copy_color_table(dstInfo, fColorTable, inputColorPtr, inputColorCount); // Initialize a swizzler if necessary if (!this->initializeStreamBuffer()) { SkCodecPrintf("Error: cannot initialize swizzler.\n"); return kInvalidConversion; } // Perform the decode return decode(dstInfo, dst, dstRowBytes, opts); }