Create SkBitmapChecksummer and associated SkBitmapTransformer
As needed to start capturing gm image checksums.
Review URL: https://codereview.appspot.com/6920050
git-svn-id: http://skia.googlecode.com/svn/trunk@6759 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/utils/SkBitmapChecksummer.cpp b/src/utils/SkBitmapChecksummer.cpp
new file mode 100644
index 0000000..bb9fc8d
--- /dev/null
+++ b/src/utils/SkBitmapChecksummer.cpp
@@ -0,0 +1,69 @@
+
+/*
+ * 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 "SkBitmapChecksummer.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*/ uint64_t SkBitmapChecksummer::Compute64Internal(
+ const SkBitmap& bitmap, const SkBitmapTransformer& transformer) {
+ int pixelBufferSize = transformer.bytesNeededTotal();
+ int 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 0;
+ }
+ return SkCityHash::Compute64(bufferStart, totalBufferSize);
+}
+
+/*static*/ uint64_t SkBitmapChecksummer::Compute64(const SkBitmap& bitmap) {
+ 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 Compute64Internal(bitmap, transformer);
+ }
+
+ // 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 Compute64Internal(copyBitmap, copyTransformer);
+ } else {
+ return 0;
+ }
+}