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

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

@ -78,7 +78,7 @@ protected:
void ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest, void ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth); 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 void initDestination(jpeg_compress_struct* cinfo);
static boolean emptyOutputBuffer(jpeg_compress_struct* cinfo); static boolean emptyOutputBuffer(jpeg_compress_struct* cinfo);