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