Commit 2a3ea759 authored by cjhopman@chromium.org's avatar cjhopman@chromium.org

Add support for PNG representation in gfx::Image

Currently all conversions to or from PNG will request (and so possibly
create and cache) an ImageSkia intermediate representation.

Depends on http://codereview.chromium.org/10799014/

BUG=123865

TEST=

Review URL: https://chromiumcodereview.appspot.com/10799014

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150228 0039d316-1c4b-4281-b951-d872f2087c98
parent 83cb753f
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
......@@ -30,8 +30,8 @@ TEST_F(UiGfxImageTest, CheckColor) {
CGFloat components[4] = { 0 };
[color getComponents:components];
EXPECT_GT(components[0], 0.95);
EXPECT_LT(components[1], 0.05);
EXPECT_LT(components[0], 0.05);
EXPECT_GT(components[1], 0.95);
EXPECT_LT(components[2], 0.05);
EXPECT_GT(components[3], 0.95);
}
......
......@@ -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();
}
......
......@@ -55,6 +55,7 @@ class UI_EXPORT Image {
kImageRepCocoa,
kImageRepCairo,
kImageRepSkia,
kImageRepPNG,
};
typedef std::map<RepresentationType, internal::ImageRep*> RepresentationMap;
......@@ -62,6 +63,12 @@ class UI_EXPORT Image {
// Creates an empty image with no representations.
Image();
// Creates a new image by copying the PNG-encoded input for use as the default
// representation. For example (from an std::vector):
// std::vector<unsigned char> png = ...;
// gfx::Image image(&png.front(), png.size());
Image(const unsigned char* png, size_t input_size);
// Creates a new image by copying the ImageSkia for use as the default
// representation.
explicit Image(const ImageSkia& image);
......@@ -98,6 +105,7 @@ class UI_EXPORT Image {
// Converts the Image to the desired representation and stores it internally.
// The returned result is a weak pointer owned by and scoped to the life of
// the Image. Must only be called if IsEmpty() is false.
const std::vector<unsigned char>* ToImagePNG() const;
const SkBitmap* ToSkBitmap() const;
const ImageSkia* ToImageSkia() const;
#if defined(TOOLKIT_GTK)
......@@ -125,6 +133,7 @@ class UI_EXPORT Image {
// backing pixels are shared amongst all copies (a fact of each of the
// converted representations, rather than a limitation imposed by Image) and
// so the result should be considered immutable.
std::vector<unsigned char>* CopyImagePNG() const;
ImageSkia* CopyImageSkia() const;
SkBitmap* CopySkBitmap() const;
#if defined(TOOLKIT_GTK)
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gfx/image/image.h"
#import <AppKit/AppKit.h>
#include "base/logging.h"
#include "base/memory/scoped_nsobject.h"
namespace gfx {
namespace internal {
void PNGFromNSImage(NSImage* nsimage, std::vector<unsigned char>* png) {
CGImageRef cg_image = [nsimage CGImageForProposedRect:NULL
context:nil
hints:nil];
scoped_nsobject<NSBitmapImageRep> ns_bitmap(
[[NSBitmapImageRep alloc] initWithCGImage:cg_image]);
NSData* ns_data = [ns_bitmap representationUsingType:NSPNGFileType
properties:nil];
const unsigned char* bytes =
static_cast<const unsigned char*>([ns_data bytes]);
png->assign(bytes, bytes + [ns_data length]);
}
NSImage* NSImageFromPNG(const std::vector<unsigned char>& png) {
scoped_nsobject<NSData> ns_data(
[[NSData alloc] initWithBytes:&png.front() length:png.size()]);
scoped_nsobject<NSImage> image([[NSImage alloc] initWithData:ns_data]);
if (!image) {
LOG(WARNING) << "Unable to decode PNG.";
// Return a 16x16 red image to visually show error.
NSRect rect = NSMakeRect(0, 0, 16, 16);
image.reset([[NSImage alloc] initWithSize:rect.size]);
[image lockFocus];
[[NSColor colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0] set];
NSRectFill(rect);
[image unlockFocus];
}
return image.release();
}
} // namespace internal
} // namespace gfx
......@@ -93,6 +93,68 @@ TEST_F(ImageTest, SkiaToSkiaRef) {
EXPECT_FALSE(image.HasRepresentation(gt::GetPlatformRepresentationType()));
}
TEST_F(ImageTest, SkiaToPNGEncodeAndDecode) {
gfx::Image image(gt::CreateBitmap(25, 25));
const std::vector<unsigned char>* png = image.ToImagePNG();
EXPECT_TRUE(png);
EXPECT_FALSE(png->empty());
EXPECT_TRUE(image.HasRepresentation(gfx::Image::kImageRepPNG));
gfx::Image from_png(&png->front(), png->size());
EXPECT_TRUE(image.HasRepresentation(gfx::Image::kImageRepPNG));
EXPECT_TRUE(gt::IsEqual(from_png, image));
}
TEST_F(ImageTest, PlatformToPNGEncodeAndDecode) {
gfx::Image image(gt::CreatePlatformImage());
const std::vector<unsigned char>* png = image.ToImagePNG();
EXPECT_TRUE(png);
EXPECT_FALSE(png->empty());
EXPECT_TRUE(image.HasRepresentation(gfx::Image::kImageRepPNG));
gfx::Image from_png(&png->front(), png->size());
EXPECT_TRUE(image.HasRepresentation(gfx::Image::kImageRepPNG));
EXPECT_TRUE(gt::IsPlatformImageValid(gt::ToPlatformType(image)));
}
// The platform types use the platform provided encoding/decoding of PNGs. Make
// sure these work with the Skia Encode/Decode.
TEST_F(ImageTest, PNGEncodeFromSkiaDecodeToPlatform) {
// Force the conversion sequence skia to png to platform_type.
gfx::Image from_skia(gt::CreateBitmap(25, 25));
const std::vector<unsigned char>* png = from_skia.ToImagePNG();
gfx::Image from_png(&png->front(), png->size());
gfx::Image from_platform(gt::CopyPlatformType(from_png));
EXPECT_TRUE(gt::IsPlatformImageValid(gt::ToPlatformType(from_platform)));
EXPECT_TRUE(gt::IsEqual(from_skia, from_platform));
}
TEST_F(ImageTest, PNGEncodeFromPlatformDecodeToSkia) {
// Force the conversion sequence platform_type to png to skia.
gfx::Image from_platform(gt::CreatePlatformImage());
const std::vector<unsigned char>* png = from_platform.ToImagePNG();
gfx::Image from_png(&png->front(), png->size());
gfx::Image from_skia(*from_png.ToImageSkia());
EXPECT_TRUE(gt::IsEqual(from_skia, from_platform));
}
TEST_F(ImageTest, PNGDecodeToSkiaFailure) {
std::vector<unsigned char> png(100, 0);
gfx::Image image(&png.front(), png.size());
const SkBitmap* bitmap = image.ToSkBitmap();
SkAutoLockPixels auto_lock(*bitmap);
gt::CheckColor(bitmap->getColor(10, 10), true);
}
TEST_F(ImageTest, PNGDecodeToPlatformFailure) {
std::vector<unsigned char> png(100, 0);
gfx::Image image(&png.front(), png.size());
gt::CheckColor(gt::GetPlatformImageColor(gt::ToPlatformType(image)), true);
}
TEST_F(ImageTest, SkiaToPlatform) {
gfx::Image image(gt::CreateBitmap(25, 25));
const size_t kRepCount = kUsesSkiaNatively ? 1U : 2U;
......@@ -196,11 +258,10 @@ TEST_F(ImageTest, SkiaToCocoaCopy) {
TEST_F(ImageTest, CheckSkiaColor) {
gfx::Image image(gt::CreatePlatformImage());
const SkBitmap* bitmap = image.ToSkBitmap();
const SkBitmap* bitmap = image.ToSkBitmap();
SkAutoLockPixels auto_lock(*bitmap);
uint32_t* pixel = bitmap->getAddr32(10, 10);
EXPECT_EQ(SK_ColorRED, *pixel);
gt::CheckColor(bitmap->getColor(10, 10), false);
}
TEST_F(ImageTest, SwapRepresentations) {
......
......@@ -12,6 +12,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#if defined(TOOLKIT_GTK)
#include <gtk/gtk.h>
#include "ui/gfx/gtk_util.h"
#elif defined(OS_MACOSX)
#include "base/mac/mac_util.h"
......@@ -36,7 +37,7 @@ const SkBitmap CreateBitmap(int width, int height) {
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
bitmap.allocPixels();
bitmap.eraseRGB(255, 0, 0);
bitmap.eraseRGB(0, 255, 0);
return bitmap;
}
......@@ -113,6 +114,44 @@ PlatformImage ToPlatformType(const gfx::Image& image) {
#endif
}
PlatformImage CopyPlatformType(const gfx::Image& image) {
#if defined(OS_MACOSX)
return image.CopyNSImage();
#elif defined(TOOLKIT_GTK)
return image.CopyGdkPixbuf();
#else
return *image.ToSkBitmap();
#endif
}
#if defined(OS_MACOSX)
// Defined in image_unittest_util_mac.mm.
#elif defined(TOOLKIT_GTK)
SkColor GetPlatformImageColor(PlatformImage image) {
guchar* gdk_pixels = gdk_pixbuf_get_pixels(image);
guchar alpha = gdk_pixbuf_get_has_alpha(image) ? gdk_pixels[3] : 255;
return SkColorSetARGB(alpha, gdk_pixels[0], gdk_pixels[1], gdk_pixels[2]);
}
#else
SkColor GetPlatformImageColor(PlatformImage image) {
SkAutoLockPixels auto_lock(image);
return image.getColor(10, 10);
}
#endif
void CheckColor(SkColor color, bool is_red) {
// Be tolerant of floating point rounding and lossy color space conversions.
if (is_red) {
EXPECT_GT(SkColorGetR(color), 0.95);
EXPECT_LT(SkColorGetG(color), 0.05);
} else {
EXPECT_GT(SkColorGetG(color), 0.95);
EXPECT_LT(SkColorGetR(color), 0.05);
}
EXPECT_LT(SkColorGetB(color), 0.05);
EXPECT_GT(SkColorGetA(color), 0.95);
}
bool IsPlatformImageValid(PlatformImage image) {
#if defined(OS_MACOSX) || defined(TOOLKIT_GTK)
return image != NULL;
......
......@@ -9,6 +9,7 @@
#define UI_GFX_IMAGE_IMAGE_UNITTEST_UTIL_H_
#include "ui/gfx/image/image.h"
#include "third_party/skia/include/core/SkColor.h"
namespace gfx {
namespace test {
......@@ -40,6 +41,10 @@ PlatformImage CreatePlatformImage();
gfx::Image::RepresentationType GetPlatformRepresentationType();
PlatformImage ToPlatformType(const gfx::Image& image);
PlatformImage CopyPlatformType(const gfx::Image& image);
SkColor GetPlatformImageColor(PlatformImage image);
void CheckColor(SkColor color, bool is_red);
bool IsPlatformImageValid(PlatformImage image);
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <AppKit/AppKit.h>
#include "skia/ext/skia_utils_mac.h"
#include "ui/gfx/image/image_unittest_util.h"
namespace gfx {
namespace test {
SkColor GetPlatformImageColor(PlatformImage image) {
[image lockFocus];
NSColor* color = NSReadPixel(NSMakePoint(10, 10));
[image unlockFocus];
return NSDeviceColorToSkColor(color);
}
} // namespace test
} // namespace gfx
......@@ -7,17 +7,14 @@
#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
namespace gfx {
Image* ImageFromPNGEncodedData(const unsigned char* input, size_t input_size) {
SkBitmap bitmap;
if (gfx::PNGCodec::Decode(input, input_size, &bitmap))
return new Image(bitmap);
return NULL;
Image* image = new Image(input, input_size);
return image;
}
Image ImageFromJPEGEncodedData(const unsigned char* input, size_t input_size) {
......@@ -30,8 +27,8 @@ Image ImageFromJPEGEncodedData(const unsigned char* input, size_t input_size) {
bool PNGEncodedDataFromImage(const Image& image,
std::vector<unsigned char>* dst) {
const SkBitmap& bitmap = *image.ToSkBitmap();
return gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, dst);
*dst = *image.ToImagePNG();
return !dst->empty();
}
bool JPEGEncodedDataFromImage(const Image& image, int quality,
......
......@@ -372,6 +372,7 @@
'gfx/image/canvas_image_source.h',
'gfx/image/image.cc',
'gfx/image/image.h',
'gfx/image/image_mac.mm',
'gfx/image/image_skia.cc',
'gfx/image/image_skia.h',
'gfx/image/image_skia_operations.cc',
......
......@@ -101,6 +101,7 @@
'gfx/image/image_unittest.cc',
'gfx/image/image_unittest_util.cc',
'gfx/image/image_unittest_util.h',
'gfx/image/image_unittest_util_mac.mm',
'gfx/image/image_util_unittest.cc',
'gfx/insets_unittest.cc',
'gfx/rect_unittest.cc',
......
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