SkBitmap::ComputeIsOpaque and SkBitmap::eraseColor support F16

Also add a unit test.

Change-Id: I9b6635ce9dd504788ca36b3246eaac2b37c2f3a6
Reviewed-on: https://skia-review.googlesource.com/5443
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Hal Canary 2016-12-07 14:59:27 -05:00 committed by Skia Commit-Bot
parent 1e41f4a111
commit 4cba3fe576
4 changed files with 81 additions and 9 deletions

View File

@ -183,6 +183,7 @@ struct SkColor4f {
float* vec() { return &fR; }
static SkColor4f Pin(float r, float g, float b, float a);
/** Convert to SkColor4f, assuming SkColor is sRGB */
static SkColor4f FromColor(SkColor);
static SkColor4f FromColor3f(SkColor3f, float a);

View File

@ -11,6 +11,7 @@
#include "SkConfig8888.h"
#include "SkData.h"
#include "SkFilterQuality.h"
#include "SkHalf.h"
#include "SkMallocPixelRef.h"
#include "SkMask.h"
#include "SkMath.h"
@ -622,6 +623,18 @@ static bool compute_is_opaque(const SkPixmap& pmap) {
}
return true;
}
case kRGBA_F16_SkColorType: {
const SkHalf* row = (const SkHalf*)pmap.addr();
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (row[4 * x + 3] < SK_Half1) {
return false;
}
}
row += pmap.rowBytes() >> 1;
}
return true;
}
default:
break;
}

View File

@ -5,13 +5,18 @@
* found in the LICENSE file.
*/
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkConfig8888.h"
#include "SkData.h"
#include "SkHalf.h"
#include "SkMask.h"
#include "SkPixmap.h"
#include "SkUtils.h"
#include "SkNx.h"
#include "SkPM4f.h"
#include "SkPixmap.h"
#include "SkSurface.h"
#include "SkUtils.h"
void SkAutoPixmapUnlock::reset(const SkPixmap& pm, void (*unlock)(void*), void* ctx) {
SkASSERT(pm.addr() != nullptr);
@ -206,15 +211,19 @@ bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
}
break;
}
case kRGBA_F16_SkColorType:
// The colorspace is unspecified, so assume linear just like getColor().
this->erase(SkColor4f{(1 / 255.0f) * r,
(1 / 255.0f) * g,
(1 / 255.0f) * b,
(1 / 255.0f) * a}, &area);
break;
default:
return false; // no change, so don't call notifyPixelsChanged()
}
return true;
}
#include "SkNx.h"
#include "SkHalf.h"
bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const {
SkPixmap pm;
if (subset) {
@ -238,10 +247,6 @@ bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const {
return true;
}
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkSurface.h"
bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const {
// Can't do anthing with empty src or dst
if (this->width() <= 0 || this->height() <= 0 || dst.width() <= 0 || dst.height() <= 0) {

View File

@ -166,3 +166,56 @@ DEF_TEST(Bitmap_eraseColor_Premul, r) {
test_erasecolor_premul(r, kRGBA_8888_SkColorType, color, color);
test_erasecolor_premul(r, kBGRA_8888_SkColorType, color, color);
}
// Test that SkBitmap::ComputeOpaque() is correct for various colortypes.
DEF_TEST(Bitmap_compute_is_opaque, r) {
struct {
SkColorType fCT;
SkAlphaType fAT;
} types[] = {
{ kGray_8_SkColorType, kOpaque_SkAlphaType },
{ kAlpha_8_SkColorType, kPremul_SkAlphaType },
{ kARGB_4444_SkColorType, kPremul_SkAlphaType },
{ kRGB_565_SkColorType, kOpaque_SkAlphaType },
{ kBGRA_8888_SkColorType, kPremul_SkAlphaType },
{ kRGBA_8888_SkColorType, kPremul_SkAlphaType },
{ kRGBA_F16_SkColorType, kPremul_SkAlphaType },
};
for (auto type : types) {
SkBitmap bm;
REPORTER_ASSERT(r, !SkBitmap::ComputeIsOpaque(bm));
bm.allocPixels(SkImageInfo::Make(13, 17, type.fCT, type.fAT));
bm.eraseColor(SkColorSetARGB(255, 10, 20, 30));
REPORTER_ASSERT(r, SkBitmap::ComputeIsOpaque(bm));
bm.eraseColor(SkColorSetARGB(128, 255, 255, 255));
bool isOpaque = SkBitmap::ComputeIsOpaque(bm);
bool shouldBeOpaque = (type.fAT == kOpaque_SkAlphaType);
REPORTER_ASSERT(r, isOpaque == shouldBeOpaque);
}
}
// Test that erase+getColor round trips with RGBA_F16 pixels.
DEF_TEST(Bitmap_erase_f16_erase_getColor, r) {
SkRandom random;
SkPixmap pm;
SkBitmap bm;
bm.allocPixels(SkImageInfo::Make(1, 1, kRGBA_F16_SkColorType, kPremul_SkAlphaType));
REPORTER_ASSERT(r, bm.peekPixels(&pm));
for (unsigned i = 0; i < 0x100; ++i) {
// Test all possible values of blue component.
SkColor color1 = (SkColor)((random.nextU() & 0xFFFFFF00) | i);
// Test all possible values of alpha component.
SkColor color2 = (SkColor)((random.nextU() & 0x00FFFFFF) | (i << 24));
for (SkColor color : {color1, color2}) {
pm.erase(color);
if (SkColorGetA(color) != 0) {
REPORTER_ASSERT(r, color == pm.getColor(0, 0));
} else {
REPORTER_ASSERT(r, 0 == SkColorGetA(pm.getColor(0, 0)));
}
}
}
}