Skip to content

Commit c7d01d3

Browse files
mattsarettCommit bot
authored andcommitted
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
1 parent b4b83dc commit c7d01d3

1 file changed

Lines changed: 16 additions & 113 deletions

File tree

src/images/SkJPEGImageEncoder.cpp

Lines changed: 16 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -28,170 +28,72 @@ extern "C" {
2828
// These enable timing code that report milliseconds for an encoding
2929
//#define TIME_ENCODE
3030

31-
// this enables our rgb->yuv code, which is faster than libjpeg on ARM
32-
#define WE_CONVERT_TO_YUV
33-
34-
///////////////////////////////////////////////////////////////////////////////
35-
36-
#include "SkColorPriv.h"
37-
38-
// taken from jcolor.c in libjpeg
39-
#if 0 // 16bit - precise but slow
40-
#define CYR 19595 // 0.299
41-
#define CYG 38470 // 0.587
42-
#define CYB 7471 // 0.114
43-
44-
#define CUR -11059 // -0.16874
45-
#define CUG -21709 // -0.33126
46-
#define CUB 32768 // 0.5
47-
48-
#define CVR 32768 // 0.5
49-
#define CVG -27439 // -0.41869
50-
#define CVB -5329 // -0.08131
51-
52-
#define CSHIFT 16
53-
#else // 8bit - fast, slightly less precise
54-
#define CYR 77 // 0.299
55-
#define CYG 150 // 0.587
56-
#define CYB 29 // 0.114
57-
58-
#define CUR -43 // -0.16874
59-
#define CUG -85 // -0.33126
60-
#define CUB 128 // 0.5
61-
62-
#define CVR 128 // 0.5
63-
#define CVG -107 // -0.41869
64-
#define CVB -21 // -0.08131
65-
66-
#define CSHIFT 8
67-
#endif
68-
69-
static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
70-
int r = SkGetPackedR32(c);
71-
int g = SkGetPackedG32(c);
72-
int b = SkGetPackedB32(c);
73-
74-
int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
75-
int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
76-
int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
77-
78-
dst[0] = SkToU8(y);
79-
dst[1] = SkToU8(u + 128);
80-
dst[2] = SkToU8(v + 128);
81-
}
82-
83-
static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
84-
int r = SkGetPackedR4444(c);
85-
int g = SkGetPackedG4444(c);
86-
int b = SkGetPackedB4444(c);
87-
88-
int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
89-
int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
90-
int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
91-
92-
dst[0] = SkToU8(y);
93-
dst[1] = SkToU8(u + 128);
94-
dst[2] = SkToU8(v + 128);
95-
}
96-
97-
static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
98-
int r = SkGetPackedR16(c);
99-
int g = SkGetPackedG16(c);
100-
int b = SkGetPackedB16(c);
101-
102-
int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
103-
int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
104-
int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
105-
106-
dst[0] = SkToU8(y);
107-
dst[1] = SkToU8(u + 128);
108-
dst[2] = SkToU8(v + 128);
109-
}
110-
111-
///////////////////////////////////////////////////////////////////////////////
112-
11331
typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
11432
const void* SK_RESTRICT src, int width,
11533
const SkPMColor* SK_RESTRICT ctable);
11634

117-
static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
35+
static void Write_32_RGB(uint8_t* SK_RESTRICT dst,
11836
const void* SK_RESTRICT srcRow, int width,
11937
const SkPMColor*) {
12038
const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
12139
while (--width >= 0) {
122-
#ifdef WE_CONVERT_TO_YUV
123-
rgb2yuv_32(dst, *src++);
124-
#else
12540
uint32_t c = *src++;
12641
dst[0] = SkGetPackedR32(c);
12742
dst[1] = SkGetPackedG32(c);
12843
dst[2] = SkGetPackedB32(c);
129-
#endif
13044
dst += 3;
13145
}
13246
}
13347

134-
static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
48+
static void Write_4444_RGB(uint8_t* SK_RESTRICT dst,
13549
const void* SK_RESTRICT srcRow, int width,
13650
const SkPMColor*) {
13751
const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
13852
while (--width >= 0) {
139-
#ifdef WE_CONVERT_TO_YUV
140-
rgb2yuv_4444(dst, *src++);
141-
#else
14253
SkPMColor16 c = *src++;
14354
dst[0] = SkPacked4444ToR32(c);
14455
dst[1] = SkPacked4444ToG32(c);
14556
dst[2] = SkPacked4444ToB32(c);
146-
#endif
14757
dst += 3;
14858
}
14959
}
15060

151-
static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
61+
static void Write_16_RGB(uint8_t* SK_RESTRICT dst,
15262
const void* SK_RESTRICT srcRow, int width,
15363
const SkPMColor*) {
15464
const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
15565
while (--width >= 0) {
156-
#ifdef WE_CONVERT_TO_YUV
157-
rgb2yuv_16(dst, *src++);
158-
#else
15966
uint16_t c = *src++;
16067
dst[0] = SkPacked16ToR32(c);
16168
dst[1] = SkPacked16ToG32(c);
16269
dst[2] = SkPacked16ToB32(c);
163-
#endif
16470
dst += 3;
16571
}
16672
}
16773

168-
static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
74+
static void Write_Index_RGB(uint8_t* SK_RESTRICT dst,
16975
const void* SK_RESTRICT srcRow, int width,
17076
const SkPMColor* SK_RESTRICT ctable) {
17177
const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
17278
while (--width >= 0) {
173-
#ifdef WE_CONVERT_TO_YUV
174-
rgb2yuv_32(dst, ctable[*src++]);
175-
#else
17679
uint32_t c = ctable[*src++];
17780
dst[0] = SkGetPackedR32(c);
17881
dst[1] = SkGetPackedG32(c);
17982
dst[2] = SkGetPackedB32(c);
180-
#endif
18183
dst += 3;
18284
}
18385
}
18486

18587
static WriteScanline ChooseWriter(const SkBitmap& bm) {
18688
switch (bm.colorType()) {
18789
case kN32_SkColorType:
188-
return Write_32_YUV;
90+
return Write_32_RGB;
18991
case kRGB_565_SkColorType:
190-
return Write_16_YUV;
92+
return Write_16_RGB;
19193
case kARGB_4444_SkColorType:
192-
return Write_4444_YUV;
94+
return Write_4444_RGB;
19395
case kIndex_8_SkColorType:
194-
return Write_Index_YUV;
96+
return Write_Index_RGB;
19597
default:
19698
return nullptr;
19799
}
@@ -233,19 +135,20 @@ class SkJPEGImageEncoder : public SkImageEncoder {
233135
cinfo.image_width = bm.width();
234136
cinfo.image_height = bm.height();
235137
cinfo.input_components = 3;
236-
#ifdef WE_CONVERT_TO_YUV
237-
cinfo.in_color_space = JCS_YCbCr;
238-
#else
138+
139+
// FIXME: Can we take advantage of other in_color_spaces in libjpeg-turbo?
239140
cinfo.in_color_space = JCS_RGB;
240-
#endif
141+
142+
// The gamma value is ignored by libjpeg-turbo.
241143
cinfo.input_gamma = 1;
242144

243145
jpeg_set_defaults(&cinfo);
146+
147+
// Tells libjpeg-turbo to compute optimal Huffman coding tables
148+
// for the image. This improves compression at the cost of
149+
// slower encode performance.
244150
cinfo.optimize_coding = TRUE;
245151
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
246-
#ifdef DCT_IFAST_SUPPORTED
247-
cinfo.dct_method = JDCT_IFAST;
248-
#endif
249152

250153
jpeg_start_compress(&cinfo, TRUE);
251154

0 commit comments

Comments
 (0)