image_unittest_util.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Copyright (c) 2012 The Chromium Authors. All rights reserved.
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Use of this source code is governed by a BSD-style license that can be
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// found in the LICENSE file.
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Because the unit tests for gfx::Image are spread across multiple
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// implementation files, this header contains the reusable components.
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "ui/gfx/image/image_unittest_util.h"
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <cmath>
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "base/memory/scoped_ptr.h"
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "third_party/skia/include/core/SkBitmap.h"
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "ui/gfx/codec/png_codec.h"
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "ui/gfx/image/image_skia.h"
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(OS_IOS)
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "base/mac/foundation_util.h"
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "base/mac/scoped_cftyperef.h"
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "skia/ext/skia_utils_ios.h"
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(OS_MACOSX)
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "base/mac/mac_util.h"
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "skia/ext/skia_utils_mac.h"
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace gfx {
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace test {
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace {
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool ColorComponentsClose(SkColor component1, SkColor component2) {
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int c1 = static_cast<int>(component1);
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int c2 = static_cast<int>(component2);
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return std::abs(c1 - c2) <= 40;
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool ColorsClose(SkColor color1, SkColor color2) {
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Be tolerant of floating point rounding and lossy color space conversions.
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ColorComponentsClose(SkColorGetR(color1), SkColorGetR(color2)) &&
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org         ColorComponentsClose(SkColorGetG(color1), SkColorGetG(color2)) &&
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org         ColorComponentsClose(SkColorGetB(color1), SkColorGetB(color2)) &&
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org         ColorComponentsClose(SkColorGetA(color1), SkColorGetA(color2));
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::vector<float> Get1xAnd2xScales() {
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::vector<float> scales;
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scales.push_back(1.0f);
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scales.push_back(2.0f);
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return scales;
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst SkBitmap CreateBitmap(int width, int height) {
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SkBitmap bitmap;
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bitmap.allocPixels();
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bitmap.eraseARGB(255, 0, 255, 0);
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bitmap;
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orggfx::ImageSkia CreateImageSkia(int width, int height) {
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return gfx::ImageSkia::CreateFrom1xBitmap(CreateBitmap(width, height));
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgscoped_refptr<base::RefCountedMemory> CreatePNGBytes(int edge_size) {
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SkBitmap bitmap = CreateBitmap(edge_size, edge_size);
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes());
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bytes->data());
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return bytes;
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orggfx::Image CreateImage() {
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return CreateImage(100, 50);
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orggfx::Image CreateImage(int width, int height) {
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height));
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool IsEqual(const gfx::Image& img1, const gfx::Image& img2) {
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::vector<gfx::ImageSkiaRep> img1_reps = img1.AsImageSkia().image_reps();
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  gfx::ImageSkia image_skia2 = img2.AsImageSkia();
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (image_skia2.image_reps().size() != img1_reps.size())
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (size_t i = 0; i < img1_reps.size(); ++i) {
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    float scale = img1_reps[i].scale();
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale);
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (image_rep2.scale() != scale ||
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        !IsEqual(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap())) {
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool IsEqual(const SkBitmap& bmp1, const SkBitmap& bmp2) {
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (bmp1.isNull() && bmp2.isNull())
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (bmp1.width() != bmp2.width() ||
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      bmp1.height() != bmp2.height() ||
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      bmp1.config() != SkBitmap::kARGB_8888_Config ||
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      bmp2.config() != SkBitmap::kARGB_8888_Config) {
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SkAutoLockPixels lock1(bmp1);
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SkAutoLockPixels lock2(bmp2);
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!bmp1.getPixels() || !bmp2.getPixels())
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (int y = 0; y < bmp1.height(); ++y) {
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    for (int x = 0; x < bmp1.width(); ++x) {
117      if (!ColorsClose(bmp1.getColor(x,y), bmp2.getColor(x,y)))
118        return false;
119    }
120  }
121
122  return true;
123}
124
125bool IsEqual(const scoped_refptr<base::RefCountedMemory>& bytes,
126             const SkBitmap& bitmap) {
127  SkBitmap decoded;
128  if (!bytes.get() ||
129      !PNGCodec::Decode(bytes->front(), bytes->size(), &decoded)) {
130    return bitmap.isNull();
131  }
132
133  return IsEqual(bitmap, decoded);
134}
135
136void CheckImageIndicatesPNGDecodeFailure(const gfx::Image& image) {
137  SkBitmap bitmap = image.AsBitmap();
138  EXPECT_FALSE(bitmap.isNull());
139  EXPECT_LE(16, bitmap.width());
140  EXPECT_LE(16, bitmap.height());
141  SkAutoLockPixels auto_lock(bitmap);
142  CheckColors(bitmap.getColor(10, 10), SK_ColorRED);
143}
144
145bool ImageSkiaStructureMatches(
146    const gfx::ImageSkia& image_skia,
147    int width,
148    int height,
149    const std::vector<float>& scales) {
150  if (image_skia.isNull() ||
151      image_skia.width() != width ||
152      image_skia.height() != height ||
153      image_skia.image_reps().size() != scales.size()) {
154    return false;
155  }
156
157  for (size_t i = 0; i < scales.size(); ++i) {
158    gfx::ImageSkiaRep image_rep =
159        image_skia.GetRepresentation(scales[i]);
160    if (image_rep.is_null() || image_rep.scale() != scales[i])
161      return false;
162
163    if (image_rep.pixel_width() != static_cast<int>(width * scales[i]) ||
164        image_rep.pixel_height() != static_cast<int>(height * scales[i])) {
165      return false;
166    }
167  }
168  return true;
169}
170
171bool IsEmpty(const gfx::Image& image) {
172  const SkBitmap& bmp = *image.ToSkBitmap();
173  return bmp.isNull() ||
174         (bmp.width() == 0 && bmp.height() == 0);
175}
176
177PlatformImage CreatePlatformImage() {
178  const SkBitmap bitmap(CreateBitmap(25, 25));
179#if defined(OS_IOS)
180  float scale = ImageSkia::GetMaxSupportedScale();
181
182  base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
183      CGColorSpaceCreateDeviceRGB());
184  UIImage* image =
185      gfx::SkBitmapToUIImageWithColorSpace(bitmap, scale, color_space);
186  base::mac::NSObjectRetain(image);
187  return image;
188#elif defined(OS_MACOSX)
189  NSImage* image = gfx::SkBitmapToNSImage(bitmap);
190  base::mac::NSObjectRetain(image);
191  return image;
192#else
193  return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
194#endif
195}
196
197gfx::Image::RepresentationType GetPlatformRepresentationType() {
198#if defined(OS_IOS)
199  return gfx::Image::kImageRepCocoaTouch;
200#elif defined(OS_MACOSX)
201  return gfx::Image::kImageRepCocoa;
202#else
203  return gfx::Image::kImageRepSkia;
204#endif
205}
206
207PlatformImage ToPlatformType(const gfx::Image& image) {
208#if defined(OS_IOS)
209  return image.ToUIImage();
210#elif defined(OS_MACOSX)
211  return image.ToNSImage();
212#else
213  return image.AsImageSkia();
214#endif
215}
216
217PlatformImage CopyPlatformType(const gfx::Image& image) {
218#if defined(OS_IOS)
219  return image.CopyUIImage();
220#elif defined(OS_MACOSX)
221  return image.CopyNSImage();
222#else
223  return image.AsImageSkia();
224#endif
225}
226
227#if defined(OS_MACOSX)
228// Defined in image_unittest_util_mac.mm.
229#else
230SkColor GetPlatformImageColor(PlatformImage image, int x, int y) {
231  SkBitmap bitmap = *image.bitmap();
232  SkAutoLockPixels auto_lock(bitmap);
233  return bitmap.getColor(x, y);
234}
235#endif
236
237void CheckColors(SkColor color1, SkColor color2) {
238  EXPECT_TRUE(ColorsClose(color1, color2));
239}
240
241void CheckIsTransparent(SkColor color) {
242  EXPECT_LT(SkColorGetA(color) / 255.0, 0.05);
243}
244
245bool IsPlatformImageValid(PlatformImage image) {
246#if defined(OS_MACOSX)
247  return image != NULL;
248#else
249  return !image.isNull();
250#endif
251}
252
253bool PlatformImagesEqual(PlatformImage image1, PlatformImage image2) {
254#if defined(OS_MACOSX)
255  return image1 == image2;
256#else
257  return image1.BackedBySameObjectAs(image2);
258#endif
259}
260
261}  // namespace test
262}  // namespace gfx
263