expose direct methods for decoding to an image

These are meant to contrast MakeFromEncoded(), and emphasize that it is deferred/cached,
while the new methods are not.

Change-Id: I83ac22394cb14cdc84ff8507a514bf708734b84f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/234476
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2019-08-14 11:08:41 -04:00 committed by Skia Commit-Bot
parent 19754b5470
commit a5acbf940e
4 changed files with 122 additions and 10 deletions

View File

@ -10,6 +10,8 @@ Milestone 78
* SkDrawLooper is no longer supported in SkPaint or SkCanvas. * SkDrawLooper is no longer supported in SkPaint or SkCanvas.
* SkImage: new factories: DecodeToRaster, DecodeToTexture
* SkImageFilter API refactor started: * SkImageFilter API refactor started:
- Provide new factory API in include/effects/SkImageFilters - Provide new factory API in include/effects/SkImageFilters
- Consolidated enum types to use SkTileMode and SkColorChannel - Consolidated enum types to use SkTileMode and SkColorChannel

View File

@ -154,19 +154,77 @@ public:
static sk_sp<SkImage> MakeFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator, static sk_sp<SkImage> MakeFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator,
const SkIRect* subset = nullptr); const SkIRect* subset = nullptr);
/** Creates SkImage from encoded data. /**
subset allows selecting a portion of the full image. Pass nullptr to select the entire * Return an image backed by the encoded data, but attempt to defer decoding until the image
image; otherwise, subset must be contained by image bounds. * is actually used/drawn. This deferral allows the system to cache the result, either on the
* CPU or on the GPU, depending on where the image is drawn. If memory is low, the cache may
SkImage is returned if format of the encoded data is recognized and supported. * be purged, causing the next draw of the image to have to re-decode.
Recognized formats vary by platform. *
* The subset parameter specifies a area within the decoded image to create the image from.
@param encoded data of SkImage to decode * If subset is null, then the entire image is returned.
@param subset bounds of returned SkImage; may be nullptr *
@return created SkImage, or nullptr * This is similar to DecodeTo[Raster,Texture], but this method will attempt to defer the
* actual decode, while the DecodeTo... method explicitly decode and allocate the backend
* when the call is made.
*
* If the encoded format is not supported, or subset is outside of the bounds of the decoded
* image, nullptr is returned.
*
* @param encoded the encoded data
* @param length the number of bytes of encoded data
* @param subset the bounds of the pixels within the decoded image to return. may be null.
* @return created SkImage, or nullptr
*/ */
static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr); static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr);
/**
* Decode the data in encoded/length into a raster image.
*
* The subset parameter specifies a area within the decoded image to create the image from.
* If subset is null, then the entire image is returned.
*
* This is similar to MakeFromEncoded, but this method will always decode immediately, and
* allocate the memory for the pixels for the lifetime of the returned image.
*
* If the encoded format is not supported, or subset is outside of the bounds of the decoded
* image, nullptr is returned.
*
* @param encoded the encoded data
* @param length the number of bytes of encoded data
* @param subset the bounds of the pixels within the decoded image to return. may be null.
* @return created SkImage, or nullptr
*/
static sk_sp<SkImage> DecodeToRaster(const void* encoded, size_t length,
const SkIRect* subset = nullptr);
static sk_sp<SkImage> DecodeToRaster(const sk_sp<SkData>& data,
const SkIRect* subset = nullptr) {
return DecodeToRaster(data->data(), data->size(), subset);
}
/**
* Decode the data in encoded/length into a texture-backed image.
*
* The subset parameter specifies a area within the decoded image to create the image from.
* If subset is null, then the entire image is returned.
*
* This is similar to MakeFromEncoded, but this method will always decode immediately, and
* allocate the texture for the pixels for the lifetime of the returned image.
*
* If the encoded format is not supported, or subset is outside of the bounds of the decoded
* image, nullptr is returned.
*
* @param encoded the encoded data
* @param length the number of bytes of encoded data
* @param subset the bounds of the pixels within the decoded image to return. may be null.
* @return created SkImage, or nullptr
*/
static sk_sp<SkImage> DecodeToTexture(GrContext* ctx, const void* encoded, size_t length,
const SkIRect* subset = nullptr);
static sk_sp<SkImage> DecodeToTexture(GrContext* ctx, const sk_sp<SkData>& data,
const SkIRect* subset = nullptr) {
return DecodeToTexture(ctx, data->data(), data->size(), subset);
}
// Experimental // Experimental
enum CompressionType { enum CompressionType {
kETC1_CompressionType, kETC1_CompressionType,

View File

@ -410,6 +410,10 @@ sk_sp<SkImage> SkImage::makeRasterImage() const {
#if !SK_SUPPORT_GPU #if !SK_SUPPORT_GPU
sk_sp<SkImage> SkImage::DecodeToTexture(GrContext*, const void*, size_t, const SkIRect*) {
return nullptr;
}
sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx, sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
const GrBackendTexture& tex, GrSurfaceOrigin origin, const GrBackendTexture& tex, GrSurfaceOrigin origin,
SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs, SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,

View File

@ -287,6 +287,44 @@ sk_sp<SkImage> SkImage::MakeFromGenerator(std::unique_ptr<SkImageGenerator> gene
return validator ? sk_make_sp<SkImage_Lazy>(&validator) : nullptr; return validator ? sk_make_sp<SkImage_Lazy>(&validator) : nullptr;
} }
sk_sp<SkImage> SkImage::DecodeToRaster(const void* encoded, size_t length, const SkIRect* subset) {
// The generator will not outlive this function, so we can wrap the encoded data without copy
auto gen = SkImageGenerator::MakeFromEncoded(SkData::MakeWithoutCopy(encoded, length));
if (!gen) {
return nullptr;
}
SkImageInfo info = gen->getInfo();
if (info.isEmpty()) {
return nullptr;
}
SkIPoint origin = {0, 0};
if (subset) {
if (!SkIRect::MakeWH(info.width(), info.height()).contains(*subset)) {
return nullptr;
}
info = info.makeWH(subset->width(), subset->height());
origin = {subset->x(), subset->y()};
}
size_t rb = info.minRowBytes();
if (rb == 0) {
return nullptr; // rb was too big
}
size_t size = info.computeByteSize(rb);
if (size == SIZE_MAX) {
return nullptr;
}
auto data = SkData::MakeUninitialized(size);
SkPixmap pmap(info, data->writable_data(), rb);
if (!generate_pixels(gen.get(), pmap, origin.x(), origin.y())) {
return nullptr;
}
return SkImage::MakeRasterData(info, data, rb);
}
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
@ -498,4 +536,14 @@ sk_sp<GrTextureProxy> SkImage_Lazy::lockTextureProxy(
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkImage> SkImage::DecodeToTexture(GrContext* ctx, const void* encoded, size_t length,
const SkIRect* subset) {
// img will not survive this function, so we don't need to copy/own the encoded data,
auto img = MakeFromEncoded(SkData::MakeWithoutCopy(encoded, length), subset);
if (!img) {
return nullptr;
}
return img->makeTextureImage(ctx, nullptr);
}
#endif #endif