forked from mirrors/gecko-dev
Backed out changeset ada34cba0052 (bug 1348941) for image-related bustages
CLOSED TREE
This commit is contained in:
parent
4cb08c4110
commit
57f1484fe3
4 changed files with 33 additions and 96 deletions
|
|
@ -10,7 +10,6 @@
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsStreamUtils.h"
|
#include "nsStreamUtils.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "mozilla/CheckedInt.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::image;
|
using namespace mozilla::image;
|
||||||
|
|
@ -59,11 +58,6 @@ nsBMPEncoder::InitFromData(const uint8_t* aData,
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckedInt32 check = CheckedInt32(aWidth) * 4;
|
|
||||||
if (MOZ_UNLIKELY(!check.isValid())) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stride is the padded width of each row, so it better be longer
|
// Stride is the padded width of each row, so it better be longer
|
||||||
if ((aInputFormat == INPUT_FORMAT_RGB &&
|
if ((aInputFormat == INPUT_FORMAT_RGB &&
|
||||||
aStride < aWidth * 3) ||
|
aStride < aWidth * 3) ||
|
||||||
|
|
@ -92,15 +86,15 @@ nsBMPEncoder::InitFromData(const uint8_t* aData,
|
||||||
|
|
||||||
// Just a helper method to make it explicit in calculations that we are dealing
|
// Just a helper method to make it explicit in calculations that we are dealing
|
||||||
// with bytes and not bits
|
// with bytes and not bits
|
||||||
static inline uint16_t
|
static inline uint32_t
|
||||||
BytesPerPixel(uint16_t aBPP)
|
BytesPerPixel(uint32_t aBPP)
|
||||||
{
|
{
|
||||||
return aBPP / 8;
|
return aBPP / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates the number of padding bytes that are needed per row of image data
|
// Calculates the number of padding bytes that are needed per row of image data
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
PaddingBytes(uint16_t aBPP, uint32_t aWidth)
|
PaddingBytes(uint32_t aBPP, uint32_t aWidth)
|
||||||
{
|
{
|
||||||
uint32_t rowSize = aWidth * BytesPerPixel(aBPP);
|
uint32_t rowSize = aWidth * BytesPerPixel(aBPP);
|
||||||
uint8_t paddingSize = 0;
|
uint8_t paddingSize = 0;
|
||||||
|
|
@ -131,21 +125,14 @@ nsBMPEncoder::StartImageEncode(uint32_t aWidth,
|
||||||
|
|
||||||
// parse and check any provided output options
|
// parse and check any provided output options
|
||||||
Version version;
|
Version version;
|
||||||
uint16_t bpp;
|
uint32_t bpp;
|
||||||
nsresult rv = ParseOptions(aOutputOptions, version, bpp);
|
nsresult rv = ParseOptions(aOutputOptions, version, bpp);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(bpp <= 32);
|
|
||||||
|
|
||||||
rv = InitFileHeader(version, bpp, aWidth, aHeight);
|
InitFileHeader(version, bpp, aWidth, aHeight);
|
||||||
if (NS_FAILED(rv)) {
|
InitInfoHeader(version, bpp, aWidth, aHeight);
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
rv = InitInfoHeader(version, bpp, aWidth, aHeight);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
mImageBufferSize = mBMPFileHeader.filesize;
|
mImageBufferSize = mBMPFileHeader.filesize;
|
||||||
mImageBufferStart = static_cast<uint8_t*>(malloc(mImageBufferSize));
|
mImageBufferStart = static_cast<uint8_t*>(malloc(mImageBufferSize));
|
||||||
|
|
@ -200,26 +187,12 @@ nsBMPEncoder::AddImageFrame(const uint8_t* aData,
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBMPInfoHeader.width < 0) {
|
auto row = MakeUniqueFallible<uint8_t[]>(mBMPInfoHeader.width *
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
BytesPerPixel(mBMPInfoHeader.bpp));
|
||||||
}
|
|
||||||
|
|
||||||
CheckedUint32 size =
|
|
||||||
CheckedUint32(mBMPInfoHeader.width) * CheckedUint32(BytesPerPixel(mBMPInfoHeader.bpp));
|
|
||||||
if (MOZ_UNLIKELY(!size.isValid())) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto row = MakeUniqueFallible<uint8_t[]>(size.value());
|
|
||||||
if (!row) {
|
if (!row) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckedUint32 check = CheckedUint32(mBMPInfoHeader.height) * aStride;
|
|
||||||
if (MOZ_UNLIKELY(!check.isValid())) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write each row: if we add more input formats, we may want to
|
// write each row: if we add more input formats, we may want to
|
||||||
// generalize the conversions
|
// generalize the conversions
|
||||||
if (aInputFormat == INPUT_FORMAT_HOSTARGB) {
|
if (aInputFormat == INPUT_FORMAT_HOSTARGB) {
|
||||||
|
|
@ -283,7 +256,7 @@ nsBMPEncoder::EndImageEncode()
|
||||||
// See InitFromData for a description of the parse options
|
// See InitFromData for a description of the parse options
|
||||||
nsresult
|
nsresult
|
||||||
nsBMPEncoder::ParseOptions(const nsAString& aOptions, Version& aVersionOut,
|
nsBMPEncoder::ParseOptions(const nsAString& aOptions, Version& aVersionOut,
|
||||||
uint16_t& aBppOut)
|
uint32_t& aBppOut)
|
||||||
{
|
{
|
||||||
aVersionOut = VERSION_3;
|
aVersionOut = VERSION_3;
|
||||||
aBppOut = 24;
|
aBppOut = 24;
|
||||||
|
|
@ -451,7 +424,7 @@ nsBMPEncoder::ConvertHostARGBRow(const uint8_t* aSrc,
|
||||||
const UniquePtr<uint8_t[]>& aDest,
|
const UniquePtr<uint8_t[]>& aDest,
|
||||||
uint32_t aPixelWidth)
|
uint32_t aPixelWidth)
|
||||||
{
|
{
|
||||||
uint16_t bytes = BytesPerPixel(mBMPInfoHeader.bpp);
|
int bytes = BytesPerPixel(mBMPInfoHeader.bpp);
|
||||||
|
|
||||||
if (mBMPInfoHeader.bpp == 32) {
|
if (mBMPInfoHeader.bpp == 32) {
|
||||||
for (uint32_t x = 0; x < aPixelWidth; x++) {
|
for (uint32_t x = 0; x < aPixelWidth; x++) {
|
||||||
|
|
@ -500,8 +473,8 @@ nsBMPEncoder::NotifyListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the BMP file header mBMPFileHeader to the passed in values
|
// Initializes the BMP file header mBMPFileHeader to the passed in values
|
||||||
nsresult
|
void
|
||||||
nsBMPEncoder::InitFileHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
|
nsBMPEncoder::InitFileHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
|
||||||
uint32_t aHeight)
|
uint32_t aHeight)
|
||||||
{
|
{
|
||||||
memset(&mBMPFileHeader, 0, sizeof(mBMPFileHeader));
|
memset(&mBMPFileHeader, 0, sizeof(mBMPFileHeader));
|
||||||
|
|
@ -518,25 +491,13 @@ nsBMPEncoder::InitFileHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
|
||||||
if (aBPP <= 8) {
|
if (aBPP <= 8) {
|
||||||
uint32_t numColors = 1 << aBPP;
|
uint32_t numColors = 1 << aBPP;
|
||||||
mBMPFileHeader.dataoffset += 4 * numColors;
|
mBMPFileHeader.dataoffset += 4 * numColors;
|
||||||
CheckedUint32 filesize =
|
mBMPFileHeader.filesize = mBMPFileHeader.dataoffset + aWidth * aHeight;
|
||||||
CheckedUint32(mBMPFileHeader.dataoffset) + CheckedUint32(aWidth) * aHeight;
|
|
||||||
if (MOZ_UNLIKELY(!filesize.isValid())) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
mBMPFileHeader.filesize = filesize.value();
|
|
||||||
} else {
|
} else {
|
||||||
CheckedUint32 filesize =
|
mBMPFileHeader.filesize = mBMPFileHeader.dataoffset +
|
||||||
CheckedUint32(mBMPFileHeader.dataoffset) +
|
(aWidth * BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth)) * aHeight;
|
||||||
(CheckedUint32(aWidth) * BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth)) * aHeight;
|
|
||||||
if (MOZ_UNLIKELY(!filesize.isValid())) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
mBMPFileHeader.filesize = filesize.value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mBMPFileHeader.reserved = 0;
|
mBMPFileHeader.reserved = 0;
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENCODE(pImageBufferCurr, value) \
|
#define ENCODE(pImageBufferCurr, value) \
|
||||||
|
|
@ -544,8 +505,8 @@ nsBMPEncoder::InitFileHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
|
||||||
*pImageBufferCurr += sizeof value;
|
*pImageBufferCurr += sizeof value;
|
||||||
|
|
||||||
// Initializes the bitmap info header mBMPInfoHeader to the passed in values
|
// Initializes the bitmap info header mBMPInfoHeader to the passed in values
|
||||||
nsresult
|
void
|
||||||
nsBMPEncoder::InitInfoHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
|
nsBMPEncoder::InitInfoHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
|
||||||
uint32_t aHeight)
|
uint32_t aHeight)
|
||||||
{
|
{
|
||||||
memset(&mBMPInfoHeader, 0, sizeof(mBMPInfoHeader));
|
memset(&mBMPInfoHeader, 0, sizeof(mBMPInfoHeader));
|
||||||
|
|
@ -555,39 +516,18 @@ nsBMPEncoder::InitInfoHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
|
||||||
MOZ_ASSERT(aVersion == VERSION_5);
|
MOZ_ASSERT(aVersion == VERSION_5);
|
||||||
mBMPInfoHeader.bihsize = InfoHeaderLength::WIN_V5;
|
mBMPInfoHeader.bihsize = InfoHeaderLength::WIN_V5;
|
||||||
}
|
}
|
||||||
|
mBMPInfoHeader.width = aWidth;
|
||||||
CheckedInt32 width(aWidth);
|
mBMPInfoHeader.height = aHeight;
|
||||||
CheckedInt32 height(aHeight);
|
|
||||||
if (MOZ_UNLIKELY(!width.isValid() || !height.isValid())) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
mBMPInfoHeader.width = width.value();
|
|
||||||
mBMPInfoHeader.height = height.value();
|
|
||||||
|
|
||||||
mBMPInfoHeader.planes = 1;
|
mBMPInfoHeader.planes = 1;
|
||||||
mBMPInfoHeader.bpp = aBPP;
|
mBMPInfoHeader.bpp = aBPP;
|
||||||
mBMPInfoHeader.compression = 0;
|
mBMPInfoHeader.compression = 0;
|
||||||
mBMPInfoHeader.colors = 0;
|
mBMPInfoHeader.colors = 0;
|
||||||
mBMPInfoHeader.important_colors = 0;
|
mBMPInfoHeader.important_colors = 0;
|
||||||
|
|
||||||
CheckedUint32 check = CheckedUint32(aWidth) * BytesPerPixel(aBPP);
|
|
||||||
if (MOZ_UNLIKELY(check.isValid())) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aBPP <= 8) {
|
if (aBPP <= 8) {
|
||||||
CheckedUint32 imagesize = CheckedUint32(aWidth) * aHeight;
|
mBMPInfoHeader.image_size = aWidth * aHeight;
|
||||||
if (MOZ_UNLIKELY(imagesize.isValid())) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
mBMPInfoHeader.image_size = imagesize.value();
|
|
||||||
} else {
|
} else {
|
||||||
CheckedUint32 imagesize =
|
mBMPInfoHeader.image_size =
|
||||||
CheckedUint32(aWidth) * BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth) * CheckedUint32(aHeight);
|
(aWidth * BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth)) * aHeight;
|
||||||
if (MOZ_UNLIKELY(imagesize.isValid())) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
mBMPInfoHeader.image_size = imagesize.value();
|
|
||||||
}
|
}
|
||||||
mBMPInfoHeader.xppm = 0;
|
mBMPInfoHeader.xppm = 0;
|
||||||
mBMPInfoHeader.yppm = 0;
|
mBMPInfoHeader.yppm = 0;
|
||||||
|
|
@ -614,8 +554,6 @@ nsBMPEncoder::InitInfoHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
|
||||||
mBMPInfoHeader.profile_size = 0;
|
mBMPInfoHeader.profile_size = 0;
|
||||||
mBMPInfoHeader.reserved = 0;
|
mBMPInfoHeader.reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodes the BMP file header mBMPFileHeader
|
// Encodes the BMP file header mBMPFileHeader
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ protected:
|
||||||
|
|
||||||
// See InitData in the cpp for valid parse options
|
// See InitData in the cpp for valid parse options
|
||||||
nsresult ParseOptions(const nsAString& aOptions, Version& aVersionOut,
|
nsresult ParseOptions(const nsAString& aOptions, Version& aVersionOut,
|
||||||
uint16_t& aBppOut);
|
uint32_t& aBppOut);
|
||||||
// Obtains data with no alpha in machine-independent byte order
|
// Obtains data with no alpha in machine-independent byte order
|
||||||
void ConvertHostARGBRow(const uint8_t* aSrc,
|
void ConvertHostARGBRow(const uint8_t* aSrc,
|
||||||
const mozilla::UniquePtr<uint8_t[]>& aDest,
|
const mozilla::UniquePtr<uint8_t[]>& aDest,
|
||||||
|
|
@ -113,10 +113,10 @@ protected:
|
||||||
void NotifyListener();
|
void NotifyListener();
|
||||||
|
|
||||||
// Initializes the bitmap file header member mBMPFileHeader
|
// Initializes the bitmap file header member mBMPFileHeader
|
||||||
nsresult InitFileHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
|
void InitFileHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
|
||||||
uint32_t aHeight);
|
uint32_t aHeight);
|
||||||
// Initializes the bitmap info header member mBMPInfoHeader
|
// Initializes the bitmap info header member mBMPInfoHeader
|
||||||
nsresult InitInfoHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
|
void InitInfoHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
|
||||||
uint32_t aHeight);
|
uint32_t aHeight);
|
||||||
|
|
||||||
// Encodes the bitmap file header member mBMPFileHeader
|
// Encodes the bitmap file header member mBMPFileHeader
|
||||||
|
|
|
||||||
|
|
@ -228,11 +228,10 @@ nsICOEncoder::StartImageEncode(uint32_t aWidth,
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse and check any provided output options
|
// parse and check any provided output options
|
||||||
uint16_t bpp = 24;
|
uint32_t bpp = 24;
|
||||||
bool usePNG = true;
|
bool usePNG = true;
|
||||||
nsresult rv = ParseOptions(aOutputOptions, bpp, usePNG);
|
nsresult rv = ParseOptions(aOutputOptions, bpp, usePNG);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
MOZ_ASSERT(bpp <= 32);
|
|
||||||
|
|
||||||
mUsePNG = usePNG;
|
mUsePNG = usePNG;
|
||||||
|
|
||||||
|
|
@ -266,7 +265,7 @@ nsICOEncoder::EndImageEncode()
|
||||||
// Parses the encoder options and sets the bits per pixel to use and PNG or BMP
|
// Parses the encoder options and sets the bits per pixel to use and PNG or BMP
|
||||||
// See InitFromData for a description of the parse options
|
// See InitFromData for a description of the parse options
|
||||||
nsresult
|
nsresult
|
||||||
nsICOEncoder::ParseOptions(const nsAString& aOptions, uint16_t& aBppOut,
|
nsICOEncoder::ParseOptions(const nsAString& aOptions, uint32_t& aBppOut,
|
||||||
bool& aUsePNGOut)
|
bool& aUsePNGOut)
|
||||||
{
|
{
|
||||||
// If no parsing options just use the default of 24BPP and PNG yes
|
// If no parsing options just use the default of 24BPP and PNG yes
|
||||||
|
|
@ -470,7 +469,7 @@ nsICOEncoder::InitFileHeader()
|
||||||
|
|
||||||
// Initializes the icon directory info header mICODirEntry
|
// Initializes the icon directory info header mICODirEntry
|
||||||
void
|
void
|
||||||
nsICOEncoder::InitInfoHeader(uint16_t aBPP, uint8_t aWidth, uint8_t aHeight)
|
nsICOEncoder::InitInfoHeader(uint32_t aBPP, uint8_t aWidth, uint8_t aHeight)
|
||||||
{
|
{
|
||||||
memset(&mICODirEntry, 0, sizeof(mICODirEntry));
|
memset(&mICODirEntry, 0, sizeof(mICODirEntry));
|
||||||
mICODirEntry.mBitCount = aBPP;
|
mICODirEntry.mBitCount = aBPP;
|
||||||
|
|
|
||||||
|
|
@ -50,14 +50,14 @@ public:
|
||||||
protected:
|
protected:
|
||||||
~nsICOEncoder();
|
~nsICOEncoder();
|
||||||
|
|
||||||
nsresult ParseOptions(const nsAString& aOptions, uint16_t& aBppOut,
|
nsresult ParseOptions(const nsAString& aOptions, uint32_t& aBppOut,
|
||||||
bool& aUsePNGOut);
|
bool& aUsePNGOut);
|
||||||
void NotifyListener();
|
void NotifyListener();
|
||||||
|
|
||||||
// Initializes the icon file header mICOFileHeader
|
// Initializes the icon file header mICOFileHeader
|
||||||
void InitFileHeader();
|
void InitFileHeader();
|
||||||
// Initializes the icon directory info header mICODirEntry
|
// Initializes the icon directory info header mICODirEntry
|
||||||
void InitInfoHeader(uint16_t aBPP, uint8_t aWidth, uint8_t aHeight);
|
void InitInfoHeader(uint32_t aBPP, uint8_t aWidth, uint8_t aHeight);
|
||||||
// Encodes the icon file header mICOFileHeader
|
// Encodes the icon file header mICOFileHeader
|
||||||
void EncodeFileHeader();
|
void EncodeFileHeader();
|
||||||
// Encodes the icon directory info header mICODirEntry
|
// Encodes the icon directory info header mICODirEntry
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue