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

Side by Side Diff: src/core/SkConvolver.h

Issue 19335002: Production quality fast image up/downsampler (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: camel case and if-statement braces Created 7 years, 5 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 | « src/core/SkBitmapScaler.cpp ('k') | src/core/SkConvolver.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 SK_CONVOLVER_H
6 #define SK_CONVOLVER_H
7
8 #include "SkSize.h"
9 #include "SkTypes.h"
10 #include "SkTArray.h"
11
12 // avoid confusion with Mac OS X's math library (Carbon)
13 #if defined(__APPLE__)
14 #undef FloatToConvolutionFixed
15 #undef ConvolutionFixedToFloat
16 #endif
17
18 // Represents a filter in one dimension. Each output pixel has one entry in this
19 // object for the filter values contributing to it. You build up the filter
20 // list by calling AddFilter for each output pixel (in order).
21 //
22 // We do 2-dimensional convolution by first convolving each row by one
23 // SkConvolutionFilter1D, then convolving each column by another one.
24 //
25 // Entries are stored in ConvolutionFixed point, shifted left by kShiftBits.
26 class SkConvolutionFilter1D {
27 public:
28 typedef short ConvolutionFixed;
29
30 // The number of bits that ConvolutionFixed point values are shifted by.
31 enum { kShiftBits = 14 };
32
33 SK_API SkConvolutionFilter1D();
34 SK_API ~SkConvolutionFilter1D();
35
36 // Convert between floating point and our ConvolutionFixed point representat ion.
37 static ConvolutionFixed FloatToFixed(float f) {
38 return static_cast<ConvolutionFixed>(f * (1 << kShiftBits));
39 }
40 static unsigned char FixedToChar(ConvolutionFixed x) {
41 return static_cast<unsigned char>(x >> kShiftBits);
42 }
43 static float FixedToFloat(ConvolutionFixed x) {
44 // The cast relies on ConvolutionFixed being a short, implying that on
45 // the platforms we care about all (16) bits will fit into
46 // the mantissa of a (32-bit) float.
47 SK_COMPILE_ASSERT(sizeof(ConvolutionFixed) == 2, ConvolutionFixed_type_s hould_fit_in_float_mantissa);
48 float raw = static_cast<float>(x);
49 return ldexpf(raw, -kShiftBits);
50 }
51
52 // Returns the maximum pixel span of a filter.
53 int maxFilter() const { return fMaxFilter; }
54
55 // Returns the number of filters in this filter. This is the dimension of th e
56 // output image.
57 int numValues() const { return static_cast<int>(fFilters.count()); }
58
59 // Appends the given list of scaling values for generating a given output
60 // pixel. |filterOffset| is the distance from the edge of the image to where
61 // the scaling factors start. The scaling factors apply to the source pixels
62 // starting from this position, and going for the next |filterLength| pixels .
63 //
64 // You will probably want to make sure your input is normalized (that is,
65 // all entries in |filterValuesg| sub to one) to prevent affecting the overa ll
66 // brighness of the image.
67 //
68 // The filterLength must be > 0.
69 //
70 // This version will automatically convert your input to ConvolutionFixed po int.
71 SK_API void AddFilter(int filterOffset,
72 const float* filterValues,
73 int filterLength);
74
75 // Same as the above version, but the input is already ConvolutionFixed poin t.
76 void AddFilter(int filterOffset,
77 const ConvolutionFixed* filterValues,
78 int filterLength);
79
80 // Retrieves a filter for the given |valueOffset|, a position in the output
81 // image in the direction we're convolving. The offset and length of the
82 // filter values are put into the corresponding out arguments (see AddFilter
83 // above for what these mean), and a pointer to the first scaling factor is
84 // returned. There will be |filterLength| values in this array.
85 inline const ConvolutionFixed* FilterForValue(int valueOffset,
86 int* filterOffset,
87 int* filterLength) const {
88 const FilterInstance& filter = fFilters[valueOffset];
89 *filterOffset = filter.fOffset;
90 *filterLength = filter.fTrimmedLength;
91 if (filter.fTrimmedLength == 0) {
92 return NULL;
93 }
94 return &fFilterValues[filter.fDataLocation];
95 }
96
97 // Retrieves the filter for the offset 0, presumed to be the one and only.
98 // The offset and length of the filter values are put into the corresponding
99 // out arguments (see AddFilter). Note that |filterLegth| and
100 // |specifiedFilterLength| may be different if leading/trailing zeros of the
101 // original floating point form were clipped.
102 // There will be |filterLength| values in the return array.
103 // Returns NULL if the filter is 0-length (for instance when all floating
104 // point values passed to AddFilter were clipped to 0).
105 SK_API const ConvolutionFixed* GetSingleFilter(int* specifiedFilterLength,
106 int* filterOffset,
107 int* filterLength) const;
108
109 // Add another value to the fFilterValues array -- useful for
110 // SIMD padding which happens outside of this class.
111
112 void addFilterValue( ConvolutionFixed val ) {
113 fFilterValues.push_back( val );
114 }
115 private:
116 struct FilterInstance {
117 // Offset within filterValues for this instance of the filter.
118 int fDataLocation;
119
120 // Distance from the left of the filter to the center. IN PIXELS
121 int fOffset;
122
123 // Number of values in this filter instance.
124 int fTrimmedLength;
125
126 // Filter length as specified. Note that this may be different from
127 // 'trimmed_length' if leading/trailing zeros of the original floating
128 // point form were clipped differently on each tail.
129 int fLength;
130 };
131
132 // Stores the information for each filter added to this class.
133 SkTArray<FilterInstance> fFilters;
134
135 // We store all the filter values in this flat list, indexed by
136 // |FilterInstance.data_location| to avoid the mallocs required for storing
137 // each one separately.
138 SkTArray<ConvolutionFixed> fFilterValues;
139
140 // The maximum size of any filter we've added.
141 int fMaxFilter;
142 };
143
144 typedef void (*SkConvolveVertically_pointer)(
145 const SkConvolutionFilter1D::ConvolutionFixed* filterValues,
146 int filterLength,
147 unsigned char* const* sourceDataRows,
148 int pixelWidth,
149 unsigned char* outRow,
150 bool hasAlpha);
151 typedef void (*SkConvolve4RowsHorizontally_pointer)(
152 const unsigned char* srcData[4],
153 const SkConvolutionFilter1D& filter,
154 unsigned char* outRow[4]);
155 typedef void (*SkConvolveHorizontally_pointer)(
156 const unsigned char* srcData,
157 const SkConvolutionFilter1D& filter,
158 unsigned char* outRow,
159 bool hasAlpha);
160 typedef void (*SkConvolveFilterPadding_pointer)(
161 SkConvolutionFilter1D *filter);
162
163 struct SkConvolutionProcs {
164 // This is how many extra pixels may be read by the
165 // conolve*horizontally functions.
166 int fExtraHorizontalReads;
167 SkConvolveVertically_pointer fConvolveVertically;
168 SkConvolve4RowsHorizontally_pointer fConvolve4RowsHorizontally;
169 SkConvolveHorizontally_pointer fConvolveHorizontally;
170 SkConvolveFilterPadding_pointer fApplySIMDPadding;
171 };
172
173
174
175 // Does a two-dimensional convolution on the given source image.
176 //
177 // It is assumed the source pixel offsets referenced in the input filters
178 // reference only valid pixels, so the source image size is not required. Each
179 // row of the source image starts |sourceByteRowStride| after the previous
180 // one (this allows you to have rows with some padding at the end).
181 //
182 // The result will be put into the given output buffer. The destination image
183 // size will be xfilter.numValues() * yfilter.numValues() pixels. It will be
184 // in rows of exactly xfilter.numValues() * 4 bytes.
185 //
186 // |sourceHasAlpha| is a hint that allows us to avoid doing computations on
187 // the alpha channel if the image is opaque. If you don't know, set this to
188 // true and it will work properly, but setting this to false will be a few
189 // percent faster if you know the image is opaque.
190 //
191 // The layout in memory is assumed to be 4-bytes per pixel in B-G-R-A order
192 // (this is ARGB when loaded into 32-bit words on a little-endian machine).
193 SK_API void BGRAConvolve2D(const unsigned char* sourceData,
194 int sourceByteRowStride,
195 bool sourceHasAlpha,
196 const SkConvolutionFilter1D& xfilter,
197 const SkConvolutionFilter1D& yfilter,
198 int outputByteRowStride,
199 unsigned char* output,
200 SkConvolutionProcs *convolveProcs,
201 bool useSimdIfPossible);
202
203 #endif // SK_CONVOLVER_H
OLDNEW
« no previous file with comments | « src/core/SkBitmapScaler.cpp ('k') | src/core/SkConvolver.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698