Bug 1141979 - part4.1 - move ImageBitmapFormatUtils and its subclasses into cpp file; r?roc draft
authorKaku Kuo <tkuo@mozilla.com>
Thu, 17 Dec 2015 12:13:00 +0800
changeset 316264 6c2f8a5342d51fdec44230cd30d48adae21db5c5
parent 316263 135a6282b7f103fb72d95489c9d331eafa5f4aaf
child 316265 39a2d497672cda2633f4054cf69e860e85d9d82a
push id8521
push usertkuo@mozilla.com
push dateFri, 18 Dec 2015 07:11:01 +0000
reviewersroc
bugs1141979
milestone46.0a1
Bug 1141979 - part4.1 - move ImageBitmapFormatUtils and its subclasses into cpp file; r?roc
dom/canvas/ImageBitmapUtils.cpp
dom/canvas/ImageBitmapUtils.h
--- a/dom/canvas/ImageBitmapUtils.cpp
+++ b/dom/canvas/ImageBitmapUtils.cpp
@@ -11,209 +11,308 @@
 #include "mozilla/gfx/2D.h"
 
 using namespace libyuv;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace dom {
 
-/* static */ ImageBitmapFormatUtils*
+class ImageBitmapFormatUtils;
+class ImageBitmapFormatUtils_RGBA32;
+class ImageBitmapFormatUtils_BGRA32;
+class ImageBitmapFormatUtils_YUV420P;
+
+/*
+ * The UtilsUniquePtr is a UniquePtr to ImageBitmapFormatUtils with a customized
+ * deleter which does nothing. This is used as the return type of
+ * ImageBitmapFormatUtils::GetUtils to prevent users deleting the returned
+ * pointer.
+ */
+struct DoNotDelete { void operator()(void* p) {} };
+using UtilsUniquePtr = UniquePtr<ImageBitmapFormatUtils, DoNotDelete>;
+
+/*
+ * ImageBitmapFormatUtils is an abstract class which provides interfaces to
+ * extract information of each ImageBitmapFormat and interfaces to convert
+ * image data between different ImageBitmapFormats. For each kind of
+ * ImageBitmapFromat, we derive a subclass from the ImageBitmapFormatUtils to
+ * implement functionalities that are subject to the specific ImageBitmapFormat.
+ *
+ * ImageBitmapFormatUtils is an abstract class and its sub-classes are designed
+ * as singletons. The singleton instance of sub-classes could be initialized and
+ * accessed via the ImageBitmapFormatUtils::GetUtils() static method. The
+ * singleton instance is a static local variable which does not need to be
+ * released manually and, with the C++11 static initialization, the
+ * initialization is thread-safe.
+ *
+ * ImageBitmapFormatUtils and its sub-classes are designed to unify operations
+ * of ImageBitmap-extensions over different kinds of ImageBitmapFormats; they
+ * provide following functionalities:
+ *
+ * (1) Create default/customized ImagePixelLayout object of each kind of
+ *     ImageBitmapFormat.
+ * (2) Store the channel counts of each ImageBitmapFormat.
+ * (3) Calculate the needed buffer size of each kind of ImageBitmapFormat with
+ *     given width, height and stride.
+ * (4) Perform color conversion between supported ImageBitmapFormats. We use
+ *     _double dispatching_ to identify the source format and destination format
+ *     at run time. The _double dispatching_ here is mainly implemented by
+ *     overriding the _convertTo_ method over the ImageBitmapFormatUtils class
+ *     hierarchy and overloading the _convertFrom_ methods over all sub-classes
+ *     of ImageBitmapFormatUtils.
+ */
+
+class ImageBitmapFormatUtils
+{
+public:
+  // Get the singleton utility instance of the given ImageBitmapFormat.
+  static UtilsUniquePtr GetUtils(ImageBitmapFormat aFormat);
+
+  // Get the needed buffer size to store image data in the current
+  // ImageBitmapFormat with the given width and height.
+  // The current ImageBitmapFormat is the format used to implement the concrete
+  // subclass of which the current instance is initialized.
+  virtual uint32_t NeededBufferSize(uint32_t width, uint32_t height) = 0;
+
+  // Creates a default ImagePixelLayout object of the current ImageBitmapFormat
+  // with the given width, height and stride.
+  virtual UniquePtr<ImagePixelLayout>
+  CreateDefaultLayout(uint32_t aWidth, uint32_t aHeight, uint32_t aStride) = 0;
+
+  // Creates a customized ImagePixelLayout object of the current
+  // ImageBitmapFormatfrom using the information extracted from the aImage
+  // parameter.
+  virtual UniquePtr<ImagePixelLayout>
+  CreateCustomizedLayout(layers::Image* aImage) = 0;
+
+  // Convert the source image data (stored in the aSrcBuffer and described by
+  // the aSrcLayout) from the current ImageBitmapFormat to the given
+  // ImageBitmapFormat, aDstFormat.
+  // The converted image data is stored in the aDstBuffer and described by the
+  // returned ImagePixelLayout object.
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertTo(ImageBitmapFormatUtils* aDstFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) = 0;
+
+  // Convert the source RGBA32 source image data (stored in the aSrcBuffer and
+  // described by the aSrcLayout) to the current ImageBitmapFormat.
+  // The converted image data is stored in the aDstBuffer and described by the
+  // returned ImagePixelLayout object.
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_RGBA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) = 0;
+
+  // Convert the source BGRA32 source image data (stored in the aSrcBuffer and
+  // described by the aSrcLayout) to the current ImageBitmapFormat.
+  // The converted image data is stored in the aDstBuffer and described by the
+  // returned ImagePixelLayout object.
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) = 0;
+
+  // Convert the source YUV420P source image data (stored in the aSrcBuffer and
+  // described by the aSrcLayout) to the current ImageBitmapFormat.
+  // The converted image data is stored in the aDstBuffer and described by the
+  // returned ImagePixelLayout object.
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) = 0;
+
+  // Check whether or not the current ImageBitmapFormat can be converted from
+  // the given ImageBitmapFormat.
+  virtual bool
+  CanConvertFrom(ImageBitmapFormat aSrcFormat) = 0;
+
+  // Get the number of channels.
+  uint8_t GetChannelCount() const
+  {
+    return mChannels;
+  }
+
+protected:
+  explicit ImageBitmapFormatUtils(uint32_t aChannels)
+  : mChannels(aChannels)
+  {
+  }
+
+  virtual ~ImageBitmapFormatUtils()
+  {
+  }
+
+  const uint8_t mChannels;
+};
+
+class ImageBitmapFormatUtils_RGBA32 : public ImageBitmapFormatUtils
+{
+private:
+  explicit ImageBitmapFormatUtils_RGBA32()
+  : ImageBitmapFormatUtils(4)
+  {
+  }
+
+  ~ImageBitmapFormatUtils_RGBA32() = default;
+  ImageBitmapFormatUtils_RGBA32(ImageBitmapFormatUtils_RGBA32 const &) = delete;
+  ImageBitmapFormatUtils_RGBA32(ImageBitmapFormatUtils_RGBA32&&) = delete;
+  ImageBitmapFormatUtils_RGBA32& operator=(ImageBitmapFormatUtils_RGBA32 const &) = delete;
+  ImageBitmapFormatUtils_RGBA32& operator=(ImageBitmapFormatUtils_RGBA32&&) = delete;
+
+public:
+  static ImageBitmapFormatUtils_RGBA32& GetInstance();
+
+  virtual uint32_t NeededBufferSize(uint32_t aWidth, uint32_t aHeight) override
+  {
+    return aWidth * aHeight * (uint32_t)mChannels;
+  }
+
+  virtual UniquePtr<ImagePixelLayout>
+  CreateDefaultLayout(uint32_t aWidth, uint32_t aHeight, uint32_t aStride) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  CreateCustomizedLayout(layers::Image* aImage) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertTo(ImageBitmapFormatUtils* aDstFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override
+  {
+    return aDstFormat->ConvertFrom(this, aSrcBuffer, aSrcLayout, aDstBuffer);
+  }
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_RGBA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual bool
+  CanConvertFrom(ImageBitmapFormat aSrcFormat) override;
+};
+
+class ImageBitmapFormatUtils_BGRA32 : public ImageBitmapFormatUtils
+{
+private:
+  explicit ImageBitmapFormatUtils_BGRA32()
+  : ImageBitmapFormatUtils(4)
+  {
+  }
+
+  ~ImageBitmapFormatUtils_BGRA32() = default;
+  ImageBitmapFormatUtils_BGRA32(ImageBitmapFormatUtils_BGRA32 const &) = delete;
+  ImageBitmapFormatUtils_BGRA32(ImageBitmapFormatUtils_BGRA32&&) = delete;
+  ImageBitmapFormatUtils_BGRA32& operator=(ImageBitmapFormatUtils_BGRA32 const &) = delete;
+  ImageBitmapFormatUtils_BGRA32& operator=(ImageBitmapFormatUtils_BGRA32&&) = delete;
+
+public:
+  static ImageBitmapFormatUtils_BGRA32& GetInstance();
+
+  virtual uint32_t NeededBufferSize(uint32_t aWidth, uint32_t aHeight) override
+  {
+    return aWidth * aHeight * (uint32_t)mChannels;
+  }
+
+  virtual UniquePtr<ImagePixelLayout>
+  CreateDefaultLayout(uint32_t aWidth, uint32_t aHeight, uint32_t aStride) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  CreateCustomizedLayout(layers::Image* aImage) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertTo(ImageBitmapFormatUtils* aDstFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override
+  {
+    return aDstFormat->ConvertFrom(this, aSrcBuffer, aSrcLayout, aDstBuffer);
+  }
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_RGBA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual bool
+  CanConvertFrom(ImageBitmapFormat aSrcFormat) override;
+};
+
+class ImageBitmapFormatUtils_YUV420P : public ImageBitmapFormatUtils
+{
+private:
+  explicit ImageBitmapFormatUtils_YUV420P()
+  : ImageBitmapFormatUtils(3)
+  {
+  }
+
+  ~ImageBitmapFormatUtils_YUV420P() = default;
+  ImageBitmapFormatUtils_YUV420P(ImageBitmapFormatUtils_YUV420P const &) = delete;
+  ImageBitmapFormatUtils_YUV420P(ImageBitmapFormatUtils_YUV420P&&) = delete;
+  ImageBitmapFormatUtils_YUV420P& operator=(ImageBitmapFormatUtils_YUV420P const &) = delete;
+  ImageBitmapFormatUtils_YUV420P& operator=(ImageBitmapFormatUtils_YUV420P&&) = delete;
+
+public:
+  static ImageBitmapFormatUtils_YUV420P& GetInstance();
+
+  virtual uint32_t NeededBufferSize(uint32_t aWidth, uint32_t aHeight) override
+  {
+    return aWidth * aHeight + 2 * (aWidth / 2) * (aHeight / 2);
+  }
+
+  virtual UniquePtr<ImagePixelLayout>
+  CreateDefaultLayout(uint32_t aWidth, uint32_t aHeight, uint32_t aStride) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  CreateCustomizedLayout(layers::Image* aImage) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertTo(ImageBitmapFormatUtils* aDstFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override
+  {
+    return aDstFormat->ConvertFrom(this, aSrcBuffer, aSrcLayout, aDstBuffer);
+  }
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_RGBA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual UniquePtr<ImagePixelLayout>
+  ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
+
+  virtual bool
+  CanConvertFrom(ImageBitmapFormat aSrcFormat) override;
+};
+
+/*
+ * ImageBitmapFormatUtils.
+ */
+/* static */ UtilsUniquePtr
 ImageBitmapFormatUtils::GetUtils(ImageBitmapFormat aFormat)
 {
   switch(aFormat)
   {
   case ImageBitmapFormat::RGBA32:
-    return &ImageBitmapFormatUtils_RGBA32::GetInstance();
+    return UtilsUniquePtr(&ImageBitmapFormatUtils_RGBA32::GetInstance());
   case ImageBitmapFormat::BGRA32:
-    return &ImageBitmapFormatUtils_BGRA32::GetInstance();
+    return UtilsUniquePtr(&ImageBitmapFormatUtils_BGRA32::GetInstance());
   case ImageBitmapFormat::RGB24:
   case ImageBitmapFormat::BGR24:
   case ImageBitmapFormat::GRAY8:
   case ImageBitmapFormat::YUV444P:
   case ImageBitmapFormat::YUV422P:
     return nullptr;
   case ImageBitmapFormat::YUV420P:
-    return &ImageBitmapFormatUtils_YUV420P::GetInstance();
+    return UtilsUniquePtr(&ImageBitmapFormatUtils_YUV420P::GetInstance());
   case ImageBitmapFormat::YUV420SP_NV12:
   case ImageBitmapFormat::YUV420SP_NV21:
   case ImageBitmapFormat::HSV:
   case ImageBitmapFormat::Lab:
   case ImageBitmapFormat::DEPTH:
   default:
     return nullptr;
   }
 }
 
-/* static */ UniquePtr<ImagePixelLayout>
-ImageBitmapFormatUtils::CreateDefaultLayout(ImageBitmapFormat aFormat,
-                                            uint32_t aWidth,
-                                            uint32_t aHeight,
-                                            uint32_t aStride)
-{
-  // information from format
-  uint8_t channelCount = GetChannelCountOfImageFormat(aFormat);
-
-  UniquePtr<ImagePixelLayout> layout(new ImagePixelLayout(channelCount));
-
-  // set mChannels
-  switch (aFormat) {
-  case ImageBitmapFormat::RGBA32:
-  case ImageBitmapFormat::BGRA32:
-  case ImageBitmapFormat::RGB24:
-  case ImageBitmapFormat::BGR24:
-  {
-    for (uint8_t i = 0; i < channelCount; ++i) {
-      ChannelPixelLayout* channel = layout->AppendElement();
-      channel->mOffset = i;
-      channel->mWidth = aWidth;
-      channel->mHeight = aHeight;
-      channel->mDataType = ChannelPixelLayoutDataType::Uint8;
-      channel->mStride = aStride;
-      channel->mSkip = channelCount - 1;
-    }
-    break;
-  }
-  case ImageBitmapFormat::GRAY8:
-  {
-    return nullptr;
-  }
-  case ImageBitmapFormat::YUV444P:
-  case ImageBitmapFormat::YUV422P:
-  case ImageBitmapFormat::YUV420P:
-  {
-    ChannelPixelLayout* ychannel = layout->AppendElement();
-    ChannelPixelLayout* uchannel = layout->AppendElement();
-    ChannelPixelLayout* vchannel = layout->AppendElement();
-    ychannel->mOffset = 0;
-    ychannel->mWidth  = aWidth;
-    ychannel->mHeight = aHeight;
-    ychannel->mDataType = ChannelPixelLayoutDataType::Uint8;
-    ychannel->mStride = aStride;
-    ychannel->mSkip   = 0; // aYSkip;
-
-    uchannel->mOffset = ychannel->mOffset + ychannel->mStride * ychannel->mHeight;
-    uchannel->mWidth  = aWidth / 2;
-    uchannel->mHeight = aHeight / 2;
-    uchannel->mDataType = ChannelPixelLayoutDataType::Uint8;
-    uchannel->mStride = aStride / 2;
-    uchannel->mSkip   = 0; // aUSkip;
-
-    vchannel->mOffset = uchannel->mOffset + uchannel->mStride * uchannel->mHeight;
-    vchannel->mWidth  = aWidth / 2;
-    vchannel->mHeight = aHeight / 2;
-    vchannel->mDataType = ChannelPixelLayoutDataType::Uint8;
-    vchannel->mStride = aStride / 2;
-    vchannel->mSkip   = 0; // aVSkip;
-    break;
-  }
-  case ImageBitmapFormat::YUV420SP_NV12:
-  case ImageBitmapFormat::YUV420SP_NV21:
-  case ImageBitmapFormat::HSV:
-  case ImageBitmapFormat::Lab:
-  case ImageBitmapFormat::DEPTH:
-  default:
-    return nullptr;
-  }
-
-  return layout;
-}
-
-/* static */ UniquePtr<ImagePixelLayout>
-ImageBitmapFormatUtils::CreateCustomizedLayout(ImageBitmapFormat aFormat,
-                                               layers::Image* aImage)
-{
-  MOZ_ASSERT(aImage, "Create layout from a null image.");
-
-  // information from format
-  uint8_t channelCount = GetChannelCountOfImageFormat(aFormat);
-
-  UniquePtr<ImagePixelLayout> layout(new ImagePixelLayout(channelCount));
-
-  // set mChannels
-  switch (aFormat) {
-  case ImageBitmapFormat::RGBA32:
-  case ImageBitmapFormat::BGRA32:
-  case ImageBitmapFormat::RGB24:
-  case ImageBitmapFormat::BGR24:
-  {
-    layers::CairoImage* src = static_cast<layers::CairoImage*> (aImage);
-    RefPtr<SourceSurface> surface = src->GetAsSourceSurface();
-    RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
-    gfx::DataSourceSurface::ScopedMap map(dataSurface, gfx::DataSourceSurface::READ);
-    if (!map.IsMapped()) {
-      return nullptr;
-    }
-
-    const IntSize surfaceSize = surface->GetSize();
-    const uint32_t surfaceStride = map.GetStride();
-
-    for (uint8_t i = 0; i < channelCount; ++i) {
-      ChannelPixelLayout* channel = layout->AppendElement();
-      channel->mOffset = i;
-      channel->mWidth = surfaceSize.width;
-      channel->mHeight = surfaceSize.height;
-      channel->mDataType = ChannelPixelLayoutDataType::Uint8;
-      channel->mStride = surfaceStride;
-      channel->mSkip = channelCount - 1;
-    }
-    break;
-  }
-  case ImageBitmapFormat::GRAY8:
-  {
-    return nullptr;
-  }
-  case ImageBitmapFormat::YUV444P:
-  case ImageBitmapFormat::YUV422P:
-  case ImageBitmapFormat::YUV420P:
-  case ImageBitmapFormat::YUV420SP_NV12:
-  case ImageBitmapFormat::YUV420SP_NV21:
-  {
-    layers::PlanarYCbCrImage* ycbcrImage = static_cast<layers::PlanarYCbCrImage*> (aImage);
-    layers::PlanarYCbCrData const *ycbcrLayout = ycbcrImage->GetData();
-    if (!ycbcrLayout) {
-      // something wrong
-      return nullptr;
-    }
-
-    ChannelPixelLayout* ychannel = layout->AppendElement();
-    ChannelPixelLayout* uchannel = layout->AppendElement();
-    ChannelPixelLayout* vchannel = layout->AppendElement();
-
-    ychannel->mOffset = 0;
-    uchannel->mOffset = ychannel->mOffset + ycbcrLayout->mYStride * ycbcrLayout->mYSize.height;
-    vchannel->mOffset = uchannel->mOffset + ycbcrLayout->mCbCrStride * ycbcrLayout->mCbCrSize.height;
-    ychannel->mWidth = ycbcrLayout->mYSize.width;
-    ychannel->mHeight = ycbcrLayout->mYSize.height;
-    ychannel->mDataType = ChannelPixelLayoutDataType::Uint8;
-    ychannel->mStride = ycbcrLayout->mYStride;
-    ychannel->mSkip = ycbcrLayout->mYSkip;
-    uchannel->mWidth = ycbcrLayout->mCbCrSize.width;
-    uchannel->mHeight = ycbcrLayout->mCbCrSize.height;
-    uchannel->mDataType = ChannelPixelLayoutDataType::Uint8;
-    uchannel->mStride = ycbcrLayout->mCbCrStride;
-    uchannel->mSkip = ycbcrLayout->mCbSkip;
-    vchannel->mWidth = ycbcrLayout->mCbCrSize.width;
-    vchannel->mHeight = ycbcrLayout->mCbCrSize.height;
-    vchannel->mDataType = ChannelPixelLayoutDataType::Uint8;
-    vchannel->mStride = ycbcrLayout->mCbCrStride;
-    vchannel->mSkip = ycbcrLayout->mCrSkip;
-
-    break;
-  }
-  case ImageBitmapFormat::HSV:
-  case ImageBitmapFormat::Lab:
-  case ImageBitmapFormat::DEPTH:
-  default:
-    return nullptr;
-  }
-
-  return layout;
-}
-
 /*
  * ImageBitmapFormatUtils_RGBA32.
  */
 /* static */ImageBitmapFormatUtils_RGBA32&
 ImageBitmapFormatUtils_RGBA32::GetInstance()
 {
   static ImageBitmapFormatUtils_RGBA32 instance;
   return instance;
@@ -233,18 +332,17 @@ ImageBitmapFormatUtils_RGBA32::ConvertFr
   const nsTArray<ChannelPixelLayout>& channels = *aSrcLayout;
   MOZ_ASSERT(channels.Length() == aSrcFormat->GetChannelCount(),
              "The channel count is wrong.");
 
   const uint32_t length = channels[0].mHeight * channels[0].mStride;
 
   memcpy(aDstBuffer, aSrcBuffer, length);
 
-  return CreateDefaultLayout(ImageBitmapFormat::RGBA32,
-                             channels[0].mWidth,
+  return CreateDefaultLayout(channels[0].mWidth,
                              channels[0].mHeight,
                              channels[0].mStride);
 }
 
 UniquePtr<ImagePixelLayout>
 ImageBitmapFormatUtils_RGBA32::ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat,
                                            const uint8_t* aSrcBuffer,
                                            const ImagePixelLayout* aSrcLayout,
@@ -262,18 +360,17 @@ ImageBitmapFormatUtils_RGBA32::ConvertFr
   int rv = ABGRToARGB(aSrcBuffer, channels[0].mStride,
                       aDstBuffer, channels[0].mStride,
                       channels[0].mWidth, channels[0].mHeight);
 
   if (NS_WARN_IF(rv != 0)) {
     return nullptr;
   }
 
-  return CreateDefaultLayout(ImageBitmapFormat::RGBA32,
-                             channels[0].mWidth,
+  return CreateDefaultLayout(channels[0].mWidth,
                              channels[0].mHeight,
                              channels[0].mStride);
 }
 
 UniquePtr<ImagePixelLayout>
 ImageBitmapFormatUtils_RGBA32::ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat,
                                            const uint8_t* aSrcBuffer,
                                            const ImagePixelLayout* aSrcLayout,
@@ -293,34 +390,86 @@ ImageBitmapFormatUtils_RGBA32::ConvertFr
                       aSrcBuffer + channels[2].mOffset, channels[2].mStride,
                       aDstBuffer, channels[0].mWidth * 4,
                       channels[0].mWidth, channels[0].mHeight);
 
   if (NS_WARN_IF(rv != 0)) {
     return nullptr;
   }
 
-  return CreateDefaultLayout(ImageBitmapFormat::RGBA32,
-                             channels[0].mWidth,
+  return CreateDefaultLayout(channels[0].mWidth,
                              channels[0].mHeight,
                              channels[0].mWidth * 4);
 }
 
 bool
 ImageBitmapFormatUtils_RGBA32::CanConvertFrom(ImageBitmapFormat aSrcFormat)
 {
   if (aSrcFormat == ImageBitmapFormat::RGBA32 ||
       aSrcFormat == ImageBitmapFormat::BGRA32 ||
       aSrcFormat == ImageBitmapFormat::YUV420P) {
     return true;
   }
 
   return false;
 }
 
+UniquePtr<ImagePixelLayout>
+ImageBitmapFormatUtils_RGBA32::CreateDefaultLayout(uint32_t aWidth,
+                                                   uint32_t aHeight,
+                                                   uint32_t aStride)
+{
+  UniquePtr<ImagePixelLayout> layout(new ImagePixelLayout(mChannels));
+
+  // set mChannels
+  for (uint8_t i = 0; i < mChannels; ++i) {
+    ChannelPixelLayout* channel = layout->AppendElement();
+    channel->mOffset = i;
+    channel->mWidth = aWidth;
+    channel->mHeight = aHeight;
+    channel->mDataType = ChannelPixelLayoutDataType::Uint8;
+    channel->mStride = aStride;
+    channel->mSkip = mChannels - 1;
+  }
+
+  return layout;
+}
+
+UniquePtr<ImagePixelLayout>
+ImageBitmapFormatUtils_RGBA32::CreateCustomizedLayout(layers::Image* aImage)
+{
+  MOZ_ASSERT(aImage, "Create layout from a null image.");
+
+  UniquePtr<ImagePixelLayout> layout(new ImagePixelLayout(mChannels));
+
+  // set mChannels
+  layers::CairoImage* src = static_cast<layers::CairoImage*> (aImage);
+  RefPtr<SourceSurface> surface = src->GetAsSourceSurface();
+  RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
+  gfx::DataSourceSurface::ScopedMap map(dataSurface, gfx::DataSourceSurface::READ);
+  if (!map.IsMapped()) {
+    return nullptr;
+  }
+
+  const IntSize surfaceSize = surface->GetSize();
+  const uint32_t surfaceStride = map.GetStride();
+
+  for (uint8_t i = 0; i < mChannels; ++i) {
+    ChannelPixelLayout* channel = layout->AppendElement();
+    channel->mOffset = i;
+    channel->mWidth = surfaceSize.width;
+    channel->mHeight = surfaceSize.height;
+    channel->mDataType = ChannelPixelLayoutDataType::Uint8;
+    channel->mStride = surfaceStride;
+    channel->mSkip = mChannels - 1;
+  }
+
+  return layout;
+}
+
 /*
  * ImageBitmapFormatUtils_BGRA32.
  */
 /* static */ImageBitmapFormatUtils_BGRA32&
 ImageBitmapFormatUtils_BGRA32::GetInstance()
 {
   static ImageBitmapFormatUtils_BGRA32 instance;
   return instance;
@@ -344,18 +493,17 @@ ImageBitmapFormatUtils_BGRA32::ConvertFr
   int rv = ABGRToARGB(aSrcBuffer, channels[0].mStride,
                       aDstBuffer, channels[0].mStride,
                       channels[0].mWidth, channels[0].mHeight);
 
   if (NS_WARN_IF(rv != 0)) {
     return nullptr;
   }
 
-  return CreateDefaultLayout(ImageBitmapFormat::BGRA32,
-                             channels[0].mWidth,
+  return CreateDefaultLayout(channels[0].mWidth,
                              channels[0].mHeight,
                              channels[0].mStride);
 }
 
 UniquePtr<ImagePixelLayout>
 ImageBitmapFormatUtils_BGRA32::ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat,
                                            const uint8_t* aSrcBuffer,
                                            const ImagePixelLayout* aSrcLayout,
@@ -369,18 +517,17 @@ ImageBitmapFormatUtils_BGRA32::ConvertFr
   const nsTArray<ChannelPixelLayout>& channels = *aSrcLayout;
   MOZ_ASSERT(channels.Length() == aSrcFormat->GetChannelCount(),
              "The channel count is wrong.");
 
   const uint32_t length = channels[0].mHeight * channels[0].mStride;
 
   memcpy(aDstBuffer, aSrcBuffer, length);
 
-  return CreateDefaultLayout(ImageBitmapFormat::BGRA32,
-                             channels[0].mWidth,
+  return CreateDefaultLayout(channels[0].mWidth,
                              channels[0].mHeight,
                              channels[0].mStride);
 }
 
 UniquePtr<ImagePixelLayout>
 ImageBitmapFormatUtils_BGRA32::ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat,
                                            const uint8_t* aSrcBuffer,
                                            const ImagePixelLayout* aSrcLayout,
@@ -400,34 +547,53 @@ ImageBitmapFormatUtils_BGRA32::ConvertFr
                       aSrcBuffer + channels[2].mOffset, channels[2].mStride,
                       aDstBuffer, channels[0].mWidth * 4,
                       channels[0].mWidth, channels[0].mHeight);
 
   if (NS_WARN_IF(rv != 0)) {
     return nullptr;
   }
 
-  return CreateDefaultLayout(ImageBitmapFormat::BGRA32,
-                             channels[0].mWidth,
+  return CreateDefaultLayout(channels[0].mWidth,
                              channels[0].mHeight,
                              channels[0].mWidth * 4);
 }
 
 bool
 ImageBitmapFormatUtils_BGRA32::CanConvertFrom(ImageBitmapFormat aSrcFormat)
 {
   if (aSrcFormat == ImageBitmapFormat::RGBA32 ||
       aSrcFormat == ImageBitmapFormat::BGRA32 ||
       aSrcFormat == ImageBitmapFormat::YUV420P) {
     return true;
   }
 
   return false;
 }
 
+UniquePtr<ImagePixelLayout>
+ImageBitmapFormatUtils_BGRA32::CreateDefaultLayout(uint32_t aWidth,
+                                                   uint32_t aHeight,
+                                                   uint32_t aStride)
+{
+  UtilsUniquePtr format = ImageBitmapFormatUtils::GetUtils(ImageBitmapFormat::RGBA32);
+  MOZ_ASSERT(format, "Cannot get a valid ImageBitmapFormatUtils instance.");
+
+  return format->CreateDefaultLayout(aWidth, aHeight, aStride);
+}
+
+UniquePtr<ImagePixelLayout>
+ImageBitmapFormatUtils_BGRA32::CreateCustomizedLayout(layers::Image* aImage)
+{
+  UtilsUniquePtr format = ImageBitmapFormatUtils::GetUtils(ImageBitmapFormat::RGBA32);
+  MOZ_ASSERT(format, "Cannot get a valid ImageBitmapFormatUtils instance.");
+
+  return format->CreateCustomizedLayout(aImage);
+}
+
 /*
  * ImageBitmapFormatUtils_YUV420P.
  */
 /* static */ImageBitmapFormatUtils_YUV420P&
 ImageBitmapFormatUtils_YUV420P::GetInstance()
 {
   static ImageBitmapFormatUtils_YUV420P instance;
   return instance;
@@ -467,71 +633,171 @@ ImageBitmapFormatUtils_YUV420P::CanConve
       aSrcFormat == ImageBitmapFormat::BGRA32 ||
       aSrcFormat == ImageBitmapFormat::YUV420P) {
     return true;
   }
 
   return false;
 }
 
+UniquePtr<ImagePixelLayout>
+ImageBitmapFormatUtils_YUV420P::CreateDefaultLayout(uint32_t aWidth,
+                                                    uint32_t aHeight,
+                                                    uint32_t aStride)
+{
+  UniquePtr<ImagePixelLayout> layout(new ImagePixelLayout(mChannels));
+
+  // set mChannels
+  ChannelPixelLayout* ychannel = layout->AppendElement();
+  ChannelPixelLayout* uchannel = layout->AppendElement();
+  ChannelPixelLayout* vchannel = layout->AppendElement();
+  ychannel->mOffset = 0;
+  ychannel->mWidth  = aWidth;
+  ychannel->mHeight = aHeight;
+  ychannel->mDataType = ChannelPixelLayoutDataType::Uint8;
+  ychannel->mStride = aStride;
+  ychannel->mSkip   = 0; // aYSkip;
+
+  uchannel->mOffset = ychannel->mOffset + ychannel->mStride * ychannel->mHeight;
+  uchannel->mWidth  = aWidth / 2;
+  uchannel->mHeight = aHeight / 2;
+  uchannel->mDataType = ChannelPixelLayoutDataType::Uint8;
+  uchannel->mStride = aStride / 2;
+  uchannel->mSkip   = 0; // aUSkip;
+
+  vchannel->mOffset = uchannel->mOffset + uchannel->mStride * uchannel->mHeight;
+  vchannel->mWidth  = aWidth / 2;
+  vchannel->mHeight = aHeight / 2;
+  vchannel->mDataType = ChannelPixelLayoutDataType::Uint8;
+  vchannel->mStride = aStride / 2;
+  vchannel->mSkip   = 0; // aVSkip;
+
+  return layout;
+}
+
+UniquePtr<ImagePixelLayout>
+ImageBitmapFormatUtils_YUV420P::CreateCustomizedLayout(layers::Image* aImage)
+{
+  MOZ_ASSERT(aImage, "Create layout from a null image.");
+
+  UniquePtr<ImagePixelLayout> layout(new ImagePixelLayout(mChannels));
+
+  // set mChannels
+  layers::PlanarYCbCrImage* ycbcrImage = static_cast<layers::PlanarYCbCrImage*> (aImage);
+  layers::PlanarYCbCrData const *ycbcrLayout = ycbcrImage->GetData();
+  if (!ycbcrLayout) {
+    // something wrong
+    return nullptr;
+  }
+
+  ChannelPixelLayout* ychannel = layout->AppendElement();
+  ChannelPixelLayout* uchannel = layout->AppendElement();
+  ChannelPixelLayout* vchannel = layout->AppendElement();
+
+  ychannel->mOffset = 0;
+  uchannel->mOffset = ychannel->mOffset + ycbcrLayout->mYStride * ycbcrLayout->mYSize.height;
+  vchannel->mOffset = uchannel->mOffset + ycbcrLayout->mCbCrStride * ycbcrLayout->mCbCrSize.height;
+  ychannel->mWidth = ycbcrLayout->mYSize.width;
+  ychannel->mHeight = ycbcrLayout->mYSize.height;
+  ychannel->mDataType = ChannelPixelLayoutDataType::Uint8;
+  ychannel->mStride = ycbcrLayout->mYStride;
+  ychannel->mSkip = ycbcrLayout->mYSkip;
+  uchannel->mWidth = ycbcrLayout->mCbCrSize.width;
+  uchannel->mHeight = ycbcrLayout->mCbCrSize.height;
+  uchannel->mDataType = ChannelPixelLayoutDataType::Uint8;
+  uchannel->mStride = ycbcrLayout->mCbCrStride;
+  uchannel->mSkip = ycbcrLayout->mCbSkip;
+  vchannel->mWidth = ycbcrLayout->mCbCrSize.width;
+  vchannel->mHeight = ycbcrLayout->mCbCrSize.height;
+  vchannel->mDataType = ChannelPixelLayoutDataType::Uint8;
+  vchannel->mStride = ycbcrLayout->mCbCrStride;
+  vchannel->mSkip = ycbcrLayout->mCrSkip;
+
+  return layout;
+}
+
+/*
+ * Global functions.
+ */
 bool
 IsSupportedFormat(ImageBitmapFormat aFormat)
 {
   if (aFormat == ImageBitmapFormat::RGBA32 ||
       aFormat == ImageBitmapFormat::BGRA32) {
     return true;
   }
 
   return false;
 }
 
+UniquePtr<ImagePixelLayout>
+CreateDefaultLayout(ImageBitmapFormat aFormat, uint32_t aWidth,
+                    uint32_t aHeight, uint32_t aStride)
+{
+  UtilsUniquePtr format = ImageBitmapFormatUtils::GetUtils(aFormat);
+  MOZ_ASSERT(format, "Cannot get a valid ImageBitmapFormatUtils instance.");
+
+  return format->CreateDefaultLayout(aWidth, aHeight, aStride);
+}
+
+UniquePtr<ImagePixelLayout>
+CreateCustomizedLayout(ImageBitmapFormat aFormat, layers::Image* aImage)
+{
+  MOZ_ASSERT(aImage, "Create layout from a null image.");
+
+  UtilsUniquePtr format = ImageBitmapFormatUtils::GetUtils(aFormat);
+  MOZ_ASSERT(format, "Cannot get a valid ImageBitmapFormatUtils instance.");
+
+  return format->CreateCustomizedLayout(aImage);
+}
+
 uint8_t
 GetChannelCountOfImageFormat(ImageBitmapFormat aFormat)
 {
-  ImageBitmapFormatUtils* format = ImageBitmapFormatUtils::GetUtils(aFormat);
+  UtilsUniquePtr format = ImageBitmapFormatUtils::GetUtils(aFormat);
   MOZ_ASSERT(format, "Cannot get a valid ImageBitmapFormatUtils instance.");
 
   return format->GetChannelCount();
 }
 
 uint32_t
 CalculateNeededBufferSize(ImageBitmapFormat aFormat,
                           uint32_t aWidth, uint32_t aHeight)
 {
-  ImageBitmapFormatUtils* format = ImageBitmapFormatUtils::GetUtils(aFormat);
+  UtilsUniquePtr format = ImageBitmapFormatUtils::GetUtils(aFormat);
   MOZ_ASSERT(format, "Cannot get a valid ImageBitmapFormatUtils instance.");
 
   return format->NeededBufferSize(aWidth, aHeight);
 }
 
 UniquePtr<ImagePixelLayout>
 CopyAndConvertImageData(ImageBitmapFormat aSrcFormat,
                         const uint8_t* aSrcBuffer,
                         const ImagePixelLayout* aSrcLayout,
                         ImageBitmapFormat aDstFormat,
                         uint8_t* aDstBuffer)
 {
   MOZ_ASSERT(aSrcBuffer, "Convert color from a null buffer.");
   MOZ_ASSERT(aSrcLayout, "Convert color from a null layout.");
   MOZ_ASSERT(aDstBuffer, "Convert color to a null buffer.");
 
-  ImageBitmapFormatUtils* srcFormat = ImageBitmapFormatUtils::GetUtils(aSrcFormat);
-  ImageBitmapFormatUtils* dstFormat = ImageBitmapFormatUtils::GetUtils(aDstFormat);
+  UtilsUniquePtr srcFormat = ImageBitmapFormatUtils::GetUtils(aSrcFormat);
+  UtilsUniquePtr dstFormat = ImageBitmapFormatUtils::GetUtils(aDstFormat);
   MOZ_ASSERT(srcFormat, "Cannot get a valid ImageBitmapFormatUtils instance.");
   MOZ_ASSERT(dstFormat, "Cannot get a valid ImageBitmapFormatUtils instance.");
 
-  return srcFormat->ConvertTo(dstFormat, aSrcBuffer, aSrcLayout, aDstBuffer);
+  return srcFormat->ConvertTo(dstFormat.get(), aSrcBuffer, aSrcLayout, aDstBuffer);
 }
 
 ImageBitmapFormat
 FindBestMatchingFromat(ImageBitmapFormat aSrcFormat,
                        const Sequence<ImageBitmapFormat>& aCandidates) {
 
   for(auto& candidate : aCandidates) {
-    ImageBitmapFormatUtils* candidateFormat = ImageBitmapFormatUtils::GetUtils(candidate);
+    UtilsUniquePtr candidateFormat = ImageBitmapFormatUtils::GetUtils(candidate);
     MOZ_ASSERT(candidateFormat, "Cannot get a valid ImageBitmapFormatUtils instance.");
 
     if (candidateFormat->CanConvertFrom(aSrcFormat)) {
       return candidate;
     }
   }
 
   return ImageBitmapFormat::EndGuard_;
--- a/dom/canvas/ImageBitmapUtils.h
+++ b/dom/canvas/ImageBitmapUtils.h
@@ -9,256 +9,36 @@
 
 #include "mozilla/UniquePtr.h"
 #include "nsTArrayForwardDeclare.h"
 
 namespace mozilla {
 namespace dom {
 
 struct ChannelPixelLayout;
-class ImageBitmapFormatUtils;
-class ImageBitmapFormatUtils_RGBA32;
-class ImageBitmapFormatUtils_BGRA32;
-class ImageBitmapFormatUtils_YUV420P;
 template<typename> class Sequence;
 
 using ImagePixelLayout = nsTArray<ChannelPixelLayout>;
 
 /*
- * ImageBitmapFormatUtils is an abstract class which provides interfaces to
- * extract information of each ImageBitmapFormat and interfaces to convert
- * image data between different ImageBitmapFormats. For each kind of
- * ImageBitmapFromat, we derive a subclass from the ImageBitmapFormatUtils to
- * implement functionalities that are subject to the specific ImageBitmapFormat.
- *
- * ImageBitmapFormatUtils is an abstract class and its sub-classes are designed
- * as singletons. The singleton instance of sub-classes could be initialized and
- * accessed via the ImageBitmapFormatUtils::GetUtils() static method. The
- * singleton instance is a static local variable which does not need to be
- * released manually and, with the C++11 static initialization, the
- * initialization is thread-safe.
- *
- * ImageBitmapFormatUtils and its sub-classes are designed to unify operations
- * of ImageBitmap-extensions over different kinds of ImageBitmapFormats; they
- * provide following functionalities:
- *
- * (1) Create default/customized ImagePixelLayout object of each kind of
- *     ImageBitmapFormat.
- * (2) Store the channel counts of each ImageBitmapFormat.
- * (3) Calculate the needed buffer size of each kind of ImageBitmapFormat with
- *     given width, height and stride.
- * (4) Perform color conversion between supported ImageBitmapFormats. We use
- *     _double dispatching_ to identify the source format and destination format
- *     at run time. The _double dispatching_ here is mainly implemented by
- *     overriding the _convertTo_ method over the ImageBitmapFormatUtils class
- *     hierarchy and overloading the _convertFrom_ methods over all sub-classes
- *     of ImageBitmapFormatUtils.
+ * This function creates an ImagePixelLayout object which describes the
+ * default layout of the given ImageBitmapFormat with the given width, height
+ * and stride.
  */
-
-class ImageBitmapFormatUtils
-{
-public:
-  // Do not delete the returned pointer.
-  static ImageBitmapFormatUtils* GetUtils(ImageBitmapFormat aFormat);
-
-  // This function creates an ImagePixelLayout object which describes the
-  // default layout of the given ImageBitmapFormat with the given width, height
-  // and stride.
-  static UniquePtr<ImagePixelLayout>
-  CreateDefaultLayout(ImageBitmapFormat aFormat, uint32_t aWidth, uint32_t aHeight, uint32_t aStride);
-
-  // This function extracts information from the aImage parameter to customize
-  // the ImagePixelLayout object, that is, this function creates a customized
-  // ImagePixelLayout object which exactly describes the pixel layout of the
-  // given aImage.
-  static UniquePtr<ImagePixelLayout>
-  CreateCustomizedLayout(ImageBitmapFormat aFormat, layers::Image* aImage);
-
-public:
-  explicit ImageBitmapFormatUtils(uint32_t aChannels)
-  : mChannels(aChannels)
-  {
-  }
-
-  virtual ~ImageBitmapFormatUtils()
-  {
-  }
-
-  // Get the needed buffer size to store image data in the current
-  // ImageBitmapFormat with the given width and height.
-  // The current ImageBitmapFormat is the format used to implement the concrete
-  // subclass of which the current instance is initialized.
-  virtual uint32_t NeededBufferSize(uint32_t width, uint32_t height) = 0;
-
-  // Convert the source image data (stored in the aSrcBuffer and described by
-  // the aSrcLayout) from the current ImageBitmapFormat to the given
-  // ImageBitmapFormat, aDstFormat.
-  // The converted image data is stored in the aDstBuffer and described by the
-  // returned ImagePixelLayout object.
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertTo(ImageBitmapFormatUtils* aDstFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) = 0;
-
-  // Convert the source RGBA32 source image data (stored in the aSrcBuffer and
-  // described by the aSrcLayout) to the current ImageBitmapFormat.
-  // The converted image data is stored in the aDstBuffer and described by the
-  // returned ImagePixelLayout object.
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_RGBA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) = 0;
-
-  // Convert the source BGRA32 source image data (stored in the aSrcBuffer and
-  // described by the aSrcLayout) to the current ImageBitmapFormat.
-  // The converted image data is stored in the aDstBuffer and described by the
-  // returned ImagePixelLayout object.
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) = 0;
-
-  // Convert the source YUV420P source image data (stored in the aSrcBuffer and
-  // described by the aSrcLayout) to the current ImageBitmapFormat.
-  // The converted image data is stored in the aDstBuffer and described by the
-  // returned ImagePixelLayout object.
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) = 0;
-
-  // Check whether or not the current ImageBitmapFormat can be converted from
-  // the given ImageBitmapFormat.
-  virtual bool
-  CanConvertFrom(ImageBitmapFormat aSrcFormat) = 0;
-
-  // Get the number of channels.
-  uint8_t GetChannelCount() const
-  {
-    return mChannels;
-  }
-
-protected:
-  const uint8_t mChannels;
-};
+UniquePtr<ImagePixelLayout>
+CreateDefaultLayout(ImageBitmapFormat aFormat, uint32_t aWidth, uint32_t aHeight, uint32_t aStride);
 
-class ImageBitmapFormatUtils_RGBA32 : public ImageBitmapFormatUtils
-{
-private:
-  explicit ImageBitmapFormatUtils_RGBA32()
-  : ImageBitmapFormatUtils(4)
-  {
-  }
-
-  ~ImageBitmapFormatUtils_RGBA32() = default;
-  ImageBitmapFormatUtils_RGBA32(ImageBitmapFormatUtils_RGBA32 const &) = delete;
-  ImageBitmapFormatUtils_RGBA32(ImageBitmapFormatUtils_RGBA32&&) = delete;
-  ImageBitmapFormatUtils_RGBA32& operator=(ImageBitmapFormatUtils_RGBA32 const &) = delete;
-  ImageBitmapFormatUtils_RGBA32& operator=(ImageBitmapFormatUtils_RGBA32&&) = delete;
-
-public:
-  static ImageBitmapFormatUtils_RGBA32& GetInstance();
-
-  virtual uint32_t NeededBufferSize(uint32_t aWidth, uint32_t aHeight) override
-  {
-    return aWidth * aHeight * (uint32_t)mChannels;
-  }
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertTo(ImageBitmapFormatUtils* aDstFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override
-  {
-    return aDstFormat->ConvertFrom(this, aSrcBuffer, aSrcLayout, aDstBuffer);
-  }
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_RGBA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual bool
-  CanConvertFrom(ImageBitmapFormat aSrcFormat) override;
-};
-
-class ImageBitmapFormatUtils_BGRA32 : public ImageBitmapFormatUtils
-{
-private:
-  explicit ImageBitmapFormatUtils_BGRA32()
-  : ImageBitmapFormatUtils(4)
-  {
-  }
-
-  ~ImageBitmapFormatUtils_BGRA32() = default;
-  ImageBitmapFormatUtils_BGRA32(ImageBitmapFormatUtils_BGRA32 const &) = delete;
-  ImageBitmapFormatUtils_BGRA32(ImageBitmapFormatUtils_BGRA32&&) = delete;
-  ImageBitmapFormatUtils_BGRA32& operator=(ImageBitmapFormatUtils_BGRA32 const &) = delete;
-  ImageBitmapFormatUtils_BGRA32& operator=(ImageBitmapFormatUtils_BGRA32&&) = delete;
-
-public:
-  static ImageBitmapFormatUtils_BGRA32& GetInstance();
-
-  virtual uint32_t NeededBufferSize(uint32_t aWidth, uint32_t aHeight) override
-  {
-    return aWidth * aHeight * (uint32_t)mChannels;
-  }
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertTo(ImageBitmapFormatUtils* aDstFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override
-  {
-    return aDstFormat->ConvertFrom(this, aSrcBuffer, aSrcLayout, aDstBuffer);
-  }
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_RGBA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual bool
-  CanConvertFrom(ImageBitmapFormat aSrcFormat) override;
-};
-
-class ImageBitmapFormatUtils_YUV420P : public ImageBitmapFormatUtils
-{
-private:
-  explicit ImageBitmapFormatUtils_YUV420P()
-  : ImageBitmapFormatUtils(3)
-  {
-  }
-
-  ~ImageBitmapFormatUtils_YUV420P() = default;
-  ImageBitmapFormatUtils_YUV420P(ImageBitmapFormatUtils_YUV420P const &) = delete;
-  ImageBitmapFormatUtils_YUV420P(ImageBitmapFormatUtils_YUV420P&&) = delete;
-  ImageBitmapFormatUtils_YUV420P& operator=(ImageBitmapFormatUtils_YUV420P const &) = delete;
-  ImageBitmapFormatUtils_YUV420P& operator=(ImageBitmapFormatUtils_YUV420P&&) = delete;
-
-public:
-  static ImageBitmapFormatUtils_YUV420P& GetInstance();
-
-  virtual uint32_t NeededBufferSize(uint32_t aWidth, uint32_t aHeight) override
-  {
-    return aWidth * aHeight + 2 * (aWidth / 2) * (aHeight / 2);
-  }
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertTo(ImageBitmapFormatUtils* aDstFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override
-  {
-    return aDstFormat->ConvertFrom(this, aSrcBuffer, aSrcLayout, aDstBuffer);
-  }
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_RGBA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_BGRA32* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual UniquePtr<ImagePixelLayout>
-  ConvertFrom(ImageBitmapFormatUtils_YUV420P* aSrcFormat, const uint8_t* aSrcBuffer, const ImagePixelLayout* aSrcLayout, uint8_t* aDstBuffer) override;
-
-  virtual bool
-  CanConvertFrom(ImageBitmapFormat aSrcFormat) override;
-};
+/*
+ * This function extracts information from the aImage parameter to customize
+ * the ImagePixelLayout object, that is, this function creates a customized
+ * ImagePixelLayout object which exactly describes the pixel layout of the
+ * given aImage.
+ */
+UniquePtr<ImagePixelLayout>
+CreateCustomizedLayout(ImageBitmapFormat aFormat, layers::Image* aImage);
 
 /*
  * Check whether or not the given ImageBitmapFormat is supported.
  */
 bool
 IsSupportedFormat(ImageBitmapFormat aFormat);
 
 /*