Home | History | Annotate | Download | only in utils
      1 /*
      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"
      9 #include "SkBitmapHasher.h"
     10 #include "SkEndian.h"
     11 #include "SkImageEncoder.h"
     12 
     13 #include "SkMD5.h"
     14 
     15 /**
     16  * Write an int32 value to a stream in little-endian order.
     17  */
     18 static void write_int32_to_buffer(uint32_t val, SkWStream* out) {
     19     val = SkEndian_SwapLE32(val);
     20     for (size_t byte = 0; byte < 4; ++byte) {
     21         out->write8((uint8_t)(val & 0xff));
     22         val = val >> 8;
     23     }
     24 }
     25 
     26 /**
     27  * Return the first 8 bytes of a bytearray, encoded as a little-endian uint64.
     28  */
     29 static inline uint64_t first_8_bytes_as_uint64(const uint8_t *bytearray) {
     30     return SkEndian_SwapLE64(*(reinterpret_cast<const uint64_t *>(bytearray)));
     31 }
     32 
     33 /*static*/ bool SkBitmapHasher::ComputeDigestInternal(const SkBitmap& bitmap, uint64_t *result) {
     34     SkMD5 out;
     35 
     36     // start with the x/y dimensions
     37     write_int32_to_buffer(SkToU32(bitmap.width()), &out);
     38     write_int32_to_buffer(SkToU32(bitmap.height()), &out);
     39 
     40     // add all the pixel data
     41     SkAutoTDelete<SkImageEncoder> enc(CreateARGBImageEncoder());
     42     if (!enc->encodeStream(&out, bitmap, SkImageEncoder::kDefaultQuality)) {
     43         return false;
     44     }
     45 
     46     SkMD5::Digest digest;
     47     out.finish(digest);
     48     *result = first_8_bytes_as_uint64(digest.data);
     49     return true;
     50 }
     51 
     52 /*static*/ bool SkBitmapHasher::ComputeDigest(const SkBitmap& bitmap, uint64_t *result) {
     53     if (ComputeDigestInternal(bitmap, result)) {
     54         return true;
     55     }
     56 
     57     // Hmm, that didn't work. Maybe if we create a new
     58     // version of the bitmap it will work better?
     59     SkBitmap copyBitmap;
     60     if (!bitmap.copyTo(&copyBitmap, kN32_SkColorType)) {
     61         return false;
     62     }
     63     return ComputeDigestInternal(copyBitmap, result);
     64 }
     65