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 #include <Cocoa/Cocoa.h>
      6 
      7 #include "base/logging.h"
      8 #include "base/mac/scoped_nsobject.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 #include "ui/gfx/image/image.h"
     11 #include "ui/gfx/image/image_png_rep.h"
     12 #include "ui/gfx/image/image_skia.h"
     13 #include "ui/gfx/image/image_skia_util_mac.h"
     14 #include "ui/gfx/image/image_unittest_util.h"
     15 
     16 namespace {
     17 
     18 // Returns true if the structure of |ns_image| matches the structure
     19 // described by |width|, |height|, and |scales|.
     20 // The structure matches if:
     21 // - |ns_image| is not nil.
     22 // - |ns_image| has NSImageReps of |scales|.
     23 // - Each of the NSImageReps has a pixel size of [|ns_image| size] *
     24 //   scale.
     25 bool NSImageStructureMatches(
     26     NSImage* ns_image,
     27     int width,
     28     int height,
     29     const std::vector<float>& scales) {
     30   if (!ns_image ||
     31       [ns_image size].width != width ||
     32       [ns_image size].height != height ||
     33       [ns_image representations].count != scales.size()) {
     34     return false;
     35   }
     36 
     37   for (size_t i = 0; i < scales.size(); ++i) {
     38     float scale = scales[i];
     39     bool found_match = false;
     40     for (size_t j = 0; j < [ns_image representations].count; ++j) {
     41       NSImageRep* ns_image_rep = [[ns_image representations] objectAtIndex:j];
     42       if (ns_image_rep &&
     43           [ns_image_rep pixelsWide] == width * scale &&
     44           [ns_image_rep pixelsHigh] == height * scale) {
     45         found_match = true;
     46         break;
     47       }
     48     }
     49     if (!found_match)
     50       return false;
     51   }
     52   return true;
     53 }
     54 
     55 void BitmapImageRep(int width, int height,
     56      NSBitmapImageRep** image_rep) {
     57   *image_rep = [[[NSBitmapImageRep alloc]
     58       initWithBitmapDataPlanes:NULL
     59                     pixelsWide:width
     60                    pixelsHigh:height
     61                 bitsPerSample:8
     62               samplesPerPixel:3
     63                      hasAlpha:NO
     64                      isPlanar:NO
     65                colorSpaceName:NSDeviceRGBColorSpace
     66                  bitmapFormat:0
     67                   bytesPerRow:0
     68                  bitsPerPixel:0]
     69       autorelease];
     70   unsigned char* image_rep_data = [*image_rep bitmapData];
     71   for (int i = 0; i < width * height * 3; ++i)
     72     image_rep_data[i] = 255;
     73 }
     74 
     75 class ImageMacTest : public testing::Test {
     76  public:
     77   ImageMacTest() {
     78     gfx::ImageSkia::SetSupportedScales(gfx::test::Get1xAnd2xScales());
     79   }
     80 
     81   virtual ~ImageMacTest() {
     82   }
     83 
     84  private:
     85   DISALLOW_COPY_AND_ASSIGN(ImageMacTest);
     86 };
     87 
     88 namespace gt = gfx::test;
     89 
     90 TEST_F(ImageMacTest, MultiResolutionNSImageToImageSkia) {
     91   const int kWidth1x = 10;
     92   const int kHeight1x = 12;
     93   const int kWidth2x = 20;
     94   const int kHeight2x = 24;
     95 
     96   NSBitmapImageRep* ns_image_rep1;
     97   BitmapImageRep(kWidth1x, kHeight1x, &ns_image_rep1);
     98   NSBitmapImageRep* ns_image_rep2;
     99   BitmapImageRep(kWidth2x, kHeight2x, &ns_image_rep2);
    100   base::scoped_nsobject<NSImage> ns_image(
    101       [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
    102   [ns_image addRepresentation:ns_image_rep1];
    103   [ns_image addRepresentation:ns_image_rep2];
    104 
    105   gfx::Image image(ns_image.release());
    106 
    107   EXPECT_EQ(1u, image.RepresentationCount());
    108 
    109   const gfx::ImageSkia* image_skia = image.ToImageSkia();
    110 
    111   std::vector<float> scales;
    112   scales.push_back(1.0f);
    113   scales.push_back(2.0f);
    114   EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
    115                                             scales));
    116 
    117   // ToImageSkia should create a second representation.
    118   EXPECT_EQ(2u, image.RepresentationCount());
    119 }
    120 
    121 // Test that convertng to an ImageSkia from an NSImage with scale factors
    122 // other than 1x and 2x results in an ImageSkia with scale factors 1x and
    123 // 2x;
    124 TEST_F(ImageMacTest, UnalignedMultiResolutionNSImageToImageSkia) {
    125   const int kWidth1x = 10;
    126   const int kHeight1x= 12;
    127   const int kWidth4x = 40;
    128   const int kHeight4x = 48;
    129 
    130   NSBitmapImageRep* ns_image_rep4;
    131   BitmapImageRep(kWidth4x, kHeight4x, &ns_image_rep4);
    132   base::scoped_nsobject<NSImage> ns_image(
    133       [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
    134   [ns_image addRepresentation:ns_image_rep4];
    135 
    136   gfx::Image image(ns_image.release());
    137 
    138   EXPECT_EQ(1u, image.RepresentationCount());
    139 
    140   const gfx::ImageSkia* image_skia = image.ToImageSkia();
    141 
    142   std::vector<float> scales;
    143   scales.push_back(1.0f);
    144   scales.push_back(2.0f);
    145   EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
    146                                             scales));
    147 
    148   // ToImageSkia should create a second representation.
    149   EXPECT_EQ(2u, image.RepresentationCount());
    150 }
    151 
    152 TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
    153   const int kWidth1x = 10;
    154   const int kHeight1x= 12;
    155   const int kWidth2x = 20;
    156   const int kHeight2x = 24;
    157 
    158   gfx::ImageSkia image_skia;
    159   image_skia.AddRepresentation(gfx::ImageSkiaRep(
    160       gt::CreateBitmap(kWidth1x, kHeight1x), 1.0f));
    161   image_skia.AddRepresentation(gfx::ImageSkiaRep(
    162       gt::CreateBitmap(kWidth2x, kHeight2x), 2.0f));
    163 
    164   gfx::Image image(image_skia);
    165 
    166   EXPECT_EQ(1u, image.RepresentationCount());
    167   EXPECT_EQ(2u, image.ToImageSkia()->image_reps().size());
    168 
    169   NSImage* ns_image = image.ToNSImage();
    170 
    171   std::vector<float> scales;
    172   scales.push_back(1.0f);
    173   scales.push_back(2.0f);
    174   EXPECT_TRUE(NSImageStructureMatches(ns_image, kWidth1x, kHeight1x, scales));
    175 
    176   // Request for NSImage* should create a second representation.
    177   EXPECT_EQ(2u, image.RepresentationCount());
    178 }
    179 
    180 TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
    181   const int kSize1x = 25;
    182   const int kSize2x = 50;
    183 
    184   scoped_refptr<base::RefCountedMemory> bytes1x = gt::CreatePNGBytes(kSize1x);
    185   scoped_refptr<base::RefCountedMemory> bytes2x = gt::CreatePNGBytes(kSize2x);
    186   std::vector<gfx::ImagePNGRep> image_png_reps;
    187   image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, 1.0f));
    188   image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, 2.0f));
    189 
    190   gfx::Image image(image_png_reps);
    191 
    192   NSImage* ns_image = image.ToNSImage();
    193   std::vector<float> scales;
    194   scales.push_back(1.0f);
    195   scales.push_back(2.0f);
    196   EXPECT_TRUE(NSImageStructureMatches(ns_image, kSize1x, kSize1x, scales));
    197 
    198   // Converting from PNG to NSImage should not go through ImageSkia.
    199   EXPECT_FALSE(image.HasRepresentation(gfx::Image::kImageRepSkia));
    200 
    201   // Convert to ImageSkia to check pixel contents of NSImageReps.
    202   gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
    203   EXPECT_TRUE(gt::IsEqual(bytes1x,
    204       image_skia.GetRepresentation(1.0f).sk_bitmap()));
    205   EXPECT_TRUE(gt::IsEqual(bytes2x,
    206       image_skia.GetRepresentation(2.0f).sk_bitmap()));
    207 }
    208 
    209 } // namespace
    210