aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-09-11 11:47:27 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-09-11 11:47:27 -0700
commitc4a83e26526a62fb2b8913faa57e0c56b4e1e62a (patch)
tree0e2d532767bb77129a1bd22ba769c61cd23d34c5
parentd8dd47b5fa52430a1ab5c07335c0c13fcd43a82d (diff)
support colortables in cacherator
BUG=skia: TBR=scroggo Review URL: https://codereview.chromium.org/1339753002
-rw-r--r--gm/image_pict.cpp79
-rw-r--r--src/core/SkImageCacherator.cpp57
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;
}
//////////////////////////////////////////////////////////////////////////////////////////////////