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

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

Issue 1332053002: Fill incomplete images in SkCodec parent class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Use aligned memory in swizzler test 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
« no previous file with comments | « src/codec/SkBmpStandardCodec.cpp ('k') | src/codec/SkCodecPriv.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 "SkBmpCodec.h" 8 #include "SkBmpCodec.h"
9 #include "SkCodec.h" 9 #include "SkCodec.h"
10 #include "SkData.h" 10 #include "SkData.h"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 return kUnimplemented; 160 return kUnimplemented;
161 } 161 }
162 } 162 }
163 163
164 // FIXME: Support subsets somehow? Note that this works for SkWebpCodec 164 // FIXME: Support subsets somehow? Note that this works for SkWebpCodec
165 // because it supports arbitrary scaling/subset combinations. 165 // because it supports arbitrary scaling/subset combinations.
166 if (!this->dimensionsSupported(info.dimensions())) { 166 if (!this->dimensionsSupported(info.dimensions())) {
167 return kInvalidScale; 167 return kInvalidScale;
168 } 168 }
169 169
170 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount); 170 // On an incomplete decode, the subclass will specify the number of scanline s that it decoded
171 // successfully.
172 int rowsDecoded = 0;
173 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount,
174 &rowsDecoded);
171 175
172 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { 176 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) {
173 SkASSERT(*ctableCount >= 0 && *ctableCount <= 256); 177 SkASSERT(*ctableCount >= 0 && *ctableCount <= 256);
174 } 178 }
179
180 // A return value of kIncompleteInput indicates a truncated image stream.
181 // In this case, we will fill any uninitialized memory with a default value.
182 // Some subclasses will take care of filling any uninitialized memory on
183 // their own. They indicate that all of the memory has been filled by
184 // setting rowsDecoded equal to the height.
185 if (kIncompleteInput == result && rowsDecoded != info.height()) {
186 this->fillIncompleteImage(info, pixels, rowBytes, options->fZeroInitiali zed, info.height(),
187 rowsDecoded);
188 }
189
175 return result; 190 return result;
176 } 191 }
177 192
178 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 193 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
179 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr); 194 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr);
180 } 195 }
181 196
182 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, 197 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo,
183 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { 198 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) {
184 // Reset fCurrScanline in case of failure. 199 // Reset fCurrScanline in case of failure.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 fCurrScanline = 0; 241 fCurrScanline = 0;
227 fDstInfo = dstInfo; 242 fDstInfo = dstInfo;
228 fOptions = *options; 243 fOptions = *options;
229 return kSuccess; 244 return kSuccess;
230 } 245 }
231 246
232 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) { 247 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) {
233 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr); 248 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr);
234 } 249 }
235 250
236 SkCodec::Result SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes ) { 251 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) {
237 if (fCurrScanline < 0) { 252 if (fCurrScanline < 0) {
238 return kScanlineDecodingNotStarted; 253 return 0;
239 } 254 }
240 255
241 SkASSERT(!fDstInfo.isEmpty()); 256 SkASSERT(!fDstInfo.isEmpty());
242
243 if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) { 257 if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) {
244 return kInvalidParameters; 258 return 0;
245 } 259 }
246 260
247 const Result result = this->onGetScanlines(dst, countLines, rowBytes); 261 const int linesDecoded = this->onGetScanlines(dst, countLines, rowBytes);
262 if (linesDecoded < countLines) {
263 this->fillIncompleteImage(this->dstInfo(), dst, rowBytes, this->options( ).fZeroInitialized,
264 countLines, linesDecoded);
265 }
266 fCurrScanline += countLines;
267 return linesDecoded;
268 }
269
270 bool SkCodec::skipScanlines(int countLines) {
271 if (fCurrScanline < 0) {
272 return false;
273 }
274
275 SkASSERT(!fDstInfo.isEmpty());
276 if (countLines < 0 || fCurrScanline + countLines > fDstInfo.height()) {
277 // Arguably, we could just skip the scanlines which are remaining,
278 // and return true. We choose to return false so the client
279 // can catch their bug.
280 return false;
281 }
282
283 bool result = this->onSkipScanlines(countLines);
248 fCurrScanline += countLines; 284 fCurrScanline += countLines;
249 return result; 285 return result;
250 } 286 }
251 287
252 SkCodec::Result SkCodec::skipScanlines(int countLines) { 288 int SkCodec::outputScanline(int inputScanline) const {
253 if (fCurrScanline < 0) { 289 SkASSERT(0 <= inputScanline && inputScanline < this->getInfo().height());
254 return kScanlineDecodingNotStarted; 290 return this->onOutputScanline(inputScanline);
291 }
292
293 int SkCodec::onOutputScanline(int inputScanline) const {
294 switch (this->getScanlineOrder()) {
295 case kTopDown_SkScanlineOrder:
296 case kNone_SkScanlineOrder:
297 return inputScanline;
298 case kBottomUp_SkScanlineOrder:
299 return this->getInfo().height() - inputScanline - 1;
300 default:
301 // This case indicates an interlaced gif and is implemented by SkGif Codec.
302 SkASSERT(false);
303 return 0;
255 } 304 }
305 }
256 306
257 SkASSERT(!fDstInfo.isEmpty()); 307 static void fill_proc(const SkImageInfo& info, void* dst, size_t rowBytes,
258 if (fCurrScanline + countLines > fDstInfo.height()) { 308 uint32_t colorOrIndex, SkCodec::ZeroInitialized zeroInit, SkSampler* sam pler) {
259 // Arguably, we could just skip the scanlines which are remaining, 309 if (sampler) {
260 // and return kSuccess. We choose to return invalid so the client 310 sampler->fill(info, dst, rowBytes, colorOrIndex, zeroInit);
261 // can catch their bug. 311 } else {
262 return SkCodec::kInvalidParameters; 312 SkSampler::Fill(info, dst, rowBytes, colorOrIndex, zeroInit);
263 } 313 }
314 }
264 315
265 const Result result = this->onSkipScanlines(countLines); 316 void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t row Bytes,
266 fCurrScanline += countLines; 317 ZeroInitialized zeroInit, int linesRequested, int linesDecoded) {
267 return result; 318
319 void* fillDst;
320 const uint32_t fillValue = this->getFillValue(info.colorType(), info.alphaTy pe());
321 const int linesRemaining = linesRequested - linesDecoded;
322 SkSampler* sampler = this->getSampler(false);
323
324 switch (this->getScanlineOrder()) {
325 case kTopDown_SkScanlineOrder:
326 case kNone_SkScanlineOrder: {
327 const SkImageInfo fillInfo = info.makeWH(info.width(), linesRemainin g);
328 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes);
329 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ;
330 break;
331 }
332 case kBottomUp_SkScanlineOrder: {
333 fillDst = dst;
334 const SkImageInfo fillInfo = info.makeWH(info.width(), linesRemainin g);
335 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ;
336 break;
337 }
338 case kOutOfOrder_SkScanlineOrder: {
339 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested);
340 const SkImageInfo fillInfo = info.makeWH(info.width(), 1);
341 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) {
342 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes);
343 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler);
344 }
345 break;
346 }
347 }
268 } 348 }
OLDNEW
« no previous file with comments | « src/codec/SkBmpStandardCodec.cpp ('k') | src/codec/SkCodecPriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698