Changeset 166084 in webkit
- Timestamp:
- Mar 21, 2014 12:02:35 PM (10 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r166082 r166084 1 2014-03-21 Adenilson Cavalcanti <cavalcantii@gmail.com> 2 3 Optimize FEGaussian blur 4 https://bugs.webkit.org/show_bug.cgi?id=50881 5 6 Reviewed by Dirk Schulze. 7 8 Currently boxBlur() will calculate the filter for each channel in 9 a loop and also uses Uint8ClampedArray::set() to write the 10 resulting pixels into destination array. 11 12 Using Uint8ClampedArray::set() requires lots of unnecessary type 13 conversions, not to mention other function calls. This patch 14 updates the original written by Simon Fraser to apply cleanly to current 15 trunk. 16 17 It also implements code to handle EdgeModes and finally avoids use 18 of ::set() in the newly added boxBlurAlphaOnly() 19 function. Assignment of calculated pixel values rely on pointers. 20 21 No new tests, no change on behavior. 22 23 * platform/graphics/filters/FEGaussianBlur.cpp: 24 (WebCore::boxBlurAlphaOnly): Specialized version for alpha only cases. 25 (WebCore::boxBlur): 26 1 27 2014-03-21 Simon Fraser <simon.fraser@apple.com> 2 28 -
trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
r165077 r166084 91 91 } 92 92 93 inline void boxBlur(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray, 94 unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage, EdgeModeType edgeMode) 95 { 93 // This function only operates on Alpha channel. 94 inline void boxBlurAlphaOnly(const Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray, 95 unsigned dx, int& dxLeft, int& dxRight, int& stride, int& strideLine, int& effectWidth, int& effectHeight, const int& maxKernelSize) 96 { 97 unsigned char* srcData = srcPixelArray->data(); 98 unsigned char* dstData = dstPixelArray->data(); 99 // Memory alignment is: RGBA, zero-index based. 100 const int channel = 3; 101 96 102 for (int y = 0; y < effectHeight; ++y) { 97 103 int line = y * strideLine; 98 for (int channel = 3; channel >= 0; --channel) { 99 int sum = 0; 100 // The code for edgeMode='none' is the common case and highly optimized. 101 // Furthermore, this code path affects more than just the input area. 102 if (edgeMode == EDGEMODE_NONE) { 103 // Fill the kernel 104 int maxKernelSize = std::min(dxRight, effectWidth); 105 for (int i = 0; i < maxKernelSize; ++i) 106 sum += srcPixelArray->item(line + i * stride + channel); 107 108 // Blurring 109 for (int x = 0; x < effectWidth; ++x) { 110 int pixelByteOffset = line + x * stride + channel; 111 dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx)); 112 // Shift kernel. 113 if (x >= dxLeft) 114 sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride); 115 if (x + dxRight < effectWidth) 116 sum += srcPixelArray->item(pixelByteOffset + dxRight * stride); 117 } 118 } else { 119 // FIXME: Add support for 'wrap' here. 120 // Get edge values for edgeMode 'duplicate'. 121 int edgeValueLeft = srcPixelArray->item(line + channel); 122 int edgeValueRight = srcPixelArray->item(line + (effectWidth - 1) * stride + channel); 123 // Fill the kernel 124 for (int i = dxLeft * -1; i < dxRight; ++i) { 125 if (i < 0) 126 sum += edgeValueLeft; 127 else if (i >= effectWidth) 128 sum += edgeValueRight; 129 else 130 sum += srcPixelArray->item(line + i * stride + channel); 131 } 132 // Blurring 133 for (int x = 0; x < effectWidth; ++x) { 134 int pixelByteOffset = line + x * stride + channel; 135 dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx)); 136 // Shift kernel. 137 if (x < dxLeft) 138 sum -= edgeValueLeft; 139 else 140 sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride); 141 if (x + dxRight >= effectWidth) 142 sum += edgeValueRight; 143 else 144 sum += srcPixelArray->item(pixelByteOffset + dxRight * stride); 145 } 146 } 147 if (alphaImage) // Source image is black, it just has different alpha values 148 break; 104 int sum = 0; 105 106 // Fill the kernel. 107 for (int i = 0; i < maxKernelSize; ++i) { 108 unsigned offset = line + i * stride; 109 unsigned char* srcPtr = srcData + offset; 110 sum += srcPtr[channel]; 111 } 112 113 // Blurring. 114 for (int x = 0; x < effectWidth; ++x) { 115 unsigned pixelByteOffset = line + x * stride + channel; 116 unsigned char* dstPtr = dstData + pixelByteOffset; 117 *dstPtr = static_cast<unsigned char>(sum / dx); 118 119 // Shift kernel. 120 if (x >= dxLeft) { 121 unsigned leftOffset = pixelByteOffset - dxLeft * stride; 122 unsigned char* srcPtr = srcData + leftOffset; 123 sum -= *srcPtr; 124 } 125 126 if (x + dxRight < effectWidth) { 127 unsigned rightOffset = pixelByteOffset + dxRight * stride; 128 unsigned char* srcPtr = srcData + rightOffset; 129 sum += *srcPtr; 130 } 131 } 132 } 133 } 134 135 inline void boxBlur(const Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray, 136 unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage, EdgeModeType edgeMode) 137 { 138 const int maxKernelSize = std::min(dxRight, effectWidth); 139 if (alphaImage) { 140 return boxBlurAlphaOnly(srcPixelArray, dstPixelArray, dx, dxLeft, dxRight, stride, strideLine, 141 effectWidth, effectHeight, maxKernelSize); 142 } 143 144 unsigned char* srcData = srcPixelArray->data(); 145 unsigned char* dstData = dstPixelArray->data(); 146 147 // Concerning the array width/length: it is Element size + Margin + Border. The number of pixels will be 148 // P = width * height * channels. 149 for (int y = 0; y < effectHeight; ++y) { 150 int line = y * strideLine; 151 int sumR = 0, sumG = 0, sumB = 0, sumA = 0; 152 153 if (edgeMode == EDGEMODE_NONE) { 154 // Fill the kernel. 155 for (int i = 0; i < maxKernelSize; ++i) { 156 unsigned offset = line + i * stride; 157 unsigned char* srcPtr = srcData + offset; 158 sumR += *srcPtr++; 159 sumG += *srcPtr++; 160 sumB += *srcPtr++; 161 sumA += *srcPtr; 162 } 163 164 // Blurring. 165 for (int x = 0; x < effectWidth; ++x) { 166 unsigned pixelByteOffset = line + x * stride; 167 unsigned char* dstPtr = dstData + pixelByteOffset; 168 169 *dstPtr++ = static_cast<unsigned char>(sumR / dx); 170 *dstPtr++ = static_cast<unsigned char>(sumG / dx); 171 *dstPtr++ = static_cast<unsigned char>(sumB / dx); 172 *dstPtr = static_cast<unsigned char>(sumA / dx); 173 174 // Shift kernel. 175 if (x >= dxLeft) { 176 unsigned leftOffset = pixelByteOffset - dxLeft * stride; 177 unsigned char* srcPtr = srcData + leftOffset; 178 sumR -= srcPtr[0]; 179 sumG -= srcPtr[1]; 180 sumB -= srcPtr[2]; 181 sumA -= srcPtr[3]; 182 } 183 184 if (x + dxRight < effectWidth) { 185 unsigned rightOffset = pixelByteOffset + dxRight * stride; 186 unsigned char* srcPtr = srcData + rightOffset; 187 sumR += srcPtr[0]; 188 sumG += srcPtr[1]; 189 sumB += srcPtr[2]; 190 sumA += srcPtr[3]; 191 } 192 } 193 194 } else { 195 // FIXME: Add support for 'wrap' here. 196 // Get edge values for edgeMode 'duplicate'. 197 unsigned char* edgeValueLeft = srcData + line; 198 unsigned char* edgeValueRight = srcData + (line + (effectWidth - 1) * stride); 199 200 // Fill the kernel. 201 for (int i = dxLeft * -1; i < dxRight; ++i) { 202 // Is this right for negative values of 'i'? 203 unsigned offset = line + i * stride; 204 unsigned char* srcPtr = srcData + offset; 205 206 if (i < 0) { 207 sumR += edgeValueLeft[0]; 208 sumG += edgeValueLeft[1]; 209 sumB += edgeValueLeft[2]; 210 sumA += edgeValueLeft[3]; 211 } else if (i >= effectWidth) { 212 sumR += edgeValueRight[0]; 213 sumG += edgeValueRight[1]; 214 sumB += edgeValueRight[2]; 215 sumA += edgeValueRight[3]; 216 } else { 217 sumR += *srcPtr++; 218 sumG += *srcPtr++; 219 sumB += *srcPtr++; 220 sumA += *srcPtr; 221 } 222 } 223 224 // Blurring. 225 for (int x = 0; x < effectWidth; ++x) { 226 unsigned pixelByteOffset = line + x * stride; 227 unsigned char* dstPtr = dstData + pixelByteOffset; 228 229 *dstPtr++ = static_cast<unsigned char>(sumR / dx); 230 *dstPtr++ = static_cast<unsigned char>(sumG / dx); 231 *dstPtr++ = static_cast<unsigned char>(sumB / dx); 232 *dstPtr = static_cast<unsigned char>(sumA / dx); 233 234 // Shift kernel. 235 if (x < dxLeft) { 236 sumR -= edgeValueLeft[0]; 237 sumG -= edgeValueLeft[1]; 238 sumB -= edgeValueLeft[2]; 239 sumA -= edgeValueLeft[3]; 240 } else { 241 unsigned leftOffset = pixelByteOffset - dxLeft * stride; 242 unsigned char* srcPtr = srcData + leftOffset; 243 sumR -= srcPtr[0]; 244 sumG -= srcPtr[1]; 245 sumB -= srcPtr[2]; 246 sumA -= srcPtr[3]; 247 } 248 249 if (x + dxRight >= effectWidth) { 250 sumR += edgeValueRight[0]; 251 sumG += edgeValueRight[1]; 252 sumB += edgeValueRight[2]; 253 sumA += edgeValueRight[3]; 254 } else { 255 unsigned rightOffset = pixelByteOffset + dxRight * stride; 256 unsigned char* srcPtr = srcData + rightOffset; 257 sumR += srcPtr[0]; 258 sumG += srcPtr[1]; 259 sumB += srcPtr[2]; 260 sumA += srcPtr[3]; 261 } 262 } 149 263 } 150 264 }
Note: See TracChangeset
for help on using the changeset viewer.