blob: 6c861cd04bc261c52e35c1d1769703c295b8e611 [file] [log] [blame]
epoger@google.com31114c62012-12-12 17:22:23 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkBitmap.h"
epoger@google.com908f5832013-04-12 02:23:55 +00009#include "SkBitmapHasher.h"
epoger@google.com31114c62012-12-12 17:22:23 +000010#include "SkEndian.h"
bungeman@google.com8c6a4f22013-04-23 18:06:23 +000011#include "SkImageEncoder.h"
epoger@google.comb4ca46d2013-05-03 17:35:39 +000012
epoger@google.comb4ca46d2013-05-03 17:35:39 +000013#include "SkMD5.h"
epoger@google.com31114c62012-12-12 17:22:23 +000014
15/**
epoger@google.comb4ca46d2013-05-03 17:35:39 +000016 * Write an int32 value to a stream in little-endian order.
epoger@google.com31114c62012-12-12 17:22:23 +000017 */
epoger@google.comb4ca46d2013-05-03 17:35:39 +000018static void write_int32_to_buffer(uint32_t val, SkWStream* out) {
epoger@google.com31114c62012-12-12 17:22:23 +000019 val = SkEndian_SwapLE32(val);
bungeman@google.com8c6a4f22013-04-23 18:06:23 +000020 for (size_t byte = 0; byte < 4; ++byte) {
21 out->write8((uint8_t)(val & 0xff));
epoger@google.com31114c62012-12-12 17:22:23 +000022 val = val >> 8;
23 }
24}
25
epoger@google.comb4ca46d2013-05-03 17:35:39 +000026/**
27 * Return the first 8 bytes of a bytearray, encoded as a little-endian uint64.
28 */
29static inline uint64_t first_8_bytes_as_uint64(const uint8_t *bytearray) {
30 return SkEndian_SwapLE64(*(reinterpret_cast<const uint64_t *>(bytearray)));
31}
32
epoger@google.comd4993ff2013-05-24 14:33:28 +000033/*static*/ bool SkBitmapHasher::ComputeDigestInternal(const SkBitmap& bitmap, uint64_t *result) {
epoger@google.comb4ca46d2013-05-03 17:35:39 +000034 SkMD5 out;
bungeman@google.com8c6a4f22013-04-23 18:06:23 +000035
epoger@google.com31114c62012-12-12 17:22:23 +000036 // start with the x/y dimensions
epoger@google.comb4ca46d2013-05-03 17:35:39 +000037 write_int32_to_buffer(SkToU32(bitmap.width()), &out);
38 write_int32_to_buffer(SkToU32(bitmap.height()), &out);
epoger@google.com31114c62012-12-12 17:22:23 +000039
40 // add all the pixel data
bungeman@google.com8c6a4f22013-04-23 18:06:23 +000041 SkAutoTDelete<SkImageEncoder> enc(CreateARGBImageEncoder());
42 if (!enc->encodeStream(&out, bitmap, SkImageEncoder::kDefaultQuality)) {
epoger@google.com908f5832013-04-12 02:23:55 +000043 return false;
epoger@google.com31114c62012-12-12 17:22:23 +000044 }
bungeman@google.com8c6a4f22013-04-23 18:06:23 +000045
epoger@google.comb4ca46d2013-05-03 17:35:39 +000046 SkMD5::Digest digest;
47 out.finish(digest);
48 *result = first_8_bytes_as_uint64(digest.data);
epoger@google.com908f5832013-04-12 02:23:55 +000049 return true;
epoger@google.com31114c62012-12-12 17:22:23 +000050}
51
epoger@google.comd4993ff2013-05-24 14:33:28 +000052/*static*/ bool SkBitmapHasher::ComputeDigest(const SkBitmap& bitmap, uint64_t *result) {
bungeman@google.com8c6a4f22013-04-23 18:06:23 +000053 if (ComputeDigestInternal(bitmap, result)) {
54 return true;
epoger@google.com31114c62012-12-12 17:22:23 +000055 }
56
57 // Hmm, that didn't work. Maybe if we create a new
58 // kARGB_8888_Config version of the bitmap it will work better?
59 SkBitmap copyBitmap;
commit-bot@chromium.org757ebd22014-04-10 22:36:34 +000060 if (!bitmap.copyTo(&copyBitmap, kPMColor_SkColorType)) {
epoger@google.com908f5832013-04-12 02:23:55 +000061 return false;
epoger@google.com31114c62012-12-12 17:22:23 +000062 }
bungeman@google.com8c6a4f22013-04-23 18:06:23 +000063 return ComputeDigestInternal(copyBitmap, result);
epoger@google.com31114c62012-12-12 17:22:23 +000064}