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

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

Issue 1321433002: Add subsetting to SkScaledCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@gif-scan
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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 return NewFromStream(new SkMemoryStream(data)); 75 return NewFromStream(new SkMemoryStream(data));
76 } 76 }
77 77
78 SkCodec::SkCodec(const SkImageInfo& info, SkStream* stream) 78 SkCodec::SkCodec(const SkImageInfo& info, SkStream* stream)
79 : fSrcInfo(info) 79 : fSrcInfo(info)
80 , fStream(stream) 80 , fStream(stream)
81 , fNeedsRewind(false) 81 , fNeedsRewind(false)
82 , fDstInfo() 82 , fDstInfo()
83 , fOptions() 83 , fOptions()
84 , fCurrScanline(-1) 84 , fCurrScanline(-1)
85 , fSubsetWidth(0)
85 {} 86 {}
86 87
87 SkCodec::~SkCodec() {} 88 SkCodec::~SkCodec() {}
88 89
89 bool SkCodec::rewindIfNeeded() { 90 bool SkCodec::rewindIfNeeded() {
90 if (!fStream) { 91 if (!fStream) {
91 // Some codecs do not have a stream, but they hold others that do. They 92 // Some codecs do not have a stream, but they hold others that do. They
92 // must handle rewinding themselves. 93 // must handle rewinding themselves.
93 return true; 94 return true;
94 } 95 }
95 96
96 // Store the value of fNeedsRewind so we can update it. Next read will 97 // Store the value of fNeedsRewind so we can update it. Next read will
97 // require a rewind. 98 // require a rewind.
98 const bool needsRewind = fNeedsRewind; 99 const bool needsRewind = fNeedsRewind;
99 fNeedsRewind = true; 100 fNeedsRewind = true;
100 if (!needsRewind) { 101 if (!needsRewind) {
101 return true; 102 return true;
102 } 103 }
103 104
104 // startScanlineDecode will need to be called before decoding scanlines. 105 // startScanlineDecode will need to be called before decoding scanlines.
105 fCurrScanline = -1; 106 fCurrScanline = -1;
107 fSubsetWidth = 0;
106 108
107 if (!fStream->rewind()) { 109 if (!fStream->rewind()) {
108 return false; 110 return false;
109 } 111 }
110 112
111 return this->onRewind(); 113 return this->onRewind();
112 } 114 }
113 115
116 SkISize SkCodec::getScaledDimensions(float desiredScale) const {
117 // Negative and zero scales are errors.
118 SkASSERT(desiredScale > 0.0f);
119 if (desiredScale <= 0.0f) {
120 return SkISize::Make(0, 0);
121 }
122
123 // Upscaling is not supported. Return the original size if the client
124 // requests an upscale.
125 if (desiredScale >= 1.0f) {
126 return this->getInfo().dimensions();
127 }
128 return this->onGetScaledDimensions(desiredScale);
129 }
130
131 bool SkCodec::getValidSubset(SkIRect* desiredSubset) const {
132 if (!desiredSubset) {
133 return false;
134 }
135
136 if (!is_valid_subset(desiredSubset, this->getInfo().dimensions())) {
137 return false;
138 }
139
140 return this->onGetValidSubset(desiredSubset);
141 }
142
143 bool SkCodec::getScaledSubsetDimensions(float desiredScale, Options* options) co nst {
144 // Negative and zero scales are errors.
145 SkASSERT(desiredScale > 0.0f);
146 if (desiredScale <= 0.0f) {
147 return false;
148 }
149
150 // Upscaling is not supported. We will suggest a full decode if
151 // upscaling is requested.
152 if (desiredScale >= 1.0f) {
153 desiredScale = 1.0f;
154 }
155
156 // If the client is not requesting a subset decode,
157 // getScaledDimensions() should be used.
158 if (nullptr == options->fSubset) {
159 return false;
160 }
161
162 if (!is_valid_subset(options->fSubset, this->getInfo().dimensions())) {
163 return false;
164 }
165
166 return this->onGetScaledSubsetDimensions(desiredScale, options);
167 }
168
114 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 169 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
115 const Options* options, SkPMColor ctable[], i nt* ctableCount) { 170 const Options* options, SkPMColor ctable[], i nt* ctableCount) {
116 if (kUnknown_SkColorType == info.colorType()) { 171 if (kUnknown_SkColorType == info.colorType()) {
117 return kInvalidConversion; 172 return kInvalidConversion;
118 } 173 }
119 if (nullptr == pixels) { 174 if (nullptr == pixels) {
120 return kInvalidParameters; 175 return kInvalidParameters;
121 } 176 }
122 if (rowBytes < info.minRowBytes()) { 177 if (rowBytes < info.minRowBytes()) {
123 return kInvalidParameters; 178 return kInvalidParameters;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 } 230 }
176 231
177 return result; 232 return result;
178 } 233 }
179 234
180 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 235 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
181 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr); 236 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr);
182 } 237 }
183 238
184 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, 239 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo,
185 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { 240 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount, i nt subsetLeft,
241 int subsetWidth) {
186 // Reset fCurrScanline in case of failure. 242 // Reset fCurrScanline in case of failure.
187 fCurrScanline = -1; 243 fCurrScanline = -1;
244
245 // Ensure that the subset parameters are valid
246 if (0 > subsetLeft || subsetLeft >= dstInfo.width() || 0 > subsetWidth ||
scroggo 2015/10/02 18:27:03 nit: I would lean towards separating these out log
247 subsetLeft + subsetWidth > dstInfo.width()) {
248 return kInvalidParameters;
249 }
250
188 // Ensure that valid color ptrs are passed in for kIndex8 color type 251 // Ensure that valid color ptrs are passed in for kIndex8 color type
189 if (kIndex_8_SkColorType == dstInfo.colorType()) { 252 if (kIndex_8_SkColorType == dstInfo.colorType()) {
190 if (nullptr == ctable || nullptr == ctableCount) { 253 if (nullptr == ctable || nullptr == ctableCount) {
191 return SkCodec::kInvalidParameters; 254 return SkCodec::kInvalidParameters;
192 } 255 }
193 } else { 256 } else {
194 if (ctableCount) { 257 if (ctableCount) {
195 *ctableCount = 0; 258 *ctableCount = 0;
196 } 259 }
197 ctableCount = nullptr; 260 ctableCount = nullptr;
198 ctable = nullptr; 261 ctable = nullptr;
199 } 262 }
200 263
201 if (!this->rewindIfNeeded()) { 264 if (!this->rewindIfNeeded()) {
202 return kCouldNotRewind; 265 return kCouldNotRewind;
203 } 266 }
204 267
205 // Set options. 268 // Set options.
206 Options optsStorage; 269 Options optsStorage;
207 if (nullptr == options) { 270 if (nullptr == options) {
208 options = &optsStorage; 271 options = &optsStorage;
209 } 272 }
210 273
211 const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount); 274 const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount,
275 subsetLeft, subsetWidth);
212 if (result != SkCodec::kSuccess) { 276 if (result != SkCodec::kSuccess) {
213 return result; 277 return result;
214 } 278 }
215 279
216 fCurrScanline = 0; 280 fCurrScanline = 0;
217 fDstInfo = dstInfo; 281 fDstInfo = dstInfo;
218 fOptions = *options; 282 fOptions = *options;
283 fSubsetWidth = subsetWidth;
219 return kSuccess; 284 return kSuccess;
220 } 285 }
221 286
287 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo,
288 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) {
289 return this->startScanlineDecode(dstInfo, options, ctable, ctableCount, 0, d stInfo.width());
290 }
291
222 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) { 292 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) {
223 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr); 293 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr, 0, dstI nfo.width());
224 } 294 }
225 295
226 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) { 296 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) {
227 if (fCurrScanline < 0) { 297 if (fCurrScanline < 0) {
228 return 0; 298 return 0;
229 } 299 }
230 300
231 SkASSERT(!fDstInfo.isEmpty()); 301 SkASSERT(!fDstInfo.isEmpty());
232 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 302 if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) {
233 || fCurrScanline + countLines > fDstInfo.height()) {
234 return 0; 303 return 0;
235 } 304 }
236 305
237 const uint32_t linesDecoded = this->onGetScanlines(dst, countLines, rowBytes ); 306 const uint32_t linesDecoded = this->onGetScanlines(dst, countLines, rowBytes );
238 if (linesDecoded < countLines) { 307 if (linesDecoded < countLines) {
239 this->fillIncompleteImage(this->dstInfo(), dst, rowBytes, this->options( ).fZeroInitialized, 308 this->fillIncompleteImage(this->dstInfo(), dst, rowBytes, this->options( ).fZeroInitialized,
240 countLines, linesDecoded); 309 countLines, linesDecoded);
241 } 310 }
242 fCurrScanline += linesDecoded; 311 fCurrScanline += linesDecoded;
243 return linesDecoded; 312 return linesDecoded;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 return get_output_row_interlaced(inputScanline, this->getInfo().heig ht()); 344 return get_output_row_interlaced(inputScanline, this->getInfo().heig ht());
276 } 345 }
277 } 346 }
278 347
279 void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t row Bytes, 348 void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t row Bytes,
280 ZeroInitialized zeroInit, int linesRequested, int linesDecoded) { 349 ZeroInitialized zeroInit, int linesRequested, int linesDecoded) {
281 void* fillDst; 350 void* fillDst;
282 SkImageInfo fillInfo; 351 SkImageInfo fillInfo;
283 const uint32_t fillValue = this->getFillValue(info.colorType(), info.alphaTy pe()); 352 const uint32_t fillValue = this->getFillValue(info.colorType(), info.alphaTy pe());
284 const int linesRemaining = linesRequested - linesDecoded; 353 const int linesRemaining = linesRequested - linesDecoded;
354 const int fillWidth = fSubsetWidth ? fSubsetWidth : info.width();
285 switch (this->getScanlineOrder()) { 355 switch (this->getScanlineOrder()) {
286 case kTopDown_SkScanlineOrder: 356 case kTopDown_SkScanlineOrder:
287 case kNone_SkScanlineOrder: 357 case kNone_SkScanlineOrder:
288 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes); 358 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes);
289 fillInfo = info.makeWH(info.width(), linesRemaining); 359 fillInfo = info.makeWH(fillWidth, linesRemaining);
290 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroInit); 360 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroInit);
291 break; 361 break;
292 case kBottomUp_SkScanlineOrder: 362 case kBottomUp_SkScanlineOrder:
293 fillDst = dst; 363 fillDst = dst;
294 fillInfo = info.makeWH(info.width(), linesRemaining); 364 fillInfo = info.makeWH(fillWidth, linesRemaining);
295 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroInit); 365 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroInit);
296 break; 366 break;
297 case kOutOfOrder_SkScanlineOrder: 367 case kOutOfOrder_SkScanlineOrder:
298 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested); 368 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested);
299 fillInfo = info.makeWH(info.width(), 1); 369 fillInfo = info.makeWH(fillWidth, 1);
300 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { 370 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) {
301 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes); 371 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes);
302 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroIni t); 372 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroIni t);
303 } 373 }
304 break; 374 break;
305 } 375 }
306 } 376 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698