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

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: Rebase on merged SkCodec and SkScanlineDecoder 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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 146
147 if (!this->rewindIfNeeded()) { 147 if (!this->rewindIfNeeded()) {
148 return kCouldNotRewind; 148 return kCouldNotRewind;
149 } 149 }
150 150
151 // Default options. 151 // Default options.
152 Options optsStorage; 152 Options optsStorage;
153 if (nullptr == options) { 153 if (nullptr == options) {
154 options = &optsStorage; 154 options = &optsStorage;
155 } 155 }
156 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount); 156
157 // On an incomplete decode, the subclass will specify the number of scanline s that it decoded
158 // successfully.
159 int rowsDecoded = 0;
160 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount,
161 &rowsDecoded);
157 162
158 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { 163 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) {
159 SkASSERT(*ctableCount >= 0 && *ctableCount <= 256); 164 SkASSERT(*ctableCount >= 0 && *ctableCount <= 256);
160 } 165 }
166
167 // A return value of kIncompleteInput indicates a truncated image stream.
168 // In this case, we will fill any uninitialized memory with a default value.
169 // Some subclasses will take care of filling any uninitialized memory on
170 // their own. They indicate that all of the memory has been filled by
171 // setting rowsDecoded equal to the height.
172 if (kIncompleteInput == result && rowsDecoded != info.height()) {
173 this->fillIncompleteImage(info, pixels, rowBytes, options->fZeroInitiali zed,
174 info.height(), rowsDecoded);
175 }
176
161 return result; 177 return result;
162 } 178 }
163 179
164 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 180 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
165 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr); 181 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr);
166 } 182 }
167 183
168 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, 184 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo,
169 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { 185 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) {
170 // Reset fCurrScanline in case of failure. 186 // Reset fCurrScanline in case of failure.
(...skipping 29 matching lines...) Expand all
200 fCurrScanline = 0; 216 fCurrScanline = 0;
201 fDstInfo = dstInfo; 217 fDstInfo = dstInfo;
202 fOptions = *options; 218 fOptions = *options;
203 return kSuccess; 219 return kSuccess;
204 } 220 }
205 221
206 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) { 222 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) {
207 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr); 223 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr);
208 } 224 }
209 225
210 SkCodec::Result SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes ) { 226 uint32_t SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) {
scroggo 2015/10/01 14:48:31 If we wanted to, we could make getScanlines return
msarett 2015/10/01 18:14:14 It's fair to point out that this API change is no
211 if (fCurrScanline < 0) { 227 if (fCurrScanline < 0) {
212 return kScanlineDecodingNotStarted; 228 return 0;
scroggo 2015/10/01 14:48:31 Do we still need this enum value?
msarett 2015/10/01 18:14:14 Looks like we don't.
213 } 229 }
214 230
215 SkASSERT(!fDstInfo.isEmpty()); 231 SkASSERT(!fDstInfo.isEmpty());
216 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 232 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0
217 || fCurrScanline + countLines > fDstInfo.height()) { 233 || fCurrScanline + countLines > fDstInfo.height()) {
218 return kInvalidParameters; 234 return 0;
219 } 235 }
220 236
221 const Result result = this->onGetScanlines(dst, countLines, rowBytes); 237 const uint32_t linesDecoded = this->onGetScanlines(dst, countLines, rowBytes );
222 fCurrScanline += countLines; 238 if (linesDecoded < countLines) {
223 return result; 239 this->fillIncompleteImage(this->dstInfo(), dst, rowBytes, this->options( ).fZeroInitialized,
240 countLines, linesDecoded);
241 }
242 fCurrScanline += linesDecoded;
243 return linesDecoded;
224 } 244 }
225 245
226 SkCodec::Result SkCodec::skipScanlines(int countLines) { 246 bool SkCodec::skipScanlines(int countLines) {
227 if (fCurrScanline < 0) { 247 if (fCurrScanline < 0) {
228 return kScanlineDecodingNotStarted; 248 return false;
229 } 249 }
230 250
231 SkASSERT(!fDstInfo.isEmpty()); 251 SkASSERT(!fDstInfo.isEmpty());
232 if (fCurrScanline + countLines > fDstInfo.height()) { 252 if (fCurrScanline + countLines > fDstInfo.height()) {
233 // Arguably, we could just skip the scanlines which are remaining, 253 // Arguably, we could just skip the scanlines which are remaining,
234 // and return kSuccess. We choose to return invalid so the client 254 // and return true. We choose to return false so the client
235 // can catch their bug. 255 // can catch their bug.
236 return SkCodec::kInvalidParameters; 256 return false;
237 } 257 }
238 258
239 const Result result = this->onSkipScanlines(countLines); 259 if (!this->onSkipScanlines(countLines)) {
260 return false;
261 }
240 fCurrScanline += countLines; 262 fCurrScanline += countLines;
241 return result; 263 return true;
242 } 264 }
265
266 int SkCodec::nextScanline(int srcY) const {
267 SkASSERT(0 <= srcY && srcY < this->getInfo().height());
268 switch (this->getScanlineOrder()) {
269 case kTopDown_SkScanlineOrder:
270 case kNone_SkScanlineOrder:
271 return srcY;
272 case kBottomUp_SkScanlineOrder:
273 return this->dstInfo().height() - srcY - 1;
274 case kOutOfOrder_SkScanlineOrder:
275 return get_output_row_interlaced(srcY, this->getInfo().height());
scroggo 2015/10/01 14:48:31 It's odd to me that kBottomUp takes the dstInfo in
msarett 2015/10/01 18:14:14 We can use getInfo() in both places. This is prob
276 }
277 }
278
279 void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t row Bytes,
280 ZeroInitialized zeroInit, int linesRequested, int linesDecoded) {
281 void* fillDst;
282 SkImageInfo fillInfo;
283 const uint32_t fillValue = this->getFillValue(info.colorType(), info.alphaTy pe());
284 const int linesRemaining = linesRequested - linesDecoded;
285 switch (this->getScanlineOrder()) {
286 case kTopDown_SkScanlineOrder:
287 case kNone_SkScanlineOrder:
288 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes);
289 fillInfo = info.makeWH(info.width(), linesRemaining);
290 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroInit);
291 break;
292 case kBottomUp_SkScanlineOrder:
293 fillDst = dst;
294 fillInfo = info.makeWH(info.width(), linesRemaining);
295 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroInit);
296 break;
297 case kOutOfOrder_SkScanlineOrder:
298 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested);
scroggo 2015/10/01 14:48:31 Do you need the second half? It seems like if it's
msarett 2015/10/01 18:14:13 I don't understand. linesRequested can be 1 or th
scroggo 2015/10/01 20:48:57 Oh, I think I was confused. This is just to discou
msarett 2015/10/01 22:34:51 Yes!
299 fillInfo = info.makeWH(info.width(), 1);
300 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) {
301 fillDst = SkTAddOffset<void>(dst, this->nextScanline(srcY) * row Bytes);
302 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroIni t);
303 }
304 break;
305 }
306 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698