Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / gfx / image / image.cc
blobd9e51e87b3cebc044563b694c7847e9d3e2f6c73
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.
5 #include "ui/gfx/image/image.h"
7 #include <algorithm>
8 #include <set>
10 #include "base/logging.h"
11 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "ui/gfx/geometry/size.h"
13 #include "ui/gfx/image/image_png_rep.h"
14 #include "ui/gfx/image/image_skia.h"
15 #include "ui/gfx/image/image_skia_source.h"
17 #if !defined(OS_IOS)
18 #include "ui/gfx/codec/png_codec.h"
19 #endif
21 #if defined(OS_IOS)
22 #include "base/mac/foundation_util.h"
23 #include "ui/gfx/image/image_skia_util_ios.h"
24 #elif defined(OS_MACOSX)
25 #include "base/mac/foundation_util.h"
26 #include "base/mac/mac_util.h"
27 #include "ui/gfx/image/image_skia_util_mac.h"
28 #endif
30 namespace gfx {
32 namespace internal {
34 #if defined(OS_IOS)
35 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
36 UIImage* uiimage);
37 // Caller takes ownership of the returned UIImage.
38 UIImage* CreateUIImageFromPNG(
39 const std::vector<ImagePNGRep>& image_png_reps);
40 gfx::Size UIImageSize(UIImage* image);
41 #elif defined(OS_MACOSX)
42 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
43 NSImage* nsimage);
44 // Caller takes ownership of the returned NSImage.
45 NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
46 CGColorSpaceRef color_space);
47 gfx::Size NSImageSize(NSImage* image);
48 #endif // defined(OS_MACOSX)
50 #if defined(OS_IOS)
51 ImageSkia* ImageSkiaFromPNG(
52 const std::vector<ImagePNGRep>& image_png_reps);
53 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
54 const ImageSkia* skia);
55 #else
56 // Returns a 16x16 red image to visually show error in decoding PNG.
57 // Caller takes ownership of returned ImageSkia.
58 ImageSkia* GetErrorImageSkia() {
59 SkBitmap bitmap;
60 bitmap.allocN32Pixels(16, 16);
61 bitmap.eraseARGB(0xff, 0xff, 0, 0);
62 return new ImageSkia(ImageSkiaRep(bitmap, 1.0f));
65 class PNGImageSource : public ImageSkiaSource {
66 public:
67 PNGImageSource() {}
68 ~PNGImageSource() override {}
70 ImageSkiaRep GetImageForScale(float scale) override {
71 if (image_skia_reps_.empty())
72 return ImageSkiaRep();
74 const ImageSkiaRep* rep = NULL;
75 // gfx::ImageSkia passes one of the resource scale factors. The source
76 // should return:
77 // 1) The ImageSkiaRep with the highest scale if all available
78 // scales are smaller than |scale|.
79 // 2) The ImageSkiaRep with the smallest one that is larger than |scale|.
80 for (ImageSkiaRepSet::const_iterator iter = image_skia_reps_.begin();
81 iter != image_skia_reps_.end(); ++iter) {
82 if ((*iter).scale() == scale)
83 return (*iter);
84 if (!rep || rep->scale() < (*iter).scale())
85 rep = &(*iter);
86 if (rep->scale() >= scale)
87 break;
89 return rep ? *rep : ImageSkiaRep();
92 const gfx::Size size() const {
93 return size_;
96 bool AddPNGData(const ImagePNGRep& png_rep) {
97 const gfx::ImageSkiaRep rep = ToImageSkiaRep(png_rep);
98 if (rep.is_null())
99 return false;
100 if (size_.IsEmpty())
101 size_ = gfx::Size(rep.GetWidth(), rep.GetHeight());
102 image_skia_reps_.insert(rep);
103 return true;
106 static ImageSkiaRep ToImageSkiaRep(const ImagePNGRep& png_rep) {
107 scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data;
108 CHECK(raw_data.get());
109 SkBitmap bitmap;
110 if (!PNGCodec::Decode(raw_data->front(), raw_data->size(),
111 &bitmap)) {
112 LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << ".";
113 return ImageSkiaRep();
115 return ImageSkiaRep(bitmap, png_rep.scale);
118 private:
119 struct Compare {
120 bool operator()(const ImageSkiaRep& rep1, const ImageSkiaRep& rep2) {
121 return rep1.scale() < rep2.scale();
125 typedef std::set<ImageSkiaRep, Compare> ImageSkiaRepSet;
126 ImageSkiaRepSet image_skia_reps_;
127 gfx::Size size_;
129 DISALLOW_COPY_AND_ASSIGN(PNGImageSource);
132 ImageSkia* ImageSkiaFromPNG(
133 const std::vector<ImagePNGRep>& image_png_reps) {
134 if (image_png_reps.empty())
135 return GetErrorImageSkia();
136 scoped_ptr<PNGImageSource> image_source(new PNGImageSource);
138 for (size_t i = 0; i < image_png_reps.size(); ++i) {
139 if (!image_source->AddPNGData(image_png_reps[i]))
140 return GetErrorImageSkia();
142 const gfx::Size& size = image_source->size();
143 DCHECK(!size.IsEmpty());
144 if (size.IsEmpty())
145 return GetErrorImageSkia();
146 return new ImageSkia(image_source.release(), size);
149 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
150 const ImageSkia* image_skia) {
151 ImageSkiaRep image_skia_rep = image_skia->GetRepresentation(1.0f);
153 scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
154 if (image_skia_rep.scale() != 1.0f ||
155 !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
156 &png_bytes->data())) {
157 return NULL;
159 return png_bytes;
161 #endif
163 class ImageRepPNG;
164 class ImageRepSkia;
165 class ImageRepCocoa;
166 class ImageRepCocoaTouch;
168 // An ImageRep is the object that holds the backing memory for an Image. Each
169 // RepresentationType has an ImageRep subclass that is responsible for freeing
170 // the memory that the ImageRep holds. When an ImageRep is created, it expects
171 // to take ownership of the image, without having to retain it or increase its
172 // reference count.
173 class ImageRep {
174 public:
175 explicit ImageRep(Image::RepresentationType rep) : type_(rep) {}
177 // Deletes the associated pixels of an ImageRep.
178 virtual ~ImageRep() {}
180 // Cast helpers ("fake RTTI").
181 ImageRepPNG* AsImageRepPNG() {
182 CHECK_EQ(type_, Image::kImageRepPNG);
183 return reinterpret_cast<ImageRepPNG*>(this);
186 ImageRepSkia* AsImageRepSkia() {
187 CHECK_EQ(type_, Image::kImageRepSkia);
188 return reinterpret_cast<ImageRepSkia*>(this);
191 #if defined(OS_IOS)
192 ImageRepCocoaTouch* AsImageRepCocoaTouch() {
193 CHECK_EQ(type_, Image::kImageRepCocoaTouch);
194 return reinterpret_cast<ImageRepCocoaTouch*>(this);
196 #elif defined(OS_MACOSX)
197 ImageRepCocoa* AsImageRepCocoa() {
198 CHECK_EQ(type_, Image::kImageRepCocoa);
199 return reinterpret_cast<ImageRepCocoa*>(this);
201 #endif
203 Image::RepresentationType type() const { return type_; }
205 virtual int Width() const = 0;
206 virtual int Height() const = 0;
207 virtual gfx::Size Size() const = 0;
209 private:
210 Image::RepresentationType type_;
213 class ImageRepPNG : public ImageRep {
214 public:
215 ImageRepPNG() : ImageRep(Image::kImageRepPNG) {
218 ImageRepPNG(const std::vector<ImagePNGRep>& image_png_reps)
219 : ImageRep(Image::kImageRepPNG),
220 image_png_reps_(image_png_reps) {
223 ~ImageRepPNG() override {}
225 int Width() const override { return Size().width(); }
227 int Height() const override { return Size().height(); }
229 gfx::Size Size() const override {
230 // Read the PNG data to get the image size, caching it.
231 if (!size_cache_) {
232 for (std::vector<ImagePNGRep>::const_iterator it = image_reps().begin();
233 it != image_reps().end(); ++it) {
234 if (it->scale == 1.0f) {
235 size_cache_.reset(new gfx::Size(it->Size()));
236 return *size_cache_;
239 size_cache_.reset(new gfx::Size);
242 return *size_cache_;
245 const std::vector<ImagePNGRep>& image_reps() const { return image_png_reps_; }
247 private:
248 std::vector<ImagePNGRep> image_png_reps_;
250 // Cached to avoid having to parse the raw data multiple times.
251 mutable scoped_ptr<gfx::Size> size_cache_;
253 DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
256 class ImageRepSkia : public ImageRep {
257 public:
258 // Takes ownership of |image|.
259 explicit ImageRepSkia(ImageSkia* image)
260 : ImageRep(Image::kImageRepSkia),
261 image_(image) {
264 ~ImageRepSkia() override {}
266 int Width() const override { return image_->width(); }
268 int Height() const override { return image_->height(); }
270 gfx::Size Size() const override { return image_->size(); }
272 ImageSkia* image() { return image_.get(); }
274 private:
275 scoped_ptr<ImageSkia> image_;
277 DISALLOW_COPY_AND_ASSIGN(ImageRepSkia);
280 #if defined(OS_IOS)
281 class ImageRepCocoaTouch : public ImageRep {
282 public:
283 explicit ImageRepCocoaTouch(UIImage* image)
284 : ImageRep(Image::kImageRepCocoaTouch),
285 image_(image) {
286 CHECK(image);
289 ~ImageRepCocoaTouch() override {
290 base::mac::NSObjectRelease(image_);
291 image_ = nil;
294 int Width() const override { return Size().width(); }
296 int Height() const override { return Size().height(); }
298 gfx::Size Size() const override { return internal::UIImageSize(image_); }
300 UIImage* image() const { return image_; }
302 private:
303 UIImage* image_;
305 DISALLOW_COPY_AND_ASSIGN(ImageRepCocoaTouch);
307 #elif defined(OS_MACOSX)
308 class ImageRepCocoa : public ImageRep {
309 public:
310 explicit ImageRepCocoa(NSImage* image)
311 : ImageRep(Image::kImageRepCocoa),
312 image_(image) {
313 CHECK(image);
316 ~ImageRepCocoa() override {
317 base::mac::NSObjectRelease(image_);
318 image_ = nil;
321 int Width() const override { return Size().width(); }
323 int Height() const override { return Size().height(); }
325 gfx::Size Size() const override { return internal::NSImageSize(image_); }
327 NSImage* image() const { return image_; }
329 private:
330 NSImage* image_;
332 DISALLOW_COPY_AND_ASSIGN(ImageRepCocoa);
334 #endif // defined(OS_MACOSX)
336 // The Storage class acts similarly to the pixels in a SkBitmap: the Image
337 // class holds a refptr instance of Storage, which in turn holds all the
338 // ImageReps. This way, the Image can be cheaply copied.
339 class ImageStorage : public base::RefCounted<ImageStorage> {
340 public:
341 ImageStorage(Image::RepresentationType default_type)
342 : default_representation_type_(default_type)
343 #if defined(OS_MACOSX) && !defined(OS_IOS)
345 default_representation_color_space_(
346 base::mac::GetGenericRGBColorSpace())
347 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
351 Image::RepresentationType default_representation_type() {
352 return default_representation_type_;
354 Image::RepresentationMap& representations() { return representations_; }
356 #if defined(OS_MACOSX) && !defined(OS_IOS)
357 void set_default_representation_color_space(CGColorSpaceRef color_space) {
358 default_representation_color_space_ = color_space;
360 CGColorSpaceRef default_representation_color_space() {
361 return default_representation_color_space_;
363 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
365 private:
366 friend class base::RefCounted<ImageStorage>;
368 ~ImageStorage() {}
370 // The type of image that was passed to the constructor. This key will always
371 // exist in the |representations_| map.
372 Image::RepresentationType default_representation_type_;
374 #if defined(OS_MACOSX) && !defined(OS_IOS)
375 // The default representation's colorspace. This is used for converting to
376 // NSImage. This field exists to compensate for PNGCodec not writing or
377 // reading colorspace ancillary chunks. (sRGB, iCCP).
378 // Not owned.
379 CGColorSpaceRef default_representation_color_space_;
380 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
382 // All the representations of an Image. Size will always be at least one, with
383 // more for any converted representations.
384 Image::RepresentationMap representations_;
386 DISALLOW_COPY_AND_ASSIGN(ImageStorage);
389 } // namespace internal
391 Image::Image() {
392 // |storage_| is NULL for empty Images.
395 Image::Image(const std::vector<ImagePNGRep>& image_reps) {
396 // Do not store obviously invalid ImagePNGReps.
397 std::vector<ImagePNGRep> filtered;
398 for (size_t i = 0; i < image_reps.size(); ++i) {
399 if (image_reps[i].raw_data.get() && image_reps[i].raw_data->size())
400 filtered.push_back(image_reps[i]);
403 if (filtered.empty())
404 return;
406 storage_ = new internal::ImageStorage(Image::kImageRepPNG);
407 AddRepresentation(make_scoped_ptr(new internal::ImageRepPNG(filtered)));
410 Image::Image(const ImageSkia& image) {
411 if (!image.isNull()) {
412 storage_ = new internal::ImageStorage(Image::kImageRepSkia);
413 AddRepresentation(
414 make_scoped_ptr(new internal::ImageRepSkia(new ImageSkia(image))));
418 #if defined(OS_IOS)
419 Image::Image(UIImage* image)
420 : storage_(new internal::ImageStorage(Image::kImageRepCocoaTouch)) {
421 if (image)
422 AddRepresentation(make_scoped_ptr(new internal::ImageRepCocoaTouch(image)));
424 #elif defined(OS_MACOSX)
425 Image::Image(NSImage* image) {
426 if (image) {
427 storage_ = new internal::ImageStorage(Image::kImageRepCocoa);
428 AddRepresentation(make_scoped_ptr(new internal::ImageRepCocoa(image)));
431 #endif
433 Image::Image(const Image& other) : storage_(other.storage_) {
436 Image& Image::operator=(const Image& other) {
437 storage_ = other.storage_;
438 return *this;
441 Image::~Image() {
444 // static
445 Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) {
446 return Image(ImageSkia::CreateFrom1xBitmap(bitmap));
449 // static
450 Image Image::CreateFrom1xPNGBytes(const unsigned char* input,
451 size_t input_size) {
452 if (input_size == 0u)
453 return Image();
455 scoped_refptr<base::RefCountedBytes> raw_data(new base::RefCountedBytes());
456 raw_data->data().assign(input, input + input_size);
458 return CreateFrom1xPNGBytes(raw_data);
461 Image Image::CreateFrom1xPNGBytes(
462 const scoped_refptr<base::RefCountedMemory>& input) {
463 if (!input.get() || input->size() == 0u)
464 return Image();
466 std::vector<ImagePNGRep> image_reps;
467 image_reps.push_back(ImagePNGRep(input, 1.0f));
468 return Image(image_reps);
471 const SkBitmap* Image::ToSkBitmap() const {
472 // Possibly create and cache an intermediate ImageRepSkia.
473 return ToImageSkia()->bitmap();
476 const ImageSkia* Image::ToImageSkia() const {
477 internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false);
478 if (!rep) {
479 scoped_ptr<internal::ImageRep> scoped_rep;
480 switch (DefaultRepresentationType()) {
481 case kImageRepPNG: {
482 internal::ImageRepPNG* png_rep =
483 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
484 scoped_rep.reset(new internal::ImageRepSkia(
485 internal::ImageSkiaFromPNG(png_rep->image_reps())));
486 break;
488 #if defined(OS_IOS)
489 case kImageRepCocoaTouch: {
490 internal::ImageRepCocoaTouch* native_rep =
491 GetRepresentation(kImageRepCocoaTouch, true)
492 ->AsImageRepCocoaTouch();
493 scoped_rep.reset(new internal::ImageRepSkia(
494 new ImageSkia(ImageSkiaFromUIImage(native_rep->image()))));
495 break;
497 #elif defined(OS_MACOSX)
498 case kImageRepCocoa: {
499 internal::ImageRepCocoa* native_rep =
500 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
501 scoped_rep.reset(new internal::ImageRepSkia(
502 new ImageSkia(ImageSkiaFromNSImage(native_rep->image()))));
503 break;
505 #endif
506 default:
507 NOTREACHED();
509 CHECK(scoped_rep);
510 rep = scoped_rep.get();
511 AddRepresentation(scoped_rep.Pass());
513 return rep->AsImageRepSkia()->image();
516 #if defined(OS_IOS)
517 UIImage* Image::ToUIImage() const {
518 internal::ImageRep* rep = GetRepresentation(kImageRepCocoaTouch, false);
519 if (!rep) {
520 scoped_ptr<internal::ImageRep> scoped_rep;
521 switch (DefaultRepresentationType()) {
522 case kImageRepPNG: {
523 internal::ImageRepPNG* png_rep =
524 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
525 scoped_rep.reset(new internal::ImageRepCocoaTouch(
526 internal::CreateUIImageFromPNG(png_rep->image_reps())));
527 break;
529 case kImageRepSkia: {
530 internal::ImageRepSkia* skia_rep =
531 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
532 UIImage* image = UIImageFromImageSkia(*skia_rep->image());
533 base::mac::NSObjectRetain(image);
534 scoped_rep.reset(new internal::ImageRepCocoaTouch(image));
535 break;
537 default:
538 NOTREACHED();
540 CHECK(scoped_rep);
541 rep = scoped_rep.get();
542 AddRepresentation(scoped_rep.Pass());
544 return rep->AsImageRepCocoaTouch()->image();
546 #elif defined(OS_MACOSX)
547 NSImage* Image::ToNSImage() const {
548 internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
549 if (!rep) {
550 scoped_ptr<internal::ImageRep> scoped_rep;
551 CGColorSpaceRef default_representation_color_space =
552 storage_->default_representation_color_space();
554 switch (DefaultRepresentationType()) {
555 case kImageRepPNG: {
556 internal::ImageRepPNG* png_rep =
557 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
558 scoped_rep.reset(new internal::ImageRepCocoa(internal::NSImageFromPNG(
559 png_rep->image_reps(), default_representation_color_space)));
560 break;
562 case kImageRepSkia: {
563 internal::ImageRepSkia* skia_rep =
564 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
565 NSImage* image = NSImageFromImageSkiaWithColorSpace(*skia_rep->image(),
566 default_representation_color_space);
567 base::mac::NSObjectRetain(image);
568 scoped_rep.reset(new internal::ImageRepCocoa(image));
569 break;
571 default:
572 NOTREACHED();
574 CHECK(scoped_rep);
575 rep = scoped_rep.get();
576 AddRepresentation(scoped_rep.Pass());
578 return rep->AsImageRepCocoa()->image();
580 #endif
582 scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
583 if (IsEmpty())
584 return new base::RefCountedBytes();
586 internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
588 if (rep) {
589 const std::vector<ImagePNGRep>& image_png_reps =
590 rep->AsImageRepPNG()->image_reps();
591 for (size_t i = 0; i < image_png_reps.size(); ++i) {
592 if (image_png_reps[i].scale == 1.0f)
593 return image_png_reps[i].raw_data;
595 return new base::RefCountedBytes();
598 scoped_refptr<base::RefCountedMemory> png_bytes(NULL);
599 switch (DefaultRepresentationType()) {
600 #if defined(OS_IOS)
601 case kImageRepCocoaTouch: {
602 internal::ImageRepCocoaTouch* cocoa_touch_rep =
603 GetRepresentation(kImageRepCocoaTouch, true)
604 ->AsImageRepCocoaTouch();
605 png_bytes = internal::Get1xPNGBytesFromUIImage(
606 cocoa_touch_rep->image());
607 break;
609 #elif defined(OS_MACOSX)
610 case kImageRepCocoa: {
611 internal::ImageRepCocoa* cocoa_rep =
612 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
613 png_bytes = internal::Get1xPNGBytesFromNSImage(cocoa_rep->image());
614 break;
616 #endif
617 case kImageRepSkia: {
618 internal::ImageRepSkia* skia_rep =
619 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
620 png_bytes = internal::Get1xPNGBytesFromImageSkia(skia_rep->image());
621 break;
623 default:
624 NOTREACHED();
626 if (!png_bytes.get() || !png_bytes->size()) {
627 // Add an ImageRepPNG with no data such that the conversion is not
628 // attempted each time we want the PNG bytes.
629 AddRepresentation(make_scoped_ptr(new internal::ImageRepPNG()));
630 return new base::RefCountedBytes();
633 // Do not insert representations for scale factors other than 1x even if
634 // they are available because:
635 // - Only the 1x PNG bytes can be accessed.
636 // - ImageRepPNG is not used as an intermediate type in converting to a
637 // final type eg (converting from ImageRepSkia to ImageRepPNG to get an
638 // ImageRepCocoa).
639 std::vector<ImagePNGRep> image_png_reps;
640 image_png_reps.push_back(ImagePNGRep(png_bytes, 1.0f));
641 AddRepresentation(make_scoped_ptr(new internal::ImageRepPNG(image_png_reps)));
642 return png_bytes;
645 SkBitmap Image::AsBitmap() const {
646 return IsEmpty() ? SkBitmap() : *ToSkBitmap();
649 ImageSkia Image::AsImageSkia() const {
650 return IsEmpty() ? ImageSkia() : *ToImageSkia();
653 #if defined(OS_MACOSX) && !defined(OS_IOS)
654 NSImage* Image::AsNSImage() const {
655 return IsEmpty() ? nil : ToNSImage();
657 #endif
659 scoped_refptr<base::RefCountedMemory> Image::Copy1xPNGBytes() const {
660 scoped_refptr<base::RefCountedMemory> original = As1xPNGBytes();
661 scoped_refptr<base::RefCountedBytes> copy(new base::RefCountedBytes());
662 copy->data().assign(original->front(), original->front() + original->size());
663 return copy;
666 ImageSkia* Image::CopyImageSkia() const {
667 return new ImageSkia(*ToImageSkia());
670 SkBitmap* Image::CopySkBitmap() const {
671 return new SkBitmap(*ToSkBitmap());
674 #if defined(OS_IOS)
675 UIImage* Image::CopyUIImage() const {
676 UIImage* image = ToUIImage();
677 base::mac::NSObjectRetain(image);
678 return image;
680 #elif defined(OS_MACOSX)
681 NSImage* Image::CopyNSImage() const {
682 NSImage* image = ToNSImage();
683 base::mac::NSObjectRetain(image);
684 return image;
686 #endif
688 bool Image::HasRepresentation(RepresentationType type) const {
689 return storage_.get() && storage_->representations().count(type) != 0;
692 size_t Image::RepresentationCount() const {
693 if (!storage_.get())
694 return 0;
696 return storage_->representations().size();
699 bool Image::IsEmpty() const {
700 return RepresentationCount() == 0;
703 int Image::Width() const {
704 if (IsEmpty())
705 return 0;
706 return GetRepresentation(DefaultRepresentationType(), true)->Width();
709 int Image::Height() const {
710 if (IsEmpty())
711 return 0;
712 return GetRepresentation(DefaultRepresentationType(), true)->Height();
715 gfx::Size Image::Size() const {
716 if (IsEmpty())
717 return gfx::Size();
718 return GetRepresentation(DefaultRepresentationType(), true)->Size();
721 void Image::SwapRepresentations(Image* other) {
722 storage_.swap(other->storage_);
725 #if defined(OS_MACOSX) && !defined(OS_IOS)
726 void Image::SetSourceColorSpace(CGColorSpaceRef color_space) {
727 if (storage_.get())
728 storage_->set_default_representation_color_space(color_space);
730 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
732 Image::RepresentationType Image::DefaultRepresentationType() const {
733 CHECK(storage_.get());
734 return storage_->default_representation_type();
737 internal::ImageRep* Image::GetRepresentation(
738 RepresentationType rep_type, bool must_exist) const {
739 CHECK(storage_.get());
740 RepresentationMap::const_iterator it =
741 storage_->representations().find(rep_type);
742 if (it == storage_->representations().end()) {
743 CHECK(!must_exist);
744 return NULL;
746 return it->second;
749 void Image::AddRepresentation(scoped_ptr<internal::ImageRep> rep) const {
750 CHECK(storage_.get());
751 RepresentationType type = rep->type();
752 storage_->representations().insert(type, rep.Pass());
755 } // namespace gfx