1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/test/pixel_test_utils.h"
6
7#include <string>
8#include <vector>
9
10#include "base/base64.h"
11#include "base/files/file_util.h"
12#include "base/logging.h"
13#include "third_party/skia/include/core/SkBitmap.h"
14#include "ui/gfx/codec/png_codec.h"
15
16namespace cc {
17
18bool WritePNGFile(const SkBitmap& bitmap, const base::FilePath& file_path,
19    bool discard_transparency) {
20  std::vector<unsigned char> png_data;
21  if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap,
22                                        discard_transparency,
23                                        &png_data) &&
24      base::CreateDirectory(file_path.DirName())) {
25    char* data = reinterpret_cast<char*>(&png_data[0]);
26    int size = static_cast<int>(png_data.size());
27    return base::WriteFile(file_path, data, size) == size;
28  }
29  return false;
30}
31
32std::string GetPNGDataUrl(const SkBitmap& bitmap) {
33  std::vector<unsigned char> png_data;
34  gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &png_data);
35  std::string data_url;
36  data_url.insert(data_url.end(), png_data.begin(), png_data.end());
37  base::Base64Encode(data_url, &data_url);
38  data_url.insert(0, "data:image/png;base64,");
39
40  return data_url;
41}
42
43bool ReadPNGFile(const base::FilePath& file_path, SkBitmap* bitmap) {
44  DCHECK(bitmap);
45  std::string png_data;
46  return base::ReadFileToString(file_path, &png_data) &&
47         gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&png_data[0]),
48                               png_data.length(),
49                               bitmap);
50}
51
52bool MatchesPNGFile(const SkBitmap& gen_bmp, base::FilePath ref_img_path,
53                    const PixelComparator& comparator) {
54  SkBitmap ref_bmp;
55  if (!ReadPNGFile(ref_img_path, &ref_bmp)) {
56    LOG(ERROR) << "Cannot read reference image: " << ref_img_path.value();
57    return false;
58  }
59
60  // Check if images size matches
61  if (gen_bmp.width() != ref_bmp.width() ||
62      gen_bmp.height() != ref_bmp.height()) {
63    LOG(ERROR)
64        << "Dimensions do not match! "
65        << "Actual: " << gen_bmp.width() << "x" << gen_bmp.height()
66        << "; "
67        << "Expected: " << ref_bmp.width() << "x" << ref_bmp.height();
68    return false;
69  }
70
71  // Shortcut for empty images. They are always equal.
72  if (gen_bmp.width() == 0 || gen_bmp.height() == 0)
73    return true;
74
75  bool compare = comparator.Compare(gen_bmp, ref_bmp);
76  if (!compare) {
77    std::string gen_bmp_data_url = GetPNGDataUrl(gen_bmp);
78    std::string ref_bmp_data_url = GetPNGDataUrl(ref_bmp);
79    LOG(ERROR) << "Pixels do not match!";
80    LOG(ERROR) << "Actual: " << gen_bmp_data_url;
81    LOG(ERROR) << "Expected: " << ref_bmp_data_url;
82  }
83  return compare;
84}
85
86}  // namespace cc
87