Bug 723221 - Premultiply JPG data correctly - r=joe

This commit is contained in:
Jeff Gilbert 2012-02-10 15:37:16 -08:00
Родитель 0cba88efa3
Коммит 111d23ae54
2 изменённых файлов: 23 добавлений и 20 удалений

Просмотреть файл

@ -41,6 +41,7 @@
#include "prprf.h"
#include "nsString.h"
#include "nsStreamUtils.h"
#include "gfxColor.h"
#include <setjmp.h>
#include "jerror.h"
@ -186,7 +187,7 @@ NS_IMETHODIMP nsJPEGEncoder::InitFromData(const PRUint8* aData,
} else if (aInputFormat == INPUT_FORMAT_RGBA) {
PRUint8* row = new PRUint8[aWidth * 3];
while (cinfo.next_scanline < cinfo.image_height) {
StripAlpha(&aData[cinfo.next_scanline * aStride], row, aWidth);
ConvertRGBARow(&aData[cinfo.next_scanline * aStride], row, aWidth);
jpeg_write_scanlines(&cinfo, &row, 1);
}
delete[] row;
@ -350,46 +351,48 @@ NS_IMETHODIMP nsJPEGEncoder::CloseWithStatus(nsresult aStatus)
return Close();
}
// nsJPEGEncoder::ConvertHostARGBRow
//
// Our colors are stored with premultiplied alphas, but we need
// an output with no alpha in machine-independent byte order.
//
// See gfx/cairo/cairo/src/cairo-png.c
void
nsJPEGEncoder::ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth)
PRUint32 aPixelWidth)
{
for (PRUint32 x = 0; x < aPixelWidth; x ++) {
for (PRUint32 x = 0; x < aPixelWidth; x++) {
const PRUint32& pixelIn = ((const PRUint32*)(aSrc))[x];
PRUint8 *pixelOut = &aDest[x * 3];
pixelOut[0] = (((pixelIn & 0xff0000) >> 16));
pixelOut[1] = (((pixelIn & 0x00ff00) >> 8));
pixelOut[2] = (((pixelIn & 0x0000ff) >> 0));
pixelOut[0] = (pixelIn & 0xff0000) >> 16;
pixelOut[1] = (pixelIn & 0x00ff00) >> 8;
pixelOut[2] = (pixelIn & 0x0000ff) >> 0;
}
}
// nsJPEGEncoder::StripAlpha
//
// Input is RGBA, output is RGB
/**
* nsJPEGEncoder::ConvertRGBARow
*
* Input is RGBA, output is RGB, so we should alpha-premultiply.
*/
void
nsJPEGEncoder::StripAlpha(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth)
nsJPEGEncoder::ConvertRGBARow(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth)
{
for (PRUint32 x = 0; x < aPixelWidth; x ++) {
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];
PRUint8 alpha = pixelIn[3];
pixelOut[0] = GFX_PREMULTIPLY(pixelIn[0], alpha);
pixelOut[1] = GFX_PREMULTIPLY(pixelIn[1], alpha);
pixelOut[2] = GFX_PREMULTIPLY(pixelIn[2], alpha);
}
}
// nsJPEGEncoder::initDestination
//
// Initialize destination. This is called by jpeg_start_compress() before

Просмотреть файл

@ -78,7 +78,7 @@ protected:
void ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth);
void StripAlpha(const PRUint8* aSrc, PRUint8* aDest, PRUint32 aPixelWidth);
void ConvertRGBARow(const PRUint8* aSrc, PRUint8* aDest, PRUint32 aPixelWidth);
static void initDestination(jpeg_compress_struct* cinfo);
static boolean emptyOutputBuffer(jpeg_compress_struct* cinfo);