Use libjpeg-turbo for YUV->RGB conversion in jpeg encoder

This remove the previous codepath, which performed a less
accurate conversion to YUV.

It actually faster to use the more accurate conversion, now
that we have updated to libjpeg-turbo.

z620 Performance Speed-Up:
mandrill.jpg (512x512): 1.13x
color_wheel.jpg (128x128): 1.12x

This should fix:
https://buganizer.corp.google.com/u/0/issues/28161384
https://buganizer.corp.google.com/u/0/issues/21891795

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1886183002

Review URL: https://codereview.chromium.org/1886183002
This commit is contained in:
msarett 2016-04-18 14:21:55 -07:00 committed by Commit bot
parent b4b83dc4df
commit c7d01d3e1d

View File

@ -28,156 +28,58 @@ extern "C" {
// These enable timing code that report milliseconds for an encoding
//#define TIME_ENCODE
// this enables our rgb->yuv code, which is faster than libjpeg on ARM
#define WE_CONVERT_TO_YUV
///////////////////////////////////////////////////////////////////////////////
#include "SkColorPriv.h"
// taken from jcolor.c in libjpeg
#if 0 // 16bit - precise but slow
#define CYR 19595 // 0.299
#define CYG 38470 // 0.587
#define CYB 7471 // 0.114
#define CUR -11059 // -0.16874
#define CUG -21709 // -0.33126
#define CUB 32768 // 0.5
#define CVR 32768 // 0.5
#define CVG -27439 // -0.41869
#define CVB -5329 // -0.08131
#define CSHIFT 16
#else // 8bit - fast, slightly less precise
#define CYR 77 // 0.299
#define CYG 150 // 0.587
#define CYB 29 // 0.114
#define CUR -43 // -0.16874
#define CUG -85 // -0.33126
#define CUB 128 // 0.5
#define CVR 128 // 0.5
#define CVG -107 // -0.41869
#define CVB -21 // -0.08131
#define CSHIFT 8
#endif
static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
int r = SkGetPackedR32(c);
int g = SkGetPackedG32(c);
int b = SkGetPackedB32(c);
int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
dst[0] = SkToU8(y);
dst[1] = SkToU8(u + 128);
dst[2] = SkToU8(v + 128);
}
static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
int r = SkGetPackedR4444(c);
int g = SkGetPackedG4444(c);
int b = SkGetPackedB4444(c);
int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
dst[0] = SkToU8(y);
dst[1] = SkToU8(u + 128);
dst[2] = SkToU8(v + 128);
}
static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
int r = SkGetPackedR16(c);
int g = SkGetPackedG16(c);
int b = SkGetPackedB16(c);
int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
dst[0] = SkToU8(y);
dst[1] = SkToU8(u + 128);
dst[2] = SkToU8(v + 128);
}
///////////////////////////////////////////////////////////////////////////////
typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
const void* SK_RESTRICT src, int width,
const SkPMColor* SK_RESTRICT ctable);
static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
static void Write_32_RGB(uint8_t* SK_RESTRICT dst,
const void* SK_RESTRICT srcRow, int width,
const SkPMColor*) {
const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
while (--width >= 0) {
#ifdef WE_CONVERT_TO_YUV
rgb2yuv_32(dst, *src++);
#else
uint32_t c = *src++;
dst[0] = SkGetPackedR32(c);
dst[1] = SkGetPackedG32(c);
dst[2] = SkGetPackedB32(c);
#endif
dst += 3;
}
}
static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
static void Write_4444_RGB(uint8_t* SK_RESTRICT dst,
const void* SK_RESTRICT srcRow, int width,
const SkPMColor*) {
const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
while (--width >= 0) {
#ifdef WE_CONVERT_TO_YUV
rgb2yuv_4444(dst, *src++);
#else
SkPMColor16 c = *src++;
dst[0] = SkPacked4444ToR32(c);
dst[1] = SkPacked4444ToG32(c);
dst[2] = SkPacked4444ToB32(c);
#endif
dst += 3;
}
}
static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
static void Write_16_RGB(uint8_t* SK_RESTRICT dst,
const void* SK_RESTRICT srcRow, int width,
const SkPMColor*) {
const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
while (--width >= 0) {
#ifdef WE_CONVERT_TO_YUV
rgb2yuv_16(dst, *src++);
#else
uint16_t c = *src++;
dst[0] = SkPacked16ToR32(c);
dst[1] = SkPacked16ToG32(c);
dst[2] = SkPacked16ToB32(c);
#endif
dst += 3;
}
}
static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
static void Write_Index_RGB(uint8_t* SK_RESTRICT dst,
const void* SK_RESTRICT srcRow, int width,
const SkPMColor* SK_RESTRICT ctable) {
const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
while (--width >= 0) {
#ifdef WE_CONVERT_TO_YUV
rgb2yuv_32(dst, ctable[*src++]);
#else
uint32_t c = ctable[*src++];
dst[0] = SkGetPackedR32(c);
dst[1] = SkGetPackedG32(c);
dst[2] = SkGetPackedB32(c);
#endif
dst += 3;
}
}
@ -185,13 +87,13 @@ static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
static WriteScanline ChooseWriter(const SkBitmap& bm) {
switch (bm.colorType()) {
case kN32_SkColorType:
return Write_32_YUV;
return Write_32_RGB;
case kRGB_565_SkColorType:
return Write_16_YUV;
return Write_16_RGB;
case kARGB_4444_SkColorType:
return Write_4444_YUV;
return Write_4444_RGB;
case kIndex_8_SkColorType:
return Write_Index_YUV;
return Write_Index_RGB;
default:
return nullptr;
}
@ -233,19 +135,20 @@ protected:
cinfo.image_width = bm.width();
cinfo.image_height = bm.height();
cinfo.input_components = 3;
#ifdef WE_CONVERT_TO_YUV
cinfo.in_color_space = JCS_YCbCr;
#else
// FIXME: Can we take advantage of other in_color_spaces in libjpeg-turbo?
cinfo.in_color_space = JCS_RGB;
#endif
// The gamma value is ignored by libjpeg-turbo.
cinfo.input_gamma = 1;
jpeg_set_defaults(&cinfo);
// Tells libjpeg-turbo to compute optimal Huffman coding tables
// for the image. This improves compression at the cost of
// slower encode performance.
cinfo.optimize_coding = TRUE;
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
#ifdef DCT_IFAST_SUPPORTED
cinfo.dct_method = JDCT_IFAST;
#endif
jpeg_start_compress(&cinfo, TRUE);