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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 return flags.type != SinkFlags::kRaster | 242 return flags.type != SinkFlags::kRaster |
243 || flags.approach != SinkFlags::kDirect; | 243 || flags.approach != SinkFlags::kDirect; |
244 } | 244 } |
245 | 245 |
246 Error CodecSrc::draw(SkCanvas* canvas) const { | 246 Error CodecSrc::draw(SkCanvas* canvas) const { |
247 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 247 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
248 if (!encoded) { | 248 if (!encoded) { |
249 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); | 249 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); |
250 } | 250 } |
251 SkAutoTDelete<SkCodec> codec(NULL); | 251 SkAutoTDelete<SkCodec> codec(NULL); |
252 if (kScaledCodec_Mode == fMode) { | 252 if (kScaledCodec_Mode == fMode || kSubset_Mode == fMode) { |
253 codec.reset(SkScaledCodec::NewFromData(encoded)); | 253 codec.reset(SkScaledCodec::NewFromData(encoded)); |
254 // TODO (msarett): This should fall through to a fatal error once we sup
port scaled | 254 // TODO (msarett): This should fall through to a fatal error once we sup
port scaled |
255 // codecs for all image types. | 255 // codecs for all image types. |
256 if (nullptr == codec.get()) { | 256 if (nullptr == codec.get()) { |
257 return Error::Nonfatal(SkStringPrintf("Couldn't create scaled codec
for %s.", | 257 return Error::Nonfatal(SkStringPrintf("Couldn't create scaled codec
for %s.", |
258 fPath.c_str())); | 258 fPath.c_str())); |
259 } | 259 } |
260 } else { | 260 } else { |
261 codec.reset(SkCodec::NewFromData(encoded)); | 261 codec.reset(SkCodec::NewFromData(encoded)); |
262 } | 262 } |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 int divisor = 2; | 505 int divisor = 2; |
506 // Total width/height of the image. | 506 // Total width/height of the image. |
507 const int W = codec->getInfo().width(); | 507 const int W = codec->getInfo().width(); |
508 const int H = codec->getInfo().height(); | 508 const int H = codec->getInfo().height(); |
509 if (divisor > W || divisor > H) { | 509 if (divisor > W || divisor > H) { |
510 return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divi
sor %d is too big " | 510 return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divi
sor %d is too big " |
511 "for %s with dimensions (%
d x %d)", divisor, | 511 "for %s with dimensions (%
d x %d)", divisor, |
512 fPath.c_str(), W, H)); | 512 fPath.c_str(), W, H)); |
513 } | 513 } |
514 // subset dimensions | 514 // subset dimensions |
515 // SkWebpCodec, the only one that supports subsets, requires even to
p/left boundaries. | 515 const int w = W / divisor; |
516 const int w = SkAlign2(W / divisor); | 516 const int h = H / divisor; |
517 const int h = SkAlign2(H / divisor); | |
518 SkIRect subset; | 517 SkIRect subset; |
| 518 SkISize scaledSize; |
| 519 SkIRect scaledSubset; |
519 SkCodec::Options opts; | 520 SkCodec::Options opts; |
520 opts.fSubset = ⊂ | 521 opts.fSubset = ⊂ |
| 522 opts.fScaledDimensions = &scaledSize; |
| 523 opts.fScaledSubset = &scaledSubset; |
521 SkBitmap subsetBm; | 524 SkBitmap subsetBm; |
522 // We will reuse pixel memory from bitmap. | 525 // We will reuse pixel memory from bitmap. |
523 void* pixels = bitmap.getPixels(); | 526 void* pixels = bitmap.getPixels(); |
524 // Keep track of left and top (for drawing subsetBm into canvas). We
could use | 527 // Keep track of left and top (for drawing subsetBm into canvas). We
could use |
525 // fScale * x and fScale * y, but we want integers such that the nex
t subset will start | 528 // fScale * x and fScale * y, but we want integers such that the nex
t subset will start |
526 // where the last one ended. So we'll add decodeInfo.width() and hei
ght(). | 529 // where the last one ended. So we'll add decodeInfo.width() and hei
ght(). |
527 int left = 0; | 530 int left = 0; |
528 for (int x = 0; x < W; x += w) { | 531 for (int x = 0; x < W; x += w) { |
529 int top = 0; | 532 int top = 0; |
530 for (int y = 0; y < H; y+= h) { | 533 for (int y = 0; y < H; y+= h) { |
531 // Do not make the subset go off the edge of the image. | 534 // Do not make the subset go off the edge of the image. |
532 const int preScaleW = SkTMin(w, W - x); | 535 const int preScaleW = SkTMin(w, W - x); |
533 const int preScaleH = SkTMin(h, H - y); | 536 const int preScaleH = SkTMin(h, H - y); |
534 subset.setXYWH(x, y, preScaleW, preScaleH); | 537 subset.setXYWH(x, y, preScaleW, preScaleH); |
535 // And scale | 538 // And scale |
536 // FIXME: Should we have a version of getScaledDimensions th
at takes a subset | 539 if (!codec->getScaledSubsetDimensions(fScale, opts)) { |
537 // into account? | 540 return Error::Nonfatal("Subsetting not supported.\n"); |
538 decodeInfo = decodeInfo.makeWH( | 541 } |
539 SkTMax(1, SkScalarRoundToInt(preScaleW * fScale)), | 542 decodeInfo = decodeInfo.makeWH(scaledSubset.width(), scaledS
ubset.height()); |
540 SkTMax(1, SkScalarRoundToInt(preScaleH * fScale))); | |
541 size_t rowBytes = decodeInfo.minRowBytes(); | 543 size_t rowBytes = decodeInfo.minRowBytes(); |
542 if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, co
lorTable.get(), | 544 if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, co
lorTable.get(), |
543 nullptr, nullptr)) { | 545 nullptr, nullptr)) { |
544 return SkStringPrintf("could not install pixels for %s."
, fPath.c_str()); | 546 return SkStringPrintf("could not install pixels for %s."
, fPath.c_str()); |
545 } | 547 } |
546 const SkCodec::Result result = codec->getPixels(decodeInfo,
pixels, rowBytes, | 548 const SkCodec::Result result = codec->getPixels(decodeInfo,
pixels, rowBytes, |
547 &opts, colorPtr, colorCountPtr); | 549 &opts, colorPtr, colorCountPtr); |
548 switch (result) { | 550 switch (result) { |
549 case SkCodec::kSuccess: | 551 case SkCodec::kSuccess: |
550 case SkCodec::kIncompleteInput: | 552 case SkCodec::kIncompleteInput: |
551 break; | 553 break; |
552 case SkCodec::kInvalidConversion: | 554 case SkCodec::kInvalidConversion: |
553 if (0 == (x|y)) { | 555 if (0 == (x|y)) { |
554 // First subset is okay to return unimplemented. | 556 // First subset is okay to return invalid conver
sion. |
555 return Error::Nonfatal("Incompatible colortype c
onversion"); | 557 return Error::Nonfatal("Incompatible colortype c
onversion"); |
556 } | 558 } |
557 // If the first subset succeeded, a later one should
not fail. | 559 // If the first subset succeeded, a later one should
not fail. |
558 // fall through to failure | 560 // fall through to failure |
559 case SkCodec::kUnimplemented: | |
560 if (0 == (x|y)) { | |
561 // First subset is okay to return unimplemented. | |
562 return Error::Nonfatal("subset codec not support
ed"); | |
563 } | |
564 // If the first subset succeeded, why would a later
one fail? | |
565 // fall through to failure | |
566 default: | 561 default: |
567 return SkStringPrintf("subset codec failed to decode
(%d, %d, %d, %d) " | 562 return SkStringPrintf("subset codec failed to decode
(%d, %d, %d, %d) " |
568 "from %s with dimensions (%d x
%d)\t error %d", | 563 "from %s with dimensions (%d x
%d)\t error %d", |
569 x, y, decodeInfo.width(), deco
deInfo.height(), | 564 x, y, decodeInfo.width(), deco
deInfo.height(), |
570 fPath.c_str(), W, H, result); | 565 fPath.c_str(), W, H, result); |
571 } | 566 } |
572 canvas->drawBitmap(subsetBm, SkIntToScalar(left), SkIntToSca
lar(top)); | 567 canvas->drawBitmap(subsetBm, SkIntToScalar(left), SkIntToSca
lar(top)); |
573 // translate by the scaled height. | 568 // translate by the scaled height. |
574 top += decodeInfo.height(); | 569 top += decodeInfo.height(); |
575 } | 570 } |
576 // translate by the scaled width. | 571 // translate by the scaled width. |
577 left += decodeInfo.width(); | 572 left += decodeInfo.width(); |
578 } | 573 } |
579 return ""; | 574 return ""; |
580 } | 575 } |
581 } | 576 } |
582 return ""; | 577 return ""; |
583 } | 578 } |
584 | 579 |
585 SkISize CodecSrc::size() const { | 580 SkISize CodecSrc::size() const { |
586 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 581 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
587 SkAutoTDelete<SkCodec> codec(nullptr); | 582 SkAutoTDelete<SkCodec> codec(nullptr); |
588 | 583 |
589 if (kScaledCodec_Mode == fMode) { | 584 if (kScaledCodec_Mode == fMode || kSubset_Mode == fMode) { |
590 codec.reset(SkScaledCodec::NewFromData(encoded)); | 585 codec.reset(SkScaledCodec::NewFromData(encoded)); |
591 } else { | 586 } else { |
592 codec.reset(SkCodec::NewFromData(encoded)); | 587 codec.reset(SkCodec::NewFromData(encoded)); |
593 } | 588 } |
594 | 589 |
595 if (nullptr == codec) { | 590 if (nullptr == codec) { |
596 return SkISize::Make(0, 0); | 591 return SkISize::Make(0, 0); |
597 } | 592 } |
598 return codec->getScaledDimensions(fScale); | 593 return codec->getScaledDimensions(fScale); |
599 } | 594 } |
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 skr.visit<void>(i, drawsAsSingletonPictures); | 1195 skr.visit<void>(i, drawsAsSingletonPictures); |
1201 } | 1196 } |
1202 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); | 1197 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); |
1203 | 1198 |
1204 canvas->drawPicture(macroPic); | 1199 canvas->drawPicture(macroPic); |
1205 return ""; | 1200 return ""; |
1206 }); | 1201 }); |
1207 } | 1202 } |
1208 | 1203 |
1209 } // namespace DM | 1204 } // namespace DM |
OLD | NEW |