Support decoding PNG to 565.

Although we initially discussed not supporting 565, SkCodec needs to
support Android's BitmapFactory and BitmapRegionDecoder, which need to
support 565.

We could instead implement 565 on top of SkCodec, but this would require
more memory and run more slowly.

An open question is whether to support dithering, and how. In order to
support dithering, we need to pass y to RowProc, which I believe means
we will need to pass y to SkSwizzler::swizzle().

I dislike having an option which is typically ignored - SkImageDecoder
allows you to turn on dithering when decoding to any color type, but it
is only meaningful only if the output color type is 565.

We could also make the client implement dithering, which I believe would
mean forcing them to do the conversion to 565 (since we have already
thrown away data when we convered to 565 without dithering).

BUG=skia:3257

Review URL: https://codereview.chromium.org/1277593002
This commit is contained in:
scroggo 2015-08-06 06:08:18 -07:00 committed by Commit bot
parent fd3d87cf67
commit ab60c5bd9f
2 changed files with 52 additions and 1 deletions

View File

@ -419,6 +419,8 @@ static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src)
switch (dst.colorType()) {
case kN32_SkColorType:
return true;
case kRGB_565_SkColorType:
return src.alphaType() == kOpaque_SkAlphaType;
default:
return dst.colorType() == src.colorType();
}

View File

@ -209,6 +209,20 @@ static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ(
return COMPUTE_RESULT_ALPHA;
}
static SkSwizzler::ResultAlpha swizzle_index_to_565(
void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
int bytesPerPixel, const SkPMColor ctable[]) {
// FIXME: Support dithering? Requires knowing y, which I think is a bigger
// change.
uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
for (int x = 0; x < width; x++) {
dst[x] = SkPixel32ToPixel16(ctable[*src]);
src += bytesPerPixel;
}
return SkSwizzler::kOpaque_ResultAlpha;
}
#undef A32_MASK_IN_PLACE
// kGray
@ -231,6 +245,18 @@ static SkSwizzler::ResultAlpha swizzle_gray_to_gray(
return SkSwizzler::kOpaque_ResultAlpha;
}
static SkSwizzler::ResultAlpha swizzle_gray_to_565(
void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
int bytesPerPixel, const SkPMColor ctable[]) {
// FIXME: Support dithering?
uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
for (int x = 0; x < width; x++) {
dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
src += bytesPerPixel;
}
return SkSwizzler::kOpaque_ResultAlpha;
}
// kBGRX
static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
@ -277,7 +303,7 @@ static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul(
return COMPUTE_RESULT_ALPHA;
}
// n32
// kRGBX
static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
int bytesPerPixel, const SkPMColor ctable[]) {
@ -290,6 +316,20 @@ static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
return SkSwizzler::kOpaque_ResultAlpha;
}
static SkSwizzler::ResultAlpha swizzle_rgbx_to_565(
void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
int bytesPerPixel, const SkPMColor ctable[]) {
// FIXME: Support dithering?
uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
for (int x = 0; x < width; x++) {
dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
src += bytesPerPixel;
}
return SkSwizzler::kOpaque_ResultAlpha;
}
// kRGBA
static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul(
void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
int bytesPerPixel, const SkPMColor ctable[]) {
@ -418,6 +458,9 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
break;
}
break;
case kRGB_565_SkColorType:
proc = &swizzle_index_to_565;
break;
case kIndex_8_SkColorType:
proc = &swizzle_index_to_index;
break;
@ -432,6 +475,10 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
break;
case kGray_8_SkColorType:
proc = &swizzle_gray_to_gray;
break;
case kRGB_565_SkColorType:
proc = &swizzle_gray_to_565;
break;
default:
break;
}
@ -470,6 +517,8 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
case kN32_SkColorType:
proc = &swizzle_rgbx_to_n32;
break;
case kRGB_565_SkColorType:
proc = &swizzle_rgbx_to_565;
default:
break;
}