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(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<float> Get1xAnd2xScales() {
     52   std::vector<float> scales;
     53   scales.push_back(1.0f);
     54   scales.push_back(2.0f);
     55   return scales;
     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     float scale = img1_reps[i].scale();
     93     const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale);
     94     if (image_rep2.scale() != scale ||
     95         !IsEqual(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap())) {
     96       return false;
     97     }
     98   }
     99   return true;
    100 }
    101 
    102 bool IsEqual(const SkBitmap& bmp1, const SkBitmap& bmp2) {
    103   if (bmp1.isNull() && bmp2.isNull())
    104     return true;
    105 
    106   if (bmp1.width() != bmp2.width() ||
    107       bmp1.height() != bmp2.height() ||
    108       bmp1.config() != SkBitmap::kARGB_8888_Config ||
    109       bmp2.config() != SkBitmap::kARGB_8888_Config) {
    110     return false;
    111   }
    112 
    113   SkAutoLockPixels lock1(bmp1);
    114   SkAutoLockPixels lock2(bmp2);
    115   if (!bmp1.getPixels() || !bmp2.getPixels())
    116     return false;
    117 
    118   for (int y = 0; y < bmp1.height(); ++y) {
    119     for (int x = 0; x < bmp1.width(); ++x) {
    120       if (!ColorsClose(bmp1.getColor(x,y), bmp2.getColor(x,y)))
    121         return false;
    122     }
    123   }
    124 
    125   return true;
    126 }
    127 
    128 bool IsEqual(const scoped_refptr<base::RefCountedMemory>& bytes,
    129              const SkBitmap& bitmap) {
    130   SkBitmap decoded;
    131   if (!bytes.get() ||
    132       !PNGCodec::Decode(bytes->front(), bytes->size(), &decoded)) {
    133     return bitmap.isNull();
    134   }
    135 
    136   return IsEqual(bitmap, decoded);
    137 }
    138 
    139 void CheckImageIndicatesPNGDecodeFailure(const gfx::Image& image) {
    140   SkBitmap bitmap = image.AsBitmap();
    141   EXPECT_FALSE(bitmap.isNull());
    142   EXPECT_LE(16, bitmap.width());
    143   EXPECT_LE(16, bitmap.height());
    144   SkAutoLockPixels auto_lock(bitmap);
    145   CheckColors(bitmap.getColor(10, 10), SK_ColorRED);
    146 }
    147 
    148 bool ImageSkiaStructureMatches(
    149     const gfx::ImageSkia& image_skia,
    150     int width,
    151     int height,
    152     const std::vector<float>& scales) {
    153   if (image_skia.isNull() ||
    154       image_skia.width() != width ||
    155       image_skia.height() != height ||
    156       image_skia.image_reps().size() != scales.size()) {
    157     return false;
    158   }
    159 
    160   for (size_t i = 0; i < scales.size(); ++i) {
    161     gfx::ImageSkiaRep image_rep =
    162         image_skia.GetRepresentation(scales[i]);
    163     if (image_rep.is_null() || image_rep.scale() != scales[i])
    164       return false;
    165 
    166     if (image_rep.pixel_width() != static_cast<int>(width * scales[i]) ||
    167         image_rep.pixel_height() != static_cast<int>(height * scales[i])) {
    168       return false;
    169     }
    170   }
    171   return true;
    172 }
    173 
    174 bool IsEmpty(const gfx::Image& image) {
    175   const SkBitmap& bmp = *image.ToSkBitmap();
    176   return bmp.isNull() ||
    177          (bmp.width() == 0 && bmp.height() == 0);
    178 }
    179 
    180 PlatformImage CreatePlatformImage() {
    181   const SkBitmap bitmap(CreateBitmap(25, 25));
    182 #if defined(OS_IOS)
    183   float scale = ImageSkia::GetMaxSupportedScale();
    184 
    185   base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
    186       CGColorSpaceCreateDeviceRGB());
    187   UIImage* image =
    188       gfx::SkBitmapToUIImageWithColorSpace(bitmap, scale, color_space);
    189   base::mac::NSObjectRetain(image);
    190   return image;
    191 #elif defined(OS_MACOSX)
    192   NSImage* image = gfx::SkBitmapToNSImage(bitmap);
    193   base::mac::NSObjectRetain(image);
    194   return image;
    195 #elif defined(TOOLKIT_GTK)
    196   return gfx::GdkPixbufFromSkBitmap(bitmap);
    197 #else
    198   return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
    199 #endif
    200 }
    201 
    202 gfx::Image::RepresentationType GetPlatformRepresentationType() {
    203 #if defined(OS_IOS)
    204   return gfx::Image::kImageRepCocoaTouch;
    205 #elif defined(OS_MACOSX)
    206   return gfx::Image::kImageRepCocoa;
    207 #elif defined(TOOLKIT_GTK)
    208   return gfx::Image::kImageRepGdk;
    209 #else
    210   return gfx::Image::kImageRepSkia;
    211 #endif
    212 }
    213 
    214 PlatformImage ToPlatformType(const gfx::Image& image) {
    215 #if defined(OS_IOS)
    216   return image.ToUIImage();
    217 #elif defined(OS_MACOSX)
    218   return image.ToNSImage();
    219 #elif defined(TOOLKIT_GTK)
    220   return image.ToGdkPixbuf();
    221 #else
    222   return image.AsImageSkia();
    223 #endif
    224 }
    225 
    226 PlatformImage CopyPlatformType(const gfx::Image& image) {
    227 #if defined(OS_IOS)
    228   return image.CopyUIImage();
    229 #elif defined(OS_MACOSX)
    230   return image.CopyNSImage();
    231 #elif defined(TOOLKIT_GTK)
    232   return image.CopyGdkPixbuf();
    233 #else
    234   return image.AsImageSkia();
    235 #endif
    236 }
    237 
    238 #if defined(OS_MACOSX)
    239 // Defined in image_unittest_util_mac.mm.
    240 #elif defined(TOOLKIT_GTK)
    241 SkColor GetPlatformImageColor(PlatformImage image, int x, int y) {
    242   int n_channels = gdk_pixbuf_get_n_channels(image);
    243   int rowstride = gdk_pixbuf_get_rowstride(image);
    244   guchar* gdk_pixels = gdk_pixbuf_get_pixels(image);
    245 
    246   guchar* pixel = gdk_pixels + (y * rowstride) + (x * n_channels);
    247   guchar alpha = gdk_pixbuf_get_has_alpha(image) ? pixel[3] : 255;
    248   return SkColorSetARGB(alpha, pixel[0], pixel[1], pixel[2]);
    249 }
    250 #else
    251 SkColor GetPlatformImageColor(PlatformImage image, int x, int y) {
    252   SkBitmap bitmap = *image.bitmap();
    253   SkAutoLockPixels auto_lock(bitmap);
    254   return bitmap.getColor(x, y);
    255 }
    256 #endif
    257 
    258 void CheckColors(SkColor color1, SkColor color2) {
    259   EXPECT_TRUE(ColorsClose(color1, color2));
    260 }
    261 
    262 void CheckIsTransparent(SkColor color) {
    263   EXPECT_LT(SkColorGetA(color) / 255.0, 0.05);
    264 }
    265 
    266 bool IsPlatformImageValid(PlatformImage image) {
    267 #if defined(OS_MACOSX) || defined(TOOLKIT_GTK)
    268   return image != NULL;
    269 #else
    270   return !image.isNull();
    271 #endif
    272 }
    273 
    274 bool PlatformImagesEqual(PlatformImage image1, PlatformImage image2) {
    275 #if defined(OS_MACOSX) || defined(TOOLKIT_GTK)
    276   return image1 == image2;
    277 #else
    278   return image1.BackedBySameObjectAs(image2);
    279 #endif
    280 }
    281 
    282 }  // namespace test
    283 }  // namespace gfx
    284