OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef BASE_GFX_CONVOLVER_H__ | |
6 #define BASE_GFX_CONVOLVER_H__ | |
7 | |
8 #include <vector> | |
9 | |
10 #include "base/basictypes.h" | |
11 | |
12 // avoid confusion with Mac OS X's math library (Carbon) | |
13 #if defined(OS_MACOSX) | |
14 #undef FloatToFixed | |
15 #endif | |
16 | |
17 namespace gfx { | |
18 | |
19 // Represents a filter in one dimension. Each output pixel has one entry in this | |
20 // object for the filter values contributing to it. You build up the filter | |
21 // list by calling AddFilter for each output pixel (in order). | |
22 // | |
23 // We do 2-dimensional convolusion by first convolving each row by one | |
24 // ConvolusionFilter1D, then convolving each column by another one. | |
25 // | |
26 // Entries are stored in fixed point, shifted left by kShiftBits. | |
27 class ConvolusionFilter1D { | |
28 public: | |
29 // The number of bits that fixed point values are shifted by. | |
30 enum { kShiftBits = 14 }; | |
31 | |
32 ConvolusionFilter1D() : max_filter_(0) { | |
33 } | |
34 | |
35 // Convert between floating point and our fixed point representation. | |
36 static inline int16 FloatToFixed(float f) { | |
37 return static_cast<int16>(f * (1 << kShiftBits)); | |
38 } | |
39 static inline unsigned char FixedToChar(int16 x) { | |
40 return static_cast<unsigned char>(x >> kShiftBits); | |
41 } | |
42 | |
43 // Returns the maximum pixel span of a filter. | |
44 int max_filter() const { return max_filter_; } | |
45 | |
46 // Returns the number of filters in this filter. This is the dimension of the | |
47 // output image. | |
48 int num_values() const { return static_cast<int>(filters_.size()); } | |
49 | |
50 // Appends the given list of scaling values for generating a given output | |
51 // pixel. |filter_offset| is the distance from the edge of the image to where | |
52 // the scaling factors start. The scaling factors apply to the source pixels | |
53 // starting from this position, and going for the next |filter_length| pixels. | |
54 // | |
55 // You will probably want to make sure your input is normalized (that is, | |
56 // all entries in |filter_values| sub to one) to prevent affecting the overall | |
57 // brighness of the image. | |
58 // | |
59 // The filter_length must be > 0. | |
60 // | |
61 // This version will automatically convert your input to fixed point. | |
62 void AddFilter(int filter_offset, | |
63 const float* filter_values, | |
64 int filter_length); | |
65 | |
66 // Same as the above version, but the input is already fixed point. | |
67 void AddFilter(int filter_offset, | |
68 const int16* filter_values, | |
69 int filter_length); | |
70 | |
71 // Retrieves a filter for the given |value_offset|, a position in the output | |
72 // image in the direction we're convolving. The offset and length of the | |
73 // filter values are put into the corresponding out arguments (see AddFilter | |
74 // above for what these mean), and a pointer to the first scaling factor is | |
75 // returned. There will be |filter_length| values in this array. | |
76 inline const int16* FilterForValue(int value_offset, | |
77 int* filter_offset, | |
78 int* filter_length) const { | |
79 const FilterInstance& filter = filters_[value_offset]; | |
80 *filter_offset = filter.offset; | |
81 *filter_length = filter.length; | |
82 return &filter_values_[filter.data_location]; | |
83 } | |
84 | |
85 private: | |
86 struct FilterInstance { | |
87 // Offset within filter_values for this instance of the filter. | |
88 int data_location; | |
89 | |
90 // Distance from the left of the filter to the center. IN PIXELS | |
91 int offset; | |
92 | |
93 // Number of values in this filter instance. | |
94 int length; | |
95 }; | |
96 | |
97 // Stores the information for each filter added to this class. | |
98 std::vector<FilterInstance> filters_; | |
99 | |
100 // We store all the filter values in this flat list, indexed by | |
101 // |FilterInstance.data_location| to avoid the mallocs required for storing | |
102 // each one separately. | |
103 std::vector<int16> filter_values_; | |
104 | |
105 // The maximum size of any filter we've added. | |
106 int max_filter_; | |
107 }; | |
108 | |
109 // Does a two-dimensional convolusion on the given source image. | |
110 // | |
111 // It is assumed the source pixel offsets referenced in the input filters | |
112 // reference only valid pixels, so the source image size is not required. Each | |
113 // row of the source image starts |source_byte_row_stride| after the previous | |
114 // one (this allows you to have rows with some padding at the end). | |
115 // | |
116 // The result will be put into the given output buffer. The destination image | |
117 // size will be xfilter.num_values() * yfilter.num_values() pixels. It will be | |
118 // in rows of exactly xfilter.num_values() * 4 bytes. | |
119 // | |
120 // |source_has_alpha| is a hint that allows us to avoid doing computations on | |
121 // the alpha channel if the image is opaque. If you don't know, set this to | |
122 // true and it will work properly, but setting this to false will be a few | |
123 // percent faster if you know the image is opaque. | |
124 // | |
125 // The layout in memory is assumed to be 4-bytes per pixel in B-G-R-A order | |
126 // (this is ARGB when loaded into 32-bit words on a little-endian machine). | |
127 void BGRAConvolve2D(const uint8* source_data, | |
128 int source_byte_row_stride, | |
129 bool source_has_alpha, | |
130 const ConvolusionFilter1D& xfilter, | |
131 const ConvolusionFilter1D& yfilter, | |
132 uint8* output); | |
133 | |
134 } // namespace gfx | |
135 | |
136 #endif // BASE_GFX_CONVOLVER_H__ | |
137 | |
OLD | NEW |