diff options
author | reed <reed@google.com> | 2015-09-11 11:47:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-11 11:47:27 -0700 |
commit | c4a83e26526a62fb2b8913faa57e0c56b4e1e62a (patch) | |
tree | 0e2d532767bb77129a1bd22ba769c61cd23d34c5 | |
parent | d8dd47b5fa52430a1ab5c07335c0c13fcd43a82d (diff) |
support colortables in cacherator
BUG=skia:
TBR=scroggo
Review URL: https://codereview.chromium.org/1339753002
-rw-r--r-- | gm/image_pict.cpp | 79 | ||||
-rw-r--r-- | src/core/SkImageCacherator.cpp | 57 |
2 files changed, 118 insertions, 18 deletions
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp index 22b3d0067b..216b495dd3 100644 --- a/gm/image_pict.cpp +++ b/gm/image_pict.cpp @@ -108,11 +108,35 @@ static SkImageGenerator* make_pic_generator(GrContext*, SkPicture* pic) { class RasterGenerator : public SkImageGenerator { public: - RasterGenerator(const SkBitmap& bm) : SkImageGenerator(bm.info()), fBM(bm) {} + RasterGenerator(const SkBitmap& bm) : SkImageGenerator(bm.info()), fBM(bm) { + fBM.lockPixels(); + } protected: bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, - SkPMColor*, int*) override { - return fBM.readPixels(info, pixels, rowBytes, 0, 0); + SkPMColor* ctable, int* ctableCount) 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); + } } private: SkBitmap fBM; @@ -127,6 +151,54 @@ static SkImageGenerator* make_ras_generator(GrContext*, SkPicture* pic) { return new 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 SkImageGenerator* make_ctable_generator(GrContext*, 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; + SkAutoTUnref<SkColorTable> ct(new SkColorTable(colors, count)); + bm2.allocPixels(info, nullptr, ct); + 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 new RasterGenerator(bm2); +} + class EmptyGenerator : public SkImageGenerator { public: EmptyGenerator(const SkImageInfo& info) : SkImageGenerator(info) {} @@ -297,6 +369,7 @@ 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 diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp index 82f36edfb3..8c0e415770 100644 --- a/src/core/SkImageCacherator.cpp +++ b/src/core/SkImageCacherator.cpp @@ -70,36 +70,63 @@ static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { return true; } -bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { - const size_t rowBytes = fInfo.minRowBytes(); - if (!bitmap->tryAllocPixels(fInfo, rowBytes)) { +static void release_malloc_proc(void* pixels, void* ctx) { + sk_free(pixels); +} + +static bool generate_a_bitmap(SkBitmap* bitmap, SkImageGenerator* gen, const SkImageInfo& info) { + const size_t rowBytes = info.minRowBytes(); + const size_t pixelSize = info.getSafeSize(rowBytes); + if (0 == pixelSize) { + return false; + } + + SkAutoFree pixelStorage(sk_malloc_flags(pixelSize, 0)); + void* pixels = pixelStorage.get(); + if (!pixels) { + return false; + } + + SkPMColor ctStorage[256]; + int ctCount = 0; + + if (!gen->getPixels(info, pixels, rowBytes, ctStorage, &ctCount)) { return false; } - SkASSERT(bitmap->rowBytes() == rowBytes); + SkAutoTUnref<SkColorTable> ctable; + if (ctCount > 0) { + SkASSERT(kIndex_8_SkColorType == info.colorType()); + ctable.reset(new SkColorTable(ctStorage, ctCount)); + } else { + SkASSERT(kIndex_8_SkColorType != info.colorType()); + } + + return bitmap->installPixels(info, pixelStorage.detach(), rowBytes, ctable, + release_malloc_proc, nullptr); +} + +bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { ScopedGenerator generator(this); const SkImageInfo& genInfo = generator->getInfo(); if (fInfo.dimensions() == genInfo.dimensions()) { SkASSERT(fOrigin.x() == 0 && fOrigin.y() == 0); // fast-case, no copy needed - if (!generator->getPixels(bitmap->info(), bitmap->getPixels(), rowBytes)) { - bitmap->reset(); - return false; - } + return generate_a_bitmap(bitmap, generator, fInfo); } else { - // need to handle subsetting + // need to handle subsetting, so we first generate the full size version, and then + // "read" from it to get our subset. See skbug.com/4213 + SkBitmap full; - if (!full.tryAllocPixels(genInfo)) { + if (!generate_a_bitmap(&full, generator, genInfo)) { return false; } - if (!generator->getPixels(full.info(), full.getPixels(), full.rowBytes())) { - bitmap->reset(); + if (!bitmap->tryAllocPixels(fInfo, nullptr, full.getColorTable())) { return false; } - full.readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), - fOrigin.x(), fOrigin.y()); + return full.readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), + fOrigin.x(), fOrigin.y()); } - return true; } ////////////////////////////////////////////////////////////////////////////////////////////////// |