OLD | NEW |
---|---|
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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
104 // startScanlineDecode will need to be called before decoding scanlines. | 104 // startScanlineDecode will need to be called before decoding scanlines. |
105 fCurrScanline = -1; | 105 fCurrScanline = -1; |
106 | 106 |
107 if (!fStream->rewind()) { | 107 if (!fStream->rewind()) { |
108 return false; | 108 return false; |
109 } | 109 } |
110 | 110 |
111 return this->onRewind(); | 111 return this->onRewind(); |
112 } | 112 } |
113 | 113 |
114 bool SkCodec::getScaledSubsetDimensions(float desiredScale, const Options& optio ns) const { | |
115 // Negative and zero scales are errors. | |
116 SkASSERT(desiredScale > 0.0f); | |
117 if (desiredScale <= 0.0f) { | |
118 return false; | |
119 } | |
120 | |
121 // Upscaling is not supported. We will suggest a full decode if | |
122 // upscaling is requested. | |
123 if (desiredScale >= 1.0f) { | |
124 desiredScale = 1.0f; | |
125 } | |
126 | |
127 // If the client is not requesting a subset decode, | |
128 // getScaledDimensions() should be used. | |
129 if (!options.fSubset || !options.fScaledDimensions || !options.fScaledSubset ) { | |
130 return false; | |
131 } | |
132 | |
133 if (!is_valid_subset(*options.fSubset, this->getInfo().dimensions())) { | |
134 return false; | |
135 } | |
136 | |
137 return this->onGetScaledSubsetDimensions(desiredScale, options); | |
138 } | |
139 | |
140 bool SkCodec::subsetSupported(const SkIRect& subset, bool isScanlineDecode) { | |
141 if (!is_valid_subset(subset, this->getInfo().dimensions())) { | |
scroggo
2015/10/12 20:47:07
nit: fInfo.dimensions()
No need to call the acces
| |
142 return false; | |
143 } | |
144 | |
145 return this->onSubsetSupported(subset, isScanlineDecode); | |
146 } | |
147 | |
148 bool SkCodec::onSubsetSupported(const SkIRect& subset, bool isScanlineDecode) { | |
149 if (!isScanlineDecode) { | |
150 return false; | |
151 } | |
152 | |
153 // We support subsetting in the x-dimension for the scanline decoder. | |
154 // Subsetting in the y-dimension can be accomplished using skipScanlines(). | |
155 return subset.top() == 0 && subset.height() == this->getInfo().height(); | |
156 } | |
157 | |
158 bool SkCodec::scaledSubsetSupported(const SkISize& dstSize, const Options& optio ns, | |
159 bool isScanlineDecode) { | |
160 SkIRect* subset = options.fSubset; | |
161 | |
162 // If there is no subsetting, we simply check if we can scale to dstSize | |
163 if (!subset) { | |
164 return this->dimensionsSupported(dstSize); | |
165 } | |
166 | |
167 SkISize* scaledDimensions = options.fScaledDimensions; | |
168 SkIRect* scaledSubset = options.fScaledSubset; | |
169 if (!scaledDimensions && !scaledSubset) { | |
170 // If there is no scaling, check if we support the subset requested | |
171 return this->subsetSupported(*subset, isScanlineDecode); | |
172 } | |
173 | |
174 if (!scaledDimensions || !scaledSubset) { | |
175 // Both scaledDimensions and scaledSubset must be non-NULL to perform | |
176 // a scaled subset decode. | |
177 return false; | |
178 } | |
179 | |
180 if (!is_valid_subset(*scaledSubset, *scaledDimensions)) { | |
181 return false; | |
182 } | |
183 | |
184 return this->onScaledSubsetSupported(options, isScanlineDecode); | |
185 } | |
186 | |
187 bool SkCodec::onScaledSubsetSupported(const Options& options, bool isScanlineDec ode) { | |
188 if (!isScanlineDecode) { | |
189 return false; | |
190 } | |
191 | |
192 if (!this->dimensionsSupported(*options.fScaledDimensions)) { | |
193 return false; | |
194 } | |
195 | |
196 // We support subsetting in the x-dimension for the scanline decoder. | |
197 // Subsetting in the y-dimension can be accomplished using skipScanlines(). | |
198 return options.fSubset->top() == 0 && | |
199 options.fSubset->height() == options.fScaledDimensions->height(); | |
200 } | |
201 | |
114 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, | 202 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, |
115 const Options* options, SkPMColor ctable[], i nt* ctableCount) { | 203 const Options* options, SkPMColor ctable[], i nt* ctableCount) { |
116 if (kUnknown_SkColorType == info.colorType()) { | 204 if (kUnknown_SkColorType == info.colorType()) { |
117 return kInvalidConversion; | 205 return kInvalidConversion; |
118 } | 206 } |
119 if (nullptr == pixels) { | 207 if (nullptr == pixels) { |
120 return kInvalidParameters; | 208 return kInvalidParameters; |
121 } | 209 } |
122 if (rowBytes < info.minRowBytes()) { | 210 if (rowBytes < info.minRowBytes()) { |
123 return kInvalidParameters; | 211 return kInvalidParameters; |
(...skipping 21 matching lines...) Expand all Loading... | |
145 } | 233 } |
146 | 234 |
147 if (!this->rewindIfNeeded()) { | 235 if (!this->rewindIfNeeded()) { |
148 return kCouldNotRewind; | 236 return kCouldNotRewind; |
149 } | 237 } |
150 | 238 |
151 // Default options. | 239 // Default options. |
152 Options optsStorage; | 240 Options optsStorage; |
153 if (nullptr == options) { | 241 if (nullptr == options) { |
154 options = &optsStorage; | 242 options = &optsStorage; |
155 } else if (options->fSubset) { | |
156 SkIRect subset(*options->fSubset); | |
157 if (!this->onGetValidSubset(&subset) || subset != *options->fSubset) { | |
158 // FIXME: How to differentiate between not supporting subset at all | |
159 // and not supporting this particular subset? | |
160 return kUnimplemented; | |
161 } | |
162 } | 243 } |
163 | 244 |
164 // FIXME: Support subsets somehow? Note that this works for SkWebpCodec | 245 if (!this->scaledSubsetSupported(info.dimensions(), *options, false)) { |
165 // because it supports arbitrary scaling/subset combinations. | |
166 if (!this->dimensionsSupported(info.dimensions())) { | |
167 return kInvalidScale; | 246 return kInvalidScale; |
168 } | 247 } |
169 | 248 |
170 // On an incomplete decode, the subclass will specify the number of scanline s that it decoded | 249 // On an incomplete decode, the subclass will specify the number of scanline s that it decoded |
171 // successfully. | 250 // successfully. |
172 int rowsDecoded = 0; | 251 int rowsDecoded = 0; |
173 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount, | 252 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount, |
174 &rowsDecoded); | 253 &rowsDecoded); |
175 | 254 |
176 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { | 255 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 } | 291 } |
213 | 292 |
214 if (!this->rewindIfNeeded()) { | 293 if (!this->rewindIfNeeded()) { |
215 return kCouldNotRewind; | 294 return kCouldNotRewind; |
216 } | 295 } |
217 | 296 |
218 // Set options. | 297 // Set options. |
219 Options optsStorage; | 298 Options optsStorage; |
220 if (nullptr == options) { | 299 if (nullptr == options) { |
221 options = &optsStorage; | 300 options = &optsStorage; |
222 } else if (options->fSubset) { | |
223 SkIRect size = SkIRect::MakeSize(dstInfo.dimensions()); | |
224 if (!size.contains(*options->fSubset)) { | |
225 return kInvalidInput; | |
226 } | |
227 | |
228 // We only support subsetting in the x-dimension for scanline decoder. | |
229 // Subsetting in the y-dimension can be accomplished using skipScanlines (). | |
230 if (options->fSubset->top() != 0 || options->fSubset->height() != dstInf o.height()) { | |
231 return kInvalidInput; | |
232 } | |
233 } | 301 } |
234 | 302 |
235 // FIXME: Support subsets somehow? | 303 if (!this->scaledSubsetSupported(dstInfo.dimensions(), *options, true)) { |
236 if (!this->dimensionsSupported(dstInfo.dimensions())) { | |
237 return kInvalidScale; | 304 return kInvalidScale; |
238 } | 305 } |
239 | 306 |
240 const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount); | 307 const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount); |
241 if (result != SkCodec::kSuccess) { | 308 if (result != SkCodec::kSuccess) { |
242 return result; | 309 return result; |
243 } | 310 } |
244 | 311 |
245 fCurrScanline = 0; | 312 fCurrScanline = 0; |
246 fDstInfo = dstInfo; | 313 fDstInfo = dstInfo; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
343 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested); | 410 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested); |
344 const SkImageInfo fillInfo = info.makeWH(info.width(), 1); | 411 const SkImageInfo fillInfo = info.makeWH(info.width(), 1); |
345 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { | 412 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { |
346 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes); | 413 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes); |
347 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler); | 414 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler); |
348 } | 415 } |
349 break; | 416 break; |
350 } | 417 } |
351 } | 418 } |
352 } | 419 } |
OLD | NEW |