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 SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t rowBytes, ZeroInitialized zeroInit, int linesRequested, int linesDecoded) { void* fillDst; const uint32_t fillValue = this->getFillValue(info.colorType(), info.alphaType()); const int linesRemaining = linesRequested - linesDecoded; SkSampler* sampler = this->getSampler(false); switch (this->getScanlineOrder()) { case kTopDown_SkScanlineOrder: case kNone_SkScanlineOrder: { const SkImageInfo fillInfo = info.makeWH(info.width(), linesRemaining); fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes); fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler); break; } case kBottomUp_SkScanlineOrder: { fillDst = dst; const SkImageInfo fillInfo = info.makeWH(info.width(), linesRemaining); fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler); break; } case kOutOfOrder_SkScanlineOrder: { SkASSERT(1 == linesRequested || this->getInfo().height() == linesRequested); const SkImageInfo fillInfo = info.makeWH(info.width(), 1); for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * rowBytes); fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler); } break; } } }
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; }
static void test_peek(skiatest::Reporter* reporter, SkImage* image, bool expectPeekSuccess) { SkImageInfo info; size_t rowBytes; const void* addr = image->peekPixels(&info, &rowBytes); bool success = SkToBool(addr); REPORTER_ASSERT(reporter, expectPeekSuccess == success); if (success) { REPORTER_ASSERT(reporter, 20 == info.width()); REPORTER_ASSERT(reporter, 20 == info.height()); REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType()); REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() || kOpaque_SkAlphaType == info.alphaType()); REPORTER_ASSERT(reporter, info.minRowBytes() <= rowBytes); REPORTER_ASSERT(reporter, SkPreMultiplyColor(SK_ColorWHITE) == *(const SkPMColor*)addr); } }
SkImage* SkImage::NewFromBitmap(const SkBitmap& bm) { SkPixelRef* pr = bm.pixelRef(); if (nullptr == pr) { return nullptr; } #if SK_SUPPORT_GPU if (GrTexture* tex = pr->getTexture()) { SkAutoTUnref<GrTexture> unrefCopy; if (!bm.isImmutable()) { const bool notBudgeted = false; tex = GrDeepCopyTexture(tex, notBudgeted); if (nullptr == tex) { return nullptr; } unrefCopy.reset(tex); } const SkImageInfo info = bm.info(); return new SkImage_Gpu(info.width(), info.height(), bm.getGenerationID(), info.alphaType(), tex, 0, SkSurface::kNo_Budgeted); } #endif // This will check for immutable (share or copy) return SkNewImageFromRasterBitmap(bm, nullptr); }
/* * Performs the decoding */ SkCodec::Result SkBmpMaskCodec::decode(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts) { // Set constant values const int width = dstInfo.width(); const int height = dstInfo.height(); const size_t rowBytes = SkAlign4(compute_row_bytes(width, this->bitsPerPixel())); // Iterate over rows of the image uint8_t* srcRow = fSrcBuffer.get(); for (int y = 0; y < height; y++) { // Read a row of the input if (this->stream()->read(srcRow, rowBytes) != rowBytes) { SkCodecPrintf("Warning: incomplete input stream.\n"); // Fill the destination image on failure SkPMColor fillColor = dstInfo.alphaType() == kOpaque_SkAlphaType ? SK_ColorBLACK : SK_ColorTRANSPARENT; if (kNo_ZeroInitialized == opts.fZeroInitialized || 0 != fillColor) { void* dstStart = this->getDstStartRow(dst, dstRowBytes, y); SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height() - y, fillColor, nullptr); } return kIncompleteInput; } // Decode the row in destination format int row = SkBmpCodec::kBottomUp_RowOrder == this->rowOrder() ? height - 1 - y : y; void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes); fMaskSwizzler->swizzle(dstRow, srcRow); } // Finished decoding the entire image return kSuccess; }
sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(SkBudgeted budgeted, ForceCopyMode forceCopyMode) { GrRenderTarget* rt = fDevice->accessDrawContext()->accessRenderTarget(); SkASSERT(rt); GrTexture* tex = rt->asTexture(); SkAutoTUnref<GrTexture> copy; // If the original render target is a buffer originally created by the client, then we don't // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid // copy-on-write. if (kYes_ForceCopyMode == forceCopyMode || !tex || rt->resourcePriv().refsWrappedObjects()) { GrSurfaceDesc desc = fDevice->accessDrawContext()->desc(); GrContext* ctx = fDevice->context(); desc.fFlags = desc.fFlags & ~kRenderTarget_GrSurfaceFlag; copy.reset(ctx->textureProvider()->createTexture(desc, budgeted)); if (!copy) { return nullptr; } if (!ctx->copySurface(copy, rt)) { return nullptr; } tex = copy; } const SkImageInfo info = fDevice->imageInfo(); sk_sp<SkImage> image; if (tex) { image = sk_make_sp<SkImage_Gpu>(info.width(), info.height(), kNeedNewImageUniqueID, info.alphaType(), tex, sk_ref_sp(info.colorSpace()), budgeted); } return image; }
virtual Result onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options&, SkPMColor ctableEntries[], int* ctableCount) override { SkMemoryStream stream(fData->data(), fData->size(), false); SkAutoTUnref<BareMemoryAllocator> allocator(SkNEW_ARGS(BareMemoryAllocator, (info, pixels, rowBytes))); fDecoder->setAllocator(allocator); fDecoder->setRequireUnpremultipliedColors(kUnpremul_SkAlphaType == info.alphaType()); SkBitmap bm; const SkImageDecoder::Result result = fDecoder->decode(&stream, &bm, info.colorType(), SkImageDecoder::kDecodePixels_Mode); if (SkImageDecoder::kFailure == result) { return kInvalidInput; } SkASSERT(info.colorType() == bm.info().colorType()); if (kIndex_8_SkColorType == info.colorType()) { SkASSERT(ctableEntries); SkColorTable* ctable = bm.getColorTable(); if (NULL == ctable) { return kInvalidConversion; } const int count = ctable->count(); memcpy(ctableEntries, ctable->readColors(), count * sizeof(SkPMColor)); *ctableCount = count; } if (SkImageDecoder::kPartialSuccess == result) { return kIncompleteInput; } return kSuccess; }
SkImage* SkSurface_Gpu::onNewImageSnapshot(SkBudgeted budgeted, ForceCopyMode forceCopyMode) { GrRenderTarget* rt = fDevice->accessRenderTarget(); SkASSERT(rt); GrTexture* tex = rt->asTexture(); SkAutoTUnref<GrTexture> copy; // TODO: Force a copy when the rt is an external resource. if (kYes_ForceCopyMode == forceCopyMode || !tex) { GrSurfaceDesc desc = fDevice->accessRenderTarget()->desc(); GrContext* ctx = fDevice->context(); desc.fFlags = desc.fFlags & ~kRenderTarget_GrSurfaceFlag; copy.reset(ctx->textureProvider()->createTexture(desc, budgeted)); if (!copy) { return nullptr; } if (!ctx->copySurface(copy, rt)) { return nullptr; } tex = copy; } const SkImageInfo info = fDevice->imageInfo(); SkImage* image = nullptr; if (tex) { image = new SkImage_Gpu(info.width(), info.height(), kNeedNewImageUniqueID, info.alphaType(), tex, budgeted); } return image; }
static SkImageInfo make_premul(const SkImageInfo& info) { if (kUnpremul_SkAlphaType == info.alphaType()) { return info.makeAlphaType(kPremul_SkAlphaType); } return info; }
sk_sp<SkImage> SkImage::MakeFromBitmap(const SkBitmap& bm) { SkPixelRef* pr = bm.pixelRef(); if (nullptr == pr) { return nullptr; } #if SK_SUPPORT_GPU if (GrTexture* tex = pr->getTexture()) { SkAutoTUnref<GrTexture> unrefCopy; if (!bm.isImmutable()) { tex = GrDeepCopyTexture(tex, SkBudgeted::kNo); if (nullptr == tex) { return nullptr; } unrefCopy.reset(tex); } const SkImageInfo info = bm.info(); return sk_make_sp<SkImage_Gpu>(info.width(), info.height(), bm.getGenerationID(), info.alphaType(), tex, sk_ref_sp(info.colorSpace()), SkBudgeted::kNo); } #endif // This will check for immutable (share or copy) return SkMakeImageFromRasterBitmap(bm); }
static bool compatibleInfo(const SkImageInfo& src, const SkImageInfo& dst) { if (src == dst) return true; // It is legal to write kOpaque_SkAlphaType pixels into a kPremul_SkAlphaType buffer. // This can happen when DeferredImageDecoder allocates an kOpaque_SkAlphaType image // generator based on cached frame info, while the ImageFrame-allocated dest bitmap // stays kPremul_SkAlphaType. if (src.alphaType() == kOpaque_SkAlphaType && dst.alphaType() == kPremul_SkAlphaType) { const SkImageInfo& tmp = src.makeAlphaType(kPremul_SkAlphaType); return tmp == dst; } return false; }
bool SkAnimatedImage::Frame::init(const SkImageInfo& info, OnInit onInit) { if (fBitmap.getPixels()) { if (fBitmap.pixelRef()->unique()) { SkAssertResult(fBitmap.setAlphaType(info.alphaType())); return true; } // An SkCanvas provided to onDraw is still holding a reference. // Copy before we decode to ensure that we don't overwrite the // expected contents of the image. if (OnInit::kRestoreIfNecessary == onInit) { SkBitmap tmp; if (!tmp.tryAllocPixels(info)) { return false; } memcpy(tmp.getPixels(), fBitmap.getPixels(), fBitmap.computeByteSize()); using std::swap; swap(tmp, fBitmap); return true; } } return fBitmap.tryAllocPixels(info); }
static bool ico_conversion_possible(const SkImageInfo& dstInfo) { // We only support kN32_SkColorType. // This makes sense for BMP-in-ICO. The presence of an AND // mask (which changes colors and adds transparency) means that // we cannot use k565 or kIndex8. // FIXME: For PNG-in-ICO, we could technically support whichever // color types that the png supports. if (kN32_SkColorType != dstInfo.colorType()) { return false; } // We only support transparent alpha types. This is necessary for // BMP-in-ICOs since there will be an AND mask. // FIXME: For opaque PNG-in-ICOs, we should be able to support kOpaque. return kPremul_SkAlphaType == dstInfo.alphaType() || kUnpremul_SkAlphaType == dstInfo.alphaType(); }
int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count, int startRow) override { if (setjmp(png_jmpbuf(fPng_ptr))) { SkCodecPrintf("Failed to get scanlines.\n"); // FIXME (msarett): Returning 0 is pessimistic. If we can complete a single pass, // we may be able to report that all of the memory has been initialized. Even if we // fail on the first pass, we can still report than some scanlines are initialized. return 0; } SkAutoTMalloc<uint8_t> storage(count * fSrcRowBytes); uint8_t* srcRow; for (int i = 0; i < fNumberPasses; i++) { // Discard rows that we planned to skip. for (int y = 0; y < startRow; y++){ png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); } // Read rows we care about into storage. srcRow = storage.get(); for (int y = 0; y < count; y++) { png_read_row(fPng_ptr, srcRow, nullptr); srcRow += fSrcRowBytes; } // Discard rows that we don't need. for (int y = 0; y < this->getInfo().height() - startRow - count; y++) { png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr); } } // Swizzle and xform the rows we care about void* swizzlerDstRow = dst; size_t swizzlerDstRowBytes = rowBytes; bool colorXform = fColorXform && apply_xform_on_decode(dstInfo.colorType(), this->getEncodedInfo().color()); if (colorXform) { swizzlerDstRow = fColorXformSrcRow; swizzlerDstRowBytes = 0; } SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), this->getInfo().alphaType()); srcRow = storage.get(); for (int y = 0; y < count; y++) { fSwizzler->swizzle(swizzlerDstRow, srcRow); srcRow = SkTAddOffset<uint8_t>(srcRow, fSrcRowBytes); if (colorXform) { fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, fSwizzler->swizzleWidth(), dstInfo.colorType(), xformAlphaType); dst = SkTAddOffset<void>(dst, rowBytes); } swizzlerDstRow = SkTAddOffset<void>(swizzlerDstRow, swizzlerDstRowBytes); } return count; }
SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options* options, SkPMColor ctable[], int* ctableCount) { if (kUnknown_SkColorType == info.colorType()) { return kInvalidConversion; } if (NULL == pixels) { return kInvalidParameters; } if (rowBytes < info.minRowBytes()) { return kInvalidParameters; } if (kIndex_8_SkColorType == info.colorType()) { if (NULL == ctable || NULL == ctableCount) { return kInvalidParameters; } } else { if (ctableCount) { *ctableCount = 0; } ctableCount = NULL; ctable = NULL; } { SkAlphaType canonical; if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &canonical) || canonical != info.alphaType()) { return kInvalidConversion; } } // Default options. Options optsStorage; if (NULL == options) { options = &optsStorage; } const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ctable, ctableCount); if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { SkASSERT(*ctableCount >= 0 && *ctableCount <= 256); } return result; }
static bool png_conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) { // Ensure the alpha type is valid if (!valid_alpha(dst.alphaType(), src.alphaType())) { return false; } // Check for supported color types switch (dst.colorType()) { case kRGBA_8888_SkColorType: case kBGRA_8888_SkColorType: case kRGBA_F16_SkColorType: return true; case kRGB_565_SkColorType: return kOpaque_SkAlphaType == src.alphaType(); default: return dst.colorType() == src.colorType(); } }
static bool valid_for_bitmap_device(const SkImageInfo& info, SkAlphaType* newAlphaType) { if (info.width() < 0 || info.height() < 0) { return false; } // TODO: can we stop supporting kUnknown in SkBitmkapDevice? if (kUnknown_SkColorType == info.colorType()) { if (newAlphaType) { *newAlphaType = kUnknown_SkAlphaType; } return true; } switch (info.alphaType()) { case kPremul_SkAlphaType: case kOpaque_SkAlphaType: break; default: return false; } SkAlphaType canonicalAlphaType = info.alphaType(); switch (info.colorType()) { case kAlpha_8_SkColorType: break; case kRGB_565_SkColorType: canonicalAlphaType = kOpaque_SkAlphaType; break; case kN32_SkColorType: break; case kRGBA_F16_SkColorType: break; default: return false; } if (newAlphaType) { *newAlphaType = canonicalAlphaType; } return true; }
/* * Checks if the conversion between the input image and the requested output * image has been implemented * Sets the output color space */ bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) { const SkImageInfo& src = this->getInfo(); // Ensure that the profile type is unchanged if (dst.profileType() != src.profileType()) { return false; } // Ensure that the alpha type is opaque if (kOpaque_SkAlphaType != dst.alphaType()) { return false; } // Check if we will decode to CMYK because a conversion to RGBA is not supported J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->jpeg_color_space; bool isCMYK = JCS_CMYK == colorSpace || JCS_YCCK == colorSpace; // Check for valid color types and set the output color space switch (dst.colorType()) { case kN32_SkColorType: if (isCMYK) { fDecoderMgr->dinfo()->out_color_space = JCS_CMYK; } else { // Check the byte ordering of the RGBA color space for the // current platform #if defined(SK_PMCOLOR_IS_RGBA) fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA; #else fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA; #endif } return true; case kRGB_565_SkColorType: if (isCMYK) { fDecoderMgr->dinfo()->out_color_space = JCS_CMYK; } else { fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE; fDecoderMgr->dinfo()->out_color_space = JCS_RGB565; } return true; case kGray_8_SkColorType: if (isCMYK) { return false; } else { // We will enable decodes to gray even if the image is color because this is // much faster than decoding to color and then converting fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE; } return true; default: return false; } }
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; }
static bool valid_for_raster_canvas(const SkImageInfo& info) { switch (info.colorType()) { case kAlpha_8_SkColorType: case kRGB_565_SkColorType: return true; case kN32_SkColorType: return kPremul_SkAlphaType == info.alphaType() || kOpaque_SkAlphaType == info.alphaType(); default: break; } return false; }
sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info, const GrMipLevel* texels, int mipLevelCount, SkBudgeted budgeted) { if (!ctx) { return nullptr; } SkAutoTUnref<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, mipLevelCount)); if (!texture) { return nullptr; } return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID, info.alphaType(), texture, budgeted); }
SkImage* SkSurface_Gpu::onNewImageSnapshot(Budgeted budgeted) { const SkImageInfo info = fDevice->imageInfo(); SkImage* image = nullptr; GrTexture* tex = fDevice->accessRenderTarget()->asTexture(); if (tex) { image = new SkImage_Gpu(info.width(), info.height(), kNeedNewImageUniqueID, info.alphaType(), tex, budgeted); } if (image) { as_IB(image)->initWithProps(this->props()); } return image; }
static void clamp_if_necessary(const SkImageInfo& info, void* pixels) { if (kRGBA_F16_SkColorType != info.colorType()) { return; } for (int y = 0; y < info.height(); y++) { for (int x = 0; x < info.width(); x++) { uint64_t pixel = ((uint64_t*) pixels)[y * info.width() + x]; Sk4f rgba = SkHalfToFloat_finite_ftz(pixel); if (kUnpremul_SkAlphaType == info.alphaType()) { rgba = Sk4f::Max(0.0f, Sk4f::Min(rgba, 1.0f)); } else { SkASSERT(kPremul_SkAlphaType == info.alphaType()); rgba = Sk4f::Max(0.0f, Sk4f::Min(rgba, rgba[3])); } SkFloatToHalf_finite_ftz(rgba).store(&pixel); ((uint64_t*) pixels)[y * info.width() + x] = pixel; } } }
static bool raster_canvas_supports(const SkImageInfo& info) { switch (info.colorType()) { case kN32_SkColorType: return kUnpremul_SkAlphaType != info.alphaType(); case kRGB_565_SkColorType: return true; case kAlpha_8_SkColorType: return true; default: break; } return false; }
/* * Initiates the gif decode */ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts, SkPMColor* inputColorPtr, int* inputColorCount, int* rowsDecoded) { Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, opts); if (kSuccess != result) { return result; } if (dstInfo.dimensions() != this->getInfo().dimensions()) { return gif_error("Scaling not supported.\n", kInvalidScale); } // Initialize the swizzler if (fFrameIsSubset) { const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFrameRect.height()); if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) { return gif_error("Could not initialize swizzler.\n", kUnimplemented); } // Fill the background SkSampler::Fill(dstInfo, dst, dstRowBytes, this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()), opts.fZeroInitialized); // Modify the dst pointer const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorType()); dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() + dstBytesPerPixel * fFrameRect.left()); } else { if (kSuccess != this->initializeSwizzler(dstInfo, opts)) { return gif_error("Could not initialize swizzler.\n", kUnimplemented); } } // Iterate over rows of the input uint32_t height = fFrameRect.height(); for (uint32_t y = 0; y < height; y++) { if (!this->readRow()) { *rowsDecoded = y; return gif_error("Could not decode line.\n", kIncompleteInput); } void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanline(y)); fSwizzler->swizzle(dstRow, fSrcBuffer.get()); } return kSuccess; }
/* * Checks if the conversion between the input image and the requested output * image has been implemented * Sets the output color format */ bool SkHeifCodec::setOutputColorFormat(const SkImageInfo& dstInfo) { if (kUnknown_SkAlphaType == dstInfo.alphaType()) { return false; } if (kOpaque_SkAlphaType != dstInfo.alphaType()) { SkCodecPrintf("Warning: an opaque image should be decoded as opaque " "- it is being decoded as non-opaque, which will draw slower\n"); } switch (dstInfo.colorType()) { case kRGBA_8888_SkColorType: return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); case kBGRA_8888_SkColorType: return fHeifDecoder->setOutputColor(kHeifColorFormat_BGRA_8888); case kRGB_565_SkColorType: if (this->colorXform()) { return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); } else { return fHeifDecoder->setOutputColor(kHeifColorFormat_RGB565); } case kRGBA_F16_SkColorType: SkASSERT(this->colorXform()); if (!dstInfo.colorSpace()->gammaIsLinear()) { return false; } return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); default: return false; } }
/* * Checks if the conversion between the input image and the requested output * image has been implemented */ static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) { // Ensure that the profile type is unchanged if (dst.profileType() != src.profileType()) { return false; } // Ensure the alpha type is valid if (!valid_alpha(dst.alphaType(), src.alphaType())) { return false; } // Check for supported color types switch (dst.colorType()) { // Allow output to kN32 from any type of input case kN32_SkColorType: return true; // Allow output to kIndex_8 from compatible inputs case kIndex_8_SkColorType: return kIndex_8_SkColorType == src.colorType(); default: return false; } }
SkImage* SkSurface_Gpu::onNewImageSnapshot(Budgeted budgeted) { const SkImageInfo info = fDevice->imageInfo(); const int sampleCount = fDevice->accessRenderTarget()->numColorSamples(); SkImage* image = NULL; GrTexture* tex = fDevice->accessRenderTarget()->asTexture(); if (tex) { image = SkNEW_ARGS(SkImage_Gpu, (info.width(), info.height(), info.alphaType(), tex, sampleCount, budgeted)); } if (image) { as_IB(image)->initWithProps(this->props()); } return image; }
sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info, const GrMipLevel* texels, int mipLevelCount, SkBudgeted budgeted, SkSourceGammaTreatment gammaTreatment) { if (!ctx) { return nullptr; } sk_sp<GrTexture> texture(GrUploadMipMapToTexture(ctx, info, texels, mipLevelCount)); if (!texture) { return nullptr; } texture->texturePriv().setGammaTreatment(gammaTreatment); return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID, info.alphaType(), std::move(texture), sk_ref_sp(info.colorSpace()), budgeted); }