diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/images/SkImageEncoder_argb.cpp | 119 | ||||
-rw-r--r-- | src/utils/SkBitmapHasher.cpp | 51 | ||||
-rw-r--r-- | src/utils/SkBitmapHasher.h | 5 | ||||
-rw-r--r-- | src/utils/SkBitmapTransformer.cpp | 87 | ||||
-rw-r--r-- | src/utils/SkBitmapTransformer.h | 104 | ||||
-rw-r--r-- | src/utils/SkMD5.h | 2 | ||||
-rw-r--r-- | src/utils/SkSHA1.h | 2 |
7 files changed, 143 insertions, 227 deletions
diff --git a/src/images/SkImageEncoder_argb.cpp b/src/images/SkImageEncoder_argb.cpp new file mode 100644 index 0000000000..5abc23ce6f --- /dev/null +++ b/src/images/SkImageEncoder_argb.cpp @@ -0,0 +1,119 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkImageEncoder.h" +#include "SkBitmap.h" +#include "SkColorPriv.h" +#include "SkStream.h" +#include "SkTemplates.h" + +class SkARGBImageEncoder : public SkImageEncoder { +protected: + virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK_OVERRIDE; + +private: + typedef SkImageEncoder INHERITED; +}; + +typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* argb, int width, + const SkPMColor* SK_RESTRICT ctable); + +static void ARGB_8888_To_ARGB(const uint8_t* in, uint8_t* argb, int width, const SkPMColor*) { + const uint32_t* SK_RESTRICT src = (const uint32_t*)in; + for (int i = 0; i < width; ++i) { + const uint32_t c = *src++; + argb[0] = SkGetPackedA32(c); + argb[1] = SkGetPackedR32(c); + argb[2] = SkGetPackedG32(c); + argb[3] = SkGetPackedB32(c); + argb += 4; + } +} + +static void RGB_565_To_ARGB(const uint8_t* in, uint8_t* argb, int width, const SkPMColor*) { + const uint16_t* SK_RESTRICT src = (const uint16_t*)in; + for (int i = 0; i < width; ++i) { + const uint16_t c = *src++; + argb[0] = 0xFF; + argb[1] = SkPacked16ToR32(c); + argb[2] = SkPacked16ToG32(c); + argb[3] = SkPacked16ToB32(c); + argb += 4; + } +} + +static void ARGB_4444_To_ARGB(const uint8_t* in, uint8_t* argb, int width, const SkPMColor*) { + const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; + for (int i = 0; i < width; ++i) { + const SkPMColor16 c = *src++; + argb[0] = SkPacked4444ToA32(c); + argb[1] = SkPacked4444ToR32(c); + argb[2] = SkPacked4444ToG32(c); + argb[3] = SkPacked4444ToB32(c); + argb += 4; + } +} + +static void Index8_To_ARGB(const uint8_t* in, uint8_t* argb, int width, + const SkPMColor* SK_RESTRICT ctable) { + const uint8_t* SK_RESTRICT src = (const uint8_t*)in; + for (int i = 0; i < width; ++i) { + const uint32_t c = ctable[*src++]; + argb[0] = SkGetPackedA32(c); + argb[1] = SkGetPackedR32(c); + argb[2] = SkGetPackedG32(c); + argb[3] = SkGetPackedB32(c); + argb += 4; + } +} + +static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) { + switch (config) { + case SkBitmap::kARGB_8888_Config: + return ARGB_8888_To_ARGB; + case SkBitmap::kRGB_565_Config: + return RGB_565_To_ARGB; + case SkBitmap::kARGB_4444_Config: + return ARGB_4444_To_ARGB; + case SkBitmap::kIndex8_Config: + return Index8_To_ARGB; + default: + return NULL; + } +} + +bool SkARGBImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) { + const SkBitmap::Config config = bitmap.getConfig(); + const ScanlineImporter scanline_import = ChooseImporter(config); + if (NULL == scanline_import) { + return false; + } + + SkAutoLockPixels alp(bitmap); + const uint8_t* src = (uint8_t*)bitmap.getPixels(); + if (NULL == bitmap.getPixels()) { + return false; + } + + SkAutoLockColors ctLocker; + const SkPMColor* colors = ctLocker.lockColors(bitmap); + + const int argbStride = bitmap.width() * 4; + SkAutoTDeleteArray<uint8_t> ada(new uint8_t[argbStride]); + uint8_t* argb = ada.get(); + for (int y = 0; y < bitmap.height(); ++y) { + scanline_import(src + y * bitmap.rowBytes(), argb, bitmap.width(), colors); + stream->write(argb, argbStride); + } + + return true; +} + + +/////////////////////////////////////////////////////////////////////////////// +DEFINE_ENCODER_CREATOR(ARGBImageEncoder); +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/utils/SkBitmapHasher.cpp b/src/utils/SkBitmapHasher.cpp index 6df3ab9f27..e8352e59b9 100644 --- a/src/utils/SkBitmapHasher.cpp +++ b/src/utils/SkBitmapHasher.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2012 Google Inc. * @@ -8,63 +7,55 @@ #include "SkBitmap.h" #include "SkBitmapHasher.h" -#include "SkBitmapTransformer.h" #include "SkCityHash.h" #include "SkEndian.h" +#include "SkImageEncoder.h" +#include "SkStream.h" /** - * Write an integer value into a bytebuffer in little-endian order. + * Write an integer value to a stream in little-endian order. */ -static void write_int_to_buffer(int val, char* buf) { +static void write_int_to_buffer(uint32_t val, SkWStream* out) { val = SkEndian_SwapLE32(val); - for (int byte=0; byte<4; byte++) { - *buf++ = (char)(val & 0xff); + for (size_t byte = 0; byte < 4; ++byte) { + out->write8((uint8_t)(val & 0xff)); val = val >> 8; } } -/*static*/ bool SkBitmapHasher::ComputeDigestInternal( - const SkBitmap& bitmap, const SkBitmapTransformer& transformer, SkHashDigest *result) { - size_t pixelBufferSize = transformer.bytesNeededTotal(); - size_t totalBufferSize = pixelBufferSize + 8; // leave room for x/y dimensions +/*static*/ bool SkBitmapHasher::ComputeDigestInternal(const SkBitmap& bitmap, + SkHashDigest *result) { + size_t pixelBufferSize = bitmap.width() * bitmap.height() * 4; + size_t totalBufferSize = pixelBufferSize + 2 * sizeof(uint32_t); SkAutoMalloc bufferManager(totalBufferSize); char *bufferStart = static_cast<char *>(bufferManager.get()); - char *bufPtr = bufferStart; + SkMemoryWStream out(bufferStart, totalBufferSize); + // start with the x/y dimensions - write_int_to_buffer(bitmap.width(), bufPtr); - bufPtr += 4; - write_int_to_buffer(bitmap.height(), bufPtr); - bufPtr += 4; + write_int_to_buffer(SkToU32(bitmap.width()), &out); + write_int_to_buffer(SkToU32(bitmap.height()), &out); // add all the pixel data - if (!transformer.copyBitmapToPixelBuffer(bufPtr, pixelBufferSize)) { + SkAutoTDelete<SkImageEncoder> enc(CreateARGBImageEncoder()); + if (!enc->encodeStream(&out, bitmap, SkImageEncoder::kDefaultQuality)) { return false; } + *result = SkCityHash::Compute64(bufferStart, totalBufferSize); return true; } /*static*/ bool SkBitmapHasher::ComputeDigest(const SkBitmap& bitmap, SkHashDigest *result) { - const SkBitmapTransformer::PixelFormat kPixelFormat = - SkBitmapTransformer::kARGB_8888_Premul_PixelFormat; - - // First, try to transform the existing bitmap. - const SkBitmapTransformer transformer = - SkBitmapTransformer(bitmap, kPixelFormat); - if (transformer.isValid(false)) { - return ComputeDigestInternal(bitmap, transformer, result); + if (ComputeDigestInternal(bitmap, result)) { + return true; } // Hmm, that didn't work. Maybe if we create a new // kARGB_8888_Config version of the bitmap it will work better? SkBitmap copyBitmap; - bitmap.copyTo(©Bitmap, SkBitmap::kARGB_8888_Config); - const SkBitmapTransformer copyTransformer = - SkBitmapTransformer(copyBitmap, kPixelFormat); - if (copyTransformer.isValid(true)) { - return ComputeDigestInternal(copyBitmap, copyTransformer, result); - } else { + if (!bitmap.copyTo(©Bitmap, SkBitmap::kARGB_8888_Config)) { return false; } + return ComputeDigestInternal(copyBitmap, result); } diff --git a/src/utils/SkBitmapHasher.h b/src/utils/SkBitmapHasher.h index dc8685bddb..165da3dcc8 100644 --- a/src/utils/SkBitmapHasher.h +++ b/src/utils/SkBitmapHasher.h @@ -10,7 +10,6 @@ #define SkBitmapHasher_DEFINED #include "SkBitmap.h" -#include "SkBitmapTransformer.h" // TODO(epoger): Soon, SkHashDigest will become a real class of its own, // and callers won't be able to assume it converts to/from a uint64_t. @@ -34,9 +33,7 @@ public: static bool ComputeDigest(const SkBitmap& bitmap, SkHashDigest *result); private: - static bool ComputeDigestInternal(const SkBitmap& bitmap, - const SkBitmapTransformer& transformer, - SkHashDigest *result); + static bool ComputeDigestInternal(const SkBitmap& bitmap, SkHashDigest *result); }; #endif diff --git a/src/utils/SkBitmapTransformer.cpp b/src/utils/SkBitmapTransformer.cpp deleted file mode 100644 index c8356d4238..0000000000 --- a/src/utils/SkBitmapTransformer.cpp +++ /dev/null @@ -1,87 +0,0 @@ - -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkBitmap.h" -#include "SkBitmapTransformer.h" -#include "SkColorPriv.h" -#include "SkTypes.h" - -bool SkBitmapTransformer::isValid(bool logReason) const { - bool retval = true; - - switch(fPixelFormat) { - case kARGB_8888_Premul_PixelFormat: - break; - default: - if (logReason) { - SkDEBUGF(("PixelFormat %d not supported\n", fPixelFormat)); - } - retval = false; - } - - SkBitmap::Config bitmapConfig = fBitmap.config(); - switch(bitmapConfig) { - case SkBitmap::kARGB_8888_Config: - break; - default: - if (logReason) { - SkDEBUGF(("SkBitmap::Config %d not supported\n", bitmapConfig)); - } - retval = false; - } - - return retval; -} - -/** - * Transform from kARGB_8888_Config to kARGB_8888_Premul_PixelFormat. - * - * Similar to the various scanline transformers in - * src/images/transform_scanline.h . - */ -static void transform_scanline(const char* SK_RESTRICT src, int width, - char* SK_RESTRICT dst) { - const SkPMColor* SK_RESTRICT srcP = reinterpret_cast<const SkPMColor*>(src); - 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); - *dst++ = a; - *dst++ = r; - *dst++ = g; - *dst++ = b; - } -} - -bool SkBitmapTransformer::copyBitmapToPixelBuffer(void *dstBuffer, - size_t dstBufferSize) const { - if (!this->isValid(true)) { - return false; - } - size_t bytesNeeded = this->bytesNeededTotal(); - if (dstBufferSize < bytesNeeded) { - SkDEBUGF(("dstBufferSize %d must be >= %d\n", dstBufferSize, bytesNeeded)); - return false; - } - - fBitmap.lockPixels(); - int width = fBitmap.width(); - size_t srcRowBytes = fBitmap.rowBytes(); - size_t dstRowBytes = this->bytesNeededPerRow(); - const char *srcBytes = const_cast<const char *>(static_cast<char*>(fBitmap.getPixels())); - char *dstBytes = static_cast<char *>(dstBuffer); - for (int y = 0; y < fBitmap.height(); y++) { - transform_scanline(srcBytes, width, dstBytes); - srcBytes += srcRowBytes; - dstBytes += dstRowBytes; - } - fBitmap.unlockPixels(); - return true; -} diff --git a/src/utils/SkBitmapTransformer.h b/src/utils/SkBitmapTransformer.h deleted file mode 100644 index 70971ac625..0000000000 --- a/src/utils/SkBitmapTransformer.h +++ /dev/null @@ -1,104 +0,0 @@ - -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkBitmapTransformer_DEFINED -#define SkBitmapTransformer_DEFINED - -#include "SkBitmap.h" - -/** - * Class that can copy pixel data out of an SkBitmap, transforming it - * into the appropriate PixelFormat. - * - * As noted in https://codereview.appspot.com/6849119/#msg6 and - * https://codereview.appspot.com/6900047 , at some point we might want - * to make this more general purpose: - * - support more PixelFormats - * - use existing SkCanvas::Config8888 enum instead of new PixelFormat enum - * - add method to copy pixel data for a single row, instead of the whole bitmap - * - add methods to copy pixel data INTO an SkBitmap - * - * That would allow us to replace SkCopyConfig8888ToBitmap() in - * src/core/SkConfig8888.h , as well as the transformations used by - * src/images/SkImageDecoder_libpng.cpp , with this common code. - * - * But for now, we want something more narrowly targeted, just - * supplying what is needed by SkBitmapChecksummer. - */ -class SkBitmapTransformer { -public: - enum PixelFormat { - // 32 bits per pixel, ARGB byte order, with the alpha-channel - // value premultiplied into the R/G/B channel values. - kARGB_8888_Premul_PixelFormat, - - // marks the end of the list - kLast_PixelFormat = kARGB_8888_Premul_PixelFormat, - }; - - /** - * Creates an SkBitmapTransformer instance that can transform between - * the given bitmap and a pixel buffer with given pixelFormat. - * - * Call IsValid() before using, to confirm that this particular - * bitmap/pixelFormat combination is supported! - */ - SkBitmapTransformer(const SkBitmap& bitmap, PixelFormat pixelFormat) : - fBitmap(bitmap), fPixelFormat(pixelFormat) {} - - /** - * Returns true iff we can convert between fBitmap and fPixelFormat. - * If this returns false, the return values of any other methods will - * be meaningless! - * - * @param logReason whether to log the reason why this combination - * is unsupported (only applies in debug mode) - */ - bool isValid(bool logReason=false) const; - - /** - * Returns the number of bytes needed to store a single row of the - * bitmap's pixels if converted to pixelFormat. - */ - size_t bytesNeededPerRow() const { - // This is hard-coded for the single supported PixelFormat. - return fBitmap.width() * 4; - } - - /** - * Returns the number of bytes needed to store the entire bitmap - * if converted to pixelFormat, ASSUMING that it is written - * out as a single contiguous blob of pixels (no leftover bytes - * at the end of each row). - */ - size_t bytesNeededTotal() const { - return this->bytesNeededPerRow() * fBitmap.height(); - } - - /** - * Writes the entire bitmap into dstBuffer, using the already-specified - * pixelFormat. Returns true if successful. - * - * dstBufferSize is the maximum allowable bytes to write into dstBuffer; - * if that is not large enough to hold the entire bitmap, then this - * will fail immediately and return false. - * We force the caller to pass this in to avoid buffer overruns in - * unanticipated cases. - * - * All pixels for all rows will be written into dstBuffer as a - * single contiguous blob (no skipped pixels at the end of each - * row). - */ - bool copyBitmapToPixelBuffer (void *dstBuffer, size_t dstBufferSize) const; - -private: - const SkBitmap& fBitmap; - const PixelFormat fPixelFormat; -}; - -#endif diff --git a/src/utils/SkMD5.h b/src/utils/SkMD5.h index 6fbdb46b44..6b4fc53636 100644 --- a/src/utils/SkMD5.h +++ b/src/utils/SkMD5.h @@ -17,7 +17,7 @@ //SK_CPU_LENDIAN allows 32 bit <=> 8 bit conversions without copies (if alligned). //SK_CPU_FAST_UNALIGNED_ACCESS allows 32 bit <=> 8 bit conversions without copies if SK_CPU_LENDIAN. -class SkMD5 : SkWStream { +class SkMD5 : public SkWStream { public: SkMD5(); diff --git a/src/utils/SkSHA1.h b/src/utils/SkSHA1.h index 10bbc43c50..cf2cb8c679 100644 --- a/src/utils/SkSHA1.h +++ b/src/utils/SkSHA1.h @@ -17,7 +17,7 @@ //SK_CPU_BENDIAN allows 32 bit <=> 8 bit conversions without copies (if alligned). //SK_CPU_FAST_UNALIGNED_ACCESS allows 32 bit <=> 8 bit conversions without copies if SK_CPU_BENDIAN. -class SkSHA1 : SkWStream { +class SkSHA1 : public SkWStream { public: SkSHA1(); |