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 "SkCodec.h" | 8 #include "SkCodec.h" |
9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
10 #include "SkMath.h" | 10 #include "SkMath.h" |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 | 179 |
180 // Check if there is a subset. | 180 // Check if there is a subset. |
181 SkIRect subset; | 181 SkIRect subset; |
182 int subsetY = 0; | 182 int subsetY = 0; |
183 int subsetWidth = nativeSize.width(); | 183 int subsetWidth = nativeSize.width(); |
184 int subsetHeight = nativeSize.height(); | 184 int subsetHeight = nativeSize.height(); |
185 if (options.fSubset) { | 185 if (options.fSubset) { |
186 // We will need to know about subsetting in the y-dimension in order to
use the | 186 // We will need to know about subsetting in the y-dimension in order to
use the |
187 // scanline decoder. | 187 // scanline decoder. |
188 // Update the subset to account for scaling done by this->codec(). | 188 // Update the subset to account for scaling done by this->codec(). |
189 SkIRect* subsetPtr = options.fSubset; | 189 const SkIRect* subsetPtr = options.fSubset; |
190 | 190 |
191 // Do the divide ourselves, instead of calling get_scaled_dimension. If | 191 // Do the divide ourselves, instead of calling get_scaled_dimension. If |
192 // X and Y are 0, they should remain 0, rather than being upgraded to 1 | 192 // X and Y are 0, they should remain 0, rather than being upgraded to 1 |
193 // due to being smaller than the sampleSize. | 193 // due to being smaller than the sampleSize. |
194 const int subsetX = subsetPtr->x() / nativeSampleSize; | 194 const int subsetX = subsetPtr->x() / nativeSampleSize; |
195 subsetY = subsetPtr->y() / nativeSampleSize; | 195 subsetY = subsetPtr->y() / nativeSampleSize; |
196 | 196 |
197 subsetWidth = get_scaled_dimension(subsetPtr->width(), nativeSampleSize)
; | 197 subsetWidth = get_scaled_dimension(subsetPtr->width(), nativeSampleSize)
; |
198 subsetHeight = get_scaled_dimension(subsetPtr->height(), nativeSampleSiz
e); | 198 subsetHeight = get_scaled_dimension(subsetPtr->height(), nativeSampleSiz
e); |
199 | 199 |
200 // The scanline decoder only needs to be aware of subsetting in the x-di
mension. | 200 // The scanline decoder only needs to be aware of subsetting in the x-di
mension. |
201 subset.setXYWH(subsetX, 0, subsetWidth, nativeSize.height()); | 201 subset.setXYWH(subsetX, 0, subsetWidth, nativeSize.height()); |
202 sampledOptions.fSubset = ⊂ | 202 sampledOptions.fSubset = ⊂ |
203 } | 203 } |
204 | 204 |
205 // Since we guarantee that output dimensions are always at least one (even i
f the sampleSize | 205 // Since we guarantee that output dimensions are always at least one (even i
f the sampleSize |
206 // is greater than a given dimension), the input sampleSize is not always th
e sampleSize that | 206 // is greater than a given dimension), the input sampleSize is not always th
e sampleSize that |
207 // we use in practice. | 207 // we use in practice. |
208 const int sampleX = subsetWidth / info.width(); | 208 const int sampleX = subsetWidth / info.width(); |
209 const int sampleY = subsetHeight / info.height(); | 209 const int sampleY = subsetHeight / info.height(); |
210 | 210 |
211 const int samplingOffsetY = get_start_coord(sampleY); | 211 const int samplingOffsetY = get_start_coord(sampleY); |
212 const int startY = samplingOffsetY + subsetY; | 212 const int startY = samplingOffsetY + subsetY; |
213 int dstHeight = info.height(); | 213 const int dstHeight = info.height(); |
214 | 214 |
215 const SkImageInfo nativeInfo = info.makeWH(nativeSize.width(), nativeSize.he
ight()); | 215 const SkImageInfo nativeInfo = info.makeWH(nativeSize.width(), nativeSize.he
ight()); |
216 | 216 |
217 { | 217 { |
218 // Although startScanlineDecode expects the bottom and top to match the | 218 // Although startScanlineDecode expects the bottom and top to match the |
219 // SkImageInfo, startIncrementalDecode uses them to determine which rows
to | 219 // SkImageInfo, startIncrementalDecode uses them to determine which rows
to |
220 // decode. | 220 // decode. |
221 // Note: We *could* use "subsetY" and "subsetHeight" (calculated above)
for | 221 SkCodec::Options incrementalOptions = sampledOptions; |
222 // incrementalSubset, but this code gives us a tighter bounds on the sub
set, | |
223 // meaning that we can start with the first row actually needed by the o
utput, | |
224 // and stop when we've decoded the last row needed by the output. | |
225 SkIRect incrementalSubset; | 222 SkIRect incrementalSubset; |
226 incrementalSubset.fTop = startY; | |
227 incrementalSubset.fBottom = startY + (dstHeight - 1) * sampleY + 1; | |
228 if (sampledOptions.fSubset) { | 223 if (sampledOptions.fSubset) { |
| 224 incrementalSubset.fTop = subsetY; |
| 225 incrementalSubset.fBottom = subsetY + subsetHeight; |
229 incrementalSubset.fLeft = sampledOptions.fSubset->fLeft; | 226 incrementalSubset.fLeft = sampledOptions.fSubset->fLeft; |
230 incrementalSubset.fRight = sampledOptions.fSubset->fRight; | 227 incrementalSubset.fRight = sampledOptions.fSubset->fRight; |
231 } else { | 228 incrementalOptions.fSubset = &incrementalSubset; |
232 incrementalSubset.fLeft = 0; | |
233 incrementalSubset.fRight = nativeSize.width(); | |
234 } | 229 } |
235 SkCodec::Options incrementalOptions = sampledOptions; | |
236 incrementalOptions.fSubset = &incrementalSubset; | |
237 const SkCodec::Result startResult = this->codec()->startIncrementalDecod
e(nativeInfo, | 230 const SkCodec::Result startResult = this->codec()->startIncrementalDecod
e(nativeInfo, |
238 pixels, rowBytes, &incrementalOptions, options.fColorPtr, option
s.fColorCount); | 231 pixels, rowBytes, &incrementalOptions, options.fColorPtr, option
s.fColorCount); |
239 if (SkCodec::kSuccess == startResult) { | 232 if (SkCodec::kSuccess == startResult) { |
240 SkSampler* sampler = this->codec()->getSampler(true); | 233 SkSampler* sampler = this->codec()->getSampler(true); |
241 if (!sampler) { | 234 if (!sampler) { |
242 return SkCodec::kUnimplemented; | 235 return SkCodec::kUnimplemented; |
243 } | 236 } |
244 | 237 |
245 if (sampler->setSampleX(sampleX) != info.width()) { | 238 if (sampler->setSampleX(sampleX) != info.width()) { |
246 return SkCodec::kInvalidScale; | 239 return SkCodec::kInvalidScale; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 void* rowPtr = SkTAddOffset<void>(pixels, rowBytes * get_dst_coo
rd(srcY, sampleY)); | 341 void* rowPtr = SkTAddOffset<void>(pixels, rowBytes * get_dst_coo
rd(srcY, sampleY)); |
349 SkSampler::Fill(fillInfo, rowPtr, rowBytes, fillValue, options.f
ZeroInitialized); | 342 SkSampler::Fill(fillInfo, rowPtr, rowBytes, fillValue, options.f
ZeroInitialized); |
350 } | 343 } |
351 return SkCodec::kIncompleteInput; | 344 return SkCodec::kIncompleteInput; |
352 } | 345 } |
353 default: | 346 default: |
354 SkASSERT(false); | 347 SkASSERT(false); |
355 return SkCodec::kUnimplemented; | 348 return SkCodec::kUnimplemented; |
356 } | 349 } |
357 } | 350 } |
OLD | NEW |