Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(261)

Side by Side Diff: third_party/WebKit/Source/platform/image-encoders/JPEGImageEncoder.cpp

Issue 2576223002: NEON-ize RGBA to RGB code (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2010, Google Inc. All rights reserved. 2 * Copyright (c) 2010, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 15 matching lines...) Expand all
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "platform/image-encoders/JPEGImageEncoder.h" 31 #include "platform/image-encoders/JPEGImageEncoder.h"
32 32
33 #include "SkColorPriv.h" 33 #include "SkColorPriv.h"
34 #include "platform/geometry/IntSize.h" 34 #include "platform/geometry/IntSize.h"
35 #include "platform/graphics/ImageBuffer.h" 35 #include "platform/graphics/ImageBuffer.h"
36 #include "platform/image-encoders/RGBAtoRGB.h"
36 #include "wtf/CurrentTime.h" 37 #include "wtf/CurrentTime.h"
37 #include "wtf/PtrUtil.h" 38 #include "wtf/PtrUtil.h"
38 #include <memory> 39 #include <memory>
39 40
40 extern "C" { 41 extern "C" {
41 #include <setjmp.h> 42 #include <setjmp.h>
42 #include <stdio.h> // jpeglib.h needs stdio.h FILE 43 #include <stdio.h> // jpeglib.h needs stdio.h FILE
43 #include "jpeglib.h" 44 #include "jpeglib.h"
44 } 45 }
45 46
46 namespace blink { 47 namespace blink {
47 48
49 void PLATFORM_EXPORT RGBAtoRGBScalar(const unsigned char* pixels,
50 unsigned pixelCount,
51 unsigned char* output) {
52 // Per <canvas> spec, composite the input image pixels source-over on black.
53 for (; pixelCount-- > 0; pixels += 4) {
54 unsigned char alpha = pixels[3];
55 if (alpha != 255) {
56 *output++ = SkMulDiv255Round(pixels[0], alpha);
57 *output++ = SkMulDiv255Round(pixels[1], alpha);
58 *output++ = SkMulDiv255Round(pixels[2], alpha);
59 } else {
60 *output++ = pixels[0];
61 *output++ = pixels[1];
62 *output++ = pixels[2];
63 }
64 }
65 }
66
67 #ifdef __ARM_NEON__
68 void PLATFORM_EXPORT RGBAtoRGBNeon(const unsigned char* input,
69 const unsigned pixelCount,
70 unsigned char* output) {
71 const unsigned pixelsPerLoad = 16;
72 const unsigned rgbaStep = pixelsPerLoad * 4, rgbStep = pixelsPerLoad * 3;
73 // Input registers.
74 uint8x16x4_t rgba;
75 // Output registers.
76 uint8x16x3_t rgb;
77 // Intermediate registers.
78 uint16x8_t low, high;
79 uint8x16_t result;
80 unsigned counter;
81
82 for (counter = 0; counter + pixelsPerLoad <= pixelCount;
83 counter += pixelsPerLoad) {
84 // Reads 16 pixels at once, each color channel in a different
85 // 128 bits register.
86 rgba = vld4q_u8(input);
87
88 // Extracts the low/high part of the 128 bits, multiplying by the
89 // respective alpha channel.
90 low = vmull_u8(vget_low_u8(rgba.val[0]), vget_low_u8(rgba.val[3]));
91 high = vmull_u8(vget_high_u8(rgba.val[0]), vget_high_u8(rgba.val[3]));
92
93 // Original Skia formula is: (x + (x >> 8)) >> 8, where x = a*b + 128.
94 // This shifts and accumulates following by rounding in a single
95 // instruction.
96 low = vrsraq_n_u16(low, low, 8);
97 high = vrsraq_n_u16(high, high, 8);
98
99 // And now to the last shift and combining the vector.
100 result = vcombine_u8(vqrshrn_n_u16(low, 8), vqrshrn_n_u16(high, 8));
101
102 // Write back the Red channel to the first 128 bits register.
103 rgb.val[0] = result;
104
105 // Now the Green channel (don't trust the compiler to unroll the loop).
106 low = vmull_u8(vget_low_u8(rgba.val[1]), vget_low_u8(rgba.val[3]));
107 high = vmull_u8(vget_high_u8(rgba.val[1]), vget_high_u8(rgba.val[3]));
108 low = vrsraq_n_u16(low, low, 8);
109 high = vrsraq_n_u16(high, high, 8);
110 result = vcombine_u8(vqrshrn_n_u16(low, 8), vqrshrn_n_u16(high, 8));
111 rgb.val[1] = result;
112
113 // Finally the Blue channel.
114 low = vmull_u8(vget_low_u8(rgba.val[2]), vget_low_u8(rgba.val[3]));
115 high = vmull_u8(vget_high_u8(rgba.val[2]), vget_high_u8(rgba.val[3]));
116 low = vrsraq_n_u16(low, low, 8);
117 high = vrsraq_n_u16(high, high, 8);
118 result = vcombine_u8(vqrshrn_n_u16(low, 8), vqrshrn_n_u16(high, 8));
119 rgb.val[2] = result;
120
121 // Write back (interleaved) results to output.
122 vst3q_u8(output, rgb);
123
124 // Advance to next elements (could be avoided loading register with
125 // increment after i.e. "vld4 {vector}, [r1]!").
126 input += rgbaStep;
127 output += rgbStep;
128 }
129
130 // Handle the tail elements.
131 unsigned remaining = pixelCount;
132 remaining -= counter;
133 if (remaining != 0) {
134 RGBAtoRGBScalar(input, remaining, output);
135 }
136 }
137 #endif
138
48 struct JPEGOutputBuffer : public jpeg_destination_mgr { 139 struct JPEGOutputBuffer : public jpeg_destination_mgr {
49 DISALLOW_NEW(); 140 DISALLOW_NEW();
50 Vector<unsigned char>* output; 141 Vector<unsigned char>* output;
51 Vector<unsigned char> buffer; 142 Vector<unsigned char> buffer;
52 }; 143 };
53 144
54 class JPEGImageEncoderStateImpl final : public JPEGImageEncoderState { 145 class JPEGImageEncoderStateImpl final : public JPEGImageEncoderState {
55 public: 146 public:
56 JPEGImageEncoderStateImpl() {} 147 JPEGImageEncoderStateImpl() {}
57 ~JPEGImageEncoderStateImpl() override { 148 ~JPEGImageEncoderStateImpl() override {
(...skipping 30 matching lines...) Expand all
88 JPEGOutputBuffer* out = static_cast<JPEGOutputBuffer*>(cinfo->dest); 179 JPEGOutputBuffer* out = static_cast<JPEGOutputBuffer*>(cinfo->dest);
89 const size_t size = out->buffer.size() - out->free_in_buffer; 180 const size_t size = out->buffer.size() - out->free_in_buffer;
90 out->output->append(out->buffer.data(), size); 181 out->output->append(out->buffer.data(), size);
91 } 182 }
92 183
93 static void handleError(j_common_ptr common) { 184 static void handleError(j_common_ptr common) {
94 jmp_buf* jumpBufferPtr = static_cast<jmp_buf*>(common->client_data); 185 jmp_buf* jumpBufferPtr = static_cast<jmp_buf*>(common->client_data);
95 longjmp(*jumpBufferPtr, -1); 186 longjmp(*jumpBufferPtr, -1);
96 } 187 }
97 188
98 static void RGBAtoRGB(const unsigned char* pixels,
99 unsigned pixelCount,
100 unsigned char* output) {
101 // Per <canvas> spec, composite the input image pixels source-over on black.
102
103 for (; pixelCount-- > 0; pixels += 4) {
104 unsigned char alpha = pixels[3];
105 if (alpha != 255) {
106 *output++ = SkMulDiv255Round(pixels[0], alpha);
107 *output++ = SkMulDiv255Round(pixels[1], alpha);
108 *output++ = SkMulDiv255Round(pixels[2], alpha);
109 } else {
110 *output++ = pixels[0];
111 *output++ = pixels[1];
112 *output++ = pixels[2];
113 }
114 }
115 }
116
117 static void disableSubsamplingForHighQuality(jpeg_compress_struct* cinfo, 189 static void disableSubsamplingForHighQuality(jpeg_compress_struct* cinfo,
118 int quality) { 190 int quality) {
119 if (quality < 100) 191 if (quality < 100)
120 return; 192 return;
121 193
122 for (int i = 0; i < MAX_COMPONENTS; ++i) { 194 for (int i = 0; i < MAX_COMPONENTS; ++i) {
123 cinfo->comp_info[i].h_samp_factor = 1; 195 cinfo->comp_info[i].h_samp_factor = 1;
124 cinfo->comp_info[i].v_samp_factor = 1; 196 cinfo->comp_info[i].v_samp_factor = 1;
125 } 197 }
126 } 198 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 std::unique_ptr<JPEGImageEncoderState> encoderState = 322 std::unique_ptr<JPEGImageEncoderState> encoderState =
251 JPEGImageEncoderState::create(imageData.size(), quality, output); 323 JPEGImageEncoderState::create(imageData.size(), quality, output);
252 if (!encoderState) 324 if (!encoderState)
253 return false; 325 return false;
254 326
255 return JPEGImageEncoder::encodeWithPreInitializedState( 327 return JPEGImageEncoder::encodeWithPreInitializedState(
256 std::move(encoderState), imageData.pixels()); 328 std::move(encoderState), imageData.pixels());
257 } 329 }
258 330
259 } // namespace blink 331 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698