gfx::Image vs gfx::ImageSkia

133 views
Skip to first unread message

Thiago Farina

unread,
Sep 18, 2012, 11:11:09 AM9/18/12
to Chromium-dev, Peter Kotwicz, Sailesh Agrawal, Mitsuru Oshima
Hi,

Which one should I use and why? I know both of them are preferred over SkBitmap.

Is this documented somewhere?

Thanks,

--
Thiago

Ben Goodger (Google)

unread,
Sep 18, 2012, 11:24:31 AM9/18/12
to Thiago Farina, Chromium-dev, Peter Kotwicz, Sailesh Agrawal, Mitsuru Oshima
Once you figure out the answer can you add it to their respective headers :-)



--
Thiago

--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
    http://groups.google.com/a/chromium.org/group/chromium-dev

Robert Sesek

unread,
Sep 18, 2012, 11:52:01 AM9/18/12
to tfa...@chromium.org, Chromium-dev, Peter Kotwicz, Sailesh Agrawal, Mitsuru Oshima
gfx::Image is designed to wrap any type of image that's used in Chromium: SkBitmap (via ImageSkia now), GdkPixbuf, NSImage, UIImage, and raw PNG bytes. Its initial purpose was to allow the ResourceBundle to load image resources into their native format, plumb the image through cross-platform code (like a MenuModel), and then to draw the image using platform APIs. This prevents unnecessary conversions between the platform type and any intermediates (usually Skia). gfx::Image also (1) hides away all the conversion logic between the various image formats, and (2) divorces the code from a specific image type, which is useful on iOS where Skia is not used.

ImageSkia is roughly equivalent to an SkBitmap, but it supports multiple scale factors for high-density displays. Skia-based UI code (e.g. views) should use ImageSkia instead of SkBitmap.

The rule of thumb is: if the image goes through cross-platform code and is eventually going to be drawn in platform-specific code, it should be in a gfx::Image. If it's for WebUI, only exists in views code, or is part of some Skia-based compositing operation, use gfx::ImageSkia.

rsesek / @chromium.org


--
Thiago

oshima

unread,
Sep 18, 2012, 12:20:20 PM9/18/12
to Peter Kotwicz, Ben Goodger (Google), Thiago Farina, Chromium-dev, Peter Kotwicz, Sailesh Agrawal, rse...@chromium.org


On Tue, Sep 18, 2012 at 8:52 AM, Peter Kotwicz <pkot...@google.com> wrote:
The world is somewhat complicated right now.
For cross platform code, gfx::Image is preferred.
A gfx::ImageSkia is one of several representations which are contained
in a gfx::Image. The advantage with gfx::Image is that it allows
unnecessary conversions to be avoided. ie avoiding converting from
NSImage to gfx::ImageSkia and back to NSImage.

gfx::ImageSkia is preferred for non cross platform code. It is
preferred in most of the places where an SkBitmap would have been used
instead of a gfx::Image in the state of the world before ImageSkia
existed.

The eventual goal is that the methods in the gfx::ImageSkia API can be
added to the gfx::Image API.
Thus Image::ToSkBitmap(), Image::ToImagePNG() would become
    Image::ToSkBitmap(ui::ScaleFactor scale_factor)
    Image::ToImagePNG(ui::ScaleFactor scale_factor)

Hope this helps.

@oshima, and @rsesek please correct me if I missed something.

Thanks you, Peter, Robert. Your explanations sound reasonable.

- oshima

Jeffrey Yasskin

unread,
Sep 18, 2012, 3:24:31 PM9/18/12
to rse...@chromium.org, tfa...@chromium.org, Chromium-dev, Peter Kotwicz, Sailesh Agrawal, Mitsuru Oshima
I know very little about the overall graphics system design, but I've had to use and review code using ImageSkia and Image a bit, so here are my 2¢:

All image manipulation still appears to happen on SkBitmaps, generally using a class like:

class SomeImageSkiaSource : public ImageSkiaSource {
 public:
  SomeImageSkiaSource(const ImageSkia& orig) : orig_(orig) {}
  virtual ImageSkiaRep GetImageForScale(ScaleFactor scale_factor) {
    ImageSkiaRep orig_rep = orig_.GetRepresentation(scale_factor);
    // orig_rep.scale_factor() is not necessarily == scale_factor.
    SkBitmap orig_bitmap = orig_rep.sk_bitmap();
    SkBitmap transformed_bitmap = Whatever(orig_bitmap);
    return ImageSkiaRep(transformed_bitmap, orig_rep.scale_factor());
  }
 private:
  ImageSkia orig_;
}


It's easy to get this wrong by passing |scale_factor| instead of |orig_rep.scale_factor()| into the returned ImageSkiaRep.

You'd think that the CanvasImageSource would help reduce the boilerplate, but it always returns the requested scale factor instead of propagating the scale provided by the underlying image.

The good graphics folks have started providing some utility functions in ui/gfx/image/image_skia_operations.h that work on gfx::ImageSkia, but they haven't done the same for gfx::Image, which means that any transformation on gfx::Image takes an extra unwrapping/wrapping step.

gfx::Image saves redundant conversions if you can save it in a data structure and use it for multiple platform operations. However, if you're computing a new gfx::Image for each platform operation, then it saves no conversions and just costs a couple extra allocations for its internal storage.

Therefore, the guideline I'm gradually settling on is that data structures that store images, that will be drawn directly on a UI with no transformation between the data structure and the UI, should hold gfx::Images, while functions that compute or transform images should operate on ImageSkias.

Have I missed anything or gotten anything wrong?

Jeffrey

P.S. I would love to read the design doc for this system, if one exists.
Reply all
Reply to author
Forward
0 new messages