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.allocN32Pixels(width, height);
     58   bitmap.eraseARGB(255, 0, 255, 0);
     59   return bitmap;
     60 }
     61 
     62 gfx::ImageSkia CreateImageSkia(int width, int height) {
     63   return gfx::ImageSkia::CreateFrom1xBitmap(CreateBitmap(width, height));
     64 }
     65 
     66 scoped_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 
     73 gfx::Image CreateImage() {
     74   return CreateImage(100, 50);
     75 }
     76 
     77 gfx::Image CreateImage(int width, int height) {
     78   return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height));
     79 }
     80 
     81 bool 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 
    100 bool 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 
    126 bool 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 
    137 void 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 
    146 bool 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 
    172 bool IsEmpty(const gfx::Image& image) {
    173   const SkBitmap& bmp = *image.ToSkBitmap();
    174   return bmp.isNull() ||
    175          (bmp.width() == 0 && bmp.height() == 0);
    176 }
    177 
    178 PlatformImage 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 
    198 gfx::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 
    208 PlatformImage 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 
    218 PlatformImage 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
    231 SkColor 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 
    238 void CheckColors(SkColor color1, SkColor color2) {
    239   EXPECT_TRUE(ColorsClose(color1, color2));
    240 }
    241 
    242 void CheckIsTransparent(SkColor color) {
    243   EXPECT_LT(SkColorGetA(color) / 255.0, 0.05);
    244 }
    245 
    246 bool IsPlatformImageValid(PlatformImage image) {
    247 #if defined(OS_MACOSX)
    248   return image != NULL;
    249 #else
    250   return !image.isNull();
    251 #endif
    252 }
    253 
    254 bool 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