Refactor pixel conversion: premul and unpremul
Just going for simpler and more code sharing. BUG=skia: Change-Id: I84c20cd4dbb6950f7b4d0bc659c4b3b5a2af201c Reviewed-on: https://skia-review.googlesource.com/8287 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Matt Sarett <msarett@google.com>
This commit is contained in:
parent
5881e82060
commit
c7b2908947
@ -14,9 +14,10 @@
|
|||||||
#include "SkDither.h"
|
#include "SkDither.h"
|
||||||
#include "SkImageInfoPriv.h"
|
#include "SkImageInfoPriv.h"
|
||||||
#include "SkMathPriv.h"
|
#include "SkMathPriv.h"
|
||||||
|
#include "SkOpts.h"
|
||||||
#include "SkPM4fPriv.h"
|
#include "SkPM4fPriv.h"
|
||||||
#include "SkRasterPipeline.h"
|
#include "SkRasterPipeline.h"
|
||||||
#include "SkUnPreMultiply.h"
|
#include "SkUnPreMultiplyPriv.h"
|
||||||
|
|
||||||
// Fast Path 1: The memcpy() case.
|
// Fast Path 1: The memcpy() case.
|
||||||
static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
|
static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
|
||||||
@ -36,6 +37,53 @@ static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& src
|
|||||||
SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace());
|
SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum AlphaVerb {
|
||||||
|
kNothing_AlphaVerb,
|
||||||
|
kPremul_AlphaVerb,
|
||||||
|
kUnpremul_AlphaVerb,
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool kSwapRB>
|
||||||
|
static void wrap_unpremultiply(uint32_t* dst, const void* src, int count) {
|
||||||
|
SkUnpremultiplyRow<kSwapRB>(dst, (const uint32_t*) src, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast Path 2: Simple swizzles and premuls.
|
||||||
|
void swizzle_and_multiply(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
|
||||||
|
const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) {
|
||||||
|
void (*proc)(uint32_t* dst, const void* src, int count);
|
||||||
|
const bool swapRB = dstInfo.colorType() != srcInfo.colorType();
|
||||||
|
AlphaVerb alphaVerb = kNothing_AlphaVerb;
|
||||||
|
if (kPremul_SkAlphaType == dstInfo.alphaType() &&
|
||||||
|
kUnpremul_SkAlphaType == srcInfo.alphaType())
|
||||||
|
{
|
||||||
|
alphaVerb = kPremul_AlphaVerb;
|
||||||
|
} else if (kUnpremul_SkAlphaType == dstInfo.alphaType() &&
|
||||||
|
kPremul_SkAlphaType == srcInfo.alphaType()) {
|
||||||
|
alphaVerb = kUnpremul_AlphaVerb;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (alphaVerb) {
|
||||||
|
case kNothing_AlphaVerb:
|
||||||
|
// If we do not need to swap or multiply, we should hit the memcpy case.
|
||||||
|
SkASSERT(swapRB);
|
||||||
|
proc = SkOpts::RGBA_to_BGRA;
|
||||||
|
break;
|
||||||
|
case kPremul_AlphaVerb:
|
||||||
|
proc = swapRB ? SkOpts::RGBA_to_bgrA : SkOpts::RGBA_to_rgbA;
|
||||||
|
break;
|
||||||
|
case kUnpremul_AlphaVerb:
|
||||||
|
proc = swapRB ? wrap_unpremultiply<true> : wrap_unpremultiply<false>;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < dstInfo.height(); y++) {
|
||||||
|
proc((uint32_t*) dstPixels, srcPixels, dstInfo.width());
|
||||||
|
dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
|
||||||
|
srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Default: Use the pipeline.
|
// Default: Use the pipeline.
|
||||||
static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
|
static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
|
||||||
const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
|
const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
|
||||||
@ -114,107 +162,6 @@ static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AlphaVerb {
|
|
||||||
kNothing_AlphaVerb,
|
|
||||||
kPremul_AlphaVerb,
|
|
||||||
kUnpremul_AlphaVerb,
|
|
||||||
};
|
|
||||||
|
|
||||||
template <bool doSwapRB, AlphaVerb doAlpha> uint32_t convert32(uint32_t c) {
|
|
||||||
if (doSwapRB) {
|
|
||||||
c = SkSwizzle_RB(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lucky for us, in both RGBA and BGRA, the alpha component is always in the same place, so
|
|
||||||
// we can perform premul or unpremul the same way without knowing the swizzles for RGB.
|
|
||||||
switch (doAlpha) {
|
|
||||||
case kNothing_AlphaVerb:
|
|
||||||
// no change
|
|
||||||
break;
|
|
||||||
case kPremul_AlphaVerb:
|
|
||||||
c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c),
|
|
||||||
SkGetPackedG32(c), SkGetPackedB32(c));
|
|
||||||
break;
|
|
||||||
case kUnpremul_AlphaVerb:
|
|
||||||
c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool doSwapRB, AlphaVerb doAlpha>
|
|
||||||
void convert32_row(uint32_t* dst, const uint32_t* src, int count) {
|
|
||||||
// This has to be correct if src == dst (but not partial overlap)
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
dst[i] = convert32<doSwapRB, doAlpha>(src[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_32bit_colortype(SkColorType ct) {
|
|
||||||
return kRGBA_8888_SkColorType == ct || kBGRA_8888_SkColorType == ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AlphaVerb compute_AlphaVerb(SkAlphaType src, SkAlphaType dst) {
|
|
||||||
SkASSERT(kUnknown_SkAlphaType != src);
|
|
||||||
SkASSERT(kUnknown_SkAlphaType != dst);
|
|
||||||
|
|
||||||
if (kOpaque_SkAlphaType == src || kOpaque_SkAlphaType == dst || src == dst) {
|
|
||||||
return kNothing_AlphaVerb;
|
|
||||||
}
|
|
||||||
if (kPremul_SkAlphaType == dst) {
|
|
||||||
SkASSERT(kUnpremul_SkAlphaType == src);
|
|
||||||
return kPremul_AlphaVerb;
|
|
||||||
} else {
|
|
||||||
SkASSERT(kPremul_SkAlphaType == src);
|
|
||||||
SkASSERT(kUnpremul_SkAlphaType == dst);
|
|
||||||
return kUnpremul_AlphaVerb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const {
|
|
||||||
SkASSERT(width > 0 && height > 0);
|
|
||||||
|
|
||||||
if (!is_32bit_colortype(fColorType) || !is_32bit_colortype(dst->fColorType)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void (*proc)(uint32_t* dst, const uint32_t* src, int count);
|
|
||||||
AlphaVerb doAlpha = compute_AlphaVerb(fAlphaType, dst->fAlphaType);
|
|
||||||
bool doSwapRB = fColorType != dst->fColorType;
|
|
||||||
|
|
||||||
switch (doAlpha) {
|
|
||||||
case kNothing_AlphaVerb:
|
|
||||||
SkASSERT(doSwapRB);
|
|
||||||
proc = convert32_row<true, kNothing_AlphaVerb>;
|
|
||||||
break;
|
|
||||||
case kPremul_AlphaVerb:
|
|
||||||
if (doSwapRB) {
|
|
||||||
proc = convert32_row<true, kPremul_AlphaVerb>;
|
|
||||||
} else {
|
|
||||||
proc = convert32_row<false, kPremul_AlphaVerb>;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case kUnpremul_AlphaVerb:
|
|
||||||
if (doSwapRB) {
|
|
||||||
proc = convert32_row<true, kUnpremul_AlphaVerb>;
|
|
||||||
} else {
|
|
||||||
proc = convert32_row<false, kUnpremul_AlphaVerb>;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t* dstP = static_cast<uint32_t*>(dst->fPixels);
|
|
||||||
const uint32_t* srcP = static_cast<const uint32_t*>(fPixels);
|
|
||||||
size_t srcInc = fRowBytes >> 2;
|
|
||||||
size_t dstInc = dst->fRowBytes >> 2;
|
|
||||||
for (int y = 0; y < height; ++y) {
|
|
||||||
proc(dstP, srcP, width);
|
|
||||||
dstP += dstInc;
|
|
||||||
srcP += srcInc;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool extract_alpha(void* dst, size_t dstRB, const void* src, size_t srcRB,
|
static bool extract_alpha(void* dst, size_t dstRB, const void* src, size_t srcRB,
|
||||||
const SkImageInfo& srcInfo, SkColorTable* ctable) {
|
const SkImageInfo& srcInfo, SkColorTable* ctable) {
|
||||||
uint8_t* SK_RESTRICT dst8 = (uint8_t*)dst;
|
uint8_t* SK_RESTRICT dst8 = (uint8_t*)dst;
|
||||||
@ -358,21 +305,10 @@ bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t
|
|||||||
const bool isColorAware = dstInfo.colorSpace();
|
const bool isColorAware = dstInfo.colorSpace();
|
||||||
SkASSERT(srcInfo.colorSpace() || !isColorAware);
|
SkASSERT(srcInfo.colorSpace() || !isColorAware);
|
||||||
|
|
||||||
// Handle fancy alpha swizzling if both are ARGB32
|
// Fast Path 2: Simple swizzles and premuls.
|
||||||
if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) {
|
if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) {
|
||||||
SkDstPixelInfo dstPI;
|
swizzle_and_multiply(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
|
||||||
dstPI.fColorType = dstInfo.colorType();
|
return true;
|
||||||
dstPI.fAlphaType = dstInfo.alphaType();
|
|
||||||
dstPI.fPixels = dstPixels;
|
|
||||||
dstPI.fRowBytes = dstRB;
|
|
||||||
|
|
||||||
SkSrcPixelInfo srcPI;
|
|
||||||
srcPI.fColorType = srcInfo.colorType();
|
|
||||||
srcPI.fAlphaType = srcInfo.alphaType();
|
|
||||||
srcPI.fPixels = srcPixels;
|
|
||||||
srcPI.fRowBytes = srcRB;
|
|
||||||
|
|
||||||
return srcPI.convertPixelsTo(&dstPI, width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isColorAware && optimized_color_xform(dstInfo, srcInfo)) {
|
if (isColorAware && optimized_color_xform(dstInfo, srcInfo)) {
|
||||||
|
@ -23,18 +23,6 @@ struct SkPixelInfo {
|
|||||||
SkColorTable* srcCTable = nullptr);
|
SkColorTable* srcCTable = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SkDstPixelInfo : SkPixelInfo {
|
|
||||||
void* fPixels;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SkSrcPixelInfo : SkPixelInfo {
|
|
||||||
const void* fPixels;
|
|
||||||
|
|
||||||
// Guaranteed to work even if src.fPixels and dst.fPixels are the same
|
|
||||||
// (but not if they overlap partially)
|
|
||||||
bool convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void SkRectMemcpy(void* dst, size_t dstRB, const void* src, size_t srcRB,
|
static inline void SkRectMemcpy(void* dst, size_t dstRB, const void* src, size_t srcRB,
|
||||||
size_t bytesPerRow, int rowCount) {
|
size_t bytesPerRow, int rowCount) {
|
||||||
SkASSERT(bytesPerRow <= dstRB);
|
SkASSERT(bytesPerRow <= dstRB);
|
||||||
|
43
src/core/SkUnPreMultiplyPriv.h
Normal file
43
src/core/SkUnPreMultiplyPriv.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SkUnPreMultiplyPriv_DEFINED
|
||||||
|
#define SkUnPreMultiplyPriv_DEFINED
|
||||||
|
|
||||||
|
#include "SkColor.h"
|
||||||
|
|
||||||
|
template <bool kSwapRB>
|
||||||
|
void SkUnpremultiplyRow(uint32_t* dst, const uint32_t* src, int count) {
|
||||||
|
const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
uint32_t c = *src++;
|
||||||
|
uint8_t r, g, b, a;
|
||||||
|
if (kSwapRB) {
|
||||||
|
r = (c >> 16) & 0xFF;
|
||||||
|
g = (c >> 8) & 0xFF;
|
||||||
|
b = (c >> 0) & 0xFF;
|
||||||
|
a = (c >> 24) & 0xFF;
|
||||||
|
} else {
|
||||||
|
r = (c >> 0) & 0xFF;
|
||||||
|
g = (c >> 8) & 0xFF;
|
||||||
|
b = (c >> 16) & 0xFF;
|
||||||
|
a = (c >> 24) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != a && 255 != a) {
|
||||||
|
SkUnPreMultiply::Scale scale = table[a];
|
||||||
|
r = SkUnPreMultiply::ApplyScale(scale, r);
|
||||||
|
g = SkUnPreMultiply::ApplyScale(scale, g);
|
||||||
|
b = SkUnPreMultiply::ApplyScale(scale, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst++ = (r << 0) | (g << 8) | (b << 16) | (a << 24);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "SkConfig8888.h"
|
#include "SkConfig8888.h"
|
||||||
#include "SkGrPriv.h"
|
#include "SkGrPriv.h"
|
||||||
|
#include "SkUnPreMultiplyPriv.h"
|
||||||
|
|
||||||
#include "effects/GrConfigConversionEffect.h"
|
#include "effects/GrConfigConversionEffect.h"
|
||||||
#include "text/GrTextBlobCache.h"
|
#include "text/GrTextBlobCache.h"
|
||||||
@ -226,21 +227,20 @@ void GrContext::flush() {
|
|||||||
|
|
||||||
bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
|
bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
|
||||||
const void* inPixels, size_t outRowBytes, void* outPixels) {
|
const void* inPixels, size_t outRowBytes, void* outPixels) {
|
||||||
SkSrcPixelInfo srcPI;
|
SkColorType colorType;
|
||||||
if (!GrPixelConfigToColorType(srcConfig, &srcPI.fColorType)) {
|
if (!GrPixelConfigToColorType(srcConfig, &colorType) ||
|
||||||
|
4 != SkColorTypeBytesPerPixel(colorType))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
srcPI.fAlphaType = kUnpremul_SkAlphaType;
|
|
||||||
srcPI.fPixels = inPixels;
|
|
||||||
srcPI.fRowBytes = inRowBytes;
|
|
||||||
|
|
||||||
SkDstPixelInfo dstPI;
|
for (int y = 0; y < height; y++) {
|
||||||
dstPI.fColorType = srcPI.fColorType;
|
SkOpts::RGBA_to_rgbA((uint32_t*) outPixels, inPixels, width);
|
||||||
dstPI.fAlphaType = kPremul_SkAlphaType;
|
outPixels = SkTAddOffset<void>(outPixels, outRowBytes);
|
||||||
dstPI.fPixels = outPixels;
|
inPixels = SkTAddOffset<const void>(inPixels, inRowBytes);
|
||||||
dstPI.fRowBytes = outRowBytes;
|
}
|
||||||
|
|
||||||
return srcPI.convertPixelsTo(&dstPI, width, height);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpace,
|
bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpace,
|
||||||
@ -522,21 +522,17 @@ bool GrContext::readSurfacePixels(GrSurface* src, SkColorSpace* srcColorSpace,
|
|||||||
|
|
||||||
// Perform umpremul conversion if we weren't able to perform it as a draw.
|
// Perform umpremul conversion if we weren't able to perform it as a draw.
|
||||||
if (unpremul) {
|
if (unpremul) {
|
||||||
SkDstPixelInfo dstPI;
|
SkColorType colorType;
|
||||||
if (!GrPixelConfigToColorType(dstConfig, &dstPI.fColorType)) {
|
if (!GrPixelConfigToColorType(dstConfig, &colorType) ||
|
||||||
|
4 != SkColorTypeBytesPerPixel(colorType))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
dstPI.fAlphaType = kUnpremul_SkAlphaType;
|
|
||||||
dstPI.fPixels = buffer;
|
|
||||||
dstPI.fRowBytes = rowBytes;
|
|
||||||
|
|
||||||
SkSrcPixelInfo srcPI;
|
for (int y = 0; y < height; y++) {
|
||||||
srcPI.fColorType = dstPI.fColorType;
|
SkUnpremultiplyRow<false>((uint32_t*) buffer, (const uint32_t*) buffer, width);
|
||||||
srcPI.fAlphaType = kPremul_SkAlphaType;
|
buffer = SkTAddOffset<void>(buffer, rowBytes);
|
||||||
srcPI.fPixels = buffer;
|
}
|
||||||
srcPI.fRowBytes = rowBytes;
|
|
||||||
|
|
||||||
return srcPI.convertPixelsTo(&dstPI, width, height);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "SkPreConfig.h"
|
#include "SkPreConfig.h"
|
||||||
#include "SkRasterPipeline.h"
|
#include "SkRasterPipeline.h"
|
||||||
#include "SkUnPreMultiply.h"
|
#include "SkUnPreMultiply.h"
|
||||||
|
#include "SkUnPreMultiplyPriv.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function template for transforming scanlines.
|
* Function template for transforming scanlines.
|
||||||
@ -128,46 +129,12 @@ static inline void transform_scanline_444(char* SK_RESTRICT dst, const char* SK_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool kIsRGBA>
|
|
||||||
static inline void transform_scanline_unpremultiply(char* SK_RESTRICT dst,
|
|
||||||
const char* SK_RESTRICT src, int width) {
|
|
||||||
const uint32_t* srcP = (const SkPMColor*)src;
|
|
||||||
const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++) {
|
|
||||||
uint32_t c = *srcP++;
|
|
||||||
unsigned r, g, b, a;
|
|
||||||
if (kIsRGBA) {
|
|
||||||
r = (c >> 0) & 0xFF;
|
|
||||||
g = (c >> 8) & 0xFF;
|
|
||||||
b = (c >> 16) & 0xFF;
|
|
||||||
a = (c >> 24) & 0xFF;
|
|
||||||
} else {
|
|
||||||
r = (c >> 16) & 0xFF;
|
|
||||||
g = (c >> 8) & 0xFF;
|
|
||||||
b = (c >> 0) & 0xFF;
|
|
||||||
a = (c >> 24) & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != a && 255 != a) {
|
|
||||||
SkUnPreMultiply::Scale scale = table[a];
|
|
||||||
r = SkUnPreMultiply::ApplyScale(scale, r);
|
|
||||||
g = SkUnPreMultiply::ApplyScale(scale, g);
|
|
||||||
b = SkUnPreMultiply::ApplyScale(scale, b);
|
|
||||||
}
|
|
||||||
*dst++ = r;
|
|
||||||
*dst++ = g;
|
|
||||||
*dst++ = b;
|
|
||||||
*dst++ = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform from legacy kPremul, kRGBA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
|
* Transform from legacy kPremul, kRGBA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
|
||||||
*/
|
*/
|
||||||
static inline void transform_scanline_rgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
|
static inline void transform_scanline_rgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
|
||||||
int width, int, const SkPMColor*) {
|
int width, int, const SkPMColor*) {
|
||||||
transform_scanline_unpremultiply<true>(dst, src, width);
|
SkUnpremultiplyRow<false>((uint32_t*) dst, (const uint32_t*) src, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -175,7 +142,7 @@ static inline void transform_scanline_rgbA(char* SK_RESTRICT dst, const char* SK
|
|||||||
*/
|
*/
|
||||||
static inline void transform_scanline_bgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
|
static inline void transform_scanline_bgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
|
||||||
int width, int, const SkPMColor*) {
|
int width, int, const SkPMColor*) {
|
||||||
transform_scanline_unpremultiply<false>(dst, src, width);
|
SkUnpremultiplyRow<true>((uint32_t*) dst, (const uint32_t*) src, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool kIsRGBA>
|
template <bool kIsRGBA>
|
||||||
|
Loading…
Reference in New Issue
Block a user