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.allocN32Pixels(width, height); 58 bitmap.eraseARGB(255, 0, 255, 0); 59 return bitmap; 60} 61 62gfx::ImageSkia CreateImageSkia(int width, int height) { 63 return gfx::ImageSkia::CreateFrom1xBitmap(CreateBitmap(width, height)); 64} 65 66scoped_refptr<base::RefCountedMemory> CreatePNGBytes(int edge_size) { 67 SkBitmap bitmap = CreateBitmap(edge_size, edge_size); 68 scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes()); 69 PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bytes->data()); 70 return bytes; 71} 72 73gfx::Image CreateImage() { 74 return CreateImage(100, 50); 75} 76 77gfx::Image CreateImage(int width, int height) { 78 return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height)); 79} 80 81bool IsEqual(const gfx::Image& img1, const gfx::Image& img2) { 82 img1.AsImageSkia().EnsureRepsForSupportedScales(); 83 img2.AsImageSkia().EnsureRepsForSupportedScales(); 84 std::vector<gfx::ImageSkiaRep> img1_reps = img1.AsImageSkia().image_reps(); 85 gfx::ImageSkia image_skia2 = img2.AsImageSkia(); 86 if (image_skia2.image_reps().size() != img1_reps.size()) 87 return false; 88 89 for (size_t i = 0; i < img1_reps.size(); ++i) { 90 float scale = img1_reps[i].scale(); 91 const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale); 92 if (image_rep2.scale() != scale || 93 !IsEqual(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap())) { 94 return false; 95 } 96 } 97 return true; 98} 99 100bool IsEqual(const SkBitmap& bmp1, const SkBitmap& bmp2) { 101 if (bmp1.isNull() && bmp2.isNull()) 102 return true; 103 104 if (bmp1.width() != bmp2.width() || 105 bmp1.height() != bmp2.height() || 106 bmp1.colorType() != kN32_SkColorType || 107 bmp2.colorType() != kN32_SkColorType) { 108 return false; 109 } 110 111 SkAutoLockPixels lock1(bmp1); 112 SkAutoLockPixels lock2(bmp2); 113 if (!bmp1.getPixels() || !bmp2.getPixels()) 114 return false; 115 116 for (int y = 0; y < bmp1.height(); ++y) { 117 for (int x = 0; x < bmp1.width(); ++x) { 118 if (!ColorsClose(bmp1.getColor(x,y), bmp2.getColor(x,y))) 119 return false; 120 } 121 } 122 123 return true; 124} 125 126bool IsEqual(const scoped_refptr<base::RefCountedMemory>& bytes, 127 const SkBitmap& bitmap) { 128 SkBitmap decoded; 129 if (!bytes.get() || 130 !PNGCodec::Decode(bytes->front(), bytes->size(), &decoded)) { 131 return bitmap.isNull(); 132 } 133 134 return IsEqual(bitmap, decoded); 135} 136 137void CheckImageIndicatesPNGDecodeFailure(const gfx::Image& image) { 138 SkBitmap bitmap = image.AsBitmap(); 139 EXPECT_FALSE(bitmap.isNull()); 140 EXPECT_LE(16, bitmap.width()); 141 EXPECT_LE(16, bitmap.height()); 142 SkAutoLockPixels auto_lock(bitmap); 143 CheckColors(bitmap.getColor(10, 10), SK_ColorRED); 144} 145 146bool ImageSkiaStructureMatches( 147 const gfx::ImageSkia& image_skia, 148 int width, 149 int height, 150 const std::vector<float>& scales) { 151 if (image_skia.isNull() || 152 image_skia.width() != width || 153 image_skia.height() != height || 154 image_skia.image_reps().size() != scales.size()) { 155 return false; 156 } 157 158 for (size_t i = 0; i < scales.size(); ++i) { 159 gfx::ImageSkiaRep image_rep = 160 image_skia.GetRepresentation(scales[i]); 161 if (image_rep.is_null() || image_rep.scale() != scales[i]) 162 return false; 163 164 if (image_rep.pixel_width() != static_cast<int>(width * scales[i]) || 165 image_rep.pixel_height() != static_cast<int>(height * scales[i])) { 166 return false; 167 } 168 } 169 return true; 170} 171 172bool IsEmpty(const gfx::Image& image) { 173 const SkBitmap& bmp = *image.ToSkBitmap(); 174 return bmp.isNull() || 175 (bmp.width() == 0 && bmp.height() == 0); 176} 177 178PlatformImage CreatePlatformImage() { 179 const SkBitmap bitmap(CreateBitmap(25, 25)); 180#if defined(OS_IOS) 181 float scale = ImageSkia::GetMaxSupportedScale(); 182 183 base::ScopedCFTypeRef<CGColorSpaceRef> color_space( 184 CGColorSpaceCreateDeviceRGB()); 185 UIImage* image = 186 gfx::SkBitmapToUIImageWithColorSpace(bitmap, scale, color_space); 187 base::mac::NSObjectRetain(image); 188 return image; 189#elif defined(OS_MACOSX) 190 NSImage* image = gfx::SkBitmapToNSImage(bitmap); 191 base::mac::NSObjectRetain(image); 192 return image; 193#else 194 return gfx::ImageSkia::CreateFrom1xBitmap(bitmap); 195#endif 196} 197 198gfx::Image::RepresentationType GetPlatformRepresentationType() { 199#if defined(OS_IOS) 200 return gfx::Image::kImageRepCocoaTouch; 201#elif defined(OS_MACOSX) 202 return gfx::Image::kImageRepCocoa; 203#else 204 return gfx::Image::kImageRepSkia; 205#endif 206} 207 208PlatformImage ToPlatformType(const gfx::Image& image) { 209#if defined(OS_IOS) 210 return image.ToUIImage(); 211#elif defined(OS_MACOSX) 212 return image.ToNSImage(); 213#else 214 return image.AsImageSkia(); 215#endif 216} 217 218PlatformImage CopyPlatformType(const gfx::Image& image) { 219#if defined(OS_IOS) 220 return image.CopyUIImage(); 221#elif defined(OS_MACOSX) 222 return image.CopyNSImage(); 223#else 224 return image.AsImageSkia(); 225#endif 226} 227 228#if defined(OS_MACOSX) 229// Defined in image_unittest_util_mac.mm. 230#else 231SkColor GetPlatformImageColor(PlatformImage image, int x, int y) { 232 SkBitmap bitmap = *image.bitmap(); 233 SkAutoLockPixels auto_lock(bitmap); 234 return bitmap.getColor(x, y); 235} 236#endif 237 238void CheckColors(SkColor color1, SkColor color2) { 239 EXPECT_TRUE(ColorsClose(color1, color2)); 240} 241 242void CheckIsTransparent(SkColor color) { 243 EXPECT_LT(SkColorGetA(color) / 255.0, 0.05); 244} 245 246bool IsPlatformImageValid(PlatformImage image) { 247#if defined(OS_MACOSX) 248 return image != NULL; 249#else 250 return !image.isNull(); 251#endif 252} 253 254bool PlatformImagesEqual(PlatformImage image1, PlatformImage image2) { 255#if defined(OS_MACOSX) 256 return image1 == image2; 257#else 258 return image1.BackedBySameObjectAs(image2); 259#endif 260} 261 262} // namespace test 263} // namespace gfx 264