aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils/SkBitmapChecksummer.cpp
blob: 883210c360059dd6fc0ad41f01f2f8be0c7967a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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) {
    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 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(&copyBitmap, SkBitmap::kARGB_8888_Config);
    const SkBitmapTransformer copyTransformer =
        SkBitmapTransformer(copyBitmap, kPixelFormat);
    if (copyTransformer.isValid(true)) {
        return Compute64Internal(copyBitmap, copyTransformer);
    } else {
        return 0;
    }
}