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 "DMSrcSink.h" | 8 #include "DMSrcSink.h" |
9 #include "SamplePipeControllers.h" | 9 #include "SamplePipeControllers.h" |
10 #include "SkCodec.h" | 10 #include "SkCodec.h" |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType); | 133 decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType); |
134 } | 134 } |
135 | 135 |
136 SkBitmap bitmap; | 136 SkBitmap bitmap; |
137 if (!bitmap.tryAllocPixels(decodeInfo, NULL, colorTable.get())) { | 137 if (!bitmap.tryAllocPixels(decodeInfo, NULL, colorTable.get())) { |
138 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(
), | 138 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(
), |
139 decodeInfo.width(), decodeInfo.height()); | 139 decodeInfo.width(), decodeInfo.height()); |
140 } | 140 } |
141 | 141 |
142 switch (fMode) { | 142 switch (fMode) { |
143 case kNormal_Mode: | 143 case kNormal_Mode: { |
144 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowB
ytes(), NULL, | 144 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowB
ytes(), NULL, |
145 colorPtr, colorCountPtr)) { | 145 colorPtr, colorCountPtr)) { |
146 case SkImageGenerator::kSuccess: | 146 case SkImageGenerator::kSuccess: |
147 // We consider incomplete to be valid, since we should still
decode what is | 147 // We consider incomplete to be valid, since we should still
decode what is |
148 // available. | 148 // available. |
149 case SkImageGenerator::kIncompleteInput: | 149 case SkImageGenerator::kIncompleteInput: |
150 break; | 150 break; |
151 case SkImageGenerator::kInvalidConversion: | 151 case SkImageGenerator::kInvalidConversion: |
152 return Error::Nonfatal("Incompatible colortype conversion"); | 152 return Error::Nonfatal("Incompatible colortype conversion"); |
153 default: | 153 default: |
154 // Everything else is considered a failure. | 154 // Everything else is considered a failure. |
155 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str(
)); | 155 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str(
)); |
156 } | 156 } |
157 canvas->drawBitmap(bitmap, 0, 0); | 157 canvas->drawBitmap(bitmap, 0, 0); |
158 break; | 158 break; |
| 159 } |
159 case kScanline_Mode: { | 160 case kScanline_Mode: { |
160 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecoder(decod
eInfo, NULL, | 161 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecoder(decod
eInfo, NULL, |
161 colorPtr, colorCountPtr); | 162 colorPtr, colorCountPtr); |
162 if (NULL == scanlineDecoder) { | 163 if (NULL == scanlineDecoder) { |
163 return Error::Nonfatal("Cannot use scanline decoder for all imag
es"); | 164 return Error::Nonfatal("Cannot use scanline decoder for all imag
es"); |
164 } | 165 } |
165 for (int y = 0; y < decodeInfo.height(); ++y) { | 166 const SkImageGenerator::Result result = scanlineDecoder->getScanline
s( |
166 const SkImageGenerator::Result result = scanlineDecoder->getScan
lines( | 167 bitmap.getAddr(0, 0), decodeInfo.height(), bitmap.rowBytes()
); |
167 bitmap.getAddr(0, y), 1, 0); | 168 switch (result) { |
168 switch (result) { | 169 case SkImageGenerator::kSuccess: |
169 case SkImageGenerator::kSuccess: | 170 case SkImageGenerator::kIncompleteInput: |
170 case SkImageGenerator::kIncompleteInput: | 171 break; |
171 break; | 172 default: |
172 default: | 173 return SkStringPrintf("%s failed with error message %d", |
173 return SkStringPrintf("%s failed after %d scanlines with
error message %d", | 174 fPath.c_str(), (int) result); |
174 fPath.c_str(), y-1, (int) result); | |
175 } | |
176 } | 175 } |
177 canvas->drawBitmap(bitmap, 0, 0); | 176 canvas->drawBitmap(bitmap, 0, 0); |
178 break; | 177 break; |
179 } | 178 } |
180 case kScanline_Subset_Mode: { | 179 case kScanline_Subset_Mode: { |
181 //this mode decodes the image in divisor*divisor subsets, using a sc
anline decoder | 180 //this mode decodes the image in divisor*divisor subsets, using a sc
anline decoder |
182 const int divisor = 2; | 181 const int divisor = 2; |
183 const int w = decodeInfo.width(); | 182 const int w = decodeInfo.width(); |
184 const int h = decodeInfo.height(); | 183 const int h = decodeInfo.height(); |
185 if (w*h == 1) { | 184 if (w*h == 1) { |
(...skipping 17 matching lines...) Expand all Loading... |
203 * subsetBm's size is determined based on the current subset and may
be larger for end | 202 * subsetBm's size is determined based on the current subset and may
be larger for end |
204 * subsets. | 203 * subsets. |
205 */ | 204 */ |
206 SkImageInfo largestSubsetDecodeInfo = | 205 SkImageInfo largestSubsetDecodeInfo = |
207 decodeInfo.makeWH(subsetWidth + extraX, subsetHeight + extra
Y); | 206 decodeInfo.makeWH(subsetWidth + extraX, subsetHeight + extra
Y); |
208 SkBitmap largestSubsetBm; | 207 SkBitmap largestSubsetBm; |
209 if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, NULL, c
olorTable.get())) { | 208 if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, NULL, c
olorTable.get())) { |
210 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPat
h.c_str(), | 209 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPat
h.c_str(), |
211 largestSubsetDecodeInfo.width(), largestSubsetDecodeInfo
.height()); | 210 largestSubsetDecodeInfo.width(), largestSubsetDecodeInfo
.height()); |
212 } | 211 } |
213 char* line = SkNEW_ARRAY(char, decodeInfo.minRowBytes()); | 212 const size_t rowBytes = decodeInfo.minRowBytes(); |
214 SkAutoTDeleteArray<char> lineDeleter(line); | 213 char* buffer = SkNEW_ARRAY(char, largestSubsetDecodeInfo.height() *
rowBytes); |
| 214 SkAutoTDeleteArray<char> lineDeleter(buffer); |
215 for (int col = 0; col < divisor; col++) { | 215 for (int col = 0; col < divisor; col++) { |
216 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets | 216 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets |
217 const int currentSubsetWidth = (col + 1 == divisor) ? | 217 const int currentSubsetWidth = (col + 1 == divisor) ? |
218 subsetWidth + extraX : subsetWidth; | 218 subsetWidth + extraX : subsetWidth; |
219 const int x = col * subsetWidth; | 219 const int x = col * subsetWidth; |
220 for (int row = 0; row < divisor; row++) { | 220 for (int row = 0; row < divisor; row++) { |
221 //currentSubsetHeight may be larger than subsetHeight for bo
ttom subsets | 221 //currentSubsetHeight may be larger than subsetHeight for bo
ttom subsets |
222 const int currentSubsetHeight = (row + 1 == divisor) ? | 222 const int currentSubsetHeight = (row + 1 == divisor) ? |
223 subsetHeight + extraY : subsetHeight; | 223 subsetHeight + extraY : subsetHeight; |
224 const int y = row * subsetHeight; | 224 const int y = row * subsetHeight; |
(...skipping 18 matching lines...) Expand all Loading... |
243 default: | 243 default: |
244 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" | 244 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" |
245 "with error message %d", fPath.c_str(), y, (
int) skipResult); | 245 "with error message %d", fPath.c_str(), y, (
int) skipResult); |
246 } | 246 } |
247 //create and set size of subsetBm | 247 //create and set size of subsetBm |
248 SkBitmap subsetBm; | 248 SkBitmap subsetBm; |
249 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); | 249 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); |
250 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight
); | 250 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight
); |
251 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun
ds)); | 251 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun
ds)); |
252 SkAutoLockPixels autlockSubsetBm(subsetBm, true); | 252 SkAutoLockPixels autlockSubsetBm(subsetBm, true); |
| 253 const SkImageGenerator::Result subsetResult = |
| 254 subsetScanlineDecoder->getScanlines(buffer, currentSubse
tHeight, rowBytes); |
| 255 switch (subsetResult) { |
| 256 case SkImageGenerator::kSuccess: |
| 257 case SkImageGenerator::kIncompleteInput: |
| 258 break; |
| 259 default: |
| 260 return SkStringPrintf("%s failed with error message
%d", |
| 261 fPath.c_str(), (int) subsetResult); |
| 262 } |
| 263 const size_t bpp = decodeInfo.bytesPerPixel(); |
| 264 /* |
| 265 * we copy all the lines at once becuase when calling getSca
nlines for |
| 266 * interlaced pngs the entire image must be read regardless
of the number |
| 267 * of lines requested. Reading an interlaced png in a loop,
line-by-line, would |
| 268 * decode the entire image height times, which is very slow |
| 269 * it is aknowledged that copying each line as you read it i
n a loop |
| 270 * may be faster for other types of images. Since this is a
correctness test |
| 271 * that's okay. |
| 272 */ |
| 273 char* bufferRow = buffer; |
253 for (int subsetY = 0; subsetY < currentSubsetHeight; ++subse
tY) { | 274 for (int subsetY = 0; subsetY < currentSubsetHeight; ++subse
tY) { |
254 const SkImageGenerator::Result subsetResult = | 275 memcpy(subsetBm.getAddr(0, subsetY), bufferRow + x*bpp, |
255 subsetScanlineDecoder->getScanlines(line, 1, 0); | 276 currentSubsetWidth*bpp); |
256 const size_t bpp = decodeInfo.bytesPerPixel(); | 277 bufferRow += rowBytes; |
257 //copy section of line based on x value | |
258 memcpy(subsetBm.getAddr(0, subsetY), line + x*bpp, curre
ntSubsetWidth*bpp); | |
259 switch (subsetResult) { | |
260 case SkImageGenerator::kSuccess: | |
261 case SkImageGenerator::kIncompleteInput: | |
262 break; | |
263 default: | |
264 return SkStringPrintf("%s failed after %d scanli
nes with error" | |
265 "message %d", fPath.c_str(), y-1, (int)
subsetResult); | |
266 } | |
267 } | 278 } |
| 279 |
268 canvas->drawBitmap(subsetBm, SkIntToScalar(x), SkIntToScalar
(y)); | 280 canvas->drawBitmap(subsetBm, SkIntToScalar(x), SkIntToScalar
(y)); |
269 } | 281 } |
270 } | 282 } |
271 break; | 283 break; |
272 } | 284 } |
273 case kStripe_Mode: { | 285 case kStripe_Mode: { |
274 const int height = decodeInfo.height(); | 286 const int height = decodeInfo.height(); |
275 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that | 287 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that |
276 // does not align with image blocks. | 288 // does not align with image blocks. |
277 const int stripeHeight = 37; | 289 const int stripeHeight = 37; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 switch (result) { | 349 switch (result) { |
338 case SkImageGenerator::kSuccess: | 350 case SkImageGenerator::kSuccess: |
339 case SkImageGenerator::kIncompleteInput: | 351 case SkImageGenerator::kIncompleteInput: |
340 break; | 352 break; |
341 default: | 353 default: |
342 return SkStringPrintf("Cannot skip scanlines for %s.
", fPath.c_str()); | 354 return SkStringPrintf("Cannot skip scanlines for %s.
", fPath.c_str()); |
343 } | 355 } |
344 } | 356 } |
345 } | 357 } |
346 canvas->drawBitmap(bitmap, 0, 0); | 358 canvas->drawBitmap(bitmap, 0, 0); |
| 359 break; |
347 } | 360 } |
348 } | 361 } |
349 return ""; | 362 return ""; |
350 } | 363 } |
351 | 364 |
352 SkISize CodecSrc::size() const { | 365 SkISize CodecSrc::size() const { |
353 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 366 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
354 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); | 367 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); |
355 if (NULL != codec) { | 368 if (NULL != codec) { |
356 SkISize size = codec->getScaledDimensions(fScale); | 369 SkISize size = codec->getScaledDimensions(fScale); |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
970 skr.visit<void>(i, drawsAsSingletonPictures); | 983 skr.visit<void>(i, drawsAsSingletonPictures); |
971 } | 984 } |
972 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); | 985 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); |
973 | 986 |
974 canvas->drawPicture(macroPic); | 987 canvas->drawPicture(macroPic); |
975 return ""; | 988 return ""; |
976 }); | 989 }); |
977 } | 990 } |
978 | 991 |
979 } // namespace DM | 992 } // namespace DM |
OLD | NEW |