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 30 namespace gfx { 31 namespace test { 32 33 namespace { 34 35 bool 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 41 bool 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 51 std::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 58 const 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 66 gfx::ImageSkia CreateImageSkia(int width, int height) { 67 return gfx::ImageSkia::CreateFrom1xBitmap(CreateBitmap(width, height)); 68 } 69 70 scoped_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 77 gfx::Image CreateImage() { 78 return CreateImage(100, 50); 79 } 80 81 gfx::Image CreateImage(int width, int height) { 82 return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height)); 83 } 84 85 bool 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 103 bool 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 129 bool 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 140 void 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 149 bool 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 177 bool IsEmpty(const gfx::Image& image) { 178 const SkBitmap& bmp = *image.ToSkBitmap(); 179 return bmp.isNull() || 180 (bmp.width() == 0 && bmp.height() == 0); 181 } 182 183 PlatformImage 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 206 gfx::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 218 PlatformImage 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 230 PlatformImage 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) 245 SkColor 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 255 SkColor 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 262 void CheckColors(SkColor color1, SkColor color2) { 263 EXPECT_TRUE(ColorsClose(color1, color2)); 264 } 265 266 void CheckIsTransparent(SkColor color) { 267 EXPECT_LT(SkColorGetA(color) / 255.0, 0.05); 268 } 269 270 bool 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 278 bool 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