blob: 1116f32e958c0b44e409284053cbe3e8c2b2c72d [file] [log] [blame]
[email protected]48091b02010-10-21 02:38:111// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]19478682009-07-13 16:11:082// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "printing/image.h"
6
7#include "base/file_util.h"
[email protected]aa82249f2009-07-16 17:23:588#include "base/md5.h"
[email protected]e83326f2010-07-31 17:29:259#include "base/string_number_conversions.h"
[email protected]48091b02010-10-21 02:38:1110#include "third_party/skia/include/core/SkColor.h"
[email protected]08397d52011-02-05 01:53:3811#include "ui/gfx/codec/png_codec.h"
[email protected]aa82249f2009-07-16 17:23:5812
13namespace printing {
14
[email protected]63597e4e2010-07-08 17:49:0515Image::Image(const FilePath& path)
[email protected]aa82249f2009-07-16 17:23:5816 : row_length_(0),
17 ignore_alpha_(true) {
[email protected]19478682009-07-13 16:11:0818 std::string data;
[email protected]63597e4e2010-07-08 17:49:0519 file_util::ReadFileToString(path, &data);
[email protected]19478682009-07-13 16:11:0820 bool success = false;
[email protected]63597e4e2010-07-08 17:49:0521 if (path.MatchesExtension(FILE_PATH_LITERAL(".png"))) {
[email protected]19478682009-07-13 16:11:0822 success = LoadPng(data);
[email protected]63597e4e2010-07-08 17:49:0523 } else if (path.MatchesExtension(FILE_PATH_LITERAL(".emf"))) {
[email protected]19478682009-07-13 16:11:0824 success = LoadMetafile(data);
25 } else {
26 DCHECK(false);
27 }
28 if (!success) {
29 size_.SetSize(0, 0);
30 row_length_ = 0;
31 data_.clear();
32 }
33}
34
[email protected]aa82249f2009-07-16 17:23:5835Image::Image(const NativeMetafile& metafile)
36 : row_length_(0),
37 ignore_alpha_(true) {
38 LoadMetafile(metafile);
39}
40
41Image::Image(const Image& image)
42 : size_(image.size_),
43 row_length_(image.row_length_),
44 data_(image.data_),
45 ignore_alpha_(image.ignore_alpha_) {
46}
47
[email protected]9b2331d92010-10-04 23:11:1948Image::~Image() {}
49
[email protected]aa82249f2009-07-16 17:23:5850std::string Image::checksum() const {
51 MD5Digest digest;
52 MD5Sum(&data_[0], data_.size(), &digest);
[email protected]e83326f2010-07-31 17:29:2553 return base::HexEncode(&digest, sizeof(digest));
[email protected]aa82249f2009-07-16 17:23:5854}
55
[email protected]72f966b2009-10-14 20:02:2756bool Image::SaveToPng(const FilePath& filepath) const {
[email protected]19478682009-07-13 16:11:0857 DCHECK(!data_.empty());
58 std::vector<unsigned char> compressed;
[email protected]468fec92009-10-03 03:12:2059 bool success = gfx::PNGCodec::Encode(&*data_.begin(),
60 gfx::PNGCodec::FORMAT_BGRA,
61 size_.width(),
62 size_.height(),
63 row_length_,
64 true,
65 &compressed);
[email protected]19478682009-07-13 16:11:0866 DCHECK(success && compressed.size());
67 if (success) {
68 int write_bytes = file_util::WriteFile(
[email protected]72f966b2009-10-14 20:02:2769 filepath,
[email protected]19478682009-07-13 16:11:0870 reinterpret_cast<char*>(&*compressed.begin()), compressed.size());
71 success = (write_bytes == static_cast<int>(compressed.size()));
72 DCHECK(success);
73 }
74 return success;
75}
76
[email protected]aa82249f2009-07-16 17:23:5877double Image::PercentageDifferent(const Image& rhs) const {
[email protected]19478682009-07-13 16:11:0878 if (size_.width() == 0 || size_.height() == 0 ||
79 rhs.size_.width() == 0 || rhs.size_.height() == 0)
80 return 100.;
81
82 int width = std::min(size_.width(), rhs.size_.width());
83 int height = std::min(size_.height(), rhs.size_.height());
84 // Compute pixels different in the overlap
85 int pixels_different = 0;
86 for (int y = 0; y < height; ++y) {
87 for (int x = 0; x < width; ++x) {
88 uint32 lhs_pixel = pixel_at(x, y);
89 uint32 rhs_pixel = rhs.pixel_at(x, y);
90 if (lhs_pixel != rhs_pixel)
91 ++pixels_different;
92 }
93
94 // Look for extra right lhs pixels. They should be white.
95 for (int x = width; x < size_.width(); ++x) {
96 uint32 lhs_pixel = pixel_at(x, y);
97 if (lhs_pixel != Color(SK_ColorWHITE))
98 ++pixels_different;
99 }
100
101 // Look for extra right rhs pixels. They should be white.
102 for (int x = width; x < rhs.size_.width(); ++x) {
103 uint32 rhs_pixel = rhs.pixel_at(x, y);
104 if (rhs_pixel != Color(SK_ColorWHITE))
105 ++pixels_different;
106 }
107 }
108
109 // Look for extra bottom lhs pixels. They should be white.
110 for (int y = height; y < size_.height(); ++y) {
111 for (int x = 0; x < size_.width(); ++x) {
112 uint32 lhs_pixel = pixel_at(x, y);
113 if (lhs_pixel != Color(SK_ColorWHITE))
114 ++pixels_different;
115 }
116 }
117
118 // Look for extra bottom rhs pixels. They should be white.
119 for (int y = height; y < rhs.size_.height(); ++y) {
120 for (int x = 0; x < rhs.size_.width(); ++x) {
121 uint32 rhs_pixel = rhs.pixel_at(x, y);
122 if (rhs_pixel != Color(SK_ColorWHITE))
123 ++pixels_different;
124 }
125 }
126
127 // Like the WebKit ImageDiff tool, we define percentage different in terms
128 // of the size of the 'actual' bitmap.
129 double total_pixels = static_cast<double>(size_.width()) *
130 static_cast<double>(height);
131 return static_cast<double>(pixels_different) / total_pixels * 100.;
132}
133
[email protected]aa82249f2009-07-16 17:23:58134bool Image::LoadPng(const std::string& compressed) {
[email protected]19478682009-07-13 16:11:08135 int w;
136 int h;
[email protected]468fec92009-10-03 03:12:20137 bool success = gfx::PNGCodec::Decode(
[email protected]19478682009-07-13 16:11:08138 reinterpret_cast<const unsigned char*>(compressed.c_str()),
[email protected]468fec92009-10-03 03:12:20139 compressed.size(), gfx::PNGCodec::FORMAT_BGRA, &data_, &w, &h);
[email protected]19478682009-07-13 16:11:08140 size_.SetSize(w, h);
141 row_length_ = size_.width() * sizeof(uint32);
142 return success;
143}
144
[email protected]aa82249f2009-07-16 17:23:58145bool Image::LoadMetafile(const std::string& data) {
[email protected]19478682009-07-13 16:11:08146 DCHECK(!data.empty());
[email protected]aa82249f2009-07-16 17:23:58147 NativeMetafile metafile;
[email protected]e8980a52010-10-07 20:11:24148 metafile.Init(data.data(), data.size());
[email protected]aa82249f2009-07-16 17:23:58149 return LoadMetafile(metafile);
[email protected]aa82249f2009-07-16 17:23:58150}
151
152} // namespace printing