Implement MoveFileLocal (with creating a snapshot).
[chromium-blink-merge.git] / ui / gfx / image / image.cc
blob170c51465df3f38fa92ab1299a6aeac7845fcf14
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 "base/memory/scoped_ptr.h"
12 #include "base/stl_util.h"
13 #include "third_party/skia/include/core/SkBitmap.h"
14 #include "ui/gfx/geometry/size.h"
15 #include "ui/gfx/image/image_png_rep.h"
16 #include "ui/gfx/image/image_skia.h"
17 #include "ui/gfx/image/image_skia_source.h"
19 #if !defined(OS_IOS)
20 #include "ui/gfx/codec/png_codec.h"
21 #endif
23 #if defined(OS_IOS)
24 #include "base/mac/foundation_util.h"
25 #include "ui/gfx/image/image_skia_util_ios.h"
26 #elif defined(OS_MACOSX)
27 #include "base/mac/foundation_util.h"
28 #include "base/mac/mac_util.h"
29 #include "ui/gfx/image/image_skia_util_mac.h"
30 #endif
32 namespace gfx {
34 namespace internal {
36 #if defined(OS_IOS)
37 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
38 UIImage* uiimage);
39 // Caller takes ownership of the returned UIImage.
40 UIImage* CreateUIImageFromPNG(
41 const std::vector<ImagePNGRep>& image_png_reps);
42 gfx::Size UIImageSize(UIImage* image);
43 #elif defined(OS_MACOSX)
44 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
45 NSImage* nsimage);
46 // Caller takes ownership of the returned NSImage.
47 NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
48 CGColorSpaceRef color_space);
49 gfx::Size NSImageSize(NSImage* image);
50 #endif // defined(OS_MACOSX)
52 #if defined(OS_IOS)
53 ImageSkia* ImageSkiaFromPNG(
54 const std::vector<ImagePNGRep>& image_png_reps);
55 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
56 const ImageSkia* skia);
57 #else
58 // Returns a 16x16 red image to visually show error in decoding PNG.
59 // Caller takes ownership of returned ImageSkia.
60 ImageSkia* GetErrorImageSkia() {
61 SkBitmap bitmap;
62 bitmap.allocN32Pixels(16, 16);
63 bitmap.eraseARGB(0xff, 0xff, 0, 0);
64 return new ImageSkia(ImageSkiaRep(bitmap, 1.0f));
67 class PNGImageSource : public ImageSkiaSource {
68 public:
69 PNGImageSource() {}
70 ~PNGImageSource() override {}
72 ImageSkiaRep GetImageForScale(float scale) override {
73 if (image_skia_reps_.empty())
74 return ImageSkiaRep();
76 const ImageSkiaRep* rep = NULL;
77 // gfx::ImageSkia passes one of the resource scale factors. The source
78 // should return:
79 // 1) The ImageSkiaRep with the highest scale if all available
80 // scales are smaller than |scale|.
81 // 2) The ImageSkiaRep with the smallest one that is larger than |scale|.
82 for (ImageSkiaRepSet::const_iterator iter = image_skia_reps_.begin();
83 iter != image_skia_reps_.end(); ++iter) {
84 if ((*iter).scale() == scale)
85 return (*iter);
86 if (!rep || rep->scale() < (*iter).scale())
87 rep = &(*iter);
88 if (rep->scale() >= scale)
89 break;
91 return rep ? *rep : ImageSkiaRep();
94 const gfx::Size size() const {
95 return size_;
98 bool AddPNGData(const ImagePNGRep& png_rep) {
99 const gfx::ImageSkiaRep rep = ToImageSkiaRep(png_rep);
100 if (rep.is_null())
101 return false;
102 if (size_.IsEmpty())
103 size_ = gfx::Size(rep.GetWidth(), rep.GetHeight());
104 image_skia_reps_.insert(rep);
105 return true;
108 static ImageSkiaRep ToImageSkiaRep(const ImagePNGRep& png_rep) {
109 scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data;
110 CHECK(raw_data.get());
111 SkBitmap bitmap;
112 if (!PNGCodec::Decode(raw_data->front(), raw_data->size(),
113 &bitmap)) {
114 LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << ".";
115 return ImageSkiaRep();
117 return ImageSkiaRep(bitmap, png_rep.scale);
120 private:
121 struct Compare {
122 bool operator()(const ImageSkiaRep& rep1, const ImageSkiaRep& rep2) {
123 return rep1.scale() < rep2.scale();
127 typedef std::set<ImageSkiaRep, Compare> ImageSkiaRepSet;
128 ImageSkiaRepSet image_skia_reps_;
129 gfx::Size size_;
131 DISALLOW_COPY_AND_ASSIGN(PNGImageSource);
134 ImageSkia* ImageSkiaFromPNG(
135 const std::vector<ImagePNGRep>& image_png_reps) {
136 if (image_png_reps.empty())
137 return GetErrorImageSkia();
138 scoped_ptr<PNGImageSource> image_source(new PNGImageSource);
140 for (size_t i = 0; i < image_png_reps.size(); ++i) {
141 if (!image_source->AddPNGData(image_png_reps[i]))
142 return GetErrorImageSkia();
144 const gfx::Size& size = image_source->size();
145 DCHECK(!size.IsEmpty());
146 if (size.IsEmpty())
147 return GetErrorImageSkia();
148 return new ImageSkia(image_source.release(), size);
151 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
152 const ImageSkia* image_skia) {
153 ImageSkiaRep image_skia_rep = image_skia->GetRepresentation(1.0f);
155 scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
156 if (image_skia_rep.scale() != 1.0f ||
157 !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
158 &png_bytes->data())) {
159 return NULL;
161 return png_bytes;
163 #endif
165 class ImageRepPNG;
166 class ImageRepSkia;
167 class ImageRepCocoa;
168 class ImageRepCocoaTouch;
170 // An ImageRep is the object that holds the backing memory for an Image. Each
171 // RepresentationType has an ImageRep subclass that is responsible for freeing
172 // the memory that the ImageRep holds. When an ImageRep is created, it expects
173 // to take ownership of the image, without having to retain it or increase its
174 // reference count.
175 class ImageRep {
176 public:
177 explicit ImageRep(Image::RepresentationType rep) : type_(rep) {}
179 // Deletes the associated pixels of an ImageRep.
180 virtual ~ImageRep() {}
182 // Cast helpers ("fake RTTI").
183 ImageRepPNG* AsImageRepPNG() {
184 CHECK_EQ(type_, Image::kImageRepPNG);
185 return reinterpret_cast<ImageRepPNG*>(this);
188 ImageRepSkia* AsImageRepSkia() {
189 CHECK_EQ(type_, Image::kImageRepSkia);
190 return reinterpret_cast<ImageRepSkia*>(this);
193 #if defined(OS_IOS)
194 ImageRepCocoaTouch* AsImageRepCocoaTouch() {
195 CHECK_EQ(type_, Image::kImageRepCocoaTouch);
196 return reinterpret_cast<ImageRepCocoaTouch*>(this);
198 #elif defined(OS_MACOSX)
199 ImageRepCocoa* AsImageRepCocoa() {
200 CHECK_EQ(type_, Image::kImageRepCocoa);
201 return reinterpret_cast<ImageRepCocoa*>(this);
203 #endif
205 Image::RepresentationType type() const { return type_; }
207 virtual int Width() const = 0;
208 virtual int Height() const = 0;
209 virtual gfx::Size Size() const = 0;
211 private:
212 Image::RepresentationType type_;
215 class ImageRepPNG : public ImageRep {
216 public:
217 ImageRepPNG() : ImageRep(Image::kImageRepPNG) {
220 ImageRepPNG(const std::vector<ImagePNGRep>& image_png_reps)
221 : ImageRep(Image::kImageRepPNG),
222 image_png_reps_(image_png_reps) {
225 ~ImageRepPNG() override {}
227 int Width() const override { return Size().width(); }
229 int Height() const override { return Size().height(); }
231 gfx::Size Size() const override {
232 // Read the PNG data to get the image size, caching it.
233 if (!size_cache_) {
234 for (std::vector<ImagePNGRep>::const_iterator it = image_reps().begin();
235 it != image_reps().end(); ++it) {
236 if (it->scale == 1.0f) {
237 size_cache_.reset(new gfx::Size(it->Size()));
238 return *size_cache_;
241 size_cache_.reset(new gfx::Size);
244 return *size_cache_;
247 const std::vector<ImagePNGRep>& image_reps() const { return image_png_reps_; }
249 private:
250 std::vector<ImagePNGRep> image_png_reps_;
252 // Cached to avoid having to parse the raw data multiple times.
253 mutable scoped_ptr<gfx::Size> size_cache_;
255 DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
258 class ImageRepSkia : public ImageRep {
259 public:
260 // Takes ownership of |image|.
261 explicit ImageRepSkia(ImageSkia* image)
262 : ImageRep(Image::kImageRepSkia),
263 image_(image) {
266 ~ImageRepSkia() override {}
268 int Width() const override { return image_->width(); }
270 int Height() const override { return image_->height(); }
272 gfx::Size Size() const override { return image_->size(); }
274 ImageSkia* image() { return image_.get(); }
276 private:
277 scoped_ptr<ImageSkia> image_;
279 DISALLOW_COPY_AND_ASSIGN(ImageRepSkia);
282 #if defined(OS_IOS)
283 class ImageRepCocoaTouch : public ImageRep {
284 public:
285 explicit ImageRepCocoaTouch(UIImage* image)
286 : ImageRep(Image::kImageRepCocoaTouch),
287 image_(image) {
288 CHECK(image);
291 ~ImageRepCocoaTouch() override {
292 base::mac::NSObjectRelease(image_);
293 image_ = nil;
296 int Width() const override { return Size().width(); }
298 int Height() const override { return Size().height(); }
300 gfx::Size Size() const override { return internal::UIImageSize(image_); }
302 UIImage* image() const { return image_; }
304 private:
305 UIImage* image_;
307 DISALLOW_COPY_AND_ASSIGN(ImageRepCocoaTouch);
309 #elif defined(OS_MACOSX)
310 class ImageRepCocoa : public ImageRep {
311 public:
312 explicit ImageRepCocoa(NSImage* image)
313 : ImageRep(Image::kImageRepCocoa),
314 image_(image) {
315 CHECK(image);
318 ~ImageRepCocoa() override {
319 base::mac::NSObjectRelease(image_);
320 image_ = nil;
323 int Width() const override { return Size().width(); }
325 int Height() const override { return Size().height(); }
327 gfx::Size Size() const override { return internal::NSImageSize(image_); }
329 NSImage* image() const { return image_; }
331 private:
332 NSImage* image_;
334 DISALLOW_COPY_AND_ASSIGN(ImageRepCocoa);
336 #endif // defined(OS_MACOSX)
338 // The Storage class acts similarly to the pixels in a SkBitmap: the Image
339 // class holds a refptr instance of Storage, which in turn holds all the
340 // ImageReps. This way, the Image can be cheaply copied.
341 class ImageStorage : public base::RefCounted<ImageStorage> {
342 public:
343 ImageStorage(Image::RepresentationType default_type)
344 : default_representation_type_(default_type),
345 #if defined(OS_MACOSX) && !defined(OS_IOS)
346 default_representation_color_space_(
347 base::mac::GetGenericRGBColorSpace()),
348 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
349 representations_deleter_(&representations_) {
352 Image::RepresentationType default_representation_type() {
353 return default_representation_type_;
355 Image::RepresentationMap& representations() { return representations_; }
357 #if defined(OS_MACOSX) && !defined(OS_IOS)
358 void set_default_representation_color_space(CGColorSpaceRef color_space) {
359 default_representation_color_space_ = color_space;
361 CGColorSpaceRef default_representation_color_space() {
362 return default_representation_color_space_;
364 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
366 private:
367 friend class base::RefCounted<ImageStorage>;
369 ~ImageStorage() {}
371 // The type of image that was passed to the constructor. This key will always
372 // exist in the |representations_| map.
373 Image::RepresentationType default_representation_type_;
375 #if defined(OS_MACOSX) && !defined(OS_IOS)
376 // The default representation's colorspace. This is used for converting to
377 // NSImage. This field exists to compensate for PNGCodec not writing or
378 // reading colorspace ancillary chunks. (sRGB, iCCP).
379 // Not owned.
380 CGColorSpaceRef default_representation_color_space_;
381 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
383 // All the representations of an Image. Size will always be at least one, with
384 // more for any converted representations.
385 Image::RepresentationMap representations_;
387 STLValueDeleter<Image::RepresentationMap> representations_deleter_;
389 DISALLOW_COPY_AND_ASSIGN(ImageStorage);
392 } // namespace internal
394 Image::Image() {
395 // |storage_| is NULL for empty Images.
398 Image::Image(const std::vector<ImagePNGRep>& image_reps) {
399 // Do not store obviously invalid ImagePNGReps.
400 std::vector<ImagePNGRep> filtered;
401 for (size_t i = 0; i < image_reps.size(); ++i) {
402 if (image_reps[i].raw_data.get() && image_reps[i].raw_data->size())
403 filtered.push_back(image_reps[i]);
406 if (filtered.empty())
407 return;
409 storage_ = new internal::ImageStorage(Image::kImageRepPNG);
410 internal::ImageRepPNG* rep = new internal::ImageRepPNG(filtered);
411 AddRepresentation(rep);
414 Image::Image(const ImageSkia& image) {
415 if (!image.isNull()) {
416 storage_ = new internal::ImageStorage(Image::kImageRepSkia);
417 internal::ImageRepSkia* rep = new internal::ImageRepSkia(
418 new ImageSkia(image));
419 AddRepresentation(rep);
423 #if defined(OS_IOS)
424 Image::Image(UIImage* image)
425 : storage_(new internal::ImageStorage(Image::kImageRepCocoaTouch)) {
426 if (image) {
427 internal::ImageRepCocoaTouch* rep = new internal::ImageRepCocoaTouch(image);
428 AddRepresentation(rep);
431 #elif defined(OS_MACOSX)
432 Image::Image(NSImage* image) {
433 if (image) {
434 storage_ = new internal::ImageStorage(Image::kImageRepCocoa);
435 internal::ImageRepCocoa* rep = new internal::ImageRepCocoa(image);
436 AddRepresentation(rep);
439 #endif
441 Image::Image(const Image& other) : storage_(other.storage_) {
444 Image& Image::operator=(const Image& other) {
445 storage_ = other.storage_;
446 return *this;
449 Image::~Image() {
452 // static
453 Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) {
454 return Image(ImageSkia::CreateFrom1xBitmap(bitmap));
457 // static
458 Image Image::CreateFrom1xPNGBytes(const unsigned char* input,
459 size_t input_size) {
460 if (input_size == 0u)
461 return Image();
463 scoped_refptr<base::RefCountedBytes> raw_data(new base::RefCountedBytes());
464 raw_data->data().assign(input, input + input_size);
466 return CreateFrom1xPNGBytes(raw_data);
469 Image Image::CreateFrom1xPNGBytes(
470 const scoped_refptr<base::RefCountedMemory>& input) {
471 if (!input.get() || input->size() == 0u)
472 return Image();
474 std::vector<ImagePNGRep> image_reps;
475 image_reps.push_back(ImagePNGRep(input, 1.0f));
476 return Image(image_reps);
479 const SkBitmap* Image::ToSkBitmap() const {
480 // Possibly create and cache an intermediate ImageRepSkia.
481 return ToImageSkia()->bitmap();
484 const ImageSkia* Image::ToImageSkia() const {
485 internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false);
486 if (!rep) {
487 switch (DefaultRepresentationType()) {
488 case kImageRepPNG: {
489 internal::ImageRepPNG* png_rep =
490 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
491 rep = new internal::ImageRepSkia(
492 internal::ImageSkiaFromPNG(png_rep->image_reps()));
493 break;
495 #if defined(OS_IOS)
496 case kImageRepCocoaTouch: {
497 internal::ImageRepCocoaTouch* native_rep =
498 GetRepresentation(kImageRepCocoaTouch, true)
499 ->AsImageRepCocoaTouch();
500 rep = new internal::ImageRepSkia(new ImageSkia(
501 ImageSkiaFromUIImage(native_rep->image())));
502 break;
504 #elif defined(OS_MACOSX)
505 case kImageRepCocoa: {
506 internal::ImageRepCocoa* native_rep =
507 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
508 rep = new internal::ImageRepSkia(new ImageSkia(
509 ImageSkiaFromNSImage(native_rep->image())));
510 break;
512 #endif
513 default:
514 NOTREACHED();
516 CHECK(rep);
517 AddRepresentation(rep);
519 return rep->AsImageRepSkia()->image();
522 #if defined(OS_IOS)
523 UIImage* Image::ToUIImage() const {
524 internal::ImageRep* rep = GetRepresentation(kImageRepCocoaTouch, false);
525 if (!rep) {
526 switch (DefaultRepresentationType()) {
527 case kImageRepPNG: {
528 internal::ImageRepPNG* png_rep =
529 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
530 rep = new internal::ImageRepCocoaTouch(internal::CreateUIImageFromPNG(
531 png_rep->image_reps()));
532 break;
534 case kImageRepSkia: {
535 internal::ImageRepSkia* skia_rep =
536 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
537 UIImage* image = UIImageFromImageSkia(*skia_rep->image());
538 base::mac::NSObjectRetain(image);
539 rep = new internal::ImageRepCocoaTouch(image);
540 break;
542 default:
543 NOTREACHED();
545 CHECK(rep);
546 AddRepresentation(rep);
548 return rep->AsImageRepCocoaTouch()->image();
550 #elif defined(OS_MACOSX)
551 NSImage* Image::ToNSImage() const {
552 internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
553 if (!rep) {
554 CGColorSpaceRef default_representation_color_space =
555 storage_->default_representation_color_space();
557 switch (DefaultRepresentationType()) {
558 case kImageRepPNG: {
559 internal::ImageRepPNG* png_rep =
560 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
561 rep = new internal::ImageRepCocoa(internal::NSImageFromPNG(
562 png_rep->image_reps(), default_representation_color_space));
563 break;
565 case kImageRepSkia: {
566 internal::ImageRepSkia* skia_rep =
567 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
568 NSImage* image = NSImageFromImageSkiaWithColorSpace(*skia_rep->image(),
569 default_representation_color_space);
570 base::mac::NSObjectRetain(image);
571 rep = new internal::ImageRepCocoa(image);
572 break;
574 default:
575 NOTREACHED();
577 CHECK(rep);
578 AddRepresentation(rep);
580 return rep->AsImageRepCocoa()->image();
582 #endif
584 scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
585 if (IsEmpty())
586 return new base::RefCountedBytes();
588 internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
590 if (rep) {
591 const std::vector<ImagePNGRep>& image_png_reps =
592 rep->AsImageRepPNG()->image_reps();
593 for (size_t i = 0; i < image_png_reps.size(); ++i) {
594 if (image_png_reps[i].scale == 1.0f)
595 return image_png_reps[i].raw_data;
597 return new base::RefCountedBytes();
600 scoped_refptr<base::RefCountedMemory> png_bytes(NULL);
601 switch (DefaultRepresentationType()) {
602 #if defined(OS_IOS)
603 case kImageRepCocoaTouch: {
604 internal::ImageRepCocoaTouch* cocoa_touch_rep =
605 GetRepresentation(kImageRepCocoaTouch, true)
606 ->AsImageRepCocoaTouch();
607 png_bytes = internal::Get1xPNGBytesFromUIImage(
608 cocoa_touch_rep->image());
609 break;
611 #elif defined(OS_MACOSX)
612 case kImageRepCocoa: {
613 internal::ImageRepCocoa* cocoa_rep =
614 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
615 png_bytes = internal::Get1xPNGBytesFromNSImage(cocoa_rep->image());
616 break;
618 #endif
619 case kImageRepSkia: {
620 internal::ImageRepSkia* skia_rep =
621 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
622 png_bytes = internal::Get1xPNGBytesFromImageSkia(skia_rep->image());
623 break;
625 default:
626 NOTREACHED();
628 if (!png_bytes.get() || !png_bytes->size()) {
629 // Add an ImageRepPNG with no data such that the conversion is not
630 // attempted each time we want the PNG bytes.
631 AddRepresentation(new internal::ImageRepPNG());
632 return new base::RefCountedBytes();
635 // Do not insert representations for scale factors other than 1x even if
636 // they are available because:
637 // - Only the 1x PNG bytes can be accessed.
638 // - ImageRepPNG is not used as an intermediate type in converting to a
639 // final type eg (converting from ImageRepSkia to ImageRepPNG to get an
640 // ImageRepCocoa).
641 std::vector<ImagePNGRep> image_png_reps;
642 image_png_reps.push_back(ImagePNGRep(png_bytes, 1.0f));
643 rep = new internal::ImageRepPNG(image_png_reps);
644 AddRepresentation(rep);
645 return png_bytes;
648 SkBitmap Image::AsBitmap() const {
649 return IsEmpty() ? SkBitmap() : *ToSkBitmap();
652 ImageSkia Image::AsImageSkia() const {
653 return IsEmpty() ? ImageSkia() : *ToImageSkia();
656 #if defined(OS_MACOSX) && !defined(OS_IOS)
657 NSImage* Image::AsNSImage() const {
658 return IsEmpty() ? nil : ToNSImage();
660 #endif
662 scoped_refptr<base::RefCountedMemory> Image::Copy1xPNGBytes() const {
663 scoped_refptr<base::RefCountedMemory> original = As1xPNGBytes();
664 scoped_refptr<base::RefCountedBytes> copy(new base::RefCountedBytes());
665 copy->data().assign(original->front(), original->front() + original->size());
666 return copy;
669 ImageSkia* Image::CopyImageSkia() const {
670 return new ImageSkia(*ToImageSkia());
673 SkBitmap* Image::CopySkBitmap() const {
674 return new SkBitmap(*ToSkBitmap());
677 #if defined(OS_IOS)
678 UIImage* Image::CopyUIImage() const {
679 UIImage* image = ToUIImage();
680 base::mac::NSObjectRetain(image);
681 return image;
683 #elif defined(OS_MACOSX)
684 NSImage* Image::CopyNSImage() const {
685 NSImage* image = ToNSImage();
686 base::mac::NSObjectRetain(image);
687 return image;
689 #endif
691 bool Image::HasRepresentation(RepresentationType type) const {
692 return storage_.get() && storage_->representations().count(type) != 0;
695 size_t Image::RepresentationCount() const {
696 if (!storage_.get())
697 return 0;
699 return storage_->representations().size();
702 bool Image::IsEmpty() const {
703 return RepresentationCount() == 0;
706 int Image::Width() const {
707 if (IsEmpty())
708 return 0;
709 return GetRepresentation(DefaultRepresentationType(), true)->Width();
712 int Image::Height() const {
713 if (IsEmpty())
714 return 0;
715 return GetRepresentation(DefaultRepresentationType(), true)->Height();
718 gfx::Size Image::Size() const {
719 if (IsEmpty())
720 return gfx::Size();
721 return GetRepresentation(DefaultRepresentationType(), true)->Size();
724 void Image::SwapRepresentations(Image* other) {
725 storage_.swap(other->storage_);
728 #if defined(OS_MACOSX) && !defined(OS_IOS)
729 void Image::SetSourceColorSpace(CGColorSpaceRef color_space) {
730 if (storage_.get())
731 storage_->set_default_representation_color_space(color_space);
733 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
735 Image::RepresentationType Image::DefaultRepresentationType() const {
736 CHECK(storage_.get());
737 return storage_->default_representation_type();
740 internal::ImageRep* Image::GetRepresentation(
741 RepresentationType rep_type, bool must_exist) const {
742 CHECK(storage_.get());
743 RepresentationMap::iterator it = storage_->representations().find(rep_type);
744 if (it == storage_->representations().end()) {
745 CHECK(!must_exist);
746 return NULL;
748 return it->second;
751 void Image::AddRepresentation(internal::ImageRep* rep) const {
752 CHECK(storage_.get());
753 storage_->representations().insert(std::make_pair(rep->type(), rep));
756 } // namespace gfx