Add new SkImageGenerator::getPixels() API, deprecate the old

This is fairly aggressive in that it will break any client
that is currently using SkImageGenerator with kIndex8.
I'm guessing that we don't have any clients doing that.

Bug: skia:6620
Change-Id: Ifd16f5232bb3a9f759c225315c57492d917ed9ca
Reviewed-on: https://skia-review.googlesource.com/16601
Commit-Queue: Matt Sarett <msarett@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Matt Sarett 2017-05-12 11:41:27 -04:00 committed by Skia Commit-Bot
parent 7c8460e101
commit ebb1b5c297
16 changed files with 87 additions and 176 deletions

View File

@ -951,10 +951,7 @@ Error ImageGenSrc::draw(SkCanvas* canvas) const {
int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
size_t rowBytes = decodeInfo.width() * bpp;
SkAutoMalloc pixels(decodeInfo.height() * rowBytes);
SkPMColor colorPtr[256];
int colorCount = 256;
if (!gen->getPixels(decodeInfo, pixels.get(), rowBytes, colorPtr, &colorCount)) {
if (!gen->getPixels(decodeInfo, pixels.get(), rowBytes)) {
SkString err =
SkStringPrintf("Image generator could not getPixels() for %s\n", fPath.c_str());
@ -968,6 +965,8 @@ Error ImageGenSrc::draw(SkCanvas* canvas) const {
return err;
}
SkPMColor colorPtr[256];
int colorCount = 256;
draw_to_canvas(canvas, decodeInfo, pixels.get(), rowBytes, colorPtr, colorCount,
CodecSrc::kGetFromCanvas_DstColorType);
return "";

View File

@ -124,30 +124,10 @@ public:
protected:
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor* ctable, int* ctableCount) override {
const Options&) override {
SkASSERT(fBM.width() == info.width());
SkASSERT(fBM.height() == info.height());
if (info.colorType() == kIndex_8_SkColorType) {
if (SkColorTable* ct = fBM.getColorTable()) {
if (ctable) {
memcpy(ctable, ct->readColors(), ct->count() * sizeof(SkPMColor));
}
if (ctableCount) {
*ctableCount = ct->count();
}
for (int y = 0; y < info.height(); ++y) {
memcpy(pixels, fBM.getAddr8(0, y), fBM.width());
pixels = (char*)pixels + rowBytes;
}
return true;
} else {
return false;
}
} else {
return fBM.readPixels(info, pixels, rowBytes, 0, 0);
}
return fBM.readPixels(info, pixels, rowBytes, 0, 0);
}
private:
SkBitmap fBM;
@ -162,53 +142,6 @@ static std::unique_ptr<SkImageGenerator> make_ras_generator(GrContext*, sk_sp<Sk
return skstd::make_unique<RasterGenerator>(bm);
}
// so we can create a color-table
static int find_closest(SkPMColor c, const SkPMColor table[], int count) {
const int cr = SkGetPackedR32(c);
const int cg = SkGetPackedG32(c);
const int cb = SkGetPackedB32(c);
int minDist = 999999999;
int index = 0;
for (int i = 0; i < count; ++i) {
int dr = SkAbs32((int)SkGetPackedR32(table[i]) - cr);
int dg = SkAbs32((int)SkGetPackedG32(table[i]) - cg);
int db = SkAbs32((int)SkGetPackedB32(table[i]) - cb);
int dist = dr + dg + db;
if (dist < minDist) {
minDist = dist;
index = i;
}
}
return index;
}
static std::unique_ptr<SkImageGenerator> make_ctable_generator(GrContext*, sk_sp<SkPicture> pic) {
SkBitmap bm;
bm.allocN32Pixels(100, 100);
SkCanvas canvas(bm);
canvas.clear(0);
canvas.translate(-100, -100);
canvas.drawPicture(pic);
const SkPMColor colors[] = {
SkPreMultiplyColor(SK_ColorRED),
SkPreMultiplyColor(0),
SkPreMultiplyColor(SK_ColorBLUE),
};
const int count = SK_ARRAY_COUNT(colors);
SkImageInfo info = SkImageInfo::Make(100, 100, kIndex_8_SkColorType, kPremul_SkAlphaType);
SkBitmap bm2;
bm2.allocPixels(info, SkColorTable::Make(colors, count));
for (int y = 0; y < info.height(); ++y) {
for (int x = 0; x < info.width(); ++x) {
*bm2.getAddr8(x, y) = find_closest(*bm.getAddr32(x, y), colors, count);
}
}
return skstd::make_unique<RasterGenerator>(bm2);
}
class EmptyGenerator : public SkImageGenerator {
public:
EmptyGenerator(const SkImageInfo& info) : SkImageGenerator(info) {}
@ -399,7 +332,6 @@ private:
};
DEF_GM( return new ImageCacheratorGM("picture", make_pic_generator); )
DEF_GM( return new ImageCacheratorGM("raster", make_ras_generator); )
DEF_GM( return new ImageCacheratorGM("ctable", make_ctable_generator); )
#if SK_SUPPORT_GPU
DEF_GM( return new ImageCacheratorGM("texture", make_tex_generator); )
#endif

View File

@ -28,12 +28,8 @@ class MaskGenerator final : public SkImageGenerator {
public:
MaskGenerator(const SkImageInfo& info) : INHERITED(info) {}
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor*,
int*) override {
if (info.colorType() == kIndex_8_SkColorType) {
return false;
}
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options&)
override {
SkImageInfo surfaceInfo = info;
if (kAlpha_8_SkColorType == info.colorType()) {
surfaceInfo = surfaceInfo.makeColorSpace(nullptr);

View File

@ -66,7 +66,7 @@ public:
* Repeated calls to this function should give the same results,
* allowing the PixelRef to be immutable.
*
* @param info A description of the format (config, size)
* @param info A description of the format
* expected by the caller. This can simply be identical
* to the info returned by getInfo().
*
@ -76,26 +76,31 @@ public:
*
* A size that does not match getInfo() implies a request
* to scale. If the generator cannot perform this scale,
* it will return kInvalidScale.
* it will return false.
*
* If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
* SkPMColor values in ctable. On success the generator must copy N colors into that storage,
* (where N is the logical number of table entries) and set ctableCount to N.
*
* If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount
* is not null, it will be set to 0.
* kIndex_8_SkColorType is not supported.
*
* @return true on success.
*/
bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor ctable[], int* ctableCount);
struct Options {
Options()
: fBehavior(SkTransferFunctionBehavior::kIgnore)
{}
SkTransferFunctionBehavior fBehavior;
};
bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options* options);
/**
* Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
* uses the default Options.
* Simplified version of getPixels() that uses the default Options.
*/
bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
#ifdef SK_SUPPORT_LEGACY_IMGEN_API
bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
int* ctableCount);
#endif
/**
* If decoding to YUV is supported, this returns true. Otherwise, this
* returns false and does not modify any of the parameters.
@ -171,30 +176,29 @@ protected:
virtual SkData* onRefEncodedData() { return nullptr; }
virtual bool onGetPixels(const SkImageInfo&, void*, size_t, SkPMColor[], int*) { return false; }
#ifdef SK_SUPPORT_LEGACY_IMGEN_API
virtual bool onGetPixels(const SkImageInfo&, void*, size_t, SkPMColor*, int*) {
return false;
}
#endif
#ifdef SK_SUPPORT_LEGACY_IMGEN_API
virtual bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
const Options&) {
return this->onGetPixels(info, pixels, rowBytes, nullptr, nullptr);
}
#else
virtual bool onGetPixels(const SkImageInfo&, void*, size_t, const Options&) {
return false;
}
#endif
virtual bool onIsValid(GrContext*) const { return true; }
virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const { return false; }
virtual bool onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) { return false; }
struct Options {
Options()
: fColorTable(nullptr)
, fColorTableCount(nullptr)
, fBehavior(SkTransferFunctionBehavior::kRespect)
{}
SkPMColor* fColorTable;
int* fColorTableCount;
SkTransferFunctionBehavior fBehavior;
};
bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options* opts);
virtual bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
const Options& opts) {
return this->onGetPixels(info, pixels, rowBytes, opts.fColorTable, opts.fColorTableCount);
}
#if SK_SUPPORT_GPU
virtual bool onCanGenerateTexture() const { return false; }
virtual sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&,

View File

@ -659,6 +659,7 @@ DEFINES_ALL = [
# Turn on a few Google3-specific build fixes.
"GOOGLE3",
# Staging flags for API changes
"SK_SUPPORT_LEGACY_IMGEN_API",
# Temporarily Disable analytic AA for Google3
"SK_NO_ANALYTIC_AA",
]

View File

@ -17,16 +17,21 @@ std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk
return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(codec, data));
}
static SkImageInfo make_premul(const SkImageInfo& info) {
static SkImageInfo adjust_info(const SkImageInfo& info) {
SkImageInfo newInfo = info;
if (kUnpremul_SkAlphaType == info.alphaType()) {
return info.makeAlphaType(kPremul_SkAlphaType);
newInfo = newInfo.makeAlphaType(kPremul_SkAlphaType);
}
return info;
if (kIndex_8_SkColorType == info.colorType()) {
newInfo = newInfo.makeColorType(kN32_SkColorType);
}
return newInfo;
}
SkCodecImageGenerator::SkCodecImageGenerator(SkCodec* codec, sk_sp<SkData> data)
: INHERITED(make_premul(codec->getInfo()))
: INHERITED(adjust_info(codec->getInfo()))
, fCodec(codec)
, fData(std::move(data))
{}
@ -35,21 +40,12 @@ SkData* SkCodecImageGenerator::onRefEncodedData() {
return SkRef(fData.get());
}
bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor ctable[], int* ctableCount) {
Options opts;
opts.fColorTable = ctable;
opts.fColorTableCount = ctableCount;
opts.fBehavior = SkTransferFunctionBehavior::kRespect;
return this->onGetPixels(info, pixels, rowBytes, opts);
}
bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
const Options& opts) {
SkCodec::Options codecOpts;
codecOpts.fPremulBehavior = opts.fBehavior;
SkCodec::Result result = fCodec->getPixels(info, pixels, rowBytes, &codecOpts, opts.fColorTable,
opts.fColorTableCount);
SkCodec::Result result = fCodec->getPixels(info, pixels, rowBytes, &codecOpts, nullptr,
nullptr);
switch (result) {
case SkCodec::kSuccess:
case SkCodec::kIncompleteInput:

View File

@ -23,8 +23,6 @@ public:
protected:
SkData* onRefEncodedData() override;
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
int* ctableCount) override;
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts)
override;

View File

@ -14,6 +14,7 @@ SkImageGenerator::SkImageGenerator(const SkImageInfo& info, uint32_t uniqueID)
, fUniqueID(kNeedNewImageUniqueID == uniqueID ? SkNextID::ImageID() : uniqueID)
{}
#ifdef SK_SUPPORT_LEGACY_IMGEN_API
bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor ctable[], int* ctableCount) {
if (kUnknown_SkColorType == info.colorType()) {
@ -44,9 +45,20 @@ bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t r
}
return success;
}
#endif
bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
const Options* opts) {
if (kUnknown_SkColorType == info.colorType() || kIndex_8_SkColorType == info.colorType()) {
return false;
}
if (nullptr == pixels) {
return false;
}
if (rowBytes < info.minRowBytes()) {
return false;
}
Options defaultOpts;
if (!opts) {
opts = &defaultOpts;
@ -55,11 +67,7 @@ bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t r
}
bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
SkASSERT(kIndex_8_SkColorType != info.colorType());
if (kIndex_8_SkColorType == info.colorType()) {
return false;
}
return this->getPixels(info, pixels, rowBytes, nullptr, nullptr);
return this->getPixels(info, pixels, rowBytes, nullptr);
}
bool SkImageGenerator::queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {

View File

@ -58,34 +58,26 @@ SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, sk_sp<
}
}
bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor ctable[], int* ctableCount) {
// Rely on SkCanvas factory to know what configs can and cannot be drawn into.
auto canvas = SkCanvas::MakeRasterDirect(info, pixels, rowBytes);
if (!canvas) {
return false;
}
canvas->clear(0);
canvas->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
return true;
}
bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
const Options& opts) {
// No need to use the xform canvas if we want fully color correct behavior or if we do not
// have a destination color space.
if (SkTransferFunctionBehavior::kRespect == opts.fBehavior || !info.colorSpace()) {
return this->onGetPixels(info, pixels, rowBytes, opts.fColorTable, opts.fColorTableCount);
}
bool useXformCanvas =
SkTransferFunctionBehavior::kIgnore == opts.fBehavior && info.colorSpace();
auto canvas = SkCanvas::MakeRasterDirect(info.makeColorSpace(nullptr), pixels, rowBytes);
SkImageInfo canvasInfo = useXformCanvas ? info.makeColorSpace(nullptr) : info;
std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(canvasInfo, pixels, rowBytes);
if (!canvas) {
return false;
}
canvas->clear(0);
auto xformCanvas = SkCreateColorSpaceXformCanvas(canvas.get(), info.refColorSpace());
xformCanvas->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
SkCanvas* canvasPtr = canvas.get();
std::unique_ptr<SkCanvas> xformCanvas;
if (useXformCanvas) {
xformCanvas = SkCreateColorSpaceXformCanvas(canvas.get(), info.refColorSpace());
canvasPtr = xformCanvas.get();
}
canvasPtr->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
return true;
}

View File

@ -17,8 +17,6 @@ public:
sk_sp<SkColorSpace>);
protected:
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
int* ctableCount) override;
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts)
override;

View File

@ -80,7 +80,7 @@ SkData* SkImageGeneratorCG::onRefEncodedData() {
}
bool SkImageGeneratorCG::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor ctable[], int* ctableCount) {
const Options&) {
if (kN32_SkColorType != info.colorType()) {
// FIXME: Support other colorTypes.
return false;

View File

@ -24,8 +24,8 @@ public:
protected:
SkData* onRefEncodedData() override;
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
int* ctableCount) override;
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options&)
override;
private:
/*

View File

@ -137,7 +137,7 @@ SkData* SkImageGeneratorWIC::onRefEncodedData() {
}
bool SkImageGeneratorWIC::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor ctable[], int* ctableCount) {
const Options&) {
if (kN32_SkColorType != info.colorType()) {
return false;
}

View File

@ -41,8 +41,8 @@ public:
protected:
SkData* onRefEncodedData() override;
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
int* ctableCount) override;
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options&)
override;
private:
/*

View File

@ -46,7 +46,7 @@ protected:
}
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
SkPMColor ctable[], int* ctableCount) override {
const Options& options) override {
REPORTER_ASSERT(fReporter, pixels != nullptr);
REPORTER_ASSERT(fReporter, rowBytes >= info.minRowBytes());
if (fType != kSucceedGetPixels_TestType) {
@ -64,14 +64,6 @@ protected:
bytePtr += rowBytes;
}
break;
case kIndex_8_SkColorType:
*ctableCount = 1;
ctable[0] = TestImageGenerator::PMColor();
for (int y = 0; y < info.height(); ++y) {
memset(bytePtr, 0, info.width());
bytePtr += rowBytes;
}
break;
case kRGB_565_SkColorType:
for (int y = 0; y < info.height(); ++y) {
sk_memset16((uint16_t*)bytePtr,
@ -101,7 +93,6 @@ DEF_TEST(Image_NewFromGenerator, r) {
};
const SkColorType testColorTypes[] = {
kN32_SkColorType,
kIndex_8_SkColorType,
kRGB_565_SkColorType
};
for (size_t i = 0; i < SK_ARRAY_COUNT(testTypes); ++i) {

View File

@ -33,13 +33,9 @@ bool GetResourceAsBitmap(const char* resource, SkBitmap* dst) {
if (!gen) {
return false;
}
SkPMColor ctStorage[256];
auto ctable = SkColorTable::Make(ctStorage, 256);
int count = ctable->count();
// ICK -- gotta clean up this pattern of writing to the ctable
return dst->tryAllocPixels(gen->getInfo(), ctable) &&
return dst->tryAllocPixels(gen->getInfo()) &&
gen->getPixels(gen->getInfo().makeColorSpace(nullptr), dst->getPixels(), dst->rowBytes(),
const_cast<SkPMColor*>(ctable->readColors()), &count);
nullptr);
}
sk_sp<SkImage> GetResourceAsImage(const char* resource) {