- add sources.
[platform/framework/web/crosswalk.git] / src / printing / image.cc
1 // Copyright (c) 2011 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 "printing/image.h"
6
7 #include <algorithm>
8
9 #include "base/file_util.h"
10 #include "base/md5.h"
11 #include "base/safe_numerics.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "printing/metafile.h"
14 #include "printing/metafile_impl.h"
15 #include "third_party/skia/include/core/SkColor.h"
16 #include "ui/gfx/codec/png_codec.h"
17
18 namespace printing {
19
20 Image::Image(const base::FilePath& path)
21     : row_length_(0),
22       ignore_alpha_(true) {
23   std::string data;
24   base::ReadFileToString(path, &data);
25   bool success = false;
26   if (path.MatchesExtension(FILE_PATH_LITERAL(".png"))) {
27     success = LoadPng(data);
28   } else if (path.MatchesExtension(FILE_PATH_LITERAL(".emf"))) {
29     success = LoadMetafile(data);
30   } else {
31     DCHECK(false);
32   }
33   if (!success) {
34     size_.SetSize(0, 0);
35     row_length_ = 0;
36     data_.clear();
37   }
38 }
39
40 Image::Image(const Metafile& metafile)
41     : row_length_(0),
42       ignore_alpha_(true) {
43   LoadMetafile(metafile);
44 }
45
46 Image::Image(const Image& image)
47     : size_(image.size_),
48       row_length_(image.row_length_),
49       data_(image.data_),
50       ignore_alpha_(image.ignore_alpha_) {
51 }
52
53 Image::~Image() {}
54
55 std::string Image::checksum() const {
56   base::MD5Digest digest;
57   base::MD5Sum(&data_[0], data_.size(), &digest);
58   return base::HexEncode(&digest, sizeof(digest));
59 }
60
61 bool Image::SaveToPng(const base::FilePath& filepath) const {
62   DCHECK(!data_.empty());
63   std::vector<unsigned char> compressed;
64   bool success = gfx::PNGCodec::Encode(&*data_.begin(),
65                                        gfx::PNGCodec::FORMAT_BGRA,
66                                        size_,
67                                        row_length_,
68                                        true,
69                                        std::vector<gfx::PNGCodec::Comment>(),
70                                        &compressed);
71   DCHECK(success && compressed.size());
72   if (success) {
73     int write_bytes = file_util::WriteFile(
74         filepath,
75         reinterpret_cast<char*>(&*compressed.begin()),
76         base::checked_numeric_cast<int>(compressed.size()));
77     success = (write_bytes == static_cast<int>(compressed.size()));
78     DCHECK(success);
79   }
80   return success;
81 }
82
83 double Image::PercentageDifferent(const Image& rhs) const {
84   if (size_.width() == 0 || size_.height() == 0 ||
85     rhs.size_.width() == 0 || rhs.size_.height() == 0)
86     return 100.;
87
88   int width = std::min(size_.width(), rhs.size_.width());
89   int height = std::min(size_.height(), rhs.size_.height());
90   // Compute pixels different in the overlap
91   int pixels_different = 0;
92   for (int y = 0; y < height; ++y) {
93     for (int x = 0; x < width; ++x) {
94       uint32 lhs_pixel = pixel_at(x, y);
95       uint32 rhs_pixel = rhs.pixel_at(x, y);
96       if (lhs_pixel != rhs_pixel)
97         ++pixels_different;
98     }
99
100     // Look for extra right lhs pixels. They should be white.
101     for (int x = width; x < size_.width(); ++x) {
102       uint32 lhs_pixel = pixel_at(x, y);
103       if (lhs_pixel != Color(SK_ColorWHITE))
104         ++pixels_different;
105     }
106
107     // Look for extra right rhs pixels. They should be white.
108     for (int x = width; x < rhs.size_.width(); ++x) {
109       uint32 rhs_pixel = rhs.pixel_at(x, y);
110       if (rhs_pixel != Color(SK_ColorWHITE))
111         ++pixels_different;
112     }
113   }
114
115   // Look for extra bottom lhs pixels. They should be white.
116   for (int y = height; y < size_.height(); ++y) {
117     for (int x = 0; x < size_.width(); ++x) {
118       uint32 lhs_pixel = pixel_at(x, y);
119       if (lhs_pixel != Color(SK_ColorWHITE))
120         ++pixels_different;
121     }
122   }
123
124   // Look for extra bottom rhs pixels. They should be white.
125   for (int y = height; y < rhs.size_.height(); ++y) {
126     for (int x = 0; x < rhs.size_.width(); ++x) {
127       uint32 rhs_pixel = rhs.pixel_at(x, y);
128       if (rhs_pixel != Color(SK_ColorWHITE))
129         ++pixels_different;
130     }
131   }
132
133   // Like the WebKit ImageDiff tool, we define percentage different in terms
134   // of the size of the 'actual' bitmap.
135   double total_pixels = static_cast<double>(size_.width()) *
136       static_cast<double>(height);
137   return static_cast<double>(pixels_different) / total_pixels * 100.;
138 }
139
140 bool Image::LoadPng(const std::string& compressed) {
141   int w;
142   int h;
143   bool success = gfx::PNGCodec::Decode(
144       reinterpret_cast<const unsigned char*>(compressed.c_str()),
145       compressed.size(), gfx::PNGCodec::FORMAT_BGRA, &data_, &w, &h);
146   size_.SetSize(w, h);
147   row_length_ = size_.width() * sizeof(uint32);
148   return success;
149 }
150
151 bool Image::LoadMetafile(const std::string& data) {
152   DCHECK(!data.empty());
153   NativeMetafile metafile;
154   if (!metafile.InitFromData(data.data(),
155                              base::checked_numeric_cast<uint32>(data.size())))
156     return false;
157   return LoadMetafile(metafile);
158 }
159
160 }  // namespace printing