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

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: Forgot to add SkSampler.cpp 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 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.colorType(), info.alphaType(), pixels, ro wBytes,
187 options->fZeroInitialized, info.height(), 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 uint32_t linesDecoded = this->onGetScanlines(dst, countLines, rowBytes );
248 fCurrScanline += countLines; 262 if (linesDecoded < countLines) {
249 return result; 263 this->fillIncompleteImage(this->dstInfo().colorType(), this->dstInfo().a lphaType(), dst,
264 rowBytes, this->options().fZeroInitialized, countLines, linesDec oded);
265 }
266 fCurrScanline += linesDecoded;
267 return linesDecoded;
250 } 268 }
251 269
252 SkCodec::Result SkCodec::skipScanlines(int countLines) { 270 bool SkCodec::skipScanlines(int countLines) {
253 if (fCurrScanline < 0) { 271 if (fCurrScanline < 0) {
254 return kScanlineDecodingNotStarted; 272 return false;
255 } 273 }
256 274
257 SkASSERT(!fDstInfo.isEmpty()); 275 SkASSERT(!fDstInfo.isEmpty());
258 if (fCurrScanline + countLines > fDstInfo.height()) { 276 if (countLines < 0 || fCurrScanline + countLines > fDstInfo.height()) {
259 // Arguably, we could just skip the scanlines which are remaining, 277 // Arguably, we could just skip the scanlines which are remaining,
260 // and return kSuccess. We choose to return invalid so the client 278 // and return true. We choose to return false so the client
261 // can catch their bug. 279 // can catch their bug.
262 return SkCodec::kInvalidParameters; 280 return false;
263 } 281 }
264 282
265 const Result result = this->onSkipScanlines(countLines); 283 if (!this->onSkipScanlines(countLines)) {
284 return false;
285 }
266 fCurrScanline += countLines; 286 fCurrScanline += countLines;
267 return result; 287 return true;
268 } 288 }
289
290 int SkCodec::outputScanline(int inputScanline) const {
291 SkASSERT(0 <= inputScanline && inputScanline < this->getInfo().height());
292 return this->onOutputScanline(inputScanline);
293 }
294
295 int SkCodec::onOutputScanline(int inputScanline) const {
296 SkASSERT(0 <= inputScanline && inputScanline < this->getInfo().height());
297 switch (this->getScanlineOrder()) {
298 case kTopDown_SkScanlineOrder:
299 case kNone_SkScanlineOrder:
300 return inputScanline;
301 case kBottomUp_SkScanlineOrder:
302 return this->getInfo().height() - inputScanline - 1;
303 case kOutOfOrder_SkScanlineOrder:
304 // This case indicates an interlaced gif and is implemented by SkGif Codec.
305 SkASSERT(false);
306 return 0;
307 }
308 }
309
310 void SkCodec::fillIncompleteImage(SkColorType colorType, SkAlphaType alphaType, void* dst,
311 size_t rowBytes, ZeroInitialized zeroInit, int linesRequested, int lines Decoded) {
312 void* fillDst;
313 SkSampler* sampler = this->getSampler();
314 SkASSERT(nullptr != sampler);
315 const uint32_t fillValue = this->getFillValue(colorType, alphaType);
316 const int linesRemaining = linesRequested - linesDecoded;
317 switch (this->getScanlineOrder()) {
318 case kTopDown_SkScanlineOrder:
319 case kNone_SkScanlineOrder:
320 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes);
321 sampler->fill(fillDst, colorType, linesRemaining, rowBytes, fillValu e, zeroInit);
322 break;
323 case kBottomUp_SkScanlineOrder:
324 fillDst = dst;
325 sampler->fill(fillDst, colorType, linesRemaining, rowBytes, fillValu e, zeroInit);
326 break;
327 case kOutOfOrder_SkScanlineOrder:
328 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested);
329 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) {
330 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes);
331 sampler->fill(fillDst, colorType, 1, rowBytes, fillValue, zeroIn it);
332 }
333 break;
334 }
335 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698