Commit e7dcbedb authored by oshima@chromium.org's avatar oshima@chromium.org

Use ImageSkiaSource to create ImageSkia from ImagePNGReps

 gfx::ImageKia will fetch the ImageSkiaRep based on resource scale factor (supported one) and scale accordingly.

BUG=381601
TEST=covered by test.
R=ananta@chromium.org, pkotwicz@chromium.org, rsesek@chromium.org

Review URL: https://codereview.chromium.org/340613004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278589 0039d316-1c4b-4281-b951-d872f2087c98
parent 298bf4d0
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ui/gfx/image/image.h" #include "ui/gfx/image/image.h"
#include <algorithm> #include <algorithm>
#include <set>
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
...@@ -12,6 +13,7 @@ ...@@ -12,6 +13,7 @@
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image_png_rep.h" #include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_source.h"
#include "ui/gfx/size.h" #include "ui/gfx/size.h"
#if !defined(OS_IOS) #if !defined(OS_IOS)
...@@ -35,20 +37,20 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage( ...@@ -35,20 +37,20 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
UIImage* uiimage); UIImage* uiimage);
// Caller takes ownership of the returned UIImage. // Caller takes ownership of the returned UIImage.
UIImage* CreateUIImageFromPNG( UIImage* CreateUIImageFromPNG(
const std::vector<gfx::ImagePNGRep>& image_png_reps); const std::vector<ImagePNGRep>& image_png_reps);
gfx::Size UIImageSize(UIImage* image); gfx::Size UIImageSize(UIImage* image);
#elif defined(OS_MACOSX) #elif defined(OS_MACOSX)
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage( scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
NSImage* nsimage); NSImage* nsimage);
// Caller takes ownership of the returned NSImage. // Caller takes ownership of the returned NSImage.
NSImage* NSImageFromPNG(const std::vector<gfx::ImagePNGRep>& image_png_reps, NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
CGColorSpaceRef color_space); CGColorSpaceRef color_space);
gfx::Size NSImageSize(NSImage* image); gfx::Size NSImageSize(NSImage* image);
#endif // defined(OS_MACOSX) #endif // defined(OS_MACOSX)
#if defined(OS_IOS) #if defined(OS_IOS)
ImageSkia* ImageSkiaFromPNG( ImageSkia* ImageSkiaFromPNG(
const std::vector<gfx::ImagePNGRep>& image_png_reps); const std::vector<ImagePNGRep>& image_png_reps);
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia( scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
const ImageSkia* skia); const ImageSkia* skia);
#else #else
...@@ -59,31 +61,91 @@ ImageSkia* GetErrorImageSkia() { ...@@ -59,31 +61,91 @@ ImageSkia* GetErrorImageSkia() {
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16); bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
bitmap.allocPixels(); bitmap.allocPixels();
bitmap.eraseARGB(0xff, 0xff, 0, 0); bitmap.eraseARGB(0xff, 0xff, 0, 0);
return new gfx::ImageSkia(gfx::ImageSkiaRep(bitmap, 1.0f)); return new ImageSkia(ImageSkiaRep(bitmap, 1.0f));
} }
class PNGImageSource : public ImageSkiaSource {
public:
PNGImageSource() {}
virtual ~PNGImageSource() {}
virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
if (image_skia_reps_.empty())
return ImageSkiaRep();
const ImageSkiaRep* rep = NULL;
// gfx::ImageSkia passes one of the resource scale factors. The source
// should return:
// 1) The ImageSkiaRep with the highest scale if all available
// scales are smaller than |scale|.
// 2) The ImageSkiaRep with the smallest one that is larger than |scale|.
for (ImageSkiaRepSet::const_iterator iter = image_skia_reps_.begin();
iter != image_skia_reps_.end(); ++iter) {
if ((*iter).scale() == scale)
return (*iter);
if (!rep || rep->scale() < (*iter).scale())
rep = &(*iter);
if (rep->scale() >= scale)
break;
}
return rep ? *rep : ImageSkiaRep();
}
const gfx::Size size() const {
return size_;
}
bool AddPNGData(const ImagePNGRep& png_rep) {
const gfx::ImageSkiaRep rep = ToImageSkiaRep(png_rep);
if (rep.is_null())
return false;
if (size_.IsEmpty())
size_ = gfx::Size(rep.GetWidth(), rep.GetHeight());
image_skia_reps_.insert(rep);
return true;
}
static ImageSkiaRep ToImageSkiaRep(const ImagePNGRep& png_rep) {
scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data;
CHECK(raw_data.get());
SkBitmap bitmap;
if (!PNGCodec::Decode(raw_data->front(), raw_data->size(),
&bitmap)) {
LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << ".";
return ImageSkiaRep();
}
return ImageSkiaRep(bitmap, png_rep.scale);
}
private:
struct Compare {
bool operator()(const ImageSkiaRep& rep1, const ImageSkiaRep& rep2) {
return rep1.scale() < rep2.scale();
}
};
typedef std::set<ImageSkiaRep, Compare> ImageSkiaRepSet;
ImageSkiaRepSet image_skia_reps_;
gfx::Size size_;
DISALLOW_COPY_AND_ASSIGN(PNGImageSource);
};
ImageSkia* ImageSkiaFromPNG( ImageSkia* ImageSkiaFromPNG(
const std::vector<gfx::ImagePNGRep>& image_png_reps) { const std::vector<ImagePNGRep>& image_png_reps) {
if (image_png_reps.empty()) if (image_png_reps.empty())
return GetErrorImageSkia(); return GetErrorImageSkia();
scoped_ptr<PNGImageSource> image_source(new PNGImageSource);
scoped_ptr<gfx::ImageSkia> image_skia(new ImageSkia());
for (size_t i = 0; i < image_png_reps.size(); ++i) { for (size_t i = 0; i < image_png_reps.size(); ++i) {
scoped_refptr<base::RefCountedMemory> raw_data = if (!image_source->AddPNGData(image_png_reps[i]))
image_png_reps[i].raw_data;
CHECK(raw_data.get());
SkBitmap bitmap;
if (!gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(),
&bitmap)) {
LOG(ERROR) << "Unable to decode PNG for "
<< image_png_reps[i].scale
<< ".";
return GetErrorImageSkia(); return GetErrorImageSkia();
}
image_skia->AddRepresentation(gfx::ImageSkiaRep(
bitmap, image_png_reps[i].scale));
} }
return image_skia.release(); const gfx::Size& size = image_source->size();
DCHECK(!size.IsEmpty());
if (size.IsEmpty())
return GetErrorImageSkia();
return new ImageSkia(image_source.release(), size);
} }
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia( scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
...@@ -92,7 +154,7 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia( ...@@ -92,7 +154,7 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes()); scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
if (image_skia_rep.scale() != 1.0f || if (image_skia_rep.scale() != 1.0f ||
!gfx::PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false, !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
&png_bytes->data())) { &png_bytes->data())) {
return NULL; return NULL;
} }
...@@ -302,7 +364,7 @@ class ImageRepCocoa : public ImageRep { ...@@ -302,7 +364,7 @@ class ImageRepCocoa : public ImageRep {
// ImageReps. This way, the Image can be cheaply copied. // ImageReps. This way, the Image can be cheaply copied.
class ImageStorage : public base::RefCounted<ImageStorage> { class ImageStorage : public base::RefCounted<ImageStorage> {
public: public:
ImageStorage(gfx::Image::RepresentationType default_type) ImageStorage(Image::RepresentationType default_type)
: default_representation_type_(default_type), : default_representation_type_(default_type),
#if defined(OS_MACOSX) && !defined(OS_IOS) #if defined(OS_MACOSX) && !defined(OS_IOS)
default_representation_color_space_( default_representation_color_space_(
...@@ -311,10 +373,10 @@ class ImageStorage : public base::RefCounted<ImageStorage> { ...@@ -311,10 +373,10 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
representations_deleter_(&representations_) { representations_deleter_(&representations_) {
} }
gfx::Image::RepresentationType default_representation_type() { Image::RepresentationType default_representation_type() {
return default_representation_type_; return default_representation_type_;
} }
gfx::Image::RepresentationMap& representations() { return representations_; } Image::RepresentationMap& representations() { return representations_; }
#if defined(OS_MACOSX) && !defined(OS_IOS) #if defined(OS_MACOSX) && !defined(OS_IOS)
void set_default_representation_color_space(CGColorSpaceRef color_space) { void set_default_representation_color_space(CGColorSpaceRef color_space) {
...@@ -332,7 +394,7 @@ class ImageStorage : public base::RefCounted<ImageStorage> { ...@@ -332,7 +394,7 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
// The type of image that was passed to the constructor. This key will always // The type of image that was passed to the constructor. This key will always
// exist in the |representations_| map. // exist in the |representations_| map.
gfx::Image::RepresentationType default_representation_type_; Image::RepresentationType default_representation_type_;
#if defined(OS_MACOSX) && !defined(OS_IOS) #if defined(OS_MACOSX) && !defined(OS_IOS)
// The default representation's colorspace. This is used for converting to // The default representation's colorspace. This is used for converting to
...@@ -344,7 +406,7 @@ class ImageStorage : public base::RefCounted<ImageStorage> { ...@@ -344,7 +406,7 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
// All the representations of an Image. Size will always be at least one, with // All the representations of an Image. Size will always be at least one, with
// more for any converted representations. // more for any converted representations.
gfx::Image::RepresentationMap representations_; Image::RepresentationMap representations_;
STLValueDeleter<Image::RepresentationMap> representations_deleter_; STLValueDeleter<Image::RepresentationMap> representations_deleter_;
...@@ -413,14 +475,14 @@ Image::~Image() { ...@@ -413,14 +475,14 @@ Image::~Image() {
// static // static
Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) { Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) {
return gfx::Image(ImageSkia::CreateFrom1xBitmap(bitmap)); return Image(ImageSkia::CreateFrom1xBitmap(bitmap));
} }
// static // static
Image Image::CreateFrom1xPNGBytes(const unsigned char* input, Image Image::CreateFrom1xPNGBytes(const unsigned char* input,
size_t input_size) { size_t input_size) {
if (input_size == 0u) if (input_size == 0u)
return gfx::Image(); return Image();
scoped_refptr<base::RefCountedBytes> raw_data(new base::RefCountedBytes()); scoped_refptr<base::RefCountedBytes> raw_data(new base::RefCountedBytes());
raw_data->data().assign(input, input + input_size); raw_data->data().assign(input, input + input_size);
...@@ -431,11 +493,11 @@ Image Image::CreateFrom1xPNGBytes(const unsigned char* input, ...@@ -431,11 +493,11 @@ Image Image::CreateFrom1xPNGBytes(const unsigned char* input,
Image Image::CreateFrom1xPNGBytes( Image Image::CreateFrom1xPNGBytes(
const scoped_refptr<base::RefCountedMemory>& input) { const scoped_refptr<base::RefCountedMemory>& input) {
if (!input.get() || input->size() == 0u) if (!input.get() || input->size() == 0u)
return gfx::Image(); return Image();
std::vector<gfx::ImagePNGRep> image_reps; std::vector<ImagePNGRep> image_reps;
image_reps.push_back(ImagePNGRep(input, 1.0f)); image_reps.push_back(ImagePNGRep(input, 1.0f));
return gfx::Image(image_reps); return Image(image_reps);
} }
const SkBitmap* Image::ToSkBitmap() const { const SkBitmap* Image::ToSkBitmap() const {
...@@ -550,7 +612,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const { ...@@ -550,7 +612,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false); internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
if (rep) { if (rep) {
const std::vector<gfx::ImagePNGRep>& image_png_reps = const std::vector<ImagePNGRep>& image_png_reps =
rep->AsImageRepPNG()->image_reps(); rep->AsImageRepPNG()->image_reps();
for (size_t i = 0; i < image_png_reps.size(); ++i) { for (size_t i = 0; i < image_png_reps.size(); ++i) {
if (image_png_reps[i].scale == 1.0f) if (image_png_reps[i].scale == 1.0f)
...@@ -601,7 +663,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const { ...@@ -601,7 +663,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
// final type eg (converting from ImageRepSkia to ImageRepPNG to get an // final type eg (converting from ImageRepSkia to ImageRepPNG to get an
// ImageRepCocoa). // ImageRepCocoa).
std::vector<ImagePNGRep> image_png_reps; std::vector<ImagePNGRep> image_png_reps;
image_png_reps.push_back(gfx::ImagePNGRep(png_bytes, 1.0f)); image_png_reps.push_back(ImagePNGRep(png_bytes, 1.0f));
rep = new internal::ImageRepPNG(image_png_reps); rep = new internal::ImageRepPNG(image_png_reps);
AddRepresentation(rep); AddRepresentation(rep);
return png_bytes; return png_bytes;
...@@ -683,7 +745,7 @@ gfx::Size Image::Size() const { ...@@ -683,7 +745,7 @@ gfx::Size Image::Size() const {
return GetRepresentation(DefaultRepresentationType(), true)->Size(); return GetRepresentation(DefaultRepresentationType(), true)->Size();
} }
void Image::SwapRepresentations(gfx::Image* other) { void Image::SwapRepresentations(Image* other) {
storage_.swap(other->storage_); storage_.swap(other->storage_);
} }
......
...@@ -243,12 +243,22 @@ TEST_F(ImageTest, MultiResolutionPNGToImageSkia) { ...@@ -243,12 +243,22 @@ TEST_F(ImageTest, MultiResolutionPNGToImageSkia) {
scales.push_back(1.0f); scales.push_back(1.0f);
scales.push_back(2.0f); scales.push_back(2.0f);
gfx::ImageSkia image_skia = image.AsImageSkia(); gfx::ImageSkia image_skia = image.AsImageSkia();
EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kSize1x, kSize1x,
scales));
EXPECT_TRUE(gt::IsEqual(bytes1x, EXPECT_TRUE(gt::IsEqual(bytes1x,
image_skia.GetRepresentation(1.0f).sk_bitmap())); image_skia.GetRepresentation(1.0f).sk_bitmap()));
EXPECT_TRUE(gt::IsEqual(bytes2x, EXPECT_TRUE(gt::IsEqual(bytes2x,
image_skia.GetRepresentation(2.0f).sk_bitmap())); image_skia.GetRepresentation(2.0f).sk_bitmap()));
EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kSize1x, kSize1x,
scales));
gfx::ImageSkiaRep rep_1_6x = image_skia.GetRepresentation(1.6f);
ASSERT_FALSE(rep_1_6x.is_null());
ASSERT_EQ(1.6f, rep_1_6x.scale());
EXPECT_EQ("40x40", rep_1_6x.pixel_size().ToString());
gfx::ImageSkiaRep rep_0_8x = image_skia.GetRepresentation(0.8f);
ASSERT_FALSE(rep_0_8x.is_null());
ASSERT_EQ(0.8f, rep_0_8x.scale());
EXPECT_EQ("20x20", rep_0_8x.pixel_size().ToString());
} }
TEST_F(ImageTest, MultiResolutionPNGToPlatform) { TEST_F(ImageTest, MultiResolutionPNGToPlatform) {
......
...@@ -80,6 +80,8 @@ gfx::Image CreateImage(int width, int height) { ...@@ -80,6 +80,8 @@ gfx::Image CreateImage(int width, int height) {
} }
bool IsEqual(const gfx::Image& img1, const gfx::Image& img2) { bool IsEqual(const gfx::Image& img1, const gfx::Image& img2) {
img1.AsImageSkia().EnsureRepsForSupportedScales();
img2.AsImageSkia().EnsureRepsForSupportedScales();
std::vector<gfx::ImageSkiaRep> img1_reps = img1.AsImageSkia().image_reps(); std::vector<gfx::ImageSkiaRep> img1_reps = img1.AsImageSkia().image_reps();
gfx::ImageSkia image_skia2 = img2.AsImageSkia(); gfx::ImageSkia image_skia2 = img2.AsImageSkia();
if (image_skia2.image_reps().size() != img1_reps.size()) if (image_skia2.image_reps().size() != img1_reps.size())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment