rename gamma to table, since it is more general than just gamma

git-svn-id: http://skia.googlecode.com/svn/trunk@412 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2009-10-29 17:37:56 +00:00
parent 3cfda413a2
commit 3f2025fdb5
4 changed files with 238 additions and 123 deletions

View File

@ -14,27 +14,45 @@
* limitations under the License.
*/
#ifndef SkGammaMaskFilter_DEFINED
#define SkGammaMaskFilter_DEFINED
#ifndef SkTableMaskFilter_DEFINED
#define SkTableMaskFilter_DEFINED
#include "SkMaskFilter.h"
#include "SkScalar.h"
/** \class SkGammaMaskFilter
/** \class SkTableMaskFilter
Applies a table lookup on each of the alpha values in the mask.
An arbitrary table can be assigned, or a gamma (pow) table is computed
based on the specified exponent.
Helper methods create some common tables (e.g. gamma, clipping)
*/
class SkGammaMaskFilter : public SkMaskFilter {
class SkTableMaskFilter : public SkMaskFilter {
public:
SkGammaMaskFilter();
SkGammaMaskFilter(SkScalar gamma);
SkGammaMaskFilter(const uint8_t table[256]);
virtual ~SkGammaMaskFilter();
SkTableMaskFilter();
SkTableMaskFilter(const uint8_t table[256]);
virtual ~SkTableMaskFilter();
void setGamma(SkScalar gamma);
void setGammaTable(const uint8_t table[256]);
void setTable(const uint8_t table[256]);
/** Utility that sets the gamma table
*/
static void MakeGammaTable(uint8_t table[256], SkScalar gamma);
/** Utility that creates a clipping table: clamps values below min to 0
and above max to 255, and rescales the remaining into 0..255
*/
static void MakeClipTable(uint8_t table[256], uint8_t min, uint8_t max);
static SkTableMaskFilter* CreateGamma(SkScalar gamma) {
uint8_t table[256];
MakeGammaTable(table, gamma);
return SkNEW_ARGS(SkTableMaskFilter, (table));
}
static SkTableMaskFilter* CreateClip(uint8_t min, uint8_t max) {
uint8_t table[256];
MakeClipTable(table, min, max);
return SkNEW_ARGS(SkTableMaskFilter, (table));
}
// overrides from SkMaskFilter
virtual SkMask::Format getFormat();
@ -45,7 +63,7 @@ public:
virtual Factory getFactory();
protected:
SkGammaMaskFilter(SkFlattenableReadBuffer& rb);
SkTableMaskFilter(SkFlattenableReadBuffer& rb);
static SkFlattenable* Factory(SkFlattenableReadBuffer&);
private:

View File

@ -8,6 +8,84 @@
#include "SkUtils.h"
#include "SkImageDecoder.h"
#include "SkBlurMaskFilter.h"
#include "SkTableMaskFilter.h"
static void test_bigblur(SkCanvas* canvas) {
canvas->drawColor(SK_ColorBLACK);
SkBitmap orig, mask;
SkImageDecoder::DecodeFile("/skimages/app_icon.png", &orig);
SkMaskFilter* mf = SkBlurMaskFilter::Create(8, SkBlurMaskFilter::kNormal_BlurStyle);
SkPaint paint;
paint.setMaskFilter(mf)->unref();
SkIPoint offset;
orig.extractAlpha(&mask, &paint, &offset);
paint.setColor(0xFFBB8800);
paint.setColor(SK_ColorWHITE);
int i;
canvas->save();
float gamma = 0.8;
for (i = 0; i < 5; i++) {
paint.setMaskFilter(SkTableMaskFilter::CreateGamma(gamma))->unref();
canvas->drawBitmap(mask, 0, 0, &paint);
paint.setMaskFilter(NULL);
canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
gamma -= 0.1;
canvas->translate(120, 0);
}
canvas->restore();
canvas->translate(0, 160);
for (i = 0; i < 5; i++) {
paint.setMaskFilter(SkTableMaskFilter::CreateClip(i*30, 255 - 20))->unref();
canvas->drawBitmap(mask, 0, 0, &paint);
paint.setMaskFilter(NULL);
canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
canvas->translate(120, 0);
}
#if 0
paint.setColor(0xFFFFFFFF);
canvas->drawBitmap(mask, 0, 0, &paint);
paint.setMaskFilter(NULL);
canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
canvas->translate(120, 0);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
canvas->translate(120, 0);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
canvas->translate(120, 0);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
canvas->translate(120, 0);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(mask, 0, 0, &paint);
canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
#endif
}
#include "SkMeshUtils.h"
static SkPoint SkMakePoint(SkScalar x, SkScalar y) {
@ -240,9 +318,6 @@ void Mesh::drawWireframe(SkCanvas* canvas, const SkPaint& paint) {
///////////////////////////////////////////////////////////////////////////////
static SkScalar gScale = 0;
static SkScalar gDScale = 0.02;
class WarpView : public SkView {
Mesh fMesh, fOrig;
SkBitmap fBitmap;
@ -282,7 +357,8 @@ protected:
}
virtual void onDraw(SkCanvas* canvas) {
canvas->drawColor(SK_ColorGRAY);
canvas->drawColor(SK_ColorLTGRAY);
// test_bigblur(canvas); return;
SkPaint paint;
paint.setFilterBitmap(true);
@ -295,18 +371,7 @@ protected:
paint.setColor(SK_ColorRED);
// fMesh.draw(canvas, paint);
#if 0
test_patch(canvas, fBitmap, gScale);
gScale += gDScale;
if (gScale > 2) {
gDScale = -gDScale;
} else if (gScale < -2) {
gDScale = -gDScale;
}
this->inval(NULL);
#else
test_drag(canvas, fBitmap, fP0, fP1);
#endif
}
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {

View File

@ -1,95 +0,0 @@
#include "SkGammaMaskFilter.h"
SkGammaMaskFilter::SkGammaMaskFilter() {
for (int i = 0; i < 256; i++) {
fTable[i] = i;
}
}
SkGammaMaskFilter::SkGammaMaskFilter(SkScalar gamma) {
this->setGamma(gamma);
}
SkGammaMaskFilter::SkGammaMaskFilter(const uint8_t table[256]) {
this->setGammaTable(table);
}
SkGammaMaskFilter::~SkGammaMaskFilter() {}
void SkGammaMaskFilter::setGamma(SkScalar gamma) {
float x = 0;
const float dx = 1 / 255.0f;
for (int i = 0; i < 256; i++) {
fTable[i] = SkPin32(SkScalarRound(powf(x, gamma) * 255), 0, 255);
x += dx;
}
}
void SkGammaMaskFilter::setGammaTable(const uint8_t table[256]) {
memcpy(fTable, table, 256);
}
SkMask::Format SkGammaMaskFilter::getFormat() {
return SkMask::kA8_Format;
}
bool SkGammaMaskFilter::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix&, SkIPoint* margin) {
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
dst->fBounds = src.fBounds;
dst->fRowBytes = SkAlign4(dst->fBounds.width());
dst->fFormat = SkMask::kA8_Format;
dst->fImage = NULL;
if (src.fImage) {
dst->fImage = SkMask::AllocImage(dst->computeImageSize());
const uint8_t* srcP = src.fImage;
uint8_t* dstP = dst->fImage;
const uint8_t* table = fTable;
int dstWidth = dst->fBounds.width();
int extraZeros = dst->fRowBytes - dstWidth;
for (int y = dst->fBounds.height() - 1; y >= 0; --y) {
for (int x = dstWidth - 1; x >= 0; --x) {
dstP[x] = table[srcP[x]];
}
srcP += src.fRowBytes;
// we can't just inc dstP by rowbytes, because if it has any
// padding between its width and its rowbytes, we need to zero those
// so that the bitters can read those safely if that is faster for
// them
dstP += dstWidth;
for (int i = extraZeros - 1; i >= 0; --i) {
*dstP++ = 0;
}
}
}
if (margin) {
margin->set(0, 0);
}
return true;
}
void SkGammaMaskFilter::flatten(SkFlattenableWriteBuffer& wb) {
this->INHERITED::flatten(wb);
wb.writePad(fTable, 256);
}
SkGammaMaskFilter::SkGammaMaskFilter(SkFlattenableReadBuffer& rb)
: INHERITED(rb) {
rb.read(fTable, 256);
}
SkFlattenable* SkGammaMaskFilter::Factory(SkFlattenableReadBuffer& rb) {
return SkNEW_ARGS(SkGammaMaskFilter, (rb));
}
SkFlattenable::Factory SkGammaMaskFilter::getFactory() {
return SkGammaMaskFilter::Factory;
}

View File

@ -0,0 +1,127 @@
#include "SkTableMaskFilter.h"
SkTableMaskFilter::SkTableMaskFilter() {
for (int i = 0; i < 256; i++) {
fTable[i] = i;
}
}
SkTableMaskFilter::SkTableMaskFilter(const uint8_t table[256]) {
this->setTable(table);
}
SkTableMaskFilter::~SkTableMaskFilter() {}
void SkTableMaskFilter::setTable(const uint8_t table[256]) {
memcpy(fTable, table, 256);
}
bool SkTableMaskFilter::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix&, SkIPoint* margin) {
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
dst->fBounds = src.fBounds;
dst->fRowBytes = SkAlign4(dst->fBounds.width());
dst->fFormat = SkMask::kA8_Format;
dst->fImage = NULL;
if (src.fImage) {
dst->fImage = SkMask::AllocImage(dst->computeImageSize());
const uint8_t* srcP = src.fImage;
uint8_t* dstP = dst->fImage;
const uint8_t* table = fTable;
int dstWidth = dst->fBounds.width();
int extraZeros = dst->fRowBytes - dstWidth;
for (int y = dst->fBounds.height() - 1; y >= 0; --y) {
for (int x = dstWidth - 1; x >= 0; --x) {
dstP[x] = table[srcP[x]];
}
srcP += src.fRowBytes;
// we can't just inc dstP by rowbytes, because if it has any
// padding between its width and its rowbytes, we need to zero those
// so that the bitters can read those safely if that is faster for
// them
dstP += dstWidth;
for (int i = extraZeros - 1; i >= 0; --i) {
*dstP++ = 0;
}
}
}
if (margin) {
margin->set(0, 0);
}
return true;
}
SkMask::Format SkTableMaskFilter::getFormat() {
return SkMask::kA8_Format;
}
void SkTableMaskFilter::flatten(SkFlattenableWriteBuffer& wb) {
this->INHERITED::flatten(wb);
wb.writePad(fTable, 256);
}
SkTableMaskFilter::SkTableMaskFilter(SkFlattenableReadBuffer& rb)
: INHERITED(rb) {
rb.read(fTable, 256);
}
SkFlattenable* SkTableMaskFilter::Factory(SkFlattenableReadBuffer& rb) {
return SkNEW_ARGS(SkTableMaskFilter, (rb));
}
SkFlattenable::Factory SkTableMaskFilter::getFactory() {
return SkTableMaskFilter::Factory;
}
///////////////////////////////////////////////////////////////////////////////
void SkTableMaskFilter::MakeGammaTable(uint8_t table[256], SkScalar gamma) {
float x = 0;
const float dx = 1 / 255.0f;
for (int i = 0; i < 256; i++) {
table[i] = SkPin32(SkScalarRound(powf(x, gamma) * 255), 0, 255);
x += dx;
}
}
void SkTableMaskFilter::MakeClipTable(uint8_t table[256], uint8_t min,
uint8_t max) {
if (0 == max) {
max = 1;
}
if (min >= max) {
min = max - 1;
}
SkASSERT(min < max);
SkFixed scale = (1 << 16) * 255 / (max - min);
memset(table, 0, min + 1);
for (int i = min + 1; i < max; i++) {
int value = SkFixedRound(scale * (i - min));
SkASSERT(value <= 255);
table[i] = value;
}
memset(table + max, 255, 256 - max);
#if 0
int j;
for (j = 0; j < 256; j++) {
if (table[j]) {
break;
}
}
SkDebugf("%d %d start [%d]", min, max, j);
for (; j < 256; j++) {
SkDebugf(" %d", table[j]);
}
SkDebugf("\n\n");
#endif
}