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

Side by Side Diff: src/codec/SkWebpCodec.cpp

Issue 1395183003: Add scaled subset API to SkCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@split0
Patch Set: Created 5 years, 2 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
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 "SkCodecPriv.h" 8 #include "SkCodecPriv.h"
9 #include "SkWebpCodec.h" 9 #include "SkWebpCodec.h"
10 #include "SkTemplates.h" 10 #include "SkTemplates.h"
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 dim.fHeight = SkTMax(1, SkScalarRoundToInt(desiredScale * dim.fHeight)); 113 dim.fHeight = SkTMax(1, SkScalarRoundToInt(desiredScale * dim.fHeight));
114 return dim; 114 return dim;
115 } 115 }
116 116
117 bool SkWebpCodec::onDimensionsSupported(const SkISize& dim) { 117 bool SkWebpCodec::onDimensionsSupported(const SkISize& dim) {
118 const SkImageInfo& info = this->getInfo(); 118 const SkImageInfo& info = this->getInfo();
119 return dim.width() >= 1 && dim.width() <= info.width() 119 return dim.width() >= 1 && dim.width() <= info.width()
120 && dim.height() >= 1 && dim.height() <= info.height(); 120 && dim.height() >= 1 && dim.height() <= info.height();
121 } 121 }
122 122
123 bool SkWebpCodec::onSubsetSupported(const SkIRect& subset, bool isScanlineDecode ) {
124 return !((subset.left() & 1) || (subset.top() & 1));
scroggo 2015/10/12 20:47:07 Could you add a comment explaining this? (Left and
125 }
126
127 bool SkWebpCodec::onScaledSubsetSupported(const Options& options, bool isScanlin eDecode) {
128 return this->onSubsetSupported(*options.fSubset, isScanlineDecode);
129 }
123 130
124 static WEBP_CSP_MODE webp_decode_mode(SkColorType ct, bool premultiply) { 131 static WEBP_CSP_MODE webp_decode_mode(SkColorType ct, bool premultiply) {
125 switch (ct) { 132 switch (ct) {
126 case kBGRA_8888_SkColorType: 133 case kBGRA_8888_SkColorType:
127 return premultiply ? MODE_bgrA : MODE_BGRA; 134 return premultiply ? MODE_bgrA : MODE_BGRA;
128 case kRGBA_8888_SkColorType: 135 case kRGBA_8888_SkColorType:
129 return premultiply ? MODE_rgbA : MODE_RGBA; 136 return premultiply ? MODE_rgbA : MODE_RGBA;
130 case kRGB_565_SkColorType: 137 case kRGB_565_SkColorType:
131 return MODE_RGB_565; 138 return MODE_RGB_565;
132 default: 139 default:
133 return MODE_LAST; 140 return MODE_LAST;
134 } 141 }
135 } 142 }
136 143
137 // The WebP decoding API allows us to incrementally pass chunks of bytes as we r eceive them to the 144 // The WebP decoding API allows us to incrementally pass chunks of bytes as we r eceive them to the
138 // decoder with WebPIAppend. In order to do so, we need to read chunks from the SkStream. This size 145 // decoder with WebPIAppend. In order to do so, we need to read chunks from the SkStream. This size
139 // is arbitrary. 146 // is arbitrary.
140 static const size_t BUFFER_SIZE = 4096; 147 static const size_t BUFFER_SIZE = 4096;
141 148
142 bool SkWebpCodec::onGetValidSubset(SkIRect* desiredSubset) const { 149 bool SkWebpCodec::onGetScaledSubsetDimensions(float desiredScale, const Options& options) const {
143 if (!desiredSubset) { 150 options.fSubset->fLeft = (options.fSubset->fLeft >> 1) << 1;
144 return false; 151 options.fSubset->fTop = (options.fSubset->fTop >> 1) << 1;
145 }
146 152
147 SkIRect dimensions = SkIRect::MakeSize(this->getInfo().dimensions()); 153 // Notice that we may round the size of the subset up to 1. This means that we must
148 if (!dimensions.contains(*desiredSubset)) { 154 // round up the scaled output dimensions to avoid suggesting a subset that i s off the
149 return false; 155 // edge of the image. This rounding behvaior is consistent with SkJpegCodec .
150 } 156 *(options.fScaledDimensions) = SkISize::Make(
157 sk_float_ceil2int(desiredScale * this->getInfo().width()),
158 sk_float_ceil2int(desiredScale * this->getInfo().height()));
151 159
152 // As stated below, libwebp snaps to even left and top. Make sure top and le ft are even, so we 160 // Notice that we may round the size of the subset up to 1. This means that we must
153 // decode this exact subset. 161 // floor the left and top offsets to ensure that we do not suggest a subset that is
154 // Leave right and bottom unmodified, so we suggest a slightly larger subset than requested. 162 // off the edge of the image.
155 desiredSubset->fLeft = (desiredSubset->fLeft >> 1) << 1; 163 *(options.fScaledSubset) = SkIRect::MakeXYWH(
156 desiredSubset->fTop = (desiredSubset->fTop >> 1) << 1; 164 int (desiredScale * options.fSubset->left()),
165 int (desiredScale * options.fSubset->top()),
166 SkTMax(1, SkScalarRoundToInt(desiredScale * options.fSubset->width() )),
167 SkTMax(1, SkScalarRoundToInt(desiredScale * options.fSubset->height( ))));
168
157 return true; 169 return true;
158 } 170 }
159 171
160 SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, 172 SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
161 const Options& options, SkPMColor*, int *, 173 const Options& options, SkPMColor*, int *,
162 int* rowsDecoded) { 174 int* rowsDecoded) {
163 if (!webp_conversion_possible(dstInfo, this->getInfo())) { 175 if (!webp_conversion_possible(dstInfo, this->getInfo())) {
164 return kInvalidConversion; 176 return kInvalidConversion;
165 } 177 }
166 178
(...skipping 19 matching lines...) Expand all
186 198
187 // This is tricky. libwebp snaps the top and left to even values. We cou ld let libwebp 199 // This is tricky. libwebp snaps the top and left to even values. We cou ld let libwebp
188 // do the snap, and return a subset which is a different one than reques ted. The problem 200 // do the snap, and return a subset which is a different one than reques ted. The problem
189 // with that approach is that the caller may try to stitch subsets toget her, and if we 201 // with that approach is that the caller may try to stitch subsets toget her, and if we
190 // returned different subsets than requested, there would be artifacts a t the boundaries. 202 // returned different subsets than requested, there would be artifacts a t the boundaries.
191 // Instead, we report that we cannot support odd values for top and left .. 203 // Instead, we report that we cannot support odd values for top and left ..
192 if (!SkIsAlign2(bounds.fLeft) || !SkIsAlign2(bounds.fTop)) { 204 if (!SkIsAlign2(bounds.fLeft) || !SkIsAlign2(bounds.fTop)) {
193 return kInvalidParameters; 205 return kInvalidParameters;
194 } 206 }
195 207
196 #ifdef SK_DEBUG
msarett 2015/10/12 18:33:29 I tried to keep a debug check here, but it is too
197 {
198 // Make a copy, since getValidSubset can change its input.
199 SkIRect subset(bounds);
200 // That said, getValidSubset should *not* change its input, in this case; otherwise
201 // getValidSubset does not match the actual subsets we can do.
202 SkASSERT(this->getValidSubset(&subset) && subset == bounds);
203 }
204 #endif
205
206 config.options.use_cropping = 1; 208 config.options.use_cropping = 1;
207 config.options.crop_left = bounds.fLeft; 209 config.options.crop_left = bounds.fLeft;
208 config.options.crop_top = bounds.fTop; 210 config.options.crop_top = bounds.fTop;
209 config.options.crop_width = bounds.width(); 211 config.options.crop_width = bounds.width();
210 config.options.crop_height = bounds.height(); 212 config.options.crop_height = bounds.height();
211 } 213 }
212 214
213 SkISize dstDimensions = dstInfo.dimensions(); 215 SkISize dstDimensions = dstInfo.dimensions();
214 if (bounds.size() != dstDimensions) { 216 if (bounds.size() != dstDimensions) {
215 // Caller is requesting scaling. 217 // Caller is requesting scaling.
(...skipping 30 matching lines...) Expand all
246 // Break out of the switch statement. Continue the loop. 248 // Break out of the switch statement. Continue the loop.
247 break; 249 break;
248 default: 250 default:
249 return kInvalidInput; 251 return kInvalidInput;
250 } 252 }
251 } 253 }
252 } 254 }
253 255
254 SkWebpCodec::SkWebpCodec(const SkImageInfo& info, SkStream* stream) 256 SkWebpCodec::SkWebpCodec(const SkImageInfo& info, SkStream* stream)
255 : INHERITED(info, stream) {} 257 : INHERITED(info, stream) {}
OLDNEW
« src/codec/SkSwizzler.cpp ('K') | « src/codec/SkWebpCodec.h ('k') | tests/CodexTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698