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<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