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

Side by Side Diff: src/core/SkBitmapScaler.cpp

Issue 2481733003: Make SSE2/Neon convolution functions not to read extra bytes (Closed)
Patch Set: Change macros to functions Created 4 years, 1 month 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
« no previous file with comments | « no previous file | src/core/SkConvolver.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 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkBitmapScaler.h" 8 #include "SkBitmapScaler.h"
9 #include "SkBitmapFilter.h" 9 #include "SkBitmapFilter.h"
10 #include "SkConvolver.h" 10 #include "SkConvolver.h"
11 #include "SkImageInfo.h" 11 #include "SkImageInfo.h"
12 #include "SkPixmap.h" 12 #include "SkPixmap.h"
13 #include "SkRect.h" 13 #include "SkRect.h"
14 #include "SkTArray.h" 14 #include "SkTArray.h"
15 15
16 // SkResizeFilter -------------------------------------------------------------- -- 16 // SkResizeFilter -------------------------------------------------------------- --
17 17
18 // Encapsulates computation and storage of the filters required for one complete 18 // Encapsulates computation and storage of the filters required for one complete
19 // resize operation. 19 // resize operation.
20 class SkResizeFilter { 20 class SkResizeFilter {
21 public: 21 public:
22 SkResizeFilter(SkBitmapScaler::ResizeMethod method, 22 SkResizeFilter(SkBitmapScaler::ResizeMethod method,
23 int srcFullWidth, int srcFullHeight, 23 int srcFullWidth, int srcFullHeight,
24 float destWidth, float destHeight, 24 float destWidth, float destHeight,
25 const SkRect& destSubset, 25 const SkRect& destSubset);
26 const SkConvolutionProcs& convolveProcs);
27 ~SkResizeFilter() { delete fBitmapFilter; } 26 ~SkResizeFilter() { delete fBitmapFilter; }
28 27
29 // Returns the filled filter values. 28 // Returns the filled filter values.
30 const SkConvolutionFilter1D& xFilter() { return fXFilter; } 29 const SkConvolutionFilter1D& xFilter() { return fXFilter; }
31 const SkConvolutionFilter1D& yFilter() { return fYFilter; } 30 const SkConvolutionFilter1D& yFilter() { return fYFilter; }
32 31
33 private: 32 private:
34 33
35 SkBitmapFilter* fBitmapFilter; 34 SkBitmapFilter* fBitmapFilter;
36 35
37 // Computes one set of filters either horizontally or vertically. The caller 36 // Computes one set of filters either horizontally or vertically. The caller
38 // will specify the "min" and "max" rather than the bottom/top and 37 // will specify the "min" and "max" rather than the bottom/top and
39 // right/bottom so that the same code can be re-used in each dimension. 38 // right/bottom so that the same code can be re-used in each dimension.
40 // 39 //
41 // |srcDependLo| and |srcDependSize| gives the range for the source 40 // |srcDependLo| and |srcDependSize| gives the range for the source
42 // depend rectangle (horizontally or vertically at the caller's discretion 41 // depend rectangle (horizontally or vertically at the caller's discretion
43 // -- see above for what this means). 42 // -- see above for what this means).
44 // 43 //
45 // Likewise, the range of destination values to compute and the scale factor 44 // Likewise, the range of destination values to compute and the scale factor
46 // for the transform is also specified. 45 // for the transform is also specified.
47 46
48 void computeFilters(int srcSize, 47 void computeFilters(int srcSize,
49 float destSubsetLo, float destSubsetSize, 48 float destSubsetLo, float destSubsetSize,
50 float scale, 49 float scale,
51 SkConvolutionFilter1D* output, 50 SkConvolutionFilter1D* output);
52 const SkConvolutionProcs& convolveProcs);
53 51
54 SkConvolutionFilter1D fXFilter; 52 SkConvolutionFilter1D fXFilter;
55 SkConvolutionFilter1D fYFilter; 53 SkConvolutionFilter1D fYFilter;
56 }; 54 };
57 55
58 SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method, 56 SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method,
59 int srcFullWidth, int srcFullHeight, 57 int srcFullWidth, int srcFullHeight,
60 float destWidth, float destHeight, 58 float destWidth, float destHeight,
61 const SkRect& destSubset, 59 const SkRect& destSubset) {
62 const SkConvolutionProcs& convolveProcs) {
63 60
64 SkASSERT(method >= SkBitmapScaler::RESIZE_FirstMethod && 61 SkASSERT(method >= SkBitmapScaler::RESIZE_FirstMethod &&
65 method <= SkBitmapScaler::RESIZE_LastMethod); 62 method <= SkBitmapScaler::RESIZE_LastMethod);
66 63
67 fBitmapFilter = nullptr; 64 fBitmapFilter = nullptr;
68 switch(method) { 65 switch(method) {
69 case SkBitmapScaler::RESIZE_BOX: 66 case SkBitmapScaler::RESIZE_BOX:
70 fBitmapFilter = new SkBoxFilter; 67 fBitmapFilter = new SkBoxFilter;
71 break; 68 break;
72 case SkBitmapScaler::RESIZE_TRIANGLE: 69 case SkBitmapScaler::RESIZE_TRIANGLE:
73 fBitmapFilter = new SkTriangleFilter; 70 fBitmapFilter = new SkTriangleFilter;
74 break; 71 break;
75 case SkBitmapScaler::RESIZE_MITCHELL: 72 case SkBitmapScaler::RESIZE_MITCHELL:
76 fBitmapFilter = new SkMitchellFilter; 73 fBitmapFilter = new SkMitchellFilter;
77 break; 74 break;
78 case SkBitmapScaler::RESIZE_HAMMING: 75 case SkBitmapScaler::RESIZE_HAMMING:
79 fBitmapFilter = new SkHammingFilter; 76 fBitmapFilter = new SkHammingFilter;
80 break; 77 break;
81 case SkBitmapScaler::RESIZE_LANCZOS3: 78 case SkBitmapScaler::RESIZE_LANCZOS3:
82 fBitmapFilter = new SkLanczosFilter; 79 fBitmapFilter = new SkLanczosFilter;
83 break; 80 break;
84 } 81 }
85 82
86 83
87 float scaleX = destWidth / srcFullWidth; 84 float scaleX = destWidth / srcFullWidth;
88 float scaleY = destHeight / srcFullHeight; 85 float scaleY = destHeight / srcFullHeight;
89 86
90 this->computeFilters(srcFullWidth, destSubset.fLeft, destSubset.width(), 87 this->computeFilters(srcFullWidth, destSubset.fLeft, destSubset.width(),
91 scaleX, &fXFilter, convolveProcs); 88 scaleX, &fXFilter);
92 if (srcFullWidth == srcFullHeight && 89 if (srcFullWidth == srcFullHeight &&
93 destSubset.fLeft == destSubset.fTop && 90 destSubset.fLeft == destSubset.fTop &&
94 destSubset.width() == destSubset.height()&& 91 destSubset.width() == destSubset.height()&&
95 scaleX == scaleY) { 92 scaleX == scaleY) {
96 fYFilter = fXFilter; 93 fYFilter = fXFilter;
97 } else { 94 } else {
98 this->computeFilters(srcFullHeight, destSubset.fTop, destSubset.height() , 95 this->computeFilters(srcFullHeight, destSubset.fTop, destSubset.height() ,
99 scaleY, &fYFilter, convolveProcs); 96 scaleY, &fYFilter);
100 } 97 }
101 } 98 }
102 99
103 // TODO(egouriou): Take advantage of periods in the convolution. 100 // TODO(egouriou): Take advantage of periods in the convolution.
104 // Practical resizing filters are periodic outside of the border area. 101 // Practical resizing filters are periodic outside of the border area.
105 // For Lanczos, a scaling by a (reduced) factor of p/q (q pixels in the 102 // For Lanczos, a scaling by a (reduced) factor of p/q (q pixels in the
106 // source become p pixels in the destination) will have a period of p. 103 // source become p pixels in the destination) will have a period of p.
107 // A nice consequence is a period of 1 when downscaling by an integral 104 // A nice consequence is a period of 1 when downscaling by an integral
108 // factor. Downscaling from typical display resolutions is also bound 105 // factor. Downscaling from typical display resolutions is also bound
109 // to produce interesting periods as those are chosen to have multiple 106 // to produce interesting periods as those are chosen to have multiple
110 // small factors. 107 // small factors.
111 // Small periods reduce computational load and improve cache usage if 108 // Small periods reduce computational load and improve cache usage if
112 // the coefficients can be shared. For periods of 1 we can consider 109 // the coefficients can be shared. For periods of 1 we can consider
113 // loading the factors only once outside the borders. 110 // loading the factors only once outside the borders.
114 void SkResizeFilter::computeFilters(int srcSize, 111 void SkResizeFilter::computeFilters(int srcSize,
115 float destSubsetLo, float destSubsetSize, 112 float destSubsetLo, float destSubsetSize,
116 float scale, 113 float scale,
117 SkConvolutionFilter1D* output, 114 SkConvolutionFilter1D* output) {
118 const SkConvolutionProcs& convolveProcs) {
119 float destSubsetHi = destSubsetLo + destSubsetSize; // [lo, hi) 115 float destSubsetHi = destSubsetLo + destSubsetSize; // [lo, hi)
120 116
121 // When we're doing a magnification, the scale will be larger than one. This 117 // When we're doing a magnification, the scale will be larger than one. This
122 // means the destination pixels are much smaller than the source pixels, and 118 // means the destination pixels are much smaller than the source pixels, and
123 // that the range covered by the filter won't necessarily cover any source 119 // that the range covered by the filter won't necessarily cover any source
124 // pixel boundaries. Therefore, we use these clamped values (max of 1) for 120 // pixel boundaries. Therefore, we use these clamped values (max of 1) for
125 // some computations. 121 // some computations.
126 float clampedScale = SkTMin(1.0f, scale); 122 float clampedScale = SkTMin(1.0f, scale);
127 123
128 // This is how many source pixels from the center we need to count 124 // This is how many source pixels from the center we need to count
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 // we add back in to avoid affecting the brightness of the image. We 189 // we add back in to avoid affecting the brightness of the image. We
194 // arbitrarily add this to the center of the filter array (this won't always 190 // arbitrarily add this to the center of the filter array (this won't always
195 // be the center of the filter function since it could get clipped on the 191 // be the center of the filter function since it could get clipped on the
196 // edges, but it doesn't matter enough to worry about that case). 192 // edges, but it doesn't matter enough to worry about that case).
197 int leftovers = SkConvolutionFilter1D::FloatToFixed(1) - fixedSum; 193 int leftovers = SkConvolutionFilter1D::FloatToFixed(1) - fixedSum;
198 fixedFilterValues[filterCount / 2] += leftovers; 194 fixedFilterValues[filterCount / 2] += leftovers;
199 195
200 // Now it's ready to go. 196 // Now it's ready to go.
201 output->AddFilter(SkScalarFloorToInt(srcBegin), fixedFilterValues, filterCou nt); 197 output->AddFilter(SkScalarFloorToInt(srcBegin), fixedFilterValues, filterCou nt);
202 } 198 }
203
204 if (convolveProcs.fApplySIMDPadding) {
205 convolveProcs.fApplySIMDPadding(output);
206 }
207 } 199 }
208 200
209 //////////////////////////////////////////////////////////////////////////////// /////////////////// 201 //////////////////////////////////////////////////////////////////////////////// ///////////////////
210 202
211 static bool valid_for_resize(const SkPixmap& source, int dstW, int dstH) { 203 static bool valid_for_resize(const SkPixmap& source, int dstW, int dstH) {
212 // TODO: Seems like we shouldn't care about the swizzle of source, just that it's 8888 204 // TODO: Seems like we shouldn't care about the swizzle of source, just that it's 8888
213 return source.addr() && source.colorType() == kN32_SkColorType && 205 return source.addr() && source.colorType() == kN32_SkColorType &&
214 source.width() >= 1 && source.height() >= 1 && dstW >= 1 && dstH >= 1 ; 206 source.width() >= 1 && source.height() >= 1 && dstW >= 1 && dstH >= 1 ;
215 } 207 }
216 208
217 bool SkBitmapScaler::Resize(const SkPixmap& result, const SkPixmap& source, Resi zeMethod method) { 209 bool SkBitmapScaler::Resize(const SkPixmap& result, const SkPixmap& source, Resi zeMethod method) {
218 if (!valid_for_resize(source, result.width(), result.height())) { 210 if (!valid_for_resize(source, result.width(), result.height())) {
219 return false; 211 return false;
220 } 212 }
221 if (!result.addr() || result.colorType() != source.colorType()) { 213 if (!result.addr() || result.colorType() != source.colorType()) {
222 return false; 214 return false;
223 } 215 }
224 216
225 SkConvolutionProcs convolveProcs= { 0, nullptr, nullptr, nullptr, nullptr }; 217 SkConvolutionProcs convolveProcs= { nullptr, nullptr, nullptr };
226 PlatformConvolutionProcs(&convolveProcs); 218 PlatformConvolutionProcs(&convolveProcs);
227 219
228 SkRect destSubset = SkRect::MakeIWH(result.width(), result.height()); 220 SkRect destSubset = SkRect::MakeIWH(result.width(), result.height());
229 221
230 SkResizeFilter filter(method, source.width(), source.height(), 222 SkResizeFilter filter(method, source.width(), source.height(),
231 result.width(), result.height(), destSubset, convolveP rocs); 223 result.width(), result.height(), destSubset);
232 224
233 // Get a subset encompassing this touched area. We construct the 225 // Get a subset encompassing this touched area. We construct the
234 // offsets and row strides such that it looks like a new bitmap, while 226 // offsets and row strides such that it looks like a new bitmap, while
235 // referring to the old data. 227 // referring to the old data.
236 const uint8_t* sourceSubset = reinterpret_cast<const uint8_t*>(source.addr() ); 228 const uint8_t* sourceSubset = reinterpret_cast<const uint8_t*>(source.addr() );
237 229
238 return BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()), 230 return BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()),
239 !source.isOpaque(), filter.xFilter(), filter.yFilter() , 231 !source.isOpaque(), filter.xFilter(), filter.yFilter() ,
240 static_cast<int>(result.rowBytes()), 232 static_cast<int>(result.rowBytes()),
241 static_cast<unsigned char*>(result.writable_addr()), 233 static_cast<unsigned char*>(result.writable_addr()),
(...skipping 17 matching lines...) Expand all
259 SkPixmap resultPM; 251 SkPixmap resultPM;
260 if (!result.peekPixels(&resultPM) || !Resize(resultPM, source, method)) { 252 if (!result.peekPixels(&resultPM) || !Resize(resultPM, source, method)) {
261 return false; 253 return false;
262 } 254 }
263 255
264 *resultPtr = result; 256 *resultPtr = result;
265 resultPtr->lockPixels(); 257 resultPtr->lockPixels();
266 SkASSERT(resultPtr->getPixels()); 258 SkASSERT(resultPtr->getPixels());
267 return true; 259 return true;
268 } 260 }
OLDNEW
« no previous file with comments | « no previous file | src/core/SkConvolver.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698