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

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

Issue 1997703003: Make SkPngCodec decode progressively. (Closed) Base URL: https://skia.googlesource.com/skia.git@foil
Patch Set: Switch statement for setjmp Created 4 years, 7 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 "SkCodecPriv.h" 10 #include "SkCodecPriv.h"
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 // startScanlineDecode will need to be called before decoding scanlines. 147 // startScanlineDecode will need to be called before decoding scanlines.
148 fCurrScanline = -1; 148 fCurrScanline = -1;
149 149
150 if (!fStream->rewind()) { 150 if (!fStream->rewind()) {
151 return false; 151 return false;
152 } 152 }
153 153
154 return this->onRewind(); 154 return this->onRewind();
155 } 155 }
156 156
157 #define CHECK_COLOR_TABLE \
158 if (kIndex_8_SkColorType == info.colorType()) { \
159 if (nullptr == ctable || nullptr == ctableCount) { \
160 return SkCodec::kInvalidParameters; \
161 } \
162 } else { \
163 if (ctableCount) { \
164 *ctableCount = 0; \
165 } \
166 ctableCount = nullptr; \
167 ctable = nullptr; \
168 }
169
170
157 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 171 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
158 const Options* options, SkPMColor ctable[], i nt* ctableCount) { 172 const Options* options, SkPMColor ctable[], i nt* ctableCount) {
159 if (kUnknown_SkColorType == info.colorType()) { 173 if (kUnknown_SkColorType == info.colorType()) {
160 return kInvalidConversion; 174 return kInvalidConversion;
161 } 175 }
162 if (nullptr == pixels) { 176 if (nullptr == pixels) {
163 return kInvalidParameters; 177 return kInvalidParameters;
164 } 178 }
165 if (rowBytes < info.minRowBytes()) { 179 if (rowBytes < info.minRowBytes()) {
166 return kInvalidParameters; 180 return kInvalidParameters;
167 } 181 }
168 182
169 if (kIndex_8_SkColorType == info.colorType()) { 183 CHECK_COLOR_TABLE;
170 if (nullptr == ctable || nullptr == ctableCount) {
171 return kInvalidParameters;
172 }
173 } else {
174 if (ctableCount) {
175 *ctableCount = 0;
176 }
177 ctableCount = nullptr;
178 ctable = nullptr;
179 }
180 184
181 if (!this->rewindIfNeeded()) { 185 if (!this->rewindIfNeeded()) {
182 return kCouldNotRewind; 186 return kCouldNotRewind;
183 } 187 }
184 188
185 // Default options. 189 // Default options.
186 Options optsStorage; 190 Options optsStorage;
187 if (nullptr == options) { 191 if (nullptr == options) {
188 options = &optsStorage; 192 options = &optsStorage;
189 } else if (options->fSubset) { 193 } else if (options->fSubset) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 rowsDecoded); 225 rowsDecoded);
222 } 226 }
223 227
224 return result; 228 return result;
225 } 229 }
226 230
227 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 231 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
228 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr); 232 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr);
229 } 233 }
230 234
231 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, 235 SkCodec::Result SkCodec::startIncrementalDecode(const SkImageInfo& info, void* p ixels, size_t rowBytes,
msarett 2016/05/24 13:14:07 nit: 100 chars
scroggo 2016/05/24 14:24:49 Done.
236 const SkCodec::Options* options, SkPMColor* ctable, int* ctableCount) {
237 fStartedIncrementalDecode = false;
238
239 if (kUnknown_SkColorType == info.colorType()) {
240 return kInvalidConversion;
241 }
242 if (nullptr == pixels) {
243 return kInvalidParameters;
244 }
245
246 // Ensure that valid color ptrs are passed in for kIndex8 color type
247 CHECK_COLOR_TABLE;
248
249 // FIXME: If the rows come after the rows of a previous incremental decode,
250 // we might be able to skip the rewind, but only the implementation knows
251 // that. (e.g. PNG will always need to rewind, since we called longjmp, but
252 // a bottom-up BMP could skip rewinding if the new rows are above the old
253 // rows.)
254 if (!this->rewindIfNeeded()) {
255 return kCouldNotRewind;
256 }
257
258 // Set options.
259 Options optsStorage;
260 if (nullptr == options) {
261 options = &optsStorage;
262 } else if (options->fSubset) {
263 SkIRect size = SkIRect::MakeSize(info.dimensions());
264 if (!size.contains(*options->fSubset)) {
265 return kInvalidParameters;
266 }
267
268 const int top = options->fSubset->top();
269 const int bottom = options->fSubset->bottom();
270 if (top < 0 || top >= info.height() || top >= bottom || bottom > info.he ight()) {
271 return kInvalidParameters;
272 }
273 }
274
275 if (!this->dimensionsSupported(info.dimensions())) {
276 return kInvalidScale;
277 }
278
279 fDstInfo = info;
280 fOptions = *options;
281
282 const Result result = this->onStartIncrementalDecode(info, pixels, rowBytes,
283 fOptions, ctable, ctableCount);
284 if (kSuccess == result) {
285 fStartedIncrementalDecode = true;
286 }
287 return result;
288 }
289
290
291 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& info,
232 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { 292 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) {
233 // Reset fCurrScanline in case of failure. 293 // Reset fCurrScanline in case of failure.
234 fCurrScanline = -1; 294 fCurrScanline = -1;
235 // Ensure that valid color ptrs are passed in for kIndex8 color type 295 // Ensure that valid color ptrs are passed in for kIndex8 color type
236 if (kIndex_8_SkColorType == dstInfo.colorType()) { 296 CHECK_COLOR_TABLE;
237 if (nullptr == ctable || nullptr == ctableCount) {
238 return SkCodec::kInvalidParameters;
239 }
240 } else {
241 if (ctableCount) {
242 *ctableCount = 0;
243 }
244 ctableCount = nullptr;
245 ctable = nullptr;
246 }
247 297
248 if (!this->rewindIfNeeded()) { 298 if (!this->rewindIfNeeded()) {
249 return kCouldNotRewind; 299 return kCouldNotRewind;
250 } 300 }
251 301
252 // Set options. 302 // Set options.
253 Options optsStorage; 303 Options optsStorage;
254 if (nullptr == options) { 304 if (nullptr == options) {
255 options = &optsStorage; 305 options = &optsStorage;
256 } else if (options->fSubset) { 306 } else if (options->fSubset) {
257 SkIRect size = SkIRect::MakeSize(dstInfo.dimensions()); 307 SkIRect size = SkIRect::MakeSize(info.dimensions());
258 if (!size.contains(*options->fSubset)) { 308 if (!size.contains(*options->fSubset)) {
259 return kInvalidInput; 309 return kInvalidInput;
260 } 310 }
261 311
262 // We only support subsetting in the x-dimension for scanline decoder. 312 // We only support subsetting in the x-dimension for scanline decoder.
263 // Subsetting in the y-dimension can be accomplished using skipScanlines (). 313 // Subsetting in the y-dimension can be accomplished using skipScanlines ().
264 if (options->fSubset->top() != 0 || options->fSubset->height() != dstInf o.height()) { 314 if (options->fSubset->top() != 0 || options->fSubset->height() != info.h eight()) {
265 return kInvalidInput; 315 return kInvalidInput;
266 } 316 }
267 } 317 }
268 318
269 // FIXME: Support subsets somehow? 319 // FIXME: Support subsets somehow?
270 if (!this->dimensionsSupported(dstInfo.dimensions())) { 320 if (!this->dimensionsSupported(info.dimensions())) {
271 return kInvalidScale; 321 return kInvalidScale;
272 } 322 }
273 323
274 const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount); 324 const Result result = this->onStartScanlineDecode(info, *options, ctable, ct ableCount);
275 if (result != SkCodec::kSuccess) { 325 if (result != SkCodec::kSuccess) {
276 return result; 326 return result;
277 } 327 }
278 328
279 fCurrScanline = 0; 329 fCurrScanline = 0;
280 fDstInfo = dstInfo; 330 fDstInfo = info;
281 fOptions = *options; 331 fOptions = *options;
282 return kSuccess; 332 return kSuccess;
283 } 333 }
284 334
285 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) { 335 #undef CHECK_COLOR_TABLE
286 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr); 336
337 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& info) {
338 return this->startScanlineDecode(info, nullptr, nullptr, nullptr);
287 } 339 }
288 340
289 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) { 341 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) {
290 if (fCurrScanline < 0) { 342 if (fCurrScanline < 0) {
291 return 0; 343 return 0;
292 } 344 }
293 345
294 SkASSERT(!fDstInfo.isEmpty()); 346 SkASSERT(!fDstInfo.isEmpty());
295 if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) { 347 if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) {
296 return 0; 348 return 0;
(...skipping 27 matching lines...) Expand all
324 } 376 }
325 377
326 int SkCodec::outputScanline(int inputScanline) const { 378 int SkCodec::outputScanline(int inputScanline) const {
327 SkASSERT(0 <= inputScanline && inputScanline < this->getInfo().height()); 379 SkASSERT(0 <= inputScanline && inputScanline < this->getInfo().height());
328 return this->onOutputScanline(inputScanline); 380 return this->onOutputScanline(inputScanline);
329 } 381 }
330 382
331 int SkCodec::onOutputScanline(int inputScanline) const { 383 int SkCodec::onOutputScanline(int inputScanline) const {
332 switch (this->getScanlineOrder()) { 384 switch (this->getScanlineOrder()) {
333 case kTopDown_SkScanlineOrder: 385 case kTopDown_SkScanlineOrder:
334 case kNone_SkScanlineOrder:
335 return inputScanline; 386 return inputScanline;
336 case kBottomUp_SkScanlineOrder: 387 case kBottomUp_SkScanlineOrder:
337 return this->getInfo().height() - inputScanline - 1; 388 return this->getInfo().height() - inputScanline - 1;
338 default: 389 default:
339 // This case indicates an interlaced gif and is implemented by SkGif Codec. 390 // This case indicates an interlaced gif and is implemented by SkGif Codec.
340 SkASSERT(false); 391 SkASSERT(false);
341 return 0; 392 return 0;
342 } 393 }
343 } 394 }
344 395
(...skipping 13 matching lines...) Expand all
358 const uint32_t fillValue = this->getFillValue(info.colorType()); 409 const uint32_t fillValue = this->getFillValue(info.colorType());
359 const int linesRemaining = linesRequested - linesDecoded; 410 const int linesRemaining = linesRequested - linesDecoded;
360 SkSampler* sampler = this->getSampler(false); 411 SkSampler* sampler = this->getSampler(false);
361 412
362 int fillWidth = info.width(); 413 int fillWidth = info.width();
363 if (fOptions.fSubset) { 414 if (fOptions.fSubset) {
364 fillWidth = fOptions.fSubset->width(); 415 fillWidth = fOptions.fSubset->width();
365 } 416 }
366 417
367 switch (this->getScanlineOrder()) { 418 switch (this->getScanlineOrder()) {
368 case kTopDown_SkScanlineOrder: 419 case kTopDown_SkScanlineOrder: {
369 case kNone_SkScanlineOrder: {
370 const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining); 420 const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining);
371 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes); 421 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes);
372 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ; 422 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ;
373 break; 423 break;
374 } 424 }
375 case kBottomUp_SkScanlineOrder: { 425 case kBottomUp_SkScanlineOrder: {
376 fillDst = dst; 426 fillDst = dst;
377 const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining); 427 const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining);
378 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ; 428 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ;
379 break; 429 break;
380 } 430 }
381 case kOutOfOrder_SkScanlineOrder: { 431 case kOutOfOrder_SkScanlineOrder: {
382 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested); 432 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested);
383 const SkImageInfo fillInfo = info.makeWH(fillWidth, 1); 433 const SkImageInfo fillInfo = info.makeWH(fillWidth, 1);
384 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { 434 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) {
385 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes); 435 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes);
386 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler); 436 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler);
387 } 437 }
388 break; 438 break;
389 } 439 }
390 } 440 }
391 } 441 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698