Bug 670466 - Add basic support for .bmp encoder. r=joe
authorBrian R. Bondy <netzen@gmail.com>
Thu, 25 Aug 2011 16:09:05 -0400
changeset 75919 52f2d362cbac1a65d099fb363a2ea8efc2d76394
parent 75918 5401cb3d7350583b5e467183b68a5b64d92b33bc
child 75920 cefa6f2d2dfb43b47c2fb241b65fac149e20f58c
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersjoe
bugs670466
milestone9.0a1
Bug 670466 - Add basic support for .bmp encoder. r=joe
modules/libpr0n/build/Makefile.in
modules/libpr0n/build/nsImageModule.cpp
modules/libpr0n/decoders/nsBMPDecoder.cpp
modules/libpr0n/decoders/nsBMPDecoder.h
modules/libpr0n/decoders/nsICODecoder.cpp
modules/libpr0n/encoders/Makefile.in
modules/libpr0n/encoders/bmp/Makefile.in
modules/libpr0n/encoders/bmp/nsBMPEncoder.cpp
modules/libpr0n/encoders/bmp/nsBMPEncoder.h
modules/libpr0n/src/BMPFileHeaders.h
modules/libpr0n/src/Endian.h
--- a/modules/libpr0n/build/Makefile.in
+++ b/modules/libpr0n/build/Makefile.in
@@ -54,19 +54,21 @@ CPPSRCS = \
 		nsImageModule.cpp \
 		$(NULL)
 
 LOCAL_INCLUDES	= \
 		-I. \
 		-I$(srcdir)/../src \
 		-I$(srcdir)/../encoders/png \
 		-I$(srcdir)/../encoders/jpeg \
+		-I$(srcdir)/../encoders/bmp \
 		$(NULL)
 
 SHARED_LIBRARY_LIBS = \
 		../src/$(LIB_PREFIX)imglib2_s.$(LIB_SUFFIX) \
 		../decoders/$(LIB_PREFIX)imgdecoders_s.$(LIB_SUFFIX) \
-		../encoders/png/$(LIB_PREFIX)imgpnge_s.$(LIB_SUFFIX)\
-		../encoders/jpeg/$(LIB_PREFIX)imgjpege_s.$(LIB_SUFFIX)\
+		../encoders/png/$(LIB_PREFIX)imgpnge_s.$(LIB_SUFFIX) \
+		../encoders/jpeg/$(LIB_PREFIX)imgjpege_s.$(LIB_SUFFIX) \
+		../encoders/bmp/$(LIB_PREFIX)imgbmpe_s.$(LIB_SUFFIX) \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/modules/libpr0n/build/nsImageModule.cpp
+++ b/modules/libpr0n/build/nsImageModule.cpp
@@ -52,55 +52,60 @@
 #include "imgLoader.h"
 #include "imgRequest.h"
 #include "imgRequestProxy.h"
 #include "imgTools.h"
 #include "DiscardTracker.h"
 
 #include "nsPNGEncoder.h"
 #include "nsJPEGEncoder.h"
+#include "nsBMPEncoder.h"
 
 // objects that just require generic constructors
 namespace mozilla {
 namespace imagelib {
 NS_GENERIC_FACTORY_CONSTRUCTOR(RasterImage)
 }
 }
 using namespace mozilla::imagelib;
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(imgLoader, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequestProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(imgTools)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJPEGEncoder)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsPNGEncoder)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsBMPEncoder)
 NS_DEFINE_NAMED_CID(NS_IMGLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_IMGREQUESTPROXY_CID);
 NS_DEFINE_NAMED_CID(NS_IMGTOOLS_CID);
 NS_DEFINE_NAMED_CID(NS_RASTERIMAGE_CID);
 NS_DEFINE_NAMED_CID(NS_JPEGENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_PNGENCODER_CID);
+NS_DEFINE_NAMED_CID(NS_BMPENCODER_CID);
 
 static const mozilla::Module::CIDEntry kImageCIDs[] = {
   { &kNS_IMGLOADER_CID, false, NULL, imgLoaderConstructor, },
   { &kNS_IMGREQUESTPROXY_CID, false, NULL, imgRequestProxyConstructor, },
   { &kNS_IMGTOOLS_CID, false, NULL, imgToolsConstructor, },
   { &kNS_RASTERIMAGE_CID, false, NULL, RasterImageConstructor, },
   { &kNS_JPEGENCODER_CID, false, NULL, nsJPEGEncoderConstructor, },
   { &kNS_PNGENCODER_CID, false, NULL, nsPNGEncoderConstructor, },
+  { &kNS_BMPENCODER_CID, false, NULL, nsBMPEncoderConstructor, },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kImageContracts[] = {
   { "@mozilla.org/image/cache;1", &kNS_IMGLOADER_CID },
   { "@mozilla.org/image/loader;1", &kNS_IMGLOADER_CID },
   { "@mozilla.org/image/request;1", &kNS_IMGREQUESTPROXY_CID },
   { "@mozilla.org/image/tools;1", &kNS_IMGTOOLS_CID },
   { "@mozilla.org/image/rasterimage;1", &kNS_RASTERIMAGE_CID },
   { "@mozilla.org/image/encoder;2?type=image/jpeg", &kNS_JPEGENCODER_CID },
   { "@mozilla.org/image/encoder;2?type=image/png", &kNS_PNGENCODER_CID },
+  { "@mozilla.org/image/encoder;2?type=image/bmp", &kNS_BMPENCODER_CID },
   { NULL }
 };
 
 static const mozilla::Module::CategoryEntry kImageCategories[] = {
   { "Gecko-Content-Viewers", "image/gif", "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", "image/jpeg", "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", "image/pjpeg", "@mozilla.org/content/document-loader-factory;1" },
   { "Gecko-Content-Viewers", "image/jpg", "@mozilla.org/content/document-loader-factory;1" },
--- a/modules/libpr0n/decoders/nsBMPDecoder.cpp
+++ b/modules/libpr0n/decoders/nsBMPDecoder.cpp
@@ -39,16 +39,17 @@
  * ***** END LICENSE BLOCK ***** */
 /* I got the format description from http://www.daubnet.com/formats/BMP.html */
 
 /* This is a Cross-Platform BMP Decoder, which should work everywhere, including
  * Big-Endian machines like the PowerPC. */
 
 #include <stdlib.h>
 
+#include "Endian.h"
 #include "nsBMPDecoder.h"
 
 #include "nsIInputStream.h"
 #include "RasterImage.h"
 #include "imgIContainerObserver.h"
 #include "ImageLogging.h"
 
 namespace mozilla {
--- a/modules/libpr0n/decoders/nsBMPDecoder.h
+++ b/modules/libpr0n/decoders/nsBMPDecoder.h
@@ -40,128 +40,21 @@
 
 #ifndef _nsBMPDecoder_h
 #define _nsBMPDecoder_h
 
 #include "nsAutoPtr.h"
 #include "imgIDecoderObserver.h"
 #include "gfxColor.h"
 #include "Decoder.h"
+#include "BMPFileHeaders.h"
 
 namespace mozilla {
 namespace imagelib {
 
-struct BMPFILEHEADER {
-    char signature[2]; // String "BM"
-    PRUint32 filesize;
-    PRInt32 reserved; // Zero
-    PRUint32 dataoffset; // Offset to raster data
-
-    PRUint32 bihsize;
-};
-
-// The length of the bitmap file header as defined in the BMP spec.
-#define BFH_LENGTH 14 
-// Internally we store the bitmap file header with an additional 4 bytes which
-// is used to store the bitmap information header size.
-#define BFH_INTERNAL_LENGTH 18
-
-#define OS2_BIH_LENGTH 12 // This is the real BIH size (as contained in the bihsize field of BMPFILEHEADER)
-#define OS2_HEADER_LENGTH (BFH_INTERNAL_LENGTH + 8)
-#define WIN_HEADER_LENGTH (BFH_INTERNAL_LENGTH + 36)
-
-struct BMPINFOHEADER {
-    PRInt32 width; // Uint16 in OS/2 BMPs
-    PRInt32 height; // Uint16 in OS/2 BMPs
-    PRUint16 planes; // =1
-    PRUint16 bpp; // Bits per pixel.
-    // The rest of the header is not available in OS/2 BMP Files
-    PRUint32 compression; // 0=no compression 1=8bit RLE 2=4bit RLE
-    PRUint32 image_size; // (compressed) image size. Can be 0 if compression==0
-    PRUint32 xppm; // Pixels per meter, horizontal
-    PRUint32 yppm; // Pixels per meter, vertical
-    PRUint32 colors; // Used Colors
-    PRUint32 important_colors; // Number of important colors. 0=all
-};
-
-struct colorTable {
-    PRUint8 red;
-    PRUint8 green;
-    PRUint8 blue;
-};
-
-struct bitFields {
-    PRUint32 red;
-    PRUint32 green;
-    PRUint32 blue;
-    PRUint8 redLeftShift;
-    PRUint8 redRightShift;
-    PRUint8 greenLeftShift;
-    PRUint8 greenRightShift;
-    PRUint8 blueLeftShift;
-    PRUint8 blueRightShift;
-};
-
-#define BITFIELD_LENGTH 12 // Length of the bitfields structure in the bmp file
-
-#if defined WORDS_BIGENDIAN || defined IS_BIG_ENDIAN
-// We must ensure that the entity is unsigned
-// otherwise, if it is signed/negative, the MSB will be
-// propagated when we shift
-#define LITTLE_TO_NATIVE16(x) (((((PRUint16) x) & 0xFF) << 8) | \
-                               (((PRUint16) x) >> 8))
-#define LITTLE_TO_NATIVE32(x) (((((PRUint32) x) & 0xFF) << 24) | \
-                               (((((PRUint32) x) >> 8) & 0xFF) << 16) | \
-                               (((((PRUint32) x) >> 16) & 0xFF) << 8) | \
-                               (((PRUint32) x) >> 24))
-
-#define NATIVE32_TO_LITTLE LITTLE_TO_NATIVE32
-
-#else
-#define LITTLE_TO_NATIVE16(x) x
-#define LITTLE_TO_NATIVE32(x) x
-#define NATIVE32_TO_LITTLE(x) x
-
-#endif
-
-#define USE_RGB
-
-// BMPINFOHEADER.compression defines
-#ifndef BI_RGB
-#define BI_RGB 0
-#endif
-#ifndef BI_RLE8
-#define BI_RLE8 1
-#endif
-#ifndef BI_RLE4
-#define BI_RLE4 2
-#endif
-#ifndef BI_BITFIELDS
-#define BI_BITFIELDS 3
-#endif
-// BI_ALPHABITFIELDS  means no compression and specifies alpha bits
-// valid only for 32bpp and 16bpp
-#define BI_ALPHABITFIELDS 4
-
-// RLE Escape codes
-#define RLE_ESCAPE       0
-#define RLE_ESCAPE_EOL   0
-#define RLE_ESCAPE_EOF   1
-#define RLE_ESCAPE_DELTA 2
-
-/// enums for mState
-enum ERLEState {
-    eRLEStateInitial,
-    eRLEStateNeedSecondEscapeByte,
-    eRLEStateNeedXDelta,
-    eRLEStateNeedYDelta,    ///< mStateData will hold x delta
-    eRLEStateAbsoluteMode,  ///< mStateData will hold count of existing data to read
-    eRLEStateAbsoluteModePadded ///< As above, but another byte of data has to be read as padding
-};
-
 class RasterImage;
 
 /**
  * Decoder for BMP-Files, as used by Windows and OS/2
  */
 class nsBMPDecoder : public Decoder
 {
 public:
--- a/modules/libpr0n/decoders/nsICODecoder.cpp
+++ b/modules/libpr0n/decoders/nsICODecoder.cpp
@@ -39,16 +39,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* This is a Cross-Platform ICO Decoder, which should work everywhere, including
  * Big-Endian machines like the PowerPC. */
 
 #include <stdlib.h>
 
+#include "Endian.h"
 #include "nsICODecoder.h"
 
 #include "nsIInputStream.h"
 #include "nsIComponentManager.h"
 #include "RasterImage.h"
 #include "imgIContainerObserver.h"
 
 #include "nsIProperties.h"
--- a/modules/libpr0n/encoders/Makefile.in
+++ b/modules/libpr0n/encoders/Makefile.in
@@ -37,12 +37,13 @@ DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS += png \
 	jpeg \
+	bmp \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/encoders/bmp/Makefile.in
@@ -0,0 +1,58 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Brian R. Bondy <netzen@gmail.com>
+# 
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= imgbmpe
+LIBRARY_NAME	= imgbmpe_s
+FORCE_STATIC_LIB = 1
+MODULE_NAME	= imgEncoderBMPModule
+LIBXUL_LIBRARY = 1
+
+# Decoders need RasterImage.h
+LOCAL_INCLUDES += -I$(topsrcdir)/modules/libpr0n/src/
+
+CPPSRCS		= nsBMPEncoder.cpp
+
+include $(topsrcdir)/config/rules.mk
+
+
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/encoders/bmp/nsBMPEncoder.cpp
@@ -0,0 +1,674 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is an implementation of a bitmap encoder.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian R. Bondy <netzen@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCRT.h"
+#include "Endian.h"
+#include "nsBMPEncoder.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "nsString.h"
+#include "nsStreamUtils.h"
+#include "nsAutoPtr.h"
+
+using namespace mozilla;
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsBMPEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
+
+nsBMPEncoder::nsBMPEncoder() : mImageBufferStart(nsnull), 
+                               mImageBufferCurr(0),
+                               mImageBufferSize(0), 
+                               mImageBufferReadPoint(0), 
+                               mFinished(PR_FALSE),
+                               mCallback(nsnull), 
+                               mCallbackTarget(nsnull), 
+                               mNotifyThreshold(0)
+{
+}
+
+nsBMPEncoder::~nsBMPEncoder()
+{
+  if (mImageBufferStart) {
+    moz_free(mImageBufferStart);
+    mImageBufferStart = nsnull;
+    mImageBufferCurr = nsnull;
+  }
+}
+
+// nsBMPEncoder::InitFromData
+//
+// One output option is supported: bpp=<bpp_value>
+// bpp specifies the bits per pixel to use where bpp_value can be 24 or 32
+NS_IMETHODIMP nsBMPEncoder::InitFromData(const PRUint8* aData,
+                                         PRUint32 aLength, // (unused,
+                                                           // req'd by JS)
+                                         PRUint32 aWidth,
+                                         PRUint32 aHeight,
+                                         PRUint32 aStride,
+                                         PRUint32 aInputFormat,
+                                         const nsAString& aOutputOptions)
+{
+  // validate input format
+  if (aInputFormat != INPUT_FORMAT_RGB &&
+      aInputFormat != INPUT_FORMAT_RGBA &&
+      aInputFormat != INPUT_FORMAT_HOSTARGB) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // Stride is the padded width of each row, so it better be longer
+  if ((aInputFormat == INPUT_FORMAT_RGB &&
+       aStride < aWidth * 3) ||
+      ((aInputFormat == INPUT_FORMAT_RGBA || aInputFormat == INPUT_FORMAT_HOSTARGB) &&
+       aStride < aWidth * 4)) {
+      NS_WARNING("Invalid stride for InitFromData");
+      return NS_ERROR_INVALID_ARG;
+  }
+
+  nsresult rv;
+  rv = StartImageEncode(aWidth, aHeight, aInputFormat, aOutputOptions);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  rv = AddImageFrame(aData, aLength, aWidth, aHeight, aStride,
+                     aInputFormat, aOutputOptions);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  rv = EndImageEncode();
+  return rv;
+}
+
+// Just a helper method to make it explicit in calculations that we are dealing
+// with bytes and not bits
+static inline PRUint32
+BytesPerPixel(PRUint32 aBPP)
+{
+  return aBPP / 8;
+}
+
+// Calculates the number of padding bytes that are needed per row of image data
+static inline PRUint32
+PaddingBytes(PRUint32 aBPP, PRUint32 aWidth)
+{
+  PRUint32 rowSize = aWidth * BytesPerPixel(aBPP);
+  PRUint8 paddingSize = 0;
+  if(rowSize % 4) {
+    paddingSize = (4 - (rowSize % 4));
+  }
+  return paddingSize;
+}
+
+// See ::InitFromData for other info.
+NS_IMETHODIMP nsBMPEncoder::StartImageEncode(PRUint32 aWidth,
+                                             PRUint32 aHeight,
+                                             PRUint32 aInputFormat,
+                                             const nsAString& aOutputOptions)
+{
+  // can't initialize more than once
+  if (mImageBufferStart || mImageBufferCurr) {
+    return NS_ERROR_ALREADY_INITIALIZED;
+  }
+
+  // validate input format
+  if (aInputFormat != INPUT_FORMAT_RGB &&
+      aInputFormat != INPUT_FORMAT_RGBA &&
+      aInputFormat != INPUT_FORMAT_HOSTARGB) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // parse and check any provided output options
+  PRUint32 bpp;
+  nsresult rv = ParseOptions(aOutputOptions, &bpp);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  InitFileHeader(bpp, aWidth, aHeight);
+  InitInfoHeader(bpp, aWidth, aHeight);
+
+  mImageBufferSize = mBMPFileHeader.filesize;
+  mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize));
+  if (!mImageBufferStart) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  mImageBufferCurr = mImageBufferStart;
+
+  EncodeFileHeader();
+  EncodeInfoHeader();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsBMPEncoder::AddImageFrame(const PRUint8* aData,
+                                          PRUint32 aLength, // (unused,
+                                                            // req'd by JS)
+                                          PRUint32 aWidth,
+                                          PRUint32 aHeight,
+                                          PRUint32 aStride,
+                                          PRUint32 aInputFormat,
+                                          const nsAString& aFrameOptions)
+{
+  // must be initialized
+  if (!mImageBufferStart || !mImageBufferCurr) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  // validate input format
+  if (aInputFormat != INPUT_FORMAT_RGB &&
+      aInputFormat != INPUT_FORMAT_RGBA &&
+      aInputFormat != INPUT_FORMAT_HOSTARGB) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  static fallible_t fallible = fallible_t();
+  nsAutoArrayPtr<PRUint8> row(new (fallible) 
+                              PRUint8[mBMPInfoHeader.width * 
+                              BytesPerPixel(mBMPInfoHeader.bpp)]);
+  if (!row) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  // write each row: if we add more input formats, we may want to
+  // generalize the conversions
+  if (aInputFormat == INPUT_FORMAT_HOSTARGB) {
+    // BMP requires RGBA with post-multiplied alpha, so we need to convert
+    for (PRInt32 y = mBMPInfoHeader.height - 1; y >= 0 ; y --) {
+      ConvertHostARGBRow(&aData[y * aStride], row, mBMPInfoHeader.width);
+      if(mBMPInfoHeader.bpp == 24) {
+        EncodeImageDataRow24(row);
+      } else {
+        EncodeImageDataRow32(row);
+      }
+    }
+  } else if (aInputFormat == INPUT_FORMAT_RGBA) {
+    // RBGA, but we need to strip the alpha
+    for (PRInt32 y = 0; y < mBMPInfoHeader.height; y ++) {
+      StripAlpha(&aData[y * aStride], row, mBMPInfoHeader.width);
+      if (mBMPInfoHeader.bpp == 24) {
+        EncodeImageDataRow24(row);
+      } else {
+        EncodeImageDataRow32(row);
+      }
+    }
+  } else if (aInputFormat == INPUT_FORMAT_RGB) {
+    // simple RBG(A), no conversion needed
+    for (PRInt32 y = 0; y < mBMPInfoHeader.height; y ++) {
+      if (mBMPInfoHeader.bpp == 24) {
+        EncodeImageDataRow24(&aData[y * aStride]);
+      } else { 
+        EncodeImageDataRow32(&aData[y * aStride]);
+      }
+    }
+  } else {
+    NS_NOTREACHED("Bad format type");
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP nsBMPEncoder::EndImageEncode()
+{
+  // must be initialized
+  if (!mImageBufferStart || !mImageBufferCurr) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  mFinished = PR_TRUE;
+  NotifyListener();
+
+  // if output callback can't get enough memory, it will free our buffer
+  if (!mImageBufferStart || !mImageBufferCurr) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  return NS_OK;
+}
+
+
+// Parses the encoder options and sets the bits per pixel to use
+// See InitFromData for a description of the parse options
+nsresult
+nsBMPEncoder::ParseOptions(const nsAString& aOptions, PRUint32* bpp)
+{
+  // If no parsing options just use the default of 24BPP
+  if (aOptions.Length() == 0) {
+    if (bpp) {
+      *bpp = 24;
+    }
+    return NS_OK;
+  }
+
+  // Parse the input string into a set of name/value pairs.
+  // From a format like: name=value;bpp=<bpp_value>;name=value
+  // to format: [0] = name=value, [1] = bpp=<bpp_value>, [2] = name=value
+  nsTArray<nsCString> nameValuePairs;
+  if (!ParseString(NS_ConvertUTF16toUTF8(aOptions), ';', nameValuePairs)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // For each name/value pair in the set
+  for (PRUint32 i = 0; i < nameValuePairs.Length(); ++i) {
+
+    // Split the name value pair [0] = name, [1] = value
+    nsTArray<nsCString> nameValuePair;
+    if (!ParseString(nameValuePairs[i], '=', nameValuePair)) {
+      return NS_ERROR_INVALID_ARG;
+    }
+    if (nameValuePair.Length() != 2) {
+      return NS_ERROR_INVALID_ARG;
+    }
+
+    // Parse the bpp portion of the string name=value;bpp=<bpp_value>;name=value
+    if (nameValuePair[0].Equals("bpp", nsCaseInsensitiveCStringComparator())) {
+      if (nameValuePair[1].Equals("24")) {
+        *bpp = 24;
+      } else if (nameValuePair[1].Equals("32")) {
+        *bpp = 32;
+      } else {
+        return NS_ERROR_INVALID_ARG;
+      }
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsBMPEncoder::Close()
+{
+  if (mImageBufferStart) {
+    moz_free(mImageBufferStart);
+    mImageBufferStart = nsnull;
+    mImageBufferSize = 0;
+    mImageBufferReadPoint = 0;
+    mImageBufferCurr = nsnull;
+  }
+
+  return NS_OK;
+}
+
+// Obtains the available bytes to read
+NS_IMETHODIMP nsBMPEncoder::Available(PRUint32 *_retval)
+{
+  if (!mImageBufferStart || !mImageBufferCurr) {
+    return NS_BASE_STREAM_CLOSED;
+  }
+
+  *_retval = GetCurrentImageBufferOffset() - mImageBufferReadPoint;
+  return NS_OK;
+}
+
+// [noscript] Reads bytes which are available
+NS_IMETHODIMP nsBMPEncoder::Read(char * aBuf, PRUint32 aCount,
+                                 PRUint32 *_retval)
+{
+  return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
+}
+
+// [noscript] Reads segments
+NS_IMETHODIMP nsBMPEncoder::ReadSegments(nsWriteSegmentFun aWriter,
+                                         void *aClosure, PRUint32 aCount,
+                                         PRUint32 *_retval)
+{
+  PRUint32 maxCount = GetCurrentImageBufferOffset() - mImageBufferReadPoint;
+  if (maxCount == 0) {
+    *_retval = 0;
+    return mFinished ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
+  }
+
+  if (aCount > maxCount) {
+    aCount = maxCount;
+  }
+  nsresult rv = aWriter(this, aClosure,
+                        reinterpret_cast<const char*>(mImageBufferStart + 
+                                                      mImageBufferReadPoint),
+                        0, aCount, _retval);
+  if (NS_SUCCEEDED(rv)) {
+    NS_ASSERTION(*_retval <= aCount, "bad write count");
+    mImageBufferReadPoint += *_retval;
+  }
+  // errors returned from the writer end here!
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+nsBMPEncoder::IsNonBlocking(PRBool *_retval)
+{
+  *_retval = PR_TRUE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+nsBMPEncoder::AsyncWait(nsIInputStreamCallback *aCallback,
+                        PRUint32 aFlags,
+                        PRUint32 aRequestedCount,
+                        nsIEventTarget *aTarget)
+{
+  if (aFlags != 0) {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
+  if (mCallback || mCallbackTarget) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  mCallbackTarget = aTarget;
+  // 0 means "any number of bytes except 0"
+  mNotifyThreshold = aRequestedCount;
+  if (!aRequestedCount) {
+    mNotifyThreshold = 1024; // We don't want to notify incessantly
+  }
+
+  // We set the callback absolutely last, because NotifyListener uses it to
+  // determine if someone needs to be notified.  If we don't set it last,
+  // NotifyListener might try to fire off a notification to a null target
+  // which will generally cause non-threadsafe objects to be used off the main thread
+  mCallback = aCallback;
+
+  // What we are being asked for may be present already
+  NotifyListener();
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsBMPEncoder::CloseWithStatus(nsresult aStatus)
+{
+  return Close();
+}
+
+// nsBMPEncoder::ConvertHostARGBRow
+//
+//    Our colors are stored with premultiplied alphas, but we need
+//    an output with no alpha in machine-independent byte order.
+//
+void
+nsBMPEncoder::ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
+                                 PRUint32 aPixelWidth)
+{
+  for (PRUint32 x = 0; x < aPixelWidth; x ++) {
+    const PRUint32& pixelIn = ((const PRUint32*)(aSrc))[x];
+    PRUint8 *pixelOut = &aDest[x * BytesPerPixel(mBMPInfoHeader.bpp)];
+
+    PRUint8 alpha = (pixelIn & 0xff000000) >> 24;
+    if (alpha == 0) {
+      pixelOut[0] = pixelOut[1] = pixelOut[2] = 0;
+    } else {
+      pixelOut[0] = (((pixelIn & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
+      pixelOut[1] = (((pixelIn & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
+      pixelOut[2] = (((pixelIn & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
+      if(mBMPInfoHeader.bpp == 32) {
+        pixelOut[3] = alpha;
+      }
+    }
+  }
+}
+
+// nsBMPEncoder::StripAlpha
+//
+//    Input is RGBA, output is RGB
+void
+nsBMPEncoder::StripAlpha(const PRUint8* aSrc, PRUint8* aDest,
+                         PRUint32 aPixelWidth)
+{
+  for (PRUint32 x = 0; x < aPixelWidth; x ++) {
+    const PRUint8* pixelIn = &aSrc[x * 4];
+    PRUint8* pixelOut = &aDest[x * 3];
+    pixelOut[0] = pixelIn[0];
+    pixelOut[1] = pixelIn[1];
+    pixelOut[2] = pixelIn[2];
+  }
+}
+
+void
+nsBMPEncoder::NotifyListener()
+{
+  if (mCallback &&
+      (GetCurrentImageBufferOffset() - mImageBufferReadPoint >= 
+       mNotifyThreshold || mFinished)) {
+    nsCOMPtr<nsIInputStreamCallback> callback;
+    if (mCallbackTarget) {
+      NS_NewInputStreamReadyEvent(getter_AddRefs(callback),
+                                  mCallback,
+                                  mCallbackTarget);
+    } else {
+      callback = mCallback;
+    }
+
+    NS_ASSERTION(callback, "Shouldn't fail to make the callback");
+    // Null the callback first because OnInputStreamReady could
+    // reenter AsyncWait
+    mCallback = nsnull;
+    mCallbackTarget = nsnull;
+    mNotifyThreshold = 0;
+
+    callback->OnInputStreamReady(this);
+  }
+}
+
+// Initializes the BMP file header mBMPFileHeader to the passed in values
+void 
+nsBMPEncoder::InitFileHeader(PRUint32 aBPP, PRUint32 aWidth, PRUint32 aHeight)
+{
+  memset(&mBMPFileHeader, 0, sizeof(mBMPFileHeader));
+  mBMPFileHeader.signature[0] = 'B';
+  mBMPFileHeader.signature[1] = 'M';
+  
+  mBMPFileHeader.dataoffset = WIN_HEADER_LENGTH;
+
+  // The color table is present only if BPP is <= 8
+  if (aBPP <= 8) {
+    PRUint32 numColors = 1 << aBPP;
+    mBMPFileHeader.dataoffset += 4 * numColors;
+    mBMPFileHeader.filesize = mBMPFileHeader.dataoffset + aWidth * aHeight;
+  } else {
+    mBMPFileHeader.filesize = mBMPFileHeader.dataoffset + (aWidth * 
+                              BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth)) *
+                              aHeight;
+  }
+
+  mBMPFileHeader.reserved = 0;
+  mBMPFileHeader.bihsize = WIN_BIH_LENGTH;
+}
+
+// Initializes the bitmap info header mBMPInfoHeader to the passed in values
+void 
+nsBMPEncoder::InitInfoHeader(PRUint32 aBPP, PRUint32 aWidth, PRUint32 aHeight)
+{
+  memset(&mBMPInfoHeader, 0, sizeof(mBMPInfoHeader));
+  mBMPInfoHeader.bpp =  aBPP;
+  mBMPInfoHeader.planes = 1;
+  mBMPInfoHeader.colors = 0;
+  mBMPInfoHeader.important_colors = 0;
+  mBMPInfoHeader.width = aWidth;
+  mBMPInfoHeader.height = aHeight;
+  mBMPInfoHeader.compression = 0;
+  if (aBPP <= 8) {
+    mBMPInfoHeader.image_size = aWidth * aHeight;
+  } else {
+    mBMPInfoHeader.image_size = (aWidth * BytesPerPixel(aBPP) + 
+                                 PaddingBytes(aBPP, aWidth)) * aHeight;
+  }
+  mBMPInfoHeader.xppm = 0;
+  mBMPInfoHeader.yppm = 0;
+}
+
+// Encodes the BMP file header mBMPFileHeader
+void 
+nsBMPEncoder::EncodeFileHeader() 
+{  
+  mozilla::imagelib::BMPFILEHEADER littleEndianBFH = mBMPFileHeader;
+  littleEndianBFH.filesize = NATIVE32_TO_LITTLE(littleEndianBFH.filesize);
+  littleEndianBFH.reserved = NATIVE32_TO_LITTLE(littleEndianBFH.reserved);
+  littleEndianBFH.dataoffset= NATIVE32_TO_LITTLE(littleEndianBFH.dataoffset);
+  littleEndianBFH.bihsize = NATIVE32_TO_LITTLE(littleEndianBFH.bihsize);
+
+  memcpy(mImageBufferCurr, &littleEndianBFH.signature, 
+         sizeof(littleEndianBFH.signature));
+  mImageBufferCurr += sizeof(littleEndianBFH.signature);
+  memcpy(mImageBufferCurr, &littleEndianBFH.filesize, 
+         sizeof(littleEndianBFH.filesize));
+  mImageBufferCurr += sizeof(littleEndianBFH.filesize);
+  memcpy(mImageBufferCurr, &littleEndianBFH.reserved, 
+         sizeof(littleEndianBFH.reserved));
+  mImageBufferCurr += sizeof(littleEndianBFH.reserved);
+  memcpy(mImageBufferCurr, &littleEndianBFH.dataoffset, 
+         sizeof(littleEndianBFH.dataoffset));
+  mImageBufferCurr += sizeof(littleEndianBFH.dataoffset);
+  memcpy(mImageBufferCurr, &littleEndianBFH.bihsize, 
+         sizeof(littleEndianBFH.bihsize));
+  mImageBufferCurr += sizeof(littleEndianBFH.bihsize);
+}
+
+// Encodes the BMP infor header mBMPInfoHeader
+void 
+nsBMPEncoder::EncodeInfoHeader()
+{
+  mozilla::imagelib::BMPINFOHEADER littleEndianmBIH = mBMPInfoHeader;
+  littleEndianmBIH.width =  NATIVE32_TO_LITTLE(littleEndianmBIH.width);
+  littleEndianmBIH.height = NATIVE32_TO_LITTLE(littleEndianmBIH.height); 
+  littleEndianmBIH.planes = NATIVE16_TO_LITTLE(littleEndianmBIH.planes);
+  littleEndianmBIH.bpp = NATIVE16_TO_LITTLE(littleEndianmBIH.bpp);
+  littleEndianmBIH.compression = NATIVE32_TO_LITTLE(
+                                 littleEndianmBIH.compression);
+  littleEndianmBIH.image_size = NATIVE32_TO_LITTLE(
+                                littleEndianmBIH.image_size);
+  littleEndianmBIH.xppm = NATIVE32_TO_LITTLE(littleEndianmBIH.xppm);
+  littleEndianmBIH.yppm = NATIVE32_TO_LITTLE(littleEndianmBIH.yppm);
+  littleEndianmBIH.colors = NATIVE32_TO_LITTLE(littleEndianmBIH.colors);
+  littleEndianmBIH.important_colors = NATIVE32_TO_LITTLE(
+                                      littleEndianmBIH.important_colors);
+
+  if (mBMPFileHeader.bihsize == 12) { // OS/2 Bitmap
+    memcpy(mImageBufferCurr, &littleEndianmBIH.width, 2);
+    mImageBufferCurr += 2; // Uint16 in OS/2 BMPs
+    memcpy(mImageBufferCurr, &littleEndianmBIH.height, 2);
+    mImageBufferCurr += 2; // Uint16 in OS/2 BMPs
+    memcpy(mImageBufferCurr, &littleEndianmBIH.planes, 
+           sizeof(littleEndianmBIH.planes));
+    mImageBufferCurr += sizeof(littleEndianmBIH.planes);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.bpp, 
+           sizeof(littleEndianmBIH.bpp));
+    mImageBufferCurr += sizeof(littleEndianmBIH.bpp);
+  }
+  else {
+    memcpy(mImageBufferCurr, &littleEndianmBIH.width, 
+           sizeof(littleEndianmBIH.width));
+    mImageBufferCurr += sizeof(littleEndianmBIH.width);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.height, 
+           sizeof(littleEndianmBIH.height));
+    mImageBufferCurr += sizeof(littleEndianmBIH.height);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.planes, 
+           sizeof(littleEndianmBIH.planes));
+    mImageBufferCurr += sizeof(littleEndianmBIH.planes);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.bpp, 
+           sizeof(littleEndianmBIH.bpp));
+    mImageBufferCurr += sizeof(littleEndianmBIH.bpp);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.compression, 
+           sizeof(littleEndianmBIH.compression));
+    mImageBufferCurr += sizeof(littleEndianmBIH.compression);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.image_size, 
+           sizeof(littleEndianmBIH.image_size));
+    mImageBufferCurr += sizeof(littleEndianmBIH.image_size);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.xppm, 
+           sizeof(littleEndianmBIH.xppm));
+    mImageBufferCurr += sizeof(littleEndianmBIH.xppm);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.yppm, 
+           sizeof(littleEndianmBIH.yppm));
+    mImageBufferCurr += sizeof(littleEndianmBIH.yppm);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.colors, 
+           sizeof(littleEndianmBIH.colors));
+    mImageBufferCurr += sizeof(littleEndianmBIH.colors);
+    memcpy(mImageBufferCurr, &littleEndianmBIH.important_colors, 
+           sizeof(littleEndianmBIH.important_colors));
+    mImageBufferCurr += sizeof(littleEndianmBIH.important_colors);
+  }
+}
+
+// Sets a pixel in the image buffer that doesn't have alpha data
+static inline void 
+  SetPixel24(PRUint8*& imageBufferCurr, PRUint8 aRed, PRUint8 aGreen, 
+  PRUint8 aBlue)
+{
+  *imageBufferCurr = aBlue;
+  *(imageBufferCurr + 1) = aGreen;
+  *(imageBufferCurr + 2) = aRed;
+}
+
+// Sets a pixel in the image buffer with alpha data
+static inline void 
+SetPixel32(PRUint8*& imageBufferCurr, PRUint8 aRed, PRUint8 aGreen, 
+           PRUint8 aBlue, PRUint8 aAlpha = 0xFF)
+{
+  *imageBufferCurr = aBlue;
+  *(imageBufferCurr + 1) = aGreen;
+  *(imageBufferCurr + 2) = aRed;
+  *(imageBufferCurr + 3) = aAlpha;
+}
+
+// Encodes a row of image data which does not have alpha data
+void 
+nsBMPEncoder::EncodeImageDataRow24(const PRUint8* aData)
+{
+  for (PRInt32 x = 0; x < mBMPInfoHeader.width; x ++) {
+    PRUint32 pos = x * BytesPerPixel(mBMPInfoHeader.bpp);
+    SetPixel24(mImageBufferCurr, aData[pos], aData[pos + 1], aData[pos + 2]);
+    mImageBufferCurr += BytesPerPixel(mBMPInfoHeader.bpp);
+  }
+  
+  for (PRUint32 x = 0; x < PaddingBytes(mBMPInfoHeader.bpp, 
+                                        mBMPInfoHeader.width); x ++) {
+    *mImageBufferCurr++ = 0;
+  }
+}
+
+// Encodes a row of image data which does have alpha data
+void 
+nsBMPEncoder::EncodeImageDataRow32(const PRUint8* aData)
+{
+  for (PRInt32 x = 0; x < mBMPInfoHeader.width; x ++) {
+    PRUint32 pos = x * BytesPerPixel(mBMPInfoHeader.bpp);
+    SetPixel32(mImageBufferCurr, aData[pos], aData[pos + 1], 
+               aData[pos + 2], aData[pos + 3]);
+    mImageBufferCurr += 4;
+  }
+
+  for (PRUint32 x = 0; x < PaddingBytes(mBMPInfoHeader.bpp, 
+                                        mBMPInfoHeader.width); x ++) {
+    *mImageBufferCurr++ = 0;
+  }
+}
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/encoders/bmp/nsBMPEncoder.h
@@ -0,0 +1,119 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is an implementation of a bitmap encoder.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian R. Bondy <netzen@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "imgIEncoder.h"
+#include "BMPFileHeaders.h"
+
+#include "mozilla/ReentrantMonitor.h"
+
+#include "nsCOMPtr.h"
+
+#define NS_BMPENCODER_CID \
+{ /* 13a5320c-4c91-4FA4-bd16-b081a3ba8c0b */         \
+     0x13a5320c,                                     \
+     0x4c91,                                         \
+     0x4fa4,                                         \
+    {0xbd, 0x16, 0xb0, 0x81, 0xa3, 0Xba, 0x8c, 0x0b} \
+}
+
+// Provides BMP encoding functionality. Use InitFromData() to do the
+// encoding. See that function definition for encoding options.
+
+class nsBMPEncoder : public imgIEncoder
+{
+  typedef mozilla::ReentrantMonitor ReentrantMonitor;
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_IMGIENCODER
+  NS_DECL_NSIINPUTSTREAM
+  NS_DECL_NSIASYNCINPUTSTREAM
+
+  nsBMPEncoder();
+
+private:
+  ~nsBMPEncoder();
+
+protected:
+  // See InitData in the cpp for valid parse options
+  nsresult ParseOptions(const nsAString& aOptions, PRUint32* bpp);
+  // Obtains data with no alpha in machine-independent byte order
+  void ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
+                          PRUint32 aPixelWidth);
+  // Strips the alpha from aSrc and puts it in aDest
+  void StripAlpha(const PRUint8* aSrc, PRUint8* aDest,
+                  PRUint32 aPixelWidth);
+  // Thread safe notify listener
+  void NotifyListener();
+
+  // Initializes the bitmap file header member mBMPFileHeader
+  void InitFileHeader(PRUint32 aBPP, PRUint32 aWidth, PRUint32 aHeight);
+  // Initializes the bitmap info header member mBMPInfoHeader
+  void InitInfoHeader(PRUint32 aBPP, PRUint32 aWidth, PRUint32 aHeight);
+  // Encodes the bitmap file header member mBMPFileHeader
+  void EncodeFileHeader();
+  // Encodes the bitmap info header member mBMPInfoHeader
+  void EncodeInfoHeader();
+  // Encodes a row of image data which does not have alpha data
+  void EncodeImageDataRow24(const PRUint8* aData);
+  // Encodes a row of image data which does have alpha data
+  void EncodeImageDataRow32(const PRUint8* aData);
+  // Obtains the current offset filled up to for the image buffer
+  inline PRInt32 GetCurrentImageBufferOffset()
+  {
+    return static_cast<PRInt32>(mImageBufferCurr - mImageBufferStart);
+  }
+
+  // These headers will always contain endian independent stuff 
+  // They store the BMP headers which will be encoded
+  mozilla::imagelib::BMPFILEHEADER mBMPFileHeader;
+  mozilla::imagelib::BMPINFOHEADER mBMPInfoHeader;
+
+  // Keeps track of the start of the image buffer
+  PRUint8* mImageBufferStart;
+  // Keeps track of the current position in the image buffer
+  PRUint8* mImageBufferCurr;
+  // Keeps track of the image buffer size
+  PRUint32 mImageBufferSize;
+  // Keeps track of the number of bytes in the image buffer which are read
+  PRUint32 mImageBufferReadPoint;
+  // Stores PR_TRUE if the image is done being encoded
+  PRPackedBool mFinished;
+
+  nsCOMPtr<nsIInputStreamCallback> mCallback;
+  nsCOMPtr<nsIEventTarget> mCallbackTarget;
+  PRUint32 mNotifyThreshold;
+};
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/src/BMPFileHeaders.h
@@ -0,0 +1,141 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is bitmap header definitions.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian R. Bondy <netzen@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_IMAGELIB_BMPHEADERS_H_
+#define MOZILLA_IMAGELIB_BMPHEADERS_H_
+
+namespace mozilla {
+  namespace imagelib {
+
+    struct BMPFILEHEADER {
+      char signature[2]; // String "BM"
+      PRUint32 filesize;
+      PRInt32 reserved; // Zero
+      PRUint32 dataoffset; // Offset to raster data
+
+      PRUint32 bihsize;
+    };
+
+// The length of the bitmap file header as defined in the BMP spec.
+#define BFH_LENGTH 14 
+// Internally we store the bitmap file header with an additional 4 bytes which
+// is used to store the bitmap information header size.
+#define BFH_INTERNAL_LENGTH 18
+
+#define OS2_INTERNAL_BIH_LENGTH 8
+#define WIN_INTERNAL_BIH_LENGTH 36
+
+#define OS2_BIH_LENGTH 12 // This is the real BIH size (as contained in the bihsize field of BMPFILEHEADER)
+#define WIN_BIH_LENGTH 40 // This is the real BIH size (as contained in the bihsize field of BMPFILEHEADER)
+
+#define OS2_HEADER_LENGTH (BFH_INTERNAL_LENGTH + OS2_INTERNAL_BIH_LENGTH)
+#define WIN_HEADER_LENGTH (BFH_INTERNAL_LENGTH + WIN_INTERNAL_BIH_LENGTH)
+
+    struct BMPINFOHEADER {
+      PRInt32 width; // Uint16 in OS/2 BMPs
+      PRInt32 height; // Uint16 in OS/2 BMPs
+      PRUint16 planes; // =1
+      PRUint16 bpp; // Bits per pixel.
+      // The rest of the header is not available in OS/2 BMP Files
+      PRUint32 compression; // 0=no compression 1=8bit RLE 2=4bit RLE
+      PRUint32 image_size; // (compressed) image size. Can be 0 if compression==0
+      PRUint32 xppm; // Pixels per meter, horizontal
+      PRUint32 yppm; // Pixels per meter, vertical
+      PRUint32 colors; // Used Colors
+      PRUint32 important_colors; // Number of important colors. 0=all
+    };
+
+    struct colorTable {
+      PRUint8 red;
+      PRUint8 green;
+      PRUint8 blue;
+    };
+
+    struct bitFields {
+      PRUint32 red;
+      PRUint32 green;
+      PRUint32 blue;
+      PRUint8 redLeftShift;
+      PRUint8 redRightShift;
+      PRUint8 greenLeftShift;
+      PRUint8 greenRightShift;
+      PRUint8 blueLeftShift;
+      PRUint8 blueRightShift;
+    };
+
+  } // namespace imagelib
+} // namespace mozilla
+
+#define BITFIELD_LENGTH 12 // Length of the bitfields structure in the bmp file
+#define USE_RGB
+
+// BMPINFOHEADER.compression defines
+#ifndef BI_RGB
+#define BI_RGB 0
+#endif
+#ifndef BI_RLE8
+#define BI_RLE8 1
+#endif
+#ifndef BI_RLE4
+#define BI_RLE4 2
+#endif
+#ifndef BI_BITFIELDS
+#define BI_BITFIELDS 3
+#endif
+// BI_ALPHABITFIELDS  means no compression and specifies alpha bits
+// valid only for 32bpp and 16bpp
+#ifndef BI_ALPHABITFIELDS
+#define BI_ALPHABITFIELDS 4
+#endif
+
+// RLE Escape codes
+#define RLE_ESCAPE       0
+#define RLE_ESCAPE_EOL   0
+#define RLE_ESCAPE_EOF   1
+#define RLE_ESCAPE_DELTA 2
+
+/// enums for mState
+enum ERLEState {
+  eRLEStateInitial,
+  eRLEStateNeedSecondEscapeByte,
+  eRLEStateNeedXDelta,
+  eRLEStateNeedYDelta,    ///< mStateData will hold x delta
+  eRLEStateAbsoluteMode,  ///< mStateData will hold count of existing data to read
+  eRLEStateAbsoluteModePadded ///< As above, but another byte of data has to be read as padding
+};
+
+#endif
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/src/Endian.h
@@ -0,0 +1,62 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is endian helper macros.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian R. Bondy <netzen@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_IMAGELIB_ENDIAN_H_
+#define MOZILLA_IMAGELIB_ENDIAN_H_
+
+#include "prtypes.h"
+
+#if defined WORDS_BIGENDIAN || defined IS_BIG_ENDIAN
+// We must ensure that the entity is unsigned
+// otherwise, if it is signed/negative, the MSB will be
+// propagated when we shift
+#define LITTLE_TO_NATIVE16(x) (((((PRUint16) x) & 0xFF) << 8) | \
+                               (((PRUint16) x) >> 8))
+#define LITTLE_TO_NATIVE32(x) (((((PRUint32) x) & 0xFF) << 24) | \
+                               (((((PRUint32) x) >> 8) & 0xFF) << 16) | \
+                               (((((PRUint32) x) >> 16) & 0xFF) << 8) | \
+                               (((PRUint32) x) >> 24))
+#define NATIVE32_TO_LITTLE LITTLE_TO_NATIVE32
+#define NATIVE16_TO_LITTLE LITTLE_TO_NATIVE16
+#else
+#define LITTLE_TO_NATIVE16(x) x
+#define LITTLE_TO_NATIVE32(x) x
+#define NATIVE32_TO_LITTLE(x) x
+#define NATIVE16_TO_LITTLE(x) x
+#endif
+
+#endif