diff options
-rw-r--r-- | include/images/SkImageEncoder.h | 30 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libpng.cpp | 96 | ||||
-rw-r--r-- | src/images/transform_scanline.h | 140 |
3 files changed, 169 insertions, 97 deletions
diff --git a/include/images/SkImageEncoder.h b/include/images/SkImageEncoder.h index 5e350d46ff..3fbfefa5f7 100644 --- a/include/images/SkImageEncoder.h +++ b/include/images/SkImageEncoder.h @@ -28,8 +28,25 @@ public: kDefaultQuality = 80 }; - bool encodeFile(const char file[], const SkBitmap&, int quality); - bool encodeStream(SkWStream*, const SkBitmap&, int quality); + /** + * Encode bitmap 'bm' in the desired format, writing results to + * file 'file', at quality level 'quality' (which can be in range + * 0-100). + * + * Calls the particular implementation's onEncode() method to + * actually do the encoding. + */ + bool encodeFile(const char file[], const SkBitmap& bm, int quality); + + /** + * Encode bitmap 'bm' in the desired format, writing results to + * stream 'stream', at quality level 'quality' (which can be in + * range 0-100). + * + * Calls the particular implementation's onEncode() method to + * actually do the encoding. + */ + bool encodeStream(SkWStream* stream, const SkBitmap& bm, int quality); static bool EncodeFile(const char file[], const SkBitmap&, Type, int quality); @@ -37,7 +54,14 @@ public: int quality); protected: - virtual bool onEncode(SkWStream*, const SkBitmap&, int quality) = 0; + /** + * Encode bitmap 'bm' in the desired format, writing results to + * stream 'stream', at quality level 'quality' (which can be in + * range 0-100). + * + * This must be overridden by each SkImageEncoder implementation. + */ + virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) = 0; }; // This macro declares a global (i.e., non-class owned) creation entry point diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp index d48bce51f8..cca69fac10 100644 --- a/src/images/SkImageDecoder_libpng.cpp +++ b/src/images/SkImageDecoder_libpng.cpp @@ -17,6 +17,7 @@ #include "SkStream.h" #include "SkTemplates.h" #include "SkUtils.h" +#include "transform_scanline.h" extern "C" { #include "png.h" @@ -503,99 +504,6 @@ static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { } } -typedef void (*transform_scanline_proc)(const char* SK_RESTRICT src, - int width, char* SK_RESTRICT dst); - -static void transform_scanline_565(const char* SK_RESTRICT src, int width, - char* SK_RESTRICT dst) { - const uint16_t* SK_RESTRICT srcP = (const uint16_t*)src; - for (int i = 0; i < width; i++) { - unsigned c = *srcP++; - *dst++ = SkPacked16ToR32(c); - *dst++ = SkPacked16ToG32(c); - *dst++ = SkPacked16ToB32(c); - } -} - -static void transform_scanline_888(const char* SK_RESTRICT src, int width, - char* SK_RESTRICT dst) { - const SkPMColor* SK_RESTRICT srcP = (const SkPMColor*)src; - for (int i = 0; i < width; i++) { - SkPMColor c = *srcP++; - *dst++ = SkGetPackedR32(c); - *dst++ = SkGetPackedG32(c); - *dst++ = SkGetPackedB32(c); - } -} - -static void transform_scanline_444(const char* SK_RESTRICT src, int width, - char* SK_RESTRICT dst) { - const SkPMColor16* SK_RESTRICT srcP = (const SkPMColor16*)src; - for (int i = 0; i < width; i++) { - SkPMColor16 c = *srcP++; - *dst++ = SkPacked4444ToR32(c); - *dst++ = SkPacked4444ToG32(c); - *dst++ = SkPacked4444ToB32(c); - } -} - -static void transform_scanline_8888(const char* SK_RESTRICT src, int width, - char* SK_RESTRICT dst) { - const SkPMColor* SK_RESTRICT srcP = (const SkPMColor*)src; - const SkUnPreMultiply::Scale* SK_RESTRICT table = - SkUnPreMultiply::GetScaleTable(); - - for (int i = 0; i < width; i++) { - SkPMColor c = *srcP++; - unsigned a = SkGetPackedA32(c); - unsigned r = SkGetPackedR32(c); - unsigned g = SkGetPackedG32(c); - unsigned b = SkGetPackedB32(c); - - 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; - } -} - -static void transform_scanline_4444(const char* SK_RESTRICT src, int width, - char* SK_RESTRICT dst) { - const SkPMColor16* SK_RESTRICT srcP = (const SkPMColor16*)src; - const SkUnPreMultiply::Scale* SK_RESTRICT table = - SkUnPreMultiply::GetScaleTable(); - - for (int i = 0; i < width; i++) { - SkPMColor16 c = *srcP++; - unsigned a = SkPacked4444ToA32(c); - unsigned r = SkPacked4444ToR32(c); - unsigned g = SkPacked4444ToG32(c); - unsigned b = SkPacked4444ToB32(c); - - 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; - } -} - -static void transform_scanline_index8(const char* SK_RESTRICT src, int width, - char* SK_RESTRICT dst) { - memcpy(dst, src, width); -} - static transform_scanline_proc choose_proc(SkBitmap::Config config, bool hasAlpha) { // we don't care about search on alpha if we're kIndex8, since only the @@ -614,7 +522,7 @@ static transform_scanline_proc choose_proc(SkBitmap::Config config, { SkBitmap::kARGB_8888_Config, true, transform_scanline_8888 }, { SkBitmap::kARGB_4444_Config, false, transform_scanline_444 }, { SkBitmap::kARGB_4444_Config, true, transform_scanline_4444 }, - { SkBitmap::kIndex8_Config, false, transform_scanline_index8 }, + { SkBitmap::kIndex8_Config, false, transform_scanline_memcpy }, }; for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { diff --git a/src/images/transform_scanline.h b/src/images/transform_scanline.h new file mode 100644 index 0000000000..36efdd84ea --- /dev/null +++ b/src/images/transform_scanline.h @@ -0,0 +1,140 @@ + +/* + * Copyright 2012 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Functions to transform scanlines between packed-pixel formats. + */ + +#include "SkBitmap.h" +#include "SkColor.h" +#include "SkColorPriv.h" +#include "SkPreConfig.h" +#include "SkUnPreMultiply.h" + +/** + * Function template for transforming scanlines. + * Transform 'width' pixels from 'src' buffer into 'dst' buffer, + * repacking color channel data as appropriate for the given transformation. + */ +typedef void (*transform_scanline_proc)(const char* SK_RESTRICT src, + int width, char* SK_RESTRICT dst); + +/** + * Identity transformation: just copy bytes from src to dst. + */ +static void transform_scanline_memcpy(const char* SK_RESTRICT src, int width, + char* SK_RESTRICT dst) { + memcpy(dst, src, width); +} + +/** + * Transform from kRGB_565_Config to 3-bytes-per-pixel RGB. + * Alpha channel data is not present in kRGB_565_Config format, so there is no + * alpha channel data to preserve. + */ +static void transform_scanline_565(const char* SK_RESTRICT src, int width, + char* SK_RESTRICT dst) { + const uint16_t* SK_RESTRICT srcP = (const uint16_t*)src; + for (int i = 0; i < width; i++) { + unsigned c = *srcP++; + *dst++ = SkPacked16ToR32(c); + *dst++ = SkPacked16ToG32(c); + *dst++ = SkPacked16ToB32(c); + } +} + +/** + * Transform from kARGB_8888_Config to 3-bytes-per-pixel RGB. + * Alpha channel data, if any, is abandoned. + */ +static void transform_scanline_888(const char* SK_RESTRICT src, int width, + char* SK_RESTRICT dst) { + const SkPMColor* SK_RESTRICT srcP = (const SkPMColor*)src; + for (int i = 0; i < width; i++) { + SkPMColor c = *srcP++; + *dst++ = SkGetPackedR32(c); + *dst++ = SkGetPackedG32(c); + *dst++ = SkGetPackedB32(c); + } +} + +/** + * Transform from kARGB_4444_Config to 3-bytes-per-pixel RGB. + * Alpha channel data, if any, is abandoned. + */ +static void transform_scanline_444(const char* SK_RESTRICT src, int width, + char* SK_RESTRICT dst) { + const SkPMColor16* SK_RESTRICT srcP = (const SkPMColor16*)src; + for (int i = 0; i < width; i++) { + SkPMColor16 c = *srcP++; + *dst++ = SkPacked4444ToR32(c); + *dst++ = SkPacked4444ToG32(c); + *dst++ = SkPacked4444ToB32(c); + } +} + +/** + * Transform from kARGB_8888_Config to 4-bytes-per-pixel RGBA. + * (This would be the identity transformation, except for byte-order and + * scaling of RGB based on alpha channel). + */ +static void transform_scanline_8888(const char* SK_RESTRICT src, int width, + char* SK_RESTRICT dst) { + const SkPMColor* SK_RESTRICT srcP = (const SkPMColor*)src; + const SkUnPreMultiply::Scale* SK_RESTRICT table = + SkUnPreMultiply::GetScaleTable(); + + for (int i = 0; i < width; i++) { + SkPMColor c = *srcP++; + unsigned a = SkGetPackedA32(c); + unsigned r = SkGetPackedR32(c); + unsigned g = SkGetPackedG32(c); + unsigned b = SkGetPackedB32(c); + + 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 kARGB_8888_Config to 4-bytes-per-pixel RGBA, + * with scaling of RGB based on alpha channel. + */ +static void transform_scanline_4444(const char* SK_RESTRICT src, int width, + char* SK_RESTRICT dst) { + const SkPMColor16* SK_RESTRICT srcP = (const SkPMColor16*)src; + const SkUnPreMultiply::Scale* SK_RESTRICT table = + SkUnPreMultiply::GetScaleTable(); + + for (int i = 0; i < width; i++) { + SkPMColor16 c = *srcP++; + unsigned a = SkPacked4444ToA32(c); + unsigned r = SkPacked4444ToR32(c); + unsigned g = SkPacked4444ToG32(c); + unsigned b = SkPacked4444ToB32(c); + + 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; + } +} |