adding support for image encoding. bug 245684. patches from Brett Wilson <brettw@gmail.com>. r=me, sr=vlad

git-svn-id: svn://10.0.0.236/trunk@179436 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
pavlov%pavlov.net
2005-08-31 22:15:33 +00:00
parent 5b425dcb54
commit 41ae11b538
14 changed files with 722 additions and 23 deletions

View File

@@ -1174,6 +1174,8 @@ embedding/components/profilesharingsetup/src/Makefile
modules/libpr0n/decoders/icon/win/Makefile
modules/libpr0n/decoders/icon/gtk/Makefile
modules/libpr0n/decoders/xbm/Makefile
modules/libpr0n/encoders/Makefile
modules/libpr0n/encoders/png/Makefile
"
MAKEFILES_accessible="

View File

@@ -87,6 +87,7 @@ MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
MOZ_DBGRINFO_MODULES = @MOZ_DBGRINFO_MODULES@
MOZ_EXTENSIONS = @MOZ_EXTENSIONS@
MOZ_IMG_DECODERS= @MOZ_IMG_DECODERS@
MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@
MOZ_JSDEBUGGER = @MOZ_JSDEBUGGER@
MOZ_PERF_METRICS = @MOZ_PERF_METRICS@
MOZ_LEAKY = @MOZ_LEAKY@

View File

@@ -3955,6 +3955,7 @@ MOZ_DBGRINFO_MODULES=
MOZ_ENABLE_LIBXUL=
MOZ_EXTENSIONS_ALL=" cookie wallet content-packs xml-rpc xmlextras help p3p pref transformiix venkman inspector irc universalchardet typeaheadfind webservices spellcheck gnomevfs auth sroaming xmlterm datetime finger cview layout-debug tasks sql xforms permissions schema-validation reporter"
MOZ_IMG_DECODERS_DEFAULT="png gif jpeg bmp xbm"
MOZ_IMG_ENCODERS_DEFAULT="png"
MOZ_IPCD=
MOZ_JSDEBUGGER=1
MOZ_JSLOADER=1
@@ -4058,6 +4059,7 @@ minimo)
MOZ_ENABLE_POSTSCRIPT=
MOZ_EXTENSIONS_DEFAULT="xml-rpc xmlextras transformiix webservices spatialnavigation"
MOZ_IMG_DECODERS="png,gif,jpeg"
MOZ_IMG_ENCODERS=
MOZ_INSTALLER=
MOZ_JSDEBUGGER=
MOZ_LDAP_XPCOM=
@@ -4884,8 +4886,35 @@ MOZ_ARG_ENABLE_STRING(image-decoders,
done],
MOZ_IMG_DECODERS="$MOZ_IMG_DECODERS_DEFAULT")
dnl Dupes are removed in the encoder section because it will also add decoders
dnl ========================================================
dnl Image encoders
dnl ========================================================
MOZ_ARG_ENABLE_STRING(image-encoders,
[ --enable-image-encoders[={mod1,mod2,default,all,none}]
Enable specific image encoders],
[ for option in `echo $enableval | sed 's/,/ /g'`; do
if test "$option" = "yes" || test "$option" = "all"; then
addencoder="$MOZ_IMG_ENCODERS_DEFAULT"
elif test "$option" = "no" || test "$option" = "none"; then
MOZ_IMG_ENCODERS=""
addencoder=""
elif test "$option" = "default"; then
addencoder="$MOZ_IMG_ENCODERS_DEFAULT"
elif test `echo "$option" | grep -c \^-` != 0; then
option=`echo $option | sed 's/^-//'`
addencoder=`echo "$MOZ_IMG_ENCODERS" | sed "s/ ${option}//"`
else
addencoder="$option"
fi
MOZ_IMG_ENCODERS="$MOZ_IMG_ENCODERS $addencoder"
done],
MOZ_IMG_ENCODERS="$MOZ_IMG_ENCODERS_DEFAULT")
dnl Remove dupes
MOZ_IMG_DECODERS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_IMG_DECODERS}`
MOZ_IMG_ENCODERS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_IMG_ENCODERS}`
dnl ========================================================
dnl experimental ldap features
@@ -6609,6 +6638,7 @@ AC_SUBST(MOZ_DEBUG_LDFLAGS)
AC_SUBST(MOZ_DBGRINFO_MODULES)
AC_SUBST(MOZ_EXTENSIONS)
AC_SUBST(MOZ_IMG_DECODERS)
AC_SUBST(MOZ_IMG_ENCODERS)
AC_SUBST(MOZ_JSDEBUGGER)
AC_SUBST(MOZ_OJI)
AC_SUBST(MOZ_NO_XPCOM_OBSOLETE)

View File

@@ -64,6 +64,11 @@ FORCE_USE_PIC = 1
include $(topsrcdir)/config/rules.mk
#ifeq (png,$(filter png,$(MOZ_IMG_ENCODERS)))
ifdef MOZ_IMG_ENCODERS
DEFINES += -DMOZ_PNG_WRITE
endif
ifeq ($(OS_ARCH),WINNT)
DEFINES += -DZLIB_DLL
ifdef BUILD_DEBUG_GC

View File

@@ -70,7 +70,36 @@
#define PNG_NO_READ_OPT_PLTE
#define PNG_NO_MNG_FEATURES
#ifdef MOZ_PNG_WRITE
#define PNG_NO_WRITE_BACKGROUND
#define PNG_NO_WRITE_DITHER
#define PNG_NO_WRITE_INVERT
#define PNG_NO_WRITE_SHIFT
#define PNG_NO_WRITE_PACK
#define PNG_NO_WRITE_PACKSWAP
#define PNG_NO_WRITE_FILLER
#define PNG_NO_WRITE_SWAP_ALPHA
#define PNG_NO_WRITE_INVERT_ALPHA
#define PNG_NO_WRITE_RGB_TO_GRAY
#define PNG_NO_WRITE_USER_TRANSFORM
#define PNG_NO_WRITE_bKGD
#define PNG_NO_WRITE_cHRM
#define PNG_NO_WRITE_hIST
#define PNG_NO_WRITE_iCCP
#define PNG_NO_WRITE_pCAL
#define PNG_NO_WRITE_pHYs
#define PNG_NO_WRITE_sBIT
#define PNG_NO_WRITE_sCAL
#define PNG_NO_WRITE_sPLT
#define PNG_NO_WRITE_TEXT
#define PNG_NO_WRITE_tIME
#define PNG_NO_WRITE_UNKNOWN_CHUNKS
#define PNG_NO_WRITE_USER_CHUNKS
#define PNG_NO_WRITE_EMPTY_PLTE
#define PNG_NO_WRITE_OPT_PLTE
#else
#define PNG_NO_WRITE_SUPPORTED
#endif
#define PNG_NO_READ_STRIP_ALPHA
#define PNG_NO_USER_TRANSFORM_PTR

View File

@@ -50,6 +50,10 @@ ifdef MOZ_IMG_DECODERS
DIRS += decoders
endif
ifdef MOZ_IMG_ENCODERS
DIRS += encoders
endif
DIRS += build
include $(topsrcdir)/config/rules.mk

View File

@@ -66,19 +66,25 @@ CPPSRCS = \
nsImageModule.cpp \
$(NULL)
DEFINES += $(foreach d,$(filter-out icon,$(MOZ_IMG_DECODERS)),\
-DIMG_BUILD_${d})
DEFINES += $(foreach d,$(filter-out icon,$(MOZ_IMG_DECODERS)), \
-DIMG_BUILD_DECODER_${d}) \
$(foreach d,$(MOZ_IMG_ENCODERS), \
-DIMG_BUILD_ENCODER_${d})
LOCAL_INCLUDES = \
-I$(srcdir)/../src \
$(foreach d,$(filter-out icon,$(MOZ_IMG_DECODERS)), \
-I$(srcdir)/../decoders/${d}) \
$(foreach d,$(MOZ_IMG_ENCODERS), \
-I$(srcdir)/../encoders/${d}) \
$(NULL)
SHARED_LIBRARY_LIBS = \
../src/$(LIB_PREFIX)imglib2_s.$(LIB_SUFFIX) \
$(foreach d,$(filter-out icon,$(MOZ_IMG_DECODERS)), \
../decoders/${d}/$(LIB_PREFIX)img${d}_s.$(LIB_SUFFIX))\
$(foreach d,$(MOZ_IMG_ENCODERS), \
../encoders/${d}/$(LIB_PREFIX)img${d}e_s.$(LIB_SUFFIX))\
$(NULL)
EXTRA_DSO_LIBS = \

View File

@@ -57,33 +57,40 @@
#include "imgRequest.h"
#include "imgRequestProxy.h"
#ifdef IMG_BUILD_gif
#ifdef IMG_BUILD_DECODER_gif
// gif
#include "imgContainerGIF.h"
#include "nsGIFDecoder2.h"
#endif
#ifdef IMG_BUILD_bmp
#ifdef IMG_BUILD_DECODER_bmp
// bmp/ico
#include "nsBMPDecoder.h"
#include "nsICODecoder.h"
#endif
#ifdef IMG_BUILD_png
#ifdef IMG_BUILD_DECODER_png
// png
#include "nsPNGDecoder.h"
#endif
#ifdef IMG_BUILD_jpeg
#ifdef IMG_BUILD_DECODER_jpeg
// jpeg
#include "nsJPEGDecoder.h"
#endif
#ifdef IMG_BUILD_xbm
#ifdef IMG_BUILD_DECODER_xbm
// xbm
#include "nsXBMDecoder.h"
#endif
#ifdef IMG_BUILD_ENCODER_png
// png
#include "nsPNGEncoder.h"
#endif
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(imgCache)
@@ -91,52 +98,56 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(imgContainer)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgLoader)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequestProxy)
#ifdef IMG_BUILD_gif
#ifdef IMG_BUILD_DECODER_gif
// gif
NS_GENERIC_FACTORY_CONSTRUCTOR(imgContainerGIF)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIFDecoder2)
#endif
#ifdef IMG_BUILD_jpeg
#ifdef IMG_BUILD_DECODER_jpeg
// jpeg
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJPEGDecoder)
#endif
#ifdef IMG_BUILD_bmp
#ifdef IMG_BUILD_DECODER_bmp
// bmp
NS_GENERIC_FACTORY_CONSTRUCTOR(nsICODecoder)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBMPDecoder)
#endif
#ifdef IMG_BUILD_png
#ifdef IMG_BUILD_DECODER_png
// png
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPNGDecoder)
#endif
#ifdef IMG_BUILD_ENCODER_png
// png
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPNGEncoder)
#endif
#ifdef IMG_BUILD_xbm
#ifdef IMG_BUILD_DECODER_xbm
// xbm
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXBMDecoder)
#endif
static const char* gImageMimeTypes[] = {
#ifdef IMG_BUILD_gif
#ifdef IMG_BUILD_DECODER_gif
"image/gif",
#endif
#ifdef IMG_BUILD_jpeg
#ifdef IMG_BUILD_DECODER_jpeg
"image/jpeg",
"image/pjpeg",
"image/jpg",
#endif
#ifdef IMG_BUILD_bmp
#ifdef IMG_BUILD_DECODER_bmp
"image/x-icon",
"image/vnd.microsoft.icon",
"image/bmp",
#endif
#ifdef IMG_BUILD_png
#ifdef IMG_BUILD_DECODER_png
"image/png",
"image/x-png",
#endif
#ifdef IMG_BUILD_xbm
#ifdef IMG_BUILD_DECODER_xbm
"image/x-xbitmap",
"image/x-xbm",
"image/xbm"
@@ -199,7 +210,7 @@ static const nsModuleComponentInfo components[] =
"@mozilla.org/image/request;1",
imgRequestProxyConstructor, },
#ifdef IMG_BUILD_gif
#ifdef IMG_BUILD_DECODER_gif
// gif
{ "GIF image container",
NS_GIFCONTAINER_CID,
@@ -211,7 +222,7 @@ static const nsModuleComponentInfo components[] =
nsGIFDecoder2Constructor, },
#endif
#ifdef IMG_BUILD_jpeg
#ifdef IMG_BUILD_DECODER_jpeg
// jpeg
{ "JPEG decoder",
NS_JPEGDECODER_CID,
@@ -227,7 +238,7 @@ static const nsModuleComponentInfo components[] =
nsJPEGDecoderConstructor, },
#endif
#ifdef IMG_BUILD_bmp
#ifdef IMG_BUILD_DECODER_bmp
// bmp
{ "ICO Decoder",
NS_ICODECODER_CID,
@@ -243,7 +254,7 @@ static const nsModuleComponentInfo components[] =
nsBMPDecoderConstructor, },
#endif
#ifdef IMG_BUILD_png
#ifdef IMG_BUILD_DECODER_png
// png
{ "PNG Decoder",
NS_PNGDECODER_CID,
@@ -254,8 +265,15 @@ static const nsModuleComponentInfo components[] =
"@mozilla.org/image/decoder;2?type=image/x-png",
nsPNGDecoderConstructor, },
#endif
#ifdef IMG_BUILD_ENCODER_png
// png
{ "PNG Decoder",
NS_PNGENCODER_CID,
"@mozilla.org/image/encoder;2?type=image/png",
nsPNGEncoderConstructor, },
#endif
#ifdef IMG_BUILD_xbm
#ifdef IMG_BUILD_DECODER_xbm
// xbm
{ "XBM Decoder",
NS_XBMDECODER_CID,
@@ -283,7 +301,7 @@ PR_STATIC_CALLBACK(void)
imglib_Shutdown(nsIModule* aSelf)
{
imgCache::Shutdown();
#ifdef IMG_BUILD_gif
#ifdef IMG_BUILD_DECODER_gif
nsGifShutdown();
#endif
}

View File

@@ -0,0 +1,46 @@
# ***** 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) 2005
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# 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
DIRS += $(MOZ_IMG_ENCODERS)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,63 @@
# ***** 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) 2005
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# 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 = imgpnge
LIBRARY_NAME = imgpnge_s
FORCE_STATIC_LIB = 1
MODULE_NAME = imgEncoderPNGModule
LIBXUL_LIBRARY = 1
EXTRA_DSO_LIBS = gkgfx
REQUIRES = xpcom \
gfx \
string \
imglib2 \
$(PNG_REQUIRES) \
$(ZLIB_REQUIRES) \
$(NULL)
CPPSRCS = nsPNGEncoder.cpp
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,326 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** 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 PNG Encoding code
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com>
* Stuart Parmenter <pavlov@pavlov.net>
*
* 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 "nsPNGEncoder.h"
#include "prmem.h"
#include "nsString.h"
#include "nsDependentSubstring.h"
NS_IMPL_ISUPPORTS2(nsPNGEncoder, imgIEncoder, nsIInputStream)
nsPNGEncoder::nsPNGEncoder() : mImageBuffer(nsnull), mImageBufferSize(0),
mImageBufferUsed(0), mImageBufferReadPoint(0)
{
}
nsPNGEncoder::~nsPNGEncoder()
{
if (mImageBuffer) {
PR_Free(mImageBuffer);
mImageBuffer = nsnull;
}
}
// nsPNGEncoder::InitFromData
//
// One output option is supported: "transparency=none" means that the
// output PNG will not have an alpha channel, even if the input does.
//
// Based partially on gfx/cairo/cairo/src/cairo-png.c
// See also modules/libimg/png/libpng.txt
NS_IMETHODIMP nsPNGEncoder::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 (I'm afraid
// people will not understand what stride means, so check it well)
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;
}
// can't initialize more than once
if (mImageBuffer != nsnull)
return NS_ERROR_ALREADY_INITIALIZED;
// options: we only have one option so this is easy
PRBool useTransparency = PR_TRUE;
if (aOutputOptions.Length() >= 17) {
if (StringBeginsWith(aOutputOptions, NS_LITERAL_STRING("transparency=none")))
useTransparency = PR_FALSE;
}
// initialize
png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
png_voidp_NULL,
png_error_ptr_NULL,
png_error_ptr_NULL);
if (! png_ptr)
return NS_ERROR_OUT_OF_MEMORY;
png_info* info_ptr = png_create_info_struct(png_ptr);
if (! info_ptr)
{
png_destroy_write_struct(&png_ptr, nsnull);
return NS_ERROR_FAILURE;
}
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return NS_ERROR_OUT_OF_MEMORY;
}
// Set up to read the data into our image buffer, start out with an 8K
// estimated size. Note: we don't have to worry about freeing this data
// in this function. It will be freed on object destruction.
mImageBufferSize = 8192;
mImageBuffer = (PRUint8*)PR_Malloc(mImageBufferSize);
if (!mImageBuffer) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return NS_ERROR_OUT_OF_MEMORY;
}
mImageBufferUsed = 0;
// set our callback for libpng to give us the data
png_set_write_fn(png_ptr, this, WriteCallback, NULL);
// include alpha?
int colorType;
if ((aInputFormat == INPUT_FORMAT_HOSTARGB ||
aInputFormat == INPUT_FORMAT_RGBA) && useTransparency)
colorType = PNG_COLOR_TYPE_RGB_ALPHA;
else
colorType = PNG_COLOR_TYPE_RGB;
png_set_IHDR(png_ptr, info_ptr, aWidth, aHeight, 8, colorType,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png_ptr, info_ptr);
// write each row: if we add more input formats, we may want to
// generalize the conversions
if (aInputFormat == INPUT_FORMAT_HOSTARGB) {
// PNG requires RGBA with post-multiplied alpha, so we need to convert
PRUint8* row = new PRUint8[aWidth * 4];
for (PRUint32 y = 0; y < aHeight; y ++) {
ConvertHostARGBRow(&aData[y * aStride], row, aWidth, useTransparency);
png_write_row(png_ptr, row);
}
delete[] row;
} else if (aInputFormat == INPUT_FORMAT_RGBA && ! useTransparency) {
// RBGA, but we need to strip the alpha
PRUint8* row = new PRUint8[aWidth * 4];
for (PRUint32 y = 0; y < aHeight; y ++) {
StripAlpha(&aData[y * aStride], row, aWidth);
png_write_row(png_ptr, row);
}
delete[] row;
} else if (aInputFormat == INPUT_FORMAT_RGB ||
aInputFormat == INPUT_FORMAT_RGBA) {
// simple RBG(A), no conversion needed
for (PRUint32 y = 0; y < aHeight; y ++) {
png_write_row(png_ptr, (PRUint8*)&aData[y * aStride]);
}
} else {
NS_NOTREACHED("Bad format type");
}
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
// if output callback can't get enough memory, it will free our buffer
if (mImageBuffer)
return NS_OK;
else
return NS_ERROR_OUT_OF_MEMORY;
}
/* void close (); */
NS_IMETHODIMP nsPNGEncoder::Close()
{
if (mImageBuffer != nsnull) {
PR_Free(mImageBuffer);
mImageBuffer = nsnull;
mImageBufferSize = 0;
mImageBufferUsed = 0;
}
return NS_OK;
}
/* unsigned long available (); */
NS_IMETHODIMP nsPNGEncoder::Available(PRUint32 *_retval)
{
*_retval = mImageBufferUsed - mImageBufferReadPoint;
return NS_OK;
}
/* [noscript] unsigned long read (in charPtr aBuf, in unsigned long aCount); */
NS_IMETHODIMP nsPNGEncoder::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
{
if (mImageBufferReadPoint >= mImageBufferUsed) {
// done reading
*_retval = 0;
return NS_OK;
}
PRUint32 toRead = mImageBufferUsed - mImageBufferReadPoint;
if (aCount < toRead)
toRead = aCount;
memcpy(aBuf, &mImageBuffer[mImageBufferReadPoint], toRead);
mImageBufferReadPoint += toRead;
*_retval = toRead;
return NS_OK;
}
/* [noscript] unsigned long readSegments (in nsWriteSegmentFun aWriter, in voidPtr aClosure, in unsigned long aCount); */
NS_IMETHODIMP nsPNGEncoder::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, PRUint32 aCount, PRUint32 *_retval)
{
if (mImageBufferUsed == 0)
return NS_ERROR_FAILURE;
PRUint32 writeCount = 0;
aWriter(this, aClosure, (const char*)mImageBuffer, 0, mImageBufferUsed, &writeCount);
if (writeCount > 0)
return NS_OK;
else
return NS_ERROR_FAILURE; // some problem with callback
}
/* boolean isNonBlocking (); */
NS_IMETHODIMP nsPNGEncoder::IsNonBlocking(PRBool *_retval)
{
*_retval = PR_TRUE;
return NS_OK;
}
// nsPNGEncoder::ConvertHostARGBRow
//
// Our colors are stored with premultiplied alphas, but PNGs use
// post-multiplied alpha. This swaps to PNG-style alpha.
//
// Copied from gfx/cairo/cairo/src/cairo-png.c
void
nsPNGEncoder::ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth, PRBool aUseTransparency)
{
PRUint32 pixelStride = aUseTransparency ? 4 : 3;
for (PRUint32 x = 0; x < aPixelWidth; x ++) {
const PRUint32& pixelIn = ((const PRUint32*)(aSrc))[x];
PRUint8 *pixelOut = &aDest[x * pixelStride];
PRUint8 alpha = (pixelIn & 0xff000000) >> 24;
if (alpha == 0) {
pixelOut[0] = pixelOut[1] = pixelOut[2] = pixelOut[3] = 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 (aUseTransparency)
pixelOut[3] = alpha;
}
}
}
// nsPNGEncoder::StripAlpha
//
// Input is RGBA, output is RGB
void
nsPNGEncoder::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];
}
}
// nsPNGEncoder::WriteCallback
void // static
nsPNGEncoder::WriteCallback(png_structp png, png_bytep data, png_size_t size)
{
nsPNGEncoder* that = NS_STATIC_CAST(nsPNGEncoder*, png_get_io_ptr(png));
if (! that->mImageBuffer)
return;
if (that->mImageBufferUsed + size > that->mImageBufferSize) {
// expand buffer, just double each time
that->mImageBufferSize *= 2;
PRUint8* newBuf = (PRUint8*)PR_Realloc(that->mImageBuffer,
that->mImageBufferSize);
if (! newBuf) {
// can't resize, just zero (this will keep us from writing more)
PR_Free(that->mImageBuffer);
that->mImageBufferSize = 0;
that->mImageBufferUsed = 0;
return;
}
that->mImageBuffer = newBuf;
}
memcpy(&that->mImageBuffer[that->mImageBufferUsed], data, size);
that->mImageBufferUsed += size;
}

View File

@@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** 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 Oracle Corporation code.
*
* The Initial Developer of the Original Code is Oracle Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
*
* 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 <png.h>
#define NS_PNGENCODER_CID \
{ /* 38d1592e-b81e-432b-86f8-471878bbfe07 */ \
0x38d1592e, \
0xb81e, \
0x432b, \
{0x86, 0xf8, 0x47, 0x18, 0x78, 0xbb, 0xfe, 0x07} \
}
// Provides PNG encoding functionality. Use InitFromData() to do the
// encoding. See that function definition for encoding options.
class nsPNGEncoder : public imgIEncoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIENCODER
NS_DECL_NSIINPUTSTREAM
nsPNGEncoder();
private:
~nsPNGEncoder();
protected:
void ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth, PRBool aUseTransparency);
void StripAlpha(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth);
static void WriteCallback(png_structp png, png_bytep data, png_size_t size);
// image buffer
PRUint8* mImageBuffer;
PRUint32 mImageBufferSize;
PRUint32 mImageBufferUsed;
PRUint32 mImageBufferReadPoint;
};

View File

@@ -53,6 +53,7 @@ XPIDLSRCS = \
imgIContainerObserver.idl \
imgIDecoder.idl \
imgIDecoderObserver.idl \
imgIEncoder.idl \
imgILoad.idl \
imgILoader.idl \
imgIRequest.idl \

View File

@@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** 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 Oracle Corporation code.
*
* The Initial Developer of the Original Code is Oracle Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
* Brett Wilson <brettw@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 "nsISupports.idl"
#include "nsIInputStream.idl"
/**
* imgIEncoder interface
*/
[scriptable, uuid(CCC5B3AD-3E67-4e3d-97E1-B06B2E96FEF8)]
interface imgIEncoder : nsIInputStream
{
// Possible values for input format (note that not all image formats
// support saving alpha channels):
// Input is RGB each pixel is represented by three bytes:
// R, G, and B (in that order, regardless of host endianness)
const PRUint32 INPUT_FORMAT_RGB = 0;
// Input is RGB each pixel is represented by four bytes:
// R, G, and B (in that order, regardless of host endianness).
// POST-MULTIPLIED alpha us used (50% transparent red is 0xff000080)
const PRUint32 INPUT_FORMAT_RGBA = 1;
// Input is host-endian ARGB: On big-endian machines each pixel is therefore
// ARGB, and for little-endian machiens (Intel) each pixel is BGRA
// (This is used by canvas to match it's internal representation)
//
// PRE-MULTIPLIED alpha is used (That is, 50% transparent red is 0x80800000,
// not 0x80ff0000
const PRUint32 INPUT_FORMAT_HOSTARGB = 2;
/* data - list of bytes in the format specified by inputFormat
* width - width in pixels
* height - height in pixels
* stride - number of bytes per row in the image
* Normally (width*3) or (width*4), depending on your input format,
* but some data uses padding at the end of each row, which would
* be extra.
* inputFormat - one of INPUT_FORMAT_* specifying the format of data
* outputOptions - semicolon-delimited list of name=value pairs that can
* give options to the output encoder. Options are encoder-
* specific. Just give empty string for default behavior.
*/
void initFromData([array, size_is(length), const] in PRUint8 data,
in unsigned long length,
in PRUint32 width,
in PRUint32 height,
in PRUint32 stride,
in PRUint32 inputFormat,
in AString outputOptions);
};