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

Side by Side Diff: src/codec/SkCodec.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 "SkBmpCodec.h" 8 #include "SkBmpCodec.h"
9 #include "SkCodec.h" 9 #include "SkCodec.h"
10 #include "SkData.h" 10 #include "SkData.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 // startScanlineDecode will need to be called before decoding scanlines. 104 // startScanlineDecode will need to be called before decoding scanlines.
105 fCurrScanline = -1; 105 fCurrScanline = -1;
106 106
107 if (!fStream->rewind()) { 107 if (!fStream->rewind()) {
108 return false; 108 return false;
109 } 109 }
110 110
111 return this->onRewind(); 111 return this->onRewind();
112 } 112 }
113 113
114 bool SkCodec::getScaledSubsetDimensions(float desiredScale, const Options& optio ns) const {
115 // Negative and zero scales are errors.
116 SkASSERT(desiredScale > 0.0f);
117 if (desiredScale <= 0.0f) {
118 return false;
119 }
120
121 // Upscaling is not supported. We will suggest a full decode if
122 // upscaling is requested.
123 if (desiredScale >= 1.0f) {
124 desiredScale = 1.0f;
125 }
126
127 // If the client is not requesting a subset decode,
128 // getScaledDimensions() should be used.
129 if (!options.fSubset || !options.fScaledDimensions || !options.fScaledSubset ) {
130 return false;
131 }
132
133 if (!is_valid_subset(*options.fSubset, this->getInfo().dimensions())) {
134 return false;
135 }
136
137 return this->onGetScaledSubsetDimensions(desiredScale, options);
138 }
139
140 bool SkCodec::subsetSupported(const SkIRect& subset, bool isScanlineDecode) {
141 if (!is_valid_subset(subset, this->getInfo().dimensions())) {
scroggo 2015/10/12 20:47:07 nit: fInfo.dimensions() No need to call the acces
142 return false;
143 }
144
145 return this->onSubsetSupported(subset, isScanlineDecode);
146 }
147
148 bool SkCodec::onSubsetSupported(const SkIRect& subset, bool isScanlineDecode) {
149 if (!isScanlineDecode) {
150 return false;
151 }
152
153 // We support subsetting in the x-dimension for the scanline decoder.
154 // Subsetting in the y-dimension can be accomplished using skipScanlines().
155 return subset.top() == 0 && subset.height() == this->getInfo().height();
156 }
157
158 bool SkCodec::scaledSubsetSupported(const SkISize& dstSize, const Options& optio ns,
159 bool isScanlineDecode) {
160 SkIRect* subset = options.fSubset;
161
162 // If there is no subsetting, we simply check if we can scale to dstSize
163 if (!subset) {
164 return this->dimensionsSupported(dstSize);
165 }
166
167 SkISize* scaledDimensions = options.fScaledDimensions;
168 SkIRect* scaledSubset = options.fScaledSubset;
169 if (!scaledDimensions && !scaledSubset) {
170 // If there is no scaling, check if we support the subset requested
171 return this->subsetSupported(*subset, isScanlineDecode);
172 }
173
174 if (!scaledDimensions || !scaledSubset) {
175 // Both scaledDimensions and scaledSubset must be non-NULL to perform
176 // a scaled subset decode.
177 return false;
178 }
179
180 if (!is_valid_subset(*scaledSubset, *scaledDimensions)) {
181 return false;
182 }
183
184 return this->onScaledSubsetSupported(options, isScanlineDecode);
185 }
186
187 bool SkCodec::onScaledSubsetSupported(const Options& options, bool isScanlineDec ode) {
188 if (!isScanlineDecode) {
189 return false;
190 }
191
192 if (!this->dimensionsSupported(*options.fScaledDimensions)) {
193 return false;
194 }
195
196 // We support subsetting in the x-dimension for the scanline decoder.
197 // Subsetting in the y-dimension can be accomplished using skipScanlines().
198 return options.fSubset->top() == 0 &&
199 options.fSubset->height() == options.fScaledDimensions->height();
200 }
201
114 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 202 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
115 const Options* options, SkPMColor ctable[], i nt* ctableCount) { 203 const Options* options, SkPMColor ctable[], i nt* ctableCount) {
116 if (kUnknown_SkColorType == info.colorType()) { 204 if (kUnknown_SkColorType == info.colorType()) {
117 return kInvalidConversion; 205 return kInvalidConversion;
118 } 206 }
119 if (nullptr == pixels) { 207 if (nullptr == pixels) {
120 return kInvalidParameters; 208 return kInvalidParameters;
121 } 209 }
122 if (rowBytes < info.minRowBytes()) { 210 if (rowBytes < info.minRowBytes()) {
123 return kInvalidParameters; 211 return kInvalidParameters;
(...skipping 21 matching lines...) Expand all
145 } 233 }
146 234
147 if (!this->rewindIfNeeded()) { 235 if (!this->rewindIfNeeded()) {
148 return kCouldNotRewind; 236 return kCouldNotRewind;
149 } 237 }
150 238
151 // Default options. 239 // Default options.
152 Options optsStorage; 240 Options optsStorage;
153 if (nullptr == options) { 241 if (nullptr == options) {
154 options = &optsStorage; 242 options = &optsStorage;
155 } else if (options->fSubset) {
156 SkIRect subset(*options->fSubset);
157 if (!this->onGetValidSubset(&subset) || subset != *options->fSubset) {
158 // FIXME: How to differentiate between not supporting subset at all
159 // and not supporting this particular subset?
160 return kUnimplemented;
161 }
162 } 243 }
163 244
164 // FIXME: Support subsets somehow? Note that this works for SkWebpCodec 245 if (!this->scaledSubsetSupported(info.dimensions(), *options, false)) {
165 // because it supports arbitrary scaling/subset combinations.
166 if (!this->dimensionsSupported(info.dimensions())) {
167 return kInvalidScale; 246 return kInvalidScale;
168 } 247 }
169 248
170 // On an incomplete decode, the subclass will specify the number of scanline s that it decoded 249 // On an incomplete decode, the subclass will specify the number of scanline s that it decoded
171 // successfully. 250 // successfully.
172 int rowsDecoded = 0; 251 int rowsDecoded = 0;
173 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount, 252 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount,
174 &rowsDecoded); 253 &rowsDecoded);
175 254
176 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { 255 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 } 291 }
213 292
214 if (!this->rewindIfNeeded()) { 293 if (!this->rewindIfNeeded()) {
215 return kCouldNotRewind; 294 return kCouldNotRewind;
216 } 295 }
217 296
218 // Set options. 297 // Set options.
219 Options optsStorage; 298 Options optsStorage;
220 if (nullptr == options) { 299 if (nullptr == options) {
221 options = &optsStorage; 300 options = &optsStorage;
222 } else if (options->fSubset) {
223 SkIRect size = SkIRect::MakeSize(dstInfo.dimensions());
224 if (!size.contains(*options->fSubset)) {
225 return kInvalidInput;
226 }
227
228 // We only support subsetting in the x-dimension for scanline decoder.
229 // Subsetting in the y-dimension can be accomplished using skipScanlines ().
230 if (options->fSubset->top() != 0 || options->fSubset->height() != dstInf o.height()) {
231 return kInvalidInput;
232 }
233 } 301 }
234 302
235 // FIXME: Support subsets somehow? 303 if (!this->scaledSubsetSupported(dstInfo.dimensions(), *options, true)) {
236 if (!this->dimensionsSupported(dstInfo.dimensions())) {
237 return kInvalidScale; 304 return kInvalidScale;
238 } 305 }
239 306
240 const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount); 307 const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount);
241 if (result != SkCodec::kSuccess) { 308 if (result != SkCodec::kSuccess) {
242 return result; 309 return result;
243 } 310 }
244 311
245 fCurrScanline = 0; 312 fCurrScanline = 0;
246 fDstInfo = dstInfo; 313 fDstInfo = dstInfo;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested); 410 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested);
344 const SkImageInfo fillInfo = info.makeWH(info.width(), 1); 411 const SkImageInfo fillInfo = info.makeWH(info.width(), 1);
345 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { 412 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) {
346 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes); 413 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes);
347 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler); 414 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler);
348 } 415 }
349 break; 416 break;
350 } 417 }
351 } 418 }
352 } 419 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698