1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "printing/image.h"
11 #include "base/files/file_util.h"
12 #include "base/hash/md5.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "printing/metafile.h"
16 #include "third_party/skia/include/core/SkColor.h"
17 #include "ui/gfx/codec/png_codec.h"
21 Image::Image(const Metafile& metafile) : row_length_(0), ignore_alpha_(true) {
22 LoadMetafile(metafile);
25 Image::Image(const Image& image) = default;
27 Image::~Image() = default;
29 std::string Image::checksum() const {
30 base::MD5Digest digest;
31 base::MD5Sum(&data_[0], data_.size(), &digest);
32 return base::MD5DigestToBase16(digest);
35 bool Image::SaveToPng(const base::FilePath& filepath) const {
36 DCHECK(!data_.empty());
37 std::vector<unsigned char> compressed;
38 bool success = gfx::PNGCodec::Encode(
39 &*data_.begin(), gfx::PNGCodec::FORMAT_BGRA, size_, row_length_, true,
40 std::vector<gfx::PNGCodec::Comment>(), &compressed);
41 DCHECK(success && compressed.size());
43 success = base::WriteFile(filepath, compressed);
49 double Image::PercentageDifferent(const Image& rhs) const {
50 if (size_.width() == 0 || size_.height() == 0 || rhs.size_.width() == 0 ||
51 rhs.size_.height() == 0)
54 int width = std::min(size_.width(), rhs.size_.width());
55 int height = std::min(size_.height(), rhs.size_.height());
56 // Compute pixels different in the overlap
57 int pixels_different = 0;
58 for (int y = 0; y < height; ++y) {
59 for (int x = 0; x < width; ++x) {
60 uint32_t lhs_pixel = pixel_at(x, y);
61 uint32_t rhs_pixel = rhs.pixel_at(x, y);
62 if (lhs_pixel != rhs_pixel)
66 // Look for extra right lhs pixels. They should be white.
67 for (int x = width; x < size_.width(); ++x) {
68 uint32_t lhs_pixel = pixel_at(x, y);
69 if (lhs_pixel != Color(SK_ColorWHITE))
73 // Look for extra right rhs pixels. They should be white.
74 for (int x = width; x < rhs.size_.width(); ++x) {
75 uint32_t rhs_pixel = rhs.pixel_at(x, y);
76 if (rhs_pixel != Color(SK_ColorWHITE))
81 // Look for extra bottom lhs pixels. They should be white.
82 for (int y = height; y < size_.height(); ++y) {
83 for (int x = 0; x < size_.width(); ++x) {
84 uint32_t lhs_pixel = pixel_at(x, y);
85 if (lhs_pixel != Color(SK_ColorWHITE))
90 // Look for extra bottom rhs pixels. They should be white.
91 for (int y = height; y < rhs.size_.height(); ++y) {
92 for (int x = 0; x < rhs.size_.width(); ++x) {
93 uint32_t rhs_pixel = rhs.pixel_at(x, y);
94 if (rhs_pixel != Color(SK_ColorWHITE))
99 // Like the WebKit ImageDiff tool, we define percentage different in terms
100 // of the size of the 'actual' bitmap.
101 double total_pixels =
102 static_cast<double>(size_.width()) * static_cast<double>(height);
103 return static_cast<double>(pixels_different) / total_pixels * 100.;
106 bool Image::LoadPng(const std::string& compressed) {
109 bool success = gfx::PNGCodec::Decode(
110 reinterpret_cast<const unsigned char*>(compressed.c_str()),
111 compressed.size(), gfx::PNGCodec::FORMAT_BGRA, &data_, &w, &h);
113 row_length_ = size_.width() * sizeof(uint32_t);
117 } // namespace printing