/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/private/SkColorData.h" #include "src/codec/SkCodecPriv.h" #include "src/codec/SkMaskSwizzler.h" static void swizzle_mask16_to_rgba_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPackARGB_as_RGBA(0xFF, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask16_to_bgra_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPackARGB_as_BGRA(0xFF, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask16_to_rgba_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = SkPackARGB_as_RGBA(alpha, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask16_to_bgra_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = SkPackARGB_as_BGRA(alpha, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask16_to_rgba_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = premultiply_argb_as_rgba(alpha, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask16_to_bgra_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = premultiply_argb_as_bgra(alpha, red, green, blue); srcPtr += sampleX; } } // TODO (msarett): We have promoted a two byte per pixel image to 8888, only to // convert it back to 565. Instead, we should swizzle to 565 directly. static void swizzle_mask16_to_565( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; uint16_t* dstPtr = (uint16_t*) dstRow; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPack888ToRGB16(red, green, blue); srcPtr += sampleX; } } static void swizzle_mask24_to_rgba_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination srcRow += 3 * startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPackARGB_as_RGBA(0xFF, red, green, blue); srcRow += 3 * sampleX; } } static void swizzle_mask24_to_bgra_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination srcRow += 3 * startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPackARGB_as_BGRA(0xFF, red, green, blue); srcRow += 3 * sampleX; } } static void swizzle_mask24_to_rgba_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination srcRow += 3 * startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = SkPackARGB_as_RGBA(alpha, red, green, blue); srcRow += 3 * sampleX; } } static void swizzle_mask24_to_bgra_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination srcRow += 3 * startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = SkPackARGB_as_BGRA(alpha, red, green, blue); srcRow += 3 * sampleX; } } static void swizzle_mask24_to_rgba_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination srcRow += 3 * startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = premultiply_argb_as_rgba(alpha, red, green, blue); srcRow += 3 * sampleX; } } static void swizzle_mask24_to_bgra_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination srcRow += 3 * startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = premultiply_argb_as_bgra(alpha, red, green, blue); srcRow += 3 * sampleX; } } static void swizzle_mask24_to_565( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination srcRow += 3 * startX; uint16_t* dstPtr = (uint16_t*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPack888ToRGB16(red, green, blue); srcRow += 3 * sampleX; } } static void swizzle_mask32_to_rgba_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPackARGB_as_RGBA(0xFF, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask32_to_bgra_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPackARGB_as_BGRA(0xFF, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask32_to_rgba_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = SkPackARGB_as_RGBA(alpha, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask32_to_bgra_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = SkPackARGB_as_BGRA(alpha, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask32_to_rgba_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = premultiply_argb_as_rgba(alpha, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask32_to_bgra_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); dstPtr[i] = premultiply_argb_as_bgra(alpha, red, green, blue); srcPtr += sampleX; } } static void swizzle_mask32_to_565( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, uint32_t startX, uint32_t sampleX) { // Use the masks to decode to the destination uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; uint16_t* dstPtr = (uint16_t*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[0]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPack888ToRGB16(red, green, blue); srcPtr += sampleX; } } /* * * Create a new mask swizzler * */ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(const SkImageInfo& dstInfo, bool srcIsOpaque, SkMasks* masks, uint32_t bitsPerPixel, const SkCodec::Options& options) { // Choose the appropriate row procedure RowProc proc = nullptr; switch (bitsPerPixel) { case 16: switch (dstInfo.colorType()) { case kRGBA_8888_SkColorType: if (srcIsOpaque) { proc = &swizzle_mask16_to_rgba_opaque; } else { switch (dstInfo.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask16_to_rgba_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask16_to_rgba_premul; break; default: break; } } break; case kBGRA_8888_SkColorType: if (srcIsOpaque) { proc = &swizzle_mask16_to_bgra_opaque; } else { switch (dstInfo.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask16_to_bgra_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask16_to_bgra_premul; break; default: break; } } break; case kRGB_565_SkColorType: proc = &swizzle_mask16_to_565; break; default: break; } break; case 24: switch (dstInfo.colorType()) { case kRGBA_8888_SkColorType: if (srcIsOpaque) { proc = &swizzle_mask24_to_rgba_opaque; } else { switch (dstInfo.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask24_to_rgba_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask24_to_rgba_premul; break; default: break; } } break; case kBGRA_8888_SkColorType: if (srcIsOpaque) { proc = &swizzle_mask24_to_bgra_opaque; } else { switch (dstInfo.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask24_to_bgra_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask24_to_bgra_premul; break; default: break; } } break; case kRGB_565_SkColorType: proc = &swizzle_mask24_to_565; break; default: break; } break; case 32: switch (dstInfo.colorType()) { case kRGBA_8888_SkColorType: if (srcIsOpaque) { proc = &swizzle_mask32_to_rgba_opaque; } else { switch (dstInfo.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask32_to_rgba_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask32_to_rgba_premul; break; default: break; } } break; case kBGRA_8888_SkColorType: if (srcIsOpaque) { proc = &swizzle_mask32_to_bgra_opaque; } else { switch (dstInfo.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask32_to_bgra_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask32_to_bgra_premul; break; default: break; } } break; case kRGB_565_SkColorType: proc = &swizzle_mask32_to_565; break; default: break; } break; default: SkASSERT(false); return nullptr; } int srcOffset = 0; int srcWidth = dstInfo.width(); if (options.fSubset) { srcOffset = options.fSubset->left(); srcWidth = options.fSubset->width(); } return new SkMaskSwizzler(masks, proc, srcOffset, srcWidth); } /* * * Constructor for mask swizzler * */ SkMaskSwizzler::SkMaskSwizzler(SkMasks* masks, RowProc proc, int srcOffset, int subsetWidth) : fMasks(masks) , fRowProc(proc) , fSubsetWidth(subsetWidth) , fDstWidth(subsetWidth) , fSampleX(1) , fSrcOffset(srcOffset) , fX0(srcOffset) {} int SkMaskSwizzler::onSetSampleX(int sampleX) { // FIXME: Share this function with SkSwizzler? SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be // way to report failure? fSampleX = sampleX; fX0 = get_start_coord(sampleX) + fSrcOffset; fDstWidth = get_scaled_dimension(fSubsetWidth, sampleX); // check that fX0 is valid SkASSERT(fX0 >= 0); return fDstWidth; } /* * * Swizzle the specified row * */ void SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) { SkASSERT(nullptr != dst && nullptr != src); fRowProc(dst, src, fDstWidth, fMasks, fX0, fSampleX); }