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