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