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