image_unittest_util.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
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// Because the unit tests for gfx::Image are spread across multiple
6// implementation files, this header contains the reusable components.
7
8#include "ui/gfx/image/image_unittest_util.h"
9
10#include <cmath>
11
12#include "base/memory/scoped_ptr.h"
13#include "testing/gtest/include/gtest/gtest.h"
14#include "third_party/skia/include/core/SkBitmap.h"
15#include "ui/gfx/codec/png_codec.h"
16#include "ui/gfx/image/image_skia.h"
17
18#if defined(OS_IOS)
19#include "base/mac/foundation_util.h"
20#include "base/mac/scoped_cftyperef.h"
21#include "skia/ext/skia_utils_ios.h"
22#elif defined(OS_MACOSX)
23#include "base/mac/mac_util.h"
24#include "skia/ext/skia_utils_mac.h"
25#endif
26
27namespace gfx {
28namespace test {
29
30namespace {
31
32bool ColorComponentsClose(SkColor component1, SkColor component2) {
33  int c1 = static_cast<int>(component1);
34  int c2 = static_cast<int>(component2);
35  return std::abs(c1 - c2) <= 40;
36}
37
38bool ColorsClose(SkColor color1, SkColor color2) {
39  // Be tolerant of floating point rounding and lossy color space conversions.
40  return ColorComponentsClose(SkColorGetR(color1), SkColorGetR(color2)) &&
41         ColorComponentsClose(SkColorGetG(color1), SkColorGetG(color2)) &&
42         ColorComponentsClose(SkColorGetB(color1), SkColorGetB(color2)) &&
43         ColorComponentsClose(SkColorGetA(color1), SkColorGetA(color2));
44}
45
46}  // namespace
47
48std::vector<float> Get1xAnd2xScales() {
49  std::vector<float> scales;
50  scales.push_back(1.0f);
51  scales.push_back(2.0f);
52  return scales;
53}
54
55const SkBitmap CreateBitmap(int width, int height) {
56  SkBitmap bitmap;
57  bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
58  bitmap.allocPixels();
59  bitmap.eraseARGB(255, 0, 255, 0);
60  return bitmap;
61}
62
63gfx::ImageSkia CreateImageSkia(int width, int height) {
64  return gfx::ImageSkia::CreateFrom1xBitmap(CreateBitmap(width, height));
65}
66
67scoped_refptr<base::RefCountedMemory> CreatePNGBytes(int edge_size) {
68  SkBitmap bitmap = CreateBitmap(edge_size, edge_size);
69  scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes());
70  PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bytes->data());
71  return bytes;
72}
73
74gfx::Image CreateImage() {
75  return CreateImage(100, 50);
76}
77
78gfx::Image CreateImage(int width, int height) {
79  return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height));
80}
81
82bool IsEqual(const gfx::Image& img1, const gfx::Image& img2) {
83  img1.AsImageSkia().EnsureRepsForSupportedScales();
84  img2.AsImageSkia().EnsureRepsForSupportedScales();
85  std::vector<gfx::ImageSkiaRep> img1_reps = img1.AsImageSkia().image_reps();
86  gfx::ImageSkia image_skia2 = img2.AsImageSkia();
87  if (image_skia2.image_reps().size() != img1_reps.size())
88    return false;
89
90  for (size_t i = 0; i < img1_reps.size(); ++i) {
91    float scale = img1_reps[i].scale();
92    const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale);
93    if (image_rep2.scale() != scale ||
94        !IsEqual(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap())) {
95      return false;
96    }
97  }
98  return true;
99}
100
101bool IsEqual(const SkBitmap& bmp1, const SkBitmap& bmp2) {
102  if (bmp1.isNull() && bmp2.isNull())
103    return true;
104
105  if (bmp1.width() != bmp2.width() ||
106      bmp1.height() != bmp2.height() ||
107      bmp1.config() != SkBitmap::kARGB_8888_Config ||
108      bmp2.config() != SkBitmap::kARGB_8888_Config) {
109    return false;
110  }
111
112  SkAutoLockPixels lock1(bmp1);
113  SkAutoLockPixels lock2(bmp2);
114  if (!bmp1.getPixels() || !bmp2.getPixels())
115    return false;
116
117  for (int y = 0; y < bmp1.height(); ++y) {
118    for (int x = 0; x < bmp1.width(); ++x) {
119      if (!ColorsClose(bmp1.getColor(x,y), bmp2.getColor(x,y)))
120        return false;
121    }
122  }
123
124  return true;
125}
126
127bool IsEqual(const scoped_refptr<base::RefCountedMemory>& bytes,
128             const SkBitmap& bitmap) {
129  SkBitmap decoded;
130  if (!bytes.get() ||
131      !PNGCodec::Decode(bytes->front(), bytes->size(), &decoded)) {
132    return bitmap.isNull();
133  }
134
135  return IsEqual(bitmap, decoded);
136}
137
138void CheckImageIndicatesPNGDecodeFailure(const gfx::Image& image) {
139  SkBitmap bitmap = image.AsBitmap();
140  EXPECT_FALSE(bitmap.isNull());
141  EXPECT_LE(16, bitmap.width());
142  EXPECT_LE(16, bitmap.height());
143  SkAutoLockPixels auto_lock(bitmap);
144  CheckColors(bitmap.getColor(10, 10), SK_ColorRED);
145}
146
147bool ImageSkiaStructureMatches(
148    const gfx::ImageSkia& image_skia,
149    int width,
150    int height,
151    const std::vector<float>& scales) {
152  if (image_skia.isNull() ||
153      image_skia.width() != width ||
154      image_skia.height() != height ||
155      image_skia.image_reps().size() != scales.size()) {
156    return false;
157  }
158
159  for (size_t i = 0; i < scales.size(); ++i) {
160    gfx::ImageSkiaRep image_rep =
161        image_skia.GetRepresentation(scales[i]);
162    if (image_rep.is_null() || image_rep.scale() != scales[i])
163      return false;
164
165    if (image_rep.pixel_width() != static_cast<int>(width * scales[i]) ||
166        image_rep.pixel_height() != static_cast<int>(height * scales[i])) {
167      return false;
168    }
169  }
170  return true;
171}
172
173bool IsEmpty(const gfx::Image& image) {
174  const SkBitmap& bmp = *image.ToSkBitmap();
175  return bmp.isNull() ||
176         (bmp.width() == 0 && bmp.height() == 0);
177}
178
179PlatformImage CreatePlatformImage() {
180  const SkBitmap bitmap(CreateBitmap(25, 25));
181#if defined(OS_IOS)
182  float scale = ImageSkia::GetMaxSupportedScale();
183
184  base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
185      CGColorSpaceCreateDeviceRGB());
186  UIImage* image =
187      gfx::SkBitmapToUIImageWithColorSpace(bitmap, scale, color_space);
188  base::mac::NSObjectRetain(image);
189  return image;
190#elif defined(OS_MACOSX)
191  NSImage* image = gfx::SkBitmapToNSImage(bitmap);
192  base::mac::NSObjectRetain(image);
193  return image;
194#else
195  return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
196#endif
197}
198
199gfx::Image::RepresentationType GetPlatformRepresentationType() {
200#if defined(OS_IOS)
201  return gfx::Image::kImageRepCocoaTouch;
202#elif defined(OS_MACOSX)
203  return gfx::Image::kImageRepCocoa;
204#else
205  return gfx::Image::kImageRepSkia;
206#endif
207}
208
209PlatformImage ToPlatformType(const gfx::Image& image) {
210#if defined(OS_IOS)
211  return image.ToUIImage();
212#elif defined(OS_MACOSX)
213  return image.ToNSImage();
214#else
215  return image.AsImageSkia();
216#endif
217}
218
219PlatformImage CopyPlatformType(const gfx::Image& image) {
220#if defined(OS_IOS)
221  return image.CopyUIImage();
222#elif defined(OS_MACOSX)
223  return image.CopyNSImage();
224#else
225  return image.AsImageSkia();
226#endif
227}
228
229#if defined(OS_MACOSX)
230// Defined in image_unittest_util_mac.mm.
231#else
232SkColor GetPlatformImageColor(PlatformImage image, int x, int y) {
233  SkBitmap bitmap = *image.bitmap();
234  SkAutoLockPixels auto_lock(bitmap);
235  return bitmap.getColor(x, y);
236}
237#endif
238
239void CheckColors(SkColor color1, SkColor color2) {
240  EXPECT_TRUE(ColorsClose(color1, color2));
241}
242
243void CheckIsTransparent(SkColor color) {
244  EXPECT_LT(SkColorGetA(color) / 255.0, 0.05);
245}
246
247bool IsPlatformImageValid(PlatformImage image) {
248#if defined(OS_MACOSX)
249  return image != NULL;
250#else
251  return !image.isNull();
252#endif
253}
254
255bool PlatformImagesEqual(PlatformImage image1, PlatformImage image2) {
256#if defined(OS_MACOSX)
257  return image1 == image2;
258#else
259  return image1.BackedBySameObjectAs(image2);
260#endif
261}
262
263}  // namespace test
264}  // namespace gfx
265