rename SkBitmapChecksummer as SkBitmapHasher, and prepare for it to possibly use
some algorithm other than CityHash
Review URL: https://codereview.chromium.org/14170010
git-svn-id: http://skia.googlecode.com/svn/trunk@8639 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/utils/SkBitmapHasher.cpp b/src/utils/SkBitmapHasher.cpp
new file mode 100644
index 0000000..6df3ab9
--- /dev/null
+++ b/src/utils/SkBitmapHasher.cpp
@@ -0,0 +1,70 @@
+
+/*
+ * 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 "SkBitmapHasher.h"
+#include "SkBitmapTransformer.h"
+#include "SkCityHash.h"
+#include "SkEndian.h"
+
+/**
+ * Write an integer value into a bytebuffer in little-endian order.
+ */
+static void write_int_to_buffer(int val, char* buf) {
+ val = SkEndian_SwapLE32(val);
+ for (int byte=0; byte<4; byte++) {
+ *buf++ = (char)(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
+
+ SkAutoMalloc bufferManager(totalBufferSize);
+ char *bufferStart = static_cast<char *>(bufferManager.get());
+ char *bufPtr = bufferStart;
+ // start with the x/y dimensions
+ write_int_to_buffer(bitmap.width(), bufPtr);
+ bufPtr += 4;
+ write_int_to_buffer(bitmap.height(), bufPtr);
+ bufPtr += 4;
+
+ // add all the pixel data
+ if (!transformer.copyBitmapToPixelBuffer(bufPtr, pixelBufferSize)) {
+ 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);
+ }
+
+ // 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 {
+ return false;
+ }
+}