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

Side by Side Diff: skia/ext/convolver_unittest.cc

Issue 5575010: Integration of most changes from the GoogleTV project around the convolver/sc... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Latest rounds of changes to address Brett's comments Created 9 years, 11 months 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 | Annotate | Revision Log
« no previous file with comments | « skia/ext/convolver.cc ('k') | skia/ext/image_operations.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <string.h> 5 #include <string.h>
6 #include <time.h> 6 #include <time.h>
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/basictypes.h"
9 #include "skia/ext/convolver.h" 10 #include "skia/ext/convolver.h"
10 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
11 12
12 namespace skia { 13 namespace skia {
13 14
14 namespace { 15 namespace {
15 16
16 // Fills the given filter with impulse functions for the range 0->num_entries. 17 // Fills the given filter with impulse functions for the range 0->num_entries.
17 void FillImpulseFilter(int num_entries, ConvolutionFilter1D* filter) { 18 void FillImpulseFilter(int num_entries, ConvolutionFilter1D* filter) {
18 float one = 1.0f; 19 float one = 1.0f;
19 for (int i = 0; i < num_entries; i++) 20 for (int i = 0; i < num_entries; i++)
20 filter->AddFilter(i, &one, 1); 21 filter->AddFilter(i, &one, 1);
21 } 22 }
22 23
23 // Filters the given input with the impulse function, and verifies that it 24 // Filters the given input with the impulse function, and verifies that it
24 // does not change. 25 // does not change.
25 void TestImpulseConvolution(const unsigned char* data, int width, int height) { 26 void TestImpulseConvolution(const unsigned char* data, int width, int height) {
26 int byte_count = width * height * 4; 27 int byte_count = width * height * 4;
27 28
28 ConvolutionFilter1D filter_x; 29 ConvolutionFilter1D filter_x;
29 FillImpulseFilter(width, &filter_x); 30 FillImpulseFilter(width, &filter_x);
30 31
31 ConvolutionFilter1D filter_y; 32 ConvolutionFilter1D filter_y;
32 FillImpulseFilter(height, &filter_y); 33 FillImpulseFilter(height, &filter_y);
33 34
34 std::vector<unsigned char> output; 35 std::vector<unsigned char> output;
35 output.resize(byte_count); 36 output.resize(byte_count);
36 BGRAConvolve2D(data, width * 4, true, filter_x, filter_y, &output[0]); 37 BGRAConvolve2D(data, width * 4, true, filter_x, filter_y,
38 filter_x.num_values() * 4, &output[0]);
37 39
38 // Output should exactly match input. 40 // Output should exactly match input.
39 EXPECT_EQ(0, memcmp(data, &output[0], byte_count)); 41 EXPECT_EQ(0, memcmp(data, &output[0], byte_count));
40 } 42 }
41 43
42 // Fills the destination filter with a box filter averaging every two pixels 44 // Fills the destination filter with a box filter averaging every two pixels
43 // to produce the output. 45 // to produce the output.
44 void FillBoxFilter(int size, ConvolutionFilter1D* filter) { 46 void FillBoxFilter(int size, ConvolutionFilter1D* filter) {
45 const float box[2] = { 0.5, 0.5 }; 47 const float box[2] = { 0.5, 0.5 };
46 for (int i = 0; i < size; i++) 48 for (int i = 0; i < size; i++)
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 srand(static_cast<unsigned>(time(NULL))); 98 srand(static_cast<unsigned>(time(NULL)));
97 for (int i = 0; i < src_byte_count; i++) 99 for (int i = 0; i < src_byte_count; i++)
98 input[i] = rand() * 255 / RAND_MAX; 100 input[i] = rand() * 255 / RAND_MAX;
99 101
100 // Compute the filters. 102 // Compute the filters.
101 ConvolutionFilter1D filter_x, filter_y; 103 ConvolutionFilter1D filter_x, filter_y;
102 FillBoxFilter(dest_width, &filter_x); 104 FillBoxFilter(dest_width, &filter_x);
103 FillBoxFilter(dest_height, &filter_y); 105 FillBoxFilter(dest_height, &filter_y);
104 106
105 // Do the convolution. 107 // Do the convolution.
106 BGRAConvolve2D(&input[0], src_width, true, filter_x, filter_y, &output[0]); 108 BGRAConvolve2D(&input[0], src_width, true, filter_x, filter_y,
109 filter_x.num_values() * 4, &output[0]);
107 110
108 // Compute the expected results and check, allowing for a small difference 111 // Compute the expected results and check, allowing for a small difference
109 // to account for rounding errors. 112 // to account for rounding errors.
110 for (int y = 0; y < dest_height; y++) { 113 for (int y = 0; y < dest_height; y++) {
111 for (int x = 0; x < dest_width; x++) { 114 for (int x = 0; x < dest_width; x++) {
112 for (int channel = 0; channel < 4; channel++) { 115 for (int channel = 0; channel < 4; channel++) {
113 int src_offset = (y * 2 * src_row_stride + x * 2 * 4) + channel; 116 int src_offset = (y * 2 * src_row_stride + x * 2 * 4) + channel;
114 int value = input[src_offset] + // Top left source pixel. 117 int value = input[src_offset] + // Top left source pixel.
115 input[src_offset + 4] + // Top right source pixel. 118 input[src_offset + 4] + // Top right source pixel.
116 input[src_offset + src_row_stride] + // Lower left. 119 input[src_offset + src_row_stride] + // Lower left.
117 input[src_offset + src_row_stride + 4]; // Lower right. 120 input[src_offset + src_row_stride + 4]; // Lower right.
118 value /= 4; // Average. 121 value /= 4; // Average.
119 int difference = value - output[(y * dest_width + x) * 4 + channel]; 122 int difference = value - output[(y * dest_width + x) * 4 + channel];
120 EXPECT_TRUE(difference >= -1 || difference <= 1); 123 EXPECT_TRUE(difference >= -1 || difference <= 1);
121 } 124 }
122 } 125 }
123 } 126 }
124 } 127 }
125 128
129 // Tests the optimization in Convolver1D::AddFilter that avoids storing
130 // leading/trailing zeroes.
131 TEST(Convolver, AddFilter) {
132 skia::ConvolutionFilter1D filter;
133
134 const skia::ConvolutionFilter1D::Fixed* values = NULL;
135 int filter_offset = 0;
136 int filter_length = 0;
137
138 // An all-zero filter is handled correctly, all factors ignored
139 static const float factors1[] = { 0.0f, 0.0f, 0.0f };
140 filter.AddFilter(11, factors1, arraysize(factors1));
141 ASSERT_EQ(0, filter.max_filter());
142 ASSERT_EQ(1, filter.num_values());
143
144 values = filter.FilterForValue(0, &filter_offset, &filter_length);
145 ASSERT_TRUE(values == NULL); // No values => NULL.
146 ASSERT_EQ(11, filter_offset); // Same as input offset.
147 ASSERT_EQ(0, filter_length); // But no factors since all are zeroes.
148
149 // Zeroes on the left are ignored
150 static const float factors2[] = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f };
151 filter.AddFilter(22, factors2, arraysize(factors2));
152 ASSERT_EQ(4, filter.max_filter());
153 ASSERT_EQ(2, filter.num_values());
154
155 values = filter.FilterForValue(1, &filter_offset, &filter_length);
156 ASSERT_TRUE(values != NULL);
157 ASSERT_EQ(23, filter_offset); // 22 plus 1 leading zero
158 ASSERT_EQ(4, filter_length); // 5 - 1 leading zero
159
160 // Zeroes on the right are ignored
161 static const float factors3[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f };
162 filter.AddFilter(33, factors3, arraysize(factors3));
163 ASSERT_EQ(5, filter.max_filter());
164 ASSERT_EQ(3, filter.num_values());
165
166 values = filter.FilterForValue(2, &filter_offset, &filter_length);
167 ASSERT_TRUE(values != NULL);
168 ASSERT_EQ(33, filter_offset); // 33, same as input due to no leading zero
169 ASSERT_EQ(5, filter_length); // 7 - 2 trailing zeroes
170
171 // Zeroes in leading & trailing positions
172 static const float factors4[] = { 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f };
173 filter.AddFilter(44, factors4, arraysize(factors4));
174 ASSERT_EQ(5, filter.max_filter()); // No change from existing value.
175 ASSERT_EQ(4, filter.num_values());
176
177 values = filter.FilterForValue(3, &filter_offset, &filter_length);
178 ASSERT_TRUE(values != NULL);
179 ASSERT_EQ(46, filter_offset); // 44 plus 2 leading zeroes
180 ASSERT_EQ(3, filter_length); // 7 - (2 leading + 2 trailing) zeroes
181
182 // Zeroes surrounded by non-zero values are ignored
183 static const float factors5[] = { 0.0f, 0.0f,
184 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
185 0.0f };
186 filter.AddFilter(55, factors5, arraysize(factors5));
187 ASSERT_EQ(6, filter.max_filter());
188 ASSERT_EQ(5, filter.num_values());
189
190 values = filter.FilterForValue(4, &filter_offset, &filter_length);
191 ASSERT_TRUE(values != NULL);
192 ASSERT_EQ(57, filter_offset); // 55 plus 2 leading zeroes
193 ASSERT_EQ(6, filter_length); // 9 - (2 leading + 1 trailing) zeroes
194
195 // All-zero filters after the first one also work
196 static const float factors6[] = { 0.0f };
197 filter.AddFilter(66, factors6, arraysize(factors6));
198 ASSERT_EQ(6, filter.max_filter());
199 ASSERT_EQ(6, filter.num_values());
200
201 values = filter.FilterForValue(5, &filter_offset, &filter_length);
202 ASSERT_TRUE(values == NULL); // filter_length == 0 => values is NULL
203 ASSERT_EQ(66, filter_offset); // value passed in
204 ASSERT_EQ(0, filter_length);
205 }
206
126 } // namespace skia 207 } // namespace skia
127
OLDNEW
« no previous file with comments | « skia/ext/convolver.cc ('k') | skia/ext/image_operations.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698