std::unique_ptr<SkImageGenerator> SkPictureImageGenerator::Make(const SkISize& size, sk_sp<SkPicture> picture, const SkMatrix* matrix, const SkPaint* paint, SkImage::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace) { if (!picture || size.isEmpty()) { return nullptr; } if (SkImage::BitDepth::kF16 == bitDepth && (!colorSpace || !colorSpace->gammaIsLinear())) { return nullptr; } if (colorSpace && (!colorSpace->gammaCloseToSRGB() && !colorSpace->gammaIsLinear())) { return nullptr; } SkColorType colorType = kN32_SkColorType; if (SkImage::BitDepth::kF16 == bitDepth) { colorType = kRGBA_F16_SkColorType; } SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, kPremul_SkAlphaType, std::move(colorSpace)); return std::unique_ptr<SkImageGenerator>( new SkPictureImageGenerator(info, std::move(picture), matrix, paint)); }
SkBitmap DeferredImageDecoder::createLazyDecodingBitmap() { SkISize fullSize = SkISize::Make(m_actualDecoder->size().width(), m_actualDecoder->size().height()); ASSERT(!fullSize.isEmpty()); SkIRect fullRect = SkIRect::MakeSize(fullSize); // Creates a lazily decoded SkPixelRef that references the entire image without scaling. SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullSize.width(), fullSize.height()); m_frameGenerator = ImageFrameGenerator::create(fullSize, m_data.release(), m_allDataReceived); m_actualDecoder.clear(); bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, fullRect))->unref(); // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyDecodingPixelRef. // FIXME: It would be more useful to give the actual image URI. bitmap.pixelRef()->setURI(labelLazyDecoded); // Inform the bitmap that we will never change the pixels. This is a performance hint // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.) bitmap.setImmutable(); // FIXME: Setting bitmap.setIsOpaque() is big performance gain if possible. We can // do so safely if the image is fully loaded and it is a JPEG image, or if the image was // decoded before. return bitmap; }
SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM) const { SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0); SkMatrix m; m.setConcat(matrix, this->getLocalMatrix()); if (localM) { m.preConcat(*localM); } // Use a rotation-invariant scale SkPoint scale; if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) { // Decomposition failed, use an approximation. scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m.getSkewX()), SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m.getSkewY())); } SkSize scaledSize = SkSize::Make(scale.x() * fPicture->width(), scale.y() * fPicture->height()); SkISize tileSize = scaledSize.toRound(); if (tileSize.isEmpty()) { return NULL; } // The actual scale, compensating for rounding. SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture->width(), SkIntToScalar(tileSize.height()) / fPicture->height()); SkAutoMutexAcquire ama(fCachedBitmapShaderMutex); if (!fCachedBitmapShader || tileScale != fCachedTileScale) { SkBitmap bm; if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) { return NULL; } bm.eraseColor(SK_ColorTRANSPARENT); SkCanvas canvas(bm); canvas.scale(tileScale.width(), tileScale.height()); canvas.drawPicture(fPicture); fCachedTileScale = tileScale; SkMatrix shaderMatrix = this->getLocalMatrix(); shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix)); } // Increment the ref counter inside the mutex to ensure the returned pointer is still valid. // Otherwise, the pointer may have been overwritten on a different thread before the object's // ref count was incremented. fCachedBitmapShader.get()->ref(); return fCachedBitmapShader; }
SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index) { SkISize fullSize = SkISize::Make(m_actualDecoder->size().width(), m_actualDecoder->size().height()); ASSERT(!fullSize.isEmpty()); SkIRect fullRect = SkIRect::MakeSize(fullSize); // Creates a lazily decoded SkPixelRef that references the entire image without scaling. SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullSize.width(), fullSize.height()); bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, index, fullRect))->unref(); // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyDecodingPixelRef. // FIXME: It would be more useful to give the actual image URI. bitmap.pixelRef()->setURI(labelLazyDecoded); // Inform the bitmap that we will never change the pixels. This is a performance hint // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.) bitmap.setImmutable(); return bitmap; }