| 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 |