Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: ui/gfx/image/image.cc

Issue 10826181: Revert r150228 "Add support for PNG representation in gfx::Image" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/gfx/image/image.h ('k') | ui/gfx/image/image_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/image/image.h" 5 #include "ui/gfx/image/image.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "third_party/skia/include/core/SkBitmap.h" 11 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "ui/gfx/codec/png_codec.h"
13 #include "ui/gfx/image/image_skia.h" 12 #include "ui/gfx/image/image_skia.h"
14 #include "ui/gfx/size.h" 13 #include "ui/gfx/size.h"
15 14
16 #if defined(TOOLKIT_GTK) 15 #if defined(TOOLKIT_GTK)
17 #include <gdk-pixbuf/gdk-pixbuf.h> 16 #include <gdk-pixbuf/gdk-pixbuf.h>
18 #include <gdk/gdk.h> 17 #include <gdk/gdk.h>
19 #include <glib-object.h> 18 #include <glib-object.h>
20 #include "ui/base/gtk/scoped_gobject.h"
21 #include "ui/gfx/canvas.h" 19 #include "ui/gfx/canvas.h"
22 #include "ui/gfx/gtk_util.h" 20 #include "ui/gfx/gtk_util.h"
23 #include "ui/gfx/image/cairo_cached_surface.h" 21 #include "ui/gfx/image/cairo_cached_surface.h"
24 #elif defined(OS_MACOSX) 22 #elif defined(OS_MACOSX)
25 #include "base/mac/mac_util.h" 23 #include "base/mac/mac_util.h"
26 #include "ui/gfx/image/image_skia_util_mac.h" 24 #include "ui/gfx/image/image_skia_util_mac.h"
27 #endif 25 #endif
28 26
29 namespace gfx { 27 namespace gfx {
30 28
31 namespace internal { 29 namespace internal {
32 30
33 #if defined(TOOLKIT_GTK) 31 #if defined(TOOLKIT_GTK)
34 const ImageSkia ImageSkiaFromGdkPixbuf(GdkPixbuf* pixbuf) { 32 const ImageSkia ImageSkiaFromGdkPixbuf(GdkPixbuf* pixbuf) {
35 CHECK(pixbuf); 33 CHECK(pixbuf);
36 gfx::Canvas canvas(gfx::Size(gdk_pixbuf_get_width(pixbuf), 34 gfx::Canvas canvas(gfx::Size(gdk_pixbuf_get_width(pixbuf),
37 gdk_pixbuf_get_height(pixbuf)), 35 gdk_pixbuf_get_height(pixbuf)),
38 ui::SCALE_FACTOR_100P, 36 ui::SCALE_FACTOR_100P,
39 false); 37 false);
40 skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas()); 38 skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
41 cairo_t* cr = scoped_platform_paint.GetPlatformSurface(); 39 cairo_t* cr = scoped_platform_paint.GetPlatformSurface();
42 gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); 40 gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
43 cairo_paint(cr); 41 cairo_paint(cr);
44 return ImageSkia(canvas.ExtractImageRep()); 42 return ImageSkia(canvas.ExtractImageRep());
45 } 43 }
44 #endif
46 45
47 GdkPixbuf* GdkPixbufFromPNG(const std::vector<unsigned char>& png) {
48 GdkPixbuf* pixbuf = NULL;
49 ui::ScopedGObject<GdkPixbufLoader>::Type loader(gdk_pixbuf_loader_new());
50
51 bool ok = gdk_pixbuf_loader_write(loader.get(),
52 reinterpret_cast<const guint8*>(&png.front()), png.size(), NULL);
53
54 // Calling gdk_pixbuf_loader_close forces the data to be parsed by the
55 // loader. This must be done before calling gdk_pixbuf_loader_get_pixbuf.
56 if (ok)
57 ok = gdk_pixbuf_loader_close(loader.get(), NULL);
58 if (ok)
59 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader.get());
60
61 if (pixbuf) {
62 // The pixbuf is owned by the scoped loader which will delete its ref when
63 // it goes out of scope. Add a ref so that the pixbuf still exists.
64 g_object_ref(pixbuf);
65 } else {
66 LOG(WARNING) << "Unable to decode PNG.";
67 // Return a 16x16 red image to visually show error.
68 pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 16, 16);
69 gdk_pixbuf_fill(pixbuf, 0xff0000ff);
70 }
71
72 return pixbuf;
73 }
74
75 void PNGFromGdkPixbuf(GdkPixbuf* pixbuf, std::vector<unsigned char>* png) {
76 gchar* image = NULL;
77 gsize image_size;
78 GError* error = NULL;
79 CHECK(gdk_pixbuf_save_to_buffer(
80 pixbuf, &image, &image_size, "png", &error, NULL));
81 png->assign(image, image + image_size);
82 g_free(image);
83 }
84
85 #endif // defined(TOOLKIT_GTK)
86
87 #if defined(OS_MACOSX)
88 void PNGFromNSImage(NSImage* nsimage, std::vector<unsigned char>* png);
89 NSImage* NSImageFromPNG(const std::vector<unsigned char>& png);
90 #endif // defined(OS_MACOSX)
91
92 ImageSkia* ImageSkiaFromPNG(const std::vector<unsigned char>& png) {
93 SkBitmap bitmap;
94 if (!gfx::PNGCodec::Decode(&png.front(), png.size(), &bitmap)) {
95 LOG(WARNING) << "Unable to decode PNG.";
96 // Return a 16x16 red image to visually show error.
97 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
98 bitmap.allocPixels();
99 bitmap.eraseRGB(0xff, 0, 0);
100 }
101 return new ImageSkia(bitmap);
102 }
103
104 void PNGFromImageSkia(const ImageSkia* skia, std::vector<unsigned char>* png) {
105 CHECK(gfx::PNGCodec::EncodeBGRASkBitmap(*skia->bitmap(), false, png));
106 }
107
108 class ImageRepPNG;
109 class ImageRepSkia; 46 class ImageRepSkia;
110 class ImageRepGdk; 47 class ImageRepGdk;
111 class ImageRepCairo; 48 class ImageRepCairo;
112 class ImageRepCocoa; 49 class ImageRepCocoa;
113 50
114 // An ImageRep is the object that holds the backing memory for an Image. Each 51 // An ImageRep is the object that holds the backing memory for an Image. Each
115 // RepresentationType has an ImageRep subclass that is responsible for freeing 52 // RepresentationType has an ImageRep subclass that is responsible for freeing
116 // the memory that the ImageRep holds. When an ImageRep is created, it expects 53 // the memory that the ImageRep holds. When an ImageRep is created, it expects
117 // to take ownership of the image, without having to retain it or increase its 54 // to take ownership of the image, without having to retain it or increase its
118 // reference count. 55 // reference count.
119 class ImageRep { 56 class ImageRep {
120 public: 57 public:
121 explicit ImageRep(Image::RepresentationType rep) : type_(rep) {} 58 explicit ImageRep(Image::RepresentationType rep) : type_(rep) {}
122 59
123 // Deletes the associated pixels of an ImageRep. 60 // Deletes the associated pixels of an ImageRep.
124 virtual ~ImageRep() {} 61 virtual ~ImageRep() {}
125 62
126 // Cast helpers ("fake RTTI"). 63 // Cast helpers ("fake RTTI").
127 ImageRepPNG* AsImageRepPNG() {
128 CHECK_EQ(type_, Image::kImageRepPNG);
129 return reinterpret_cast<ImageRepPNG*>(this);
130 }
131
132 ImageRepSkia* AsImageRepSkia() { 64 ImageRepSkia* AsImageRepSkia() {
133 CHECK_EQ(type_, Image::kImageRepSkia); 65 CHECK_EQ(type_, Image::kImageRepSkia);
134 return reinterpret_cast<ImageRepSkia*>(this); 66 return reinterpret_cast<ImageRepSkia*>(this);
135 } 67 }
136 68
137 #if defined(TOOLKIT_GTK) 69 #if defined(TOOLKIT_GTK)
138 ImageRepGdk* AsImageRepGdk() { 70 ImageRepGdk* AsImageRepGdk() {
139 CHECK_EQ(type_, Image::kImageRepGdk); 71 CHECK_EQ(type_, Image::kImageRepGdk);
140 return reinterpret_cast<ImageRepGdk*>(this); 72 return reinterpret_cast<ImageRepGdk*>(this);
141 } 73 }
(...skipping 10 matching lines...) Expand all
152 return reinterpret_cast<ImageRepCocoa*>(this); 84 return reinterpret_cast<ImageRepCocoa*>(this);
153 } 85 }
154 #endif 86 #endif
155 87
156 Image::RepresentationType type() const { return type_; } 88 Image::RepresentationType type() const { return type_; }
157 89
158 private: 90 private:
159 Image::RepresentationType type_; 91 Image::RepresentationType type_;
160 }; 92 };
161 93
162 class ImageRepPNG : public ImageRep {
163 public:
164 ImageRepPNG(const unsigned char* input, size_t input_size)
165 : ImageRep(Image::kImageRepPNG),
166 image_(input, input + input_size) {
167 }
168 ImageRepPNG() : ImageRep(Image::kImageRepPNG) {
169 }
170
171 virtual ~ImageRepPNG() {
172 }
173
174 std::vector<unsigned char>* image() { return &image_; }
175
176 private:
177 std::vector<unsigned char> image_;
178
179 DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
180 };
181
182 class ImageRepSkia : public ImageRep { 94 class ImageRepSkia : public ImageRep {
183 public: 95 public:
184 // Takes ownership of |image|. 96 // Takes ownership of |image|.
185 explicit ImageRepSkia(ImageSkia* image) 97 explicit ImageRepSkia(ImageSkia* image)
186 : ImageRep(Image::kImageRepSkia), 98 : ImageRep(Image::kImageRepSkia),
187 image_(image) { 99 image_(image) {
188 } 100 }
189 101
190 virtual ~ImageRepSkia() { 102 virtual ~ImageRepSkia() {
191 } 103 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 214
303 friend class base::RefCounted<ImageStorage>; 215 friend class base::RefCounted<ImageStorage>;
304 }; 216 };
305 217
306 } // namespace internal 218 } // namespace internal
307 219
308 Image::Image() { 220 Image::Image() {
309 // |storage_| is NULL for empty Images. 221 // |storage_| is NULL for empty Images.
310 } 222 }
311 223
312 Image::Image(const unsigned char* png, size_t input_size)
313 : storage_(new internal::ImageStorage(Image::kImageRepPNG)) {
314 internal::ImageRepPNG* rep = new internal::ImageRepPNG(png, input_size);
315 AddRepresentation(rep);
316 }
317
318 Image::Image(const ImageSkia& image) 224 Image::Image(const ImageSkia& image)
319 : storage_(new internal::ImageStorage(Image::kImageRepSkia)) { 225 : storage_(new internal::ImageStorage(Image::kImageRepSkia)) {
320 internal::ImageRepSkia* rep = new internal::ImageRepSkia( 226 internal::ImageRepSkia* rep = new internal::ImageRepSkia(
321 new ImageSkia(image)); 227 new ImageSkia(image));
322 AddRepresentation(rep); 228 AddRepresentation(rep);
323 } 229 }
324 230
325 Image::Image(const ImageSkiaRep& image_skia_rep) 231 Image::Image(const ImageSkiaRep& image_skia_rep)
326 : storage_(new internal::ImageStorage(Image::kImageRepSkia)) { 232 : storage_(new internal::ImageStorage(Image::kImageRepSkia)) {
327 internal::ImageRepSkia* rep = 233 internal::ImageRepSkia* rep =
(...skipping 28 matching lines...) Expand all
356 } 262 }
357 263
358 Image& Image::operator=(const Image& other) { 264 Image& Image::operator=(const Image& other) {
359 storage_ = other.storage_; 265 storage_ = other.storage_;
360 return *this; 266 return *this;
361 } 267 }
362 268
363 Image::~Image() { 269 Image::~Image() {
364 } 270 }
365 271
366 const std::vector<unsigned char>* Image::ToImagePNG() const {
367 internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
368 if (!rep) {
369 internal::ImageRepPNG* png_rep = new internal::ImageRepPNG();
370 switch (DefaultRepresentationType()) {
371 #if defined(TOOLKIT_GTK)
372 case kImageRepGdk: {
373 internal::ImageRepGdk* gdk_rep =
374 GetRepresentation(kImageRepGdk, true)->AsImageRepGdk();
375 internal::PNGFromGdkPixbuf(gdk_rep->pixbuf(), png_rep->image());
376 break;
377 }
378 #elif defined(OS_MACOSX)
379 case kImageRepCocoa: {
380 internal::ImageRepCocoa* cocoa_rep =
381 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
382 internal::PNGFromNSImage(cocoa_rep->image(), png_rep->image());
383 break;
384 }
385 #endif
386 case kImageRepSkia: {
387 internal::ImageRepSkia* skia_rep =
388 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
389 internal::PNGFromImageSkia(skia_rep->image(), png_rep->image());
390 break;
391 }
392 default:
393 NOTREACHED();
394 }
395 rep = png_rep;
396 CHECK(rep);
397 AddRepresentation(rep);
398 }
399 return rep->AsImageRepPNG()->image();
400 }
401
402 const SkBitmap* Image::ToSkBitmap() const { 272 const SkBitmap* Image::ToSkBitmap() const {
403 // Possibly create and cache an intermediate ImageRepSkia. 273 // Possibly create and cache an intermediate ImageRepSkia.
404 return ToImageSkia()->bitmap(); 274 return ToImageSkia()->bitmap();
405 } 275 }
406 276
407 const ImageSkia* Image::ToImageSkia() const { 277 const ImageSkia* Image::ToImageSkia() const {
408 internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false); 278 internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false);
409 if (!rep) { 279 if (!rep) {
410 switch (DefaultRepresentationType()) {
411 case kImageRepPNG: {
412 internal::ImageRepPNG* png_rep =
413 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
414 rep = new internal::ImageRepSkia(
415 internal::ImageSkiaFromPNG(*png_rep->image()));
416 break;
417 }
418 #if defined(TOOLKIT_GTK) 280 #if defined(TOOLKIT_GTK)
419 case kImageRepGdk: { 281 internal::ImageRepGdk* native_rep =
420 internal::ImageRepGdk* native_rep = 282 GetRepresentation(kImageRepGdk, true)->AsImageRepGdk();
421 GetRepresentation(kImageRepGdk, true)->AsImageRepGdk(); 283 rep = new internal::ImageRepSkia(new ImageSkia(
422 rep = new internal::ImageRepSkia(new ImageSkia( 284 internal::ImageSkiaFromGdkPixbuf(native_rep->pixbuf())));
423 internal::ImageSkiaFromGdkPixbuf(native_rep->pixbuf())));
424 break;
425 }
426 #elif defined(OS_MACOSX) 285 #elif defined(OS_MACOSX)
427 case kImageRepCocoa: { 286 internal::ImageRepCocoa* native_rep =
428 internal::ImageRepCocoa* native_rep = 287 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
429 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa(); 288 rep = new internal::ImageRepSkia(new ImageSkia(
430 rep = new internal::ImageRepSkia(new ImageSkia( 289 ImageSkiaFromNSImage(native_rep->image())));
431 ImageSkiaFromNSImage(native_rep->image())));
432 break;
433 }
434 #endif 290 #endif
435 default:
436 NOTREACHED();
437 }
438 CHECK(rep); 291 CHECK(rep);
439 AddRepresentation(rep); 292 AddRepresentation(rep);
440 } 293 }
441 return rep->AsImageRepSkia()->image(); 294 return rep->AsImageRepSkia()->image();
442 } 295 }
443 296
444 #if defined(TOOLKIT_GTK) 297 #if defined(TOOLKIT_GTK)
445 GdkPixbuf* Image::ToGdkPixbuf() const { 298 GdkPixbuf* Image::ToGdkPixbuf() const {
446 internal::ImageRep* rep = GetRepresentation(kImageRepGdk, false); 299 internal::ImageRep* rep = GetRepresentation(kImageRepGdk, false);
447 if (!rep) { 300 if (!rep) {
448 switch (DefaultRepresentationType()) { 301 internal::ImageRepSkia* skia_rep =
449 case kImageRepPNG: { 302 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
450 internal::ImageRepPNG* png_rep = 303 rep = new internal::ImageRepGdk(gfx::GdkPixbufFromSkBitmap(
451 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG(); 304 *skia_rep->image()->bitmap()));
452 rep = new internal::ImageRepGdk(internal::GdkPixbufFromPNG(
453 *png_rep->image()));
454 break;
455 }
456 case kImageRepSkia: {
457 internal::ImageRepSkia* skia_rep =
458 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
459 rep = new internal::ImageRepGdk(gfx::GdkPixbufFromSkBitmap(
460 *skia_rep->image()->bitmap()));
461 break;
462 }
463 default:
464 NOTREACHED();
465 }
466 CHECK(rep); 305 CHECK(rep);
467 AddRepresentation(rep); 306 AddRepresentation(rep);
468 } 307 }
469 return rep->AsImageRepGdk()->pixbuf(); 308 return rep->AsImageRepGdk()->pixbuf();
470 } 309 }
471 310
472 CairoCachedSurface* const Image::ToCairo() const { 311 CairoCachedSurface* const Image::ToCairo() const {
473 internal::ImageRep* rep = GetRepresentation(kImageRepCairo, false); 312 internal::ImageRep* rep = GetRepresentation(kImageRepCairo, false);
474 if (!rep) { 313 if (!rep) {
475 // Handle any-to-Cairo conversion. This may create and cache an intermediate 314 // Handle any-to-Cairo conversion. This may create and cache an intermediate
476 // pixbuf before sending the data to the display server. 315 // pixbuf before sending the data to the display server.
477 rep = new internal::ImageRepCairo(ToGdkPixbuf()); 316 rep = new internal::ImageRepCairo(ToGdkPixbuf());
478 CHECK(rep); 317 CHECK(rep);
479 AddRepresentation(rep); 318 AddRepresentation(rep);
480 } 319 }
481 return rep->AsImageRepCairo()->surface(); 320 return rep->AsImageRepCairo()->surface();
482 } 321 }
483 #endif 322 #endif
484 323
485 #if defined(OS_MACOSX) 324 #if defined(OS_MACOSX)
486 NSImage* Image::ToNSImage() const { 325 NSImage* Image::ToNSImage() const {
487 internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false); 326 internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
488 if (!rep) { 327 if (!rep) {
489 switch (DefaultRepresentationType()) { 328 internal::ImageRepSkia* skia_rep =
490 case kImageRepPNG: { 329 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
491 internal::ImageRepPNG* png_rep = 330 NSImage* image = NSImageFromImageSkia(*skia_rep->image());
492 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG(); 331 base::mac::NSObjectRetain(image);
493 rep = new internal::ImageRepCocoa(internal::NSImageFromPNG( 332 rep = new internal::ImageRepCocoa(image);
494 *png_rep->image()));
495 break;
496 }
497 case kImageRepSkia: {
498 internal::ImageRepSkia* skia_rep =
499 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
500 NSImage* image = NSImageFromImageSkia(*skia_rep->image());
501 base::mac::NSObjectRetain(image);
502 rep = new internal::ImageRepCocoa(image);
503 break;
504 }
505 default:
506 NOTREACHED();
507 }
508 CHECK(rep); 333 CHECK(rep);
509 AddRepresentation(rep); 334 AddRepresentation(rep);
510 } 335 }
511 return rep->AsImageRepCocoa()->image(); 336 return rep->AsImageRepCocoa()->image();
512 } 337 }
513 #endif 338 #endif
514 339
515 std::vector<unsigned char>* Image::CopyImagePNG() const {
516 return new std::vector<unsigned char>(*ToImagePNG());
517 }
518
519 SkBitmap Image::AsBitmap() const { 340 SkBitmap Image::AsBitmap() const {
520 return IsEmpty() ? SkBitmap() : *ToSkBitmap(); 341 return IsEmpty() ? SkBitmap() : *ToSkBitmap();
521 } 342 }
522 343
523 ImageSkia Image::AsImageSkia() const { 344 ImageSkia Image::AsImageSkia() const {
524 return IsEmpty() ? ImageSkia() : *ToImageSkia(); 345 return IsEmpty() ? ImageSkia() : *ToImageSkia();
525 } 346 }
526 347
527 #if defined(OS_MACOSX) 348 #if defined(OS_MACOSX)
528 NSImage* Image::AsNSImage() const { 349 NSImage* Image::AsNSImage() const {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 } 419 }
599 return it->second; 420 return it->second;
600 } 421 }
601 422
602 void Image::AddRepresentation(internal::ImageRep* rep) const { 423 void Image::AddRepresentation(internal::ImageRep* rep) const {
603 CHECK(storage_.get()); 424 CHECK(storage_.get());
604 storage_->representations().insert(std::make_pair(rep->type(), rep)); 425 storage_->representations().insert(std::make_pair(rep->type(), rep));
605 } 426 }
606 427
607 } // namespace gfx 428 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/image/image.h ('k') | ui/gfx/image/image_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698