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

Unified Diff: ui/gfx/image/image.cc

Issue 10830207: Add support for PNG representation in gfx::Image (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Missed small change from previous CL. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/gfx/image/image.h ('k') | ui/gfx/image/image_mac.mm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/image/image.cc
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc
index 9c709dce545519512899d8dc81ac0d8f292807f2..1427d47229a91c12684663d99b6e403cce46829a 100644
--- a/ui/gfx/image/image.cc
+++ b/ui/gfx/image/image.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/size.h"
@@ -16,6 +17,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdk.h>
#include <glib-object.h>
+#include "ui/base/gtk/scoped_gobject.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/gtk_util.h"
#include "ui/gfx/image/cairo_cached_surface.h"
@@ -41,8 +43,69 @@ const ImageSkia ImageSkiaFromGdkPixbuf(GdkPixbuf* pixbuf) {
cairo_paint(cr);
return ImageSkia(canvas.ExtractImageRep());
}
-#endif
+GdkPixbuf* GdkPixbufFromPNG(const std::vector<unsigned char>& png) {
+ GdkPixbuf* pixbuf = NULL;
+ ui::ScopedGObject<GdkPixbufLoader>::Type loader(gdk_pixbuf_loader_new());
+
+ bool ok = gdk_pixbuf_loader_write(loader.get(),
+ reinterpret_cast<const guint8*>(&png.front()), png.size(), NULL);
+
+ // Calling gdk_pixbuf_loader_close forces the data to be parsed by the
+ // loader. This must be done before calling gdk_pixbuf_loader_get_pixbuf.
+ if (ok)
+ ok = gdk_pixbuf_loader_close(loader.get(), NULL);
+ if (ok)
+ pixbuf = gdk_pixbuf_loader_get_pixbuf(loader.get());
+
+ if (pixbuf) {
+ // The pixbuf is owned by the scoped loader which will delete its ref when
+ // it goes out of scope. Add a ref so that the pixbuf still exists.
+ g_object_ref(pixbuf);
+ } else {
+ LOG(WARNING) << "Unable to decode PNG.";
+ // Return a 16x16 red image to visually show error.
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 16, 16);
+ gdk_pixbuf_fill(pixbuf, 0xff0000ff);
+ }
+
+ return pixbuf;
+}
+
+void PNGFromGdkPixbuf(GdkPixbuf* pixbuf, std::vector<unsigned char>* png) {
+ gchar* image = NULL;
+ gsize image_size;
+ GError* error = NULL;
+ CHECK(gdk_pixbuf_save_to_buffer(
+ pixbuf, &image, &image_size, "png", &error, NULL));
+ png->assign(image, image + image_size);
+ g_free(image);
+}
+
+#endif // defined(TOOLKIT_GTK)
+
+#if defined(OS_MACOSX)
+void PNGFromNSImage(NSImage* nsimage, std::vector<unsigned char>* png);
+NSImage* NSImageFromPNG(const std::vector<unsigned char>& png);
+#endif // defined(OS_MACOSX)
+
+ImageSkia* ImageSkiaFromPNG(const std::vector<unsigned char>& png) {
+ SkBitmap bitmap;
+ if (!gfx::PNGCodec::Decode(&png.front(), png.size(), &bitmap)) {
+ LOG(WARNING) << "Unable to decode PNG.";
+ // Return a 16x16 red image to visually show error.
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
+ bitmap.allocPixels();
+ bitmap.eraseRGB(0xff, 0, 0);
+ }
+ return new ImageSkia(bitmap);
+}
+
+void PNGFromImageSkia(const ImageSkia* skia, std::vector<unsigned char>* png) {
+ CHECK(gfx::PNGCodec::EncodeBGRASkBitmap(*skia->bitmap(), false, png));
+}
+
+class ImageRepPNG;
class ImageRepSkia;
class ImageRepGdk;
class ImageRepCairo;
@@ -61,6 +124,11 @@ class ImageRep {
virtual ~ImageRep() {}
// Cast helpers ("fake RTTI").
+ ImageRepPNG* AsImageRepPNG() {
+ CHECK_EQ(type_, Image::kImageRepPNG);
+ return reinterpret_cast<ImageRepPNG*>(this);
+ }
+
ImageRepSkia* AsImageRepSkia() {
CHECK_EQ(type_, Image::kImageRepSkia);
return reinterpret_cast<ImageRepSkia*>(this);
@@ -91,6 +159,26 @@ class ImageRep {
Image::RepresentationType type_;
};
+class ImageRepPNG : public ImageRep {
+ public:
+ ImageRepPNG(const unsigned char* input, size_t input_size)
+ : ImageRep(Image::kImageRepPNG),
+ image_(input, input + input_size) {
+ }
+ ImageRepPNG() : ImageRep(Image::kImageRepPNG) {
+ }
+
+ virtual ~ImageRepPNG() {
+ }
+
+ std::vector<unsigned char>* image() { return &image_; }
+
+ private:
+ std::vector<unsigned char> image_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
+};
+
class ImageRepSkia : public ImageRep {
public:
// Takes ownership of |image|.
@@ -221,6 +309,12 @@ Image::Image() {
// |storage_| is NULL for empty Images.
}
+Image::Image(const unsigned char* png, size_t input_size)
+ : storage_(new internal::ImageStorage(Image::kImageRepPNG)) {
+ internal::ImageRepPNG* rep = new internal::ImageRepPNG(png, input_size);
+ AddRepresentation(rep);
+}
+
Image::Image(const ImageSkia& image)
: storage_(new internal::ImageStorage(Image::kImageRepSkia)) {
internal::ImageRepSkia* rep = new internal::ImageRepSkia(
@@ -269,6 +363,42 @@ Image& Image::operator=(const Image& other) {
Image::~Image() {
}
+const std::vector<unsigned char>* Image::ToImagePNG() const {
+ internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
+ if (!rep) {
+ internal::ImageRepPNG* png_rep = new internal::ImageRepPNG();
+ switch (DefaultRepresentationType()) {
+#if defined(TOOLKIT_GTK)
+ case kImageRepGdk: {
+ internal::ImageRepGdk* gdk_rep =
+ GetRepresentation(kImageRepGdk, true)->AsImageRepGdk();
+ internal::PNGFromGdkPixbuf(gdk_rep->pixbuf(), png_rep->image());
+ break;
+ }
+#elif defined(OS_MACOSX)
+ case kImageRepCocoa: {
+ internal::ImageRepCocoa* cocoa_rep =
+ GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
+ internal::PNGFromNSImage(cocoa_rep->image(), png_rep->image());
+ break;
+ }
+#endif
+ case kImageRepSkia: {
+ internal::ImageRepSkia* skia_rep =
+ GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
+ internal::PNGFromImageSkia(skia_rep->image(), png_rep->image());
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+ rep = png_rep;
+ CHECK(rep);
+ AddRepresentation(rep);
+ }
+ return rep->AsImageRepPNG()->image();
+}
+
const SkBitmap* Image::ToSkBitmap() const {
// Possibly create and cache an intermediate ImageRepSkia.
return ToImageSkia()->bitmap();
@@ -277,17 +407,34 @@ const SkBitmap* Image::ToSkBitmap() const {
const ImageSkia* Image::ToImageSkia() const {
internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false);
if (!rep) {
+ switch (DefaultRepresentationType()) {
+ case kImageRepPNG: {
+ internal::ImageRepPNG* png_rep =
+ GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
+ rep = new internal::ImageRepSkia(
+ internal::ImageSkiaFromPNG(*png_rep->image()));
+ break;
+ }
#if defined(TOOLKIT_GTK)
- internal::ImageRepGdk* native_rep =
- GetRepresentation(kImageRepGdk, true)->AsImageRepGdk();
- rep = new internal::ImageRepSkia(new ImageSkia(
- internal::ImageSkiaFromGdkPixbuf(native_rep->pixbuf())));
+ case kImageRepGdk: {
+ internal::ImageRepGdk* native_rep =
+ GetRepresentation(kImageRepGdk, true)->AsImageRepGdk();
+ rep = new internal::ImageRepSkia(new ImageSkia(
+ internal::ImageSkiaFromGdkPixbuf(native_rep->pixbuf())));
+ break;
+ }
#elif defined(OS_MACOSX)
- internal::ImageRepCocoa* native_rep =
- GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
- rep = new internal::ImageRepSkia(new ImageSkia(
- ImageSkiaFromNSImage(native_rep->image())));
+ case kImageRepCocoa: {
+ internal::ImageRepCocoa* native_rep =
+ GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
+ rep = new internal::ImageRepSkia(new ImageSkia(
+ ImageSkiaFromNSImage(native_rep->image())));
+ break;
+ }
#endif
+ default:
+ NOTREACHED();
+ }
CHECK(rep);
AddRepresentation(rep);
}
@@ -298,10 +445,24 @@ const ImageSkia* Image::ToImageSkia() const {
GdkPixbuf* Image::ToGdkPixbuf() const {
internal::ImageRep* rep = GetRepresentation(kImageRepGdk, false);
if (!rep) {
- internal::ImageRepSkia* skia_rep =
- GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
- rep = new internal::ImageRepGdk(gfx::GdkPixbufFromSkBitmap(
- *skia_rep->image()->bitmap()));
+ switch (DefaultRepresentationType()) {
+ case kImageRepPNG: {
+ internal::ImageRepPNG* png_rep =
+ GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
+ rep = new internal::ImageRepGdk(internal::GdkPixbufFromPNG(
+ *png_rep->image()));
+ break;
+ }
+ case kImageRepSkia: {
+ internal::ImageRepSkia* skia_rep =
+ GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
+ rep = new internal::ImageRepGdk(gfx::GdkPixbufFromSkBitmap(
+ *skia_rep->image()->bitmap()));
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
CHECK(rep);
AddRepresentation(rep);
}
@@ -325,11 +486,25 @@ CairoCachedSurface* const Image::ToCairo() const {
NSImage* Image::ToNSImage() const {
internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
if (!rep) {
- internal::ImageRepSkia* skia_rep =
- GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
- NSImage* image = NSImageFromImageSkia(*skia_rep->image());
- base::mac::NSObjectRetain(image);
- rep = new internal::ImageRepCocoa(image);
+ switch (DefaultRepresentationType()) {
+ case kImageRepPNG: {
+ internal::ImageRepPNG* png_rep =
+ GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
+ rep = new internal::ImageRepCocoa(internal::NSImageFromPNG(
+ *png_rep->image()));
+ break;
+ }
+ case kImageRepSkia: {
+ internal::ImageRepSkia* skia_rep =
+ GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
+ NSImage* image = NSImageFromImageSkia(*skia_rep->image());
+ base::mac::NSObjectRetain(image);
+ rep = new internal::ImageRepCocoa(image);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
CHECK(rep);
AddRepresentation(rep);
}
@@ -337,6 +512,10 @@ NSImage* Image::ToNSImage() const {
}
#endif
+std::vector<unsigned char>* Image::CopyImagePNG() const {
+ return new std::vector<unsigned char>(*ToImagePNG());
+}
+
SkBitmap Image::AsBitmap() const {
return IsEmpty() ? SkBitmap() : *ToSkBitmap();
}
« 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