SkCodec.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. /*
  2. * Copyright 2015 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/codec/SkCodec.h"
  8. #include "include/core/SkColorSpace.h"
  9. #include "include/core/SkData.h"
  10. #include "include/private/SkHalf.h"
  11. #include "src/codec/SkBmpCodec.h"
  12. #include "src/codec/SkCodecPriv.h"
  13. #include "src/codec/SkFrameHolder.h"
  14. #ifdef SK_HAS_HEIF_LIBRARY
  15. #include "src/codec/SkHeifCodec.h"
  16. #endif
  17. #include "src/codec/SkIcoCodec.h"
  18. #include "src/codec/SkJpegCodec.h"
  19. #ifdef SK_HAS_PNG_LIBRARY
  20. #include "src/codec/SkPngCodec.h"
  21. #endif
  22. #include "include/core/SkStream.h"
  23. #include "src/codec/SkRawCodec.h"
  24. #include "src/codec/SkWbmpCodec.h"
  25. #include "src/codec/SkWebpCodec.h"
  26. #ifdef SK_HAS_WUFFS_LIBRARY
  27. #include "src/codec/SkWuffsCodec.h"
  28. #else
  29. #include "src/codec/SkGifCodec.h"
  30. #endif
  31. struct DecoderProc {
  32. bool (*IsFormat)(const void*, size_t);
  33. std::unique_ptr<SkCodec> (*MakeFromStream)(std::unique_ptr<SkStream>, SkCodec::Result*);
  34. };
  35. static std::vector<DecoderProc>* decoders() {
  36. static auto* decoders = new std::vector<DecoderProc> {
  37. #ifdef SK_HAS_JPEG_LIBRARY
  38. { SkJpegCodec::IsJpeg, SkJpegCodec::MakeFromStream },
  39. #endif
  40. #ifdef SK_HAS_WEBP_LIBRARY
  41. { SkWebpCodec::IsWebp, SkWebpCodec::MakeFromStream },
  42. #endif
  43. #ifdef SK_HAS_WUFFS_LIBRARY
  44. { SkWuffsCodec_IsFormat, SkWuffsCodec_MakeFromStream },
  45. #else
  46. { SkGifCodec::IsGif, SkGifCodec::MakeFromStream },
  47. #endif
  48. #ifdef SK_HAS_PNG_LIBRARY
  49. { SkIcoCodec::IsIco, SkIcoCodec::MakeFromStream },
  50. #endif
  51. { SkBmpCodec::IsBmp, SkBmpCodec::MakeFromStream },
  52. { SkWbmpCodec::IsWbmp, SkWbmpCodec::MakeFromStream },
  53. #ifdef SK_HAS_HEIF_LIBRARY
  54. { SkHeifCodec::IsHeif, SkHeifCodec::MakeFromStream },
  55. #endif
  56. };
  57. return decoders;
  58. }
  59. void SkCodec::Register(
  60. bool (*peek)(const void*, size_t),
  61. std::unique_ptr<SkCodec> (*make)(std::unique_ptr<SkStream>, SkCodec::Result*)) {
  62. decoders()->push_back(DecoderProc{peek, make});
  63. }
  64. std::unique_ptr<SkCodec> SkCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
  65. Result* outResult, SkPngChunkReader* chunkReader) {
  66. Result resultStorage;
  67. if (!outResult) {
  68. outResult = &resultStorage;
  69. }
  70. if (!stream) {
  71. *outResult = kInvalidInput;
  72. return nullptr;
  73. }
  74. constexpr size_t bytesToRead = MinBufferedBytesNeeded();
  75. char buffer[bytesToRead];
  76. size_t bytesRead = stream->peek(buffer, bytesToRead);
  77. // It is also possible to have a complete image less than bytesToRead bytes
  78. // (e.g. a 1 x 1 wbmp), meaning peek() would return less than bytesToRead.
  79. // Assume that if bytesRead < bytesToRead, but > 0, the stream is shorter
  80. // than bytesToRead, so pass that directly to the decoder.
  81. // It also is possible the stream uses too small a buffer for peeking, but
  82. // we trust the caller to use a large enough buffer.
  83. if (0 == bytesRead) {
  84. // TODO: After implementing peek in CreateJavaOutputStreamAdaptor.cpp, this
  85. // printf could be useful to notice failures.
  86. // SkCodecPrintf("Encoded image data failed to peek!\n");
  87. // It is possible the stream does not support peeking, but does support
  88. // rewinding.
  89. // Attempt to read() and pass the actual amount read to the decoder.
  90. bytesRead = stream->read(buffer, bytesToRead);
  91. if (!stream->rewind()) {
  92. SkCodecPrintf("Encoded image data could not peek or rewind to determine format!\n");
  93. *outResult = kCouldNotRewind;
  94. return nullptr;
  95. }
  96. }
  97. // PNG is special, since we want to be able to supply an SkPngChunkReader.
  98. // But this code follows the same pattern as the loop.
  99. #ifdef SK_HAS_PNG_LIBRARY
  100. if (SkPngCodec::IsPng(buffer, bytesRead)) {
  101. return SkPngCodec::MakeFromStream(std::move(stream), outResult, chunkReader);
  102. } else
  103. #endif
  104. {
  105. for (DecoderProc proc : *decoders()) {
  106. if (proc.IsFormat(buffer, bytesRead)) {
  107. return proc.MakeFromStream(std::move(stream), outResult);
  108. }
  109. }
  110. #ifdef SK_CODEC_DECODES_RAW
  111. // Try to treat the input as RAW if all the other checks failed.
  112. return SkRawCodec::MakeFromStream(std::move(stream), outResult);
  113. #endif
  114. }
  115. if (bytesRead < bytesToRead) {
  116. *outResult = kIncompleteInput;
  117. } else {
  118. *outResult = kUnimplemented;
  119. }
  120. return nullptr;
  121. }
  122. std::unique_ptr<SkCodec> SkCodec::MakeFromData(sk_sp<SkData> data, SkPngChunkReader* reader) {
  123. if (!data) {
  124. return nullptr;
  125. }
  126. return MakeFromStream(SkMemoryStream::Make(std::move(data)), nullptr, reader);
  127. }
  128. SkCodec::SkCodec(SkEncodedInfo&& info, XformFormat srcFormat, std::unique_ptr<SkStream> stream,
  129. SkEncodedOrigin origin)
  130. : fEncodedInfo(std::move(info))
  131. , fSrcXformFormat(srcFormat)
  132. , fStream(std::move(stream))
  133. , fNeedsRewind(false)
  134. , fOrigin(origin)
  135. , fDstInfo()
  136. , fOptions()
  137. , fCurrScanline(-1)
  138. , fStartedIncrementalDecode(false)
  139. {}
  140. SkCodec::~SkCodec() {}
  141. bool SkCodec::conversionSupported(const SkImageInfo& dst, bool srcIsOpaque, bool needsColorXform) {
  142. if (!valid_alpha(dst.alphaType(), srcIsOpaque)) {
  143. return false;
  144. }
  145. switch (dst.colorType()) {
  146. case kRGBA_8888_SkColorType:
  147. case kBGRA_8888_SkColorType:
  148. return true;
  149. case kRGBA_F16_SkColorType:
  150. return dst.colorSpace();
  151. case kRGB_565_SkColorType:
  152. return srcIsOpaque;
  153. case kGray_8_SkColorType:
  154. return SkEncodedInfo::kGray_Color == fEncodedInfo.color() && srcIsOpaque;
  155. case kAlpha_8_SkColorType:
  156. // conceptually we can convert anything into alpha_8, but we haven't actually coded
  157. // all of those other conversions yet.
  158. return SkEncodedInfo::kXAlpha_Color == fEncodedInfo.color();
  159. default:
  160. return false;
  161. }
  162. }
  163. bool SkCodec::rewindIfNeeded() {
  164. // Store the value of fNeedsRewind so we can update it. Next read will
  165. // require a rewind.
  166. const bool needsRewind = fNeedsRewind;
  167. fNeedsRewind = true;
  168. if (!needsRewind) {
  169. return true;
  170. }
  171. // startScanlineDecode will need to be called before decoding scanlines.
  172. fCurrScanline = -1;
  173. // startIncrementalDecode will need to be called before incrementalDecode.
  174. fStartedIncrementalDecode = false;
  175. // Some codecs do not have a stream. They may hold onto their own data or another codec.
  176. // They must handle rewinding themselves.
  177. if (fStream && !fStream->rewind()) {
  178. return false;
  179. }
  180. return this->onRewind();
  181. }
  182. bool zero_rect(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes,
  183. SkISize srcDimensions, SkIRect prevRect) {
  184. const auto dimensions = dstInfo.dimensions();
  185. if (dimensions != srcDimensions) {
  186. SkRect src = SkRect::Make(srcDimensions);
  187. SkRect dst = SkRect::Make(dimensions);
  188. SkMatrix map = SkMatrix::MakeRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit);
  189. SkRect asRect = SkRect::Make(prevRect);
  190. if (!map.mapRect(&asRect)) {
  191. return false;
  192. }
  193. asRect.roundIn(&prevRect);
  194. if (prevRect.isEmpty()) {
  195. // Down-scaling shrank the empty portion to nothing,
  196. // so nothing to zero.
  197. return true;
  198. }
  199. }
  200. if (!prevRect.intersect(dstInfo.bounds())) {
  201. SkCodecPrintf("rectangles do not intersect!");
  202. SkASSERT(false);
  203. return true;
  204. }
  205. const SkImageInfo info = dstInfo.makeWH(prevRect.width(), prevRect.height());
  206. const size_t bpp = dstInfo.bytesPerPixel();
  207. const size_t offset = prevRect.x() * bpp + prevRect.y() * rowBytes;
  208. void* eraseDst = SkTAddOffset<void>(pixels, offset);
  209. SkSampler::Fill(info, eraseDst, rowBytes, SkCodec::kNo_ZeroInitialized);
  210. return true;
  211. }
  212. SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, size_t rowBytes,
  213. const Options& options) {
  214. const int index = options.fFrameIndex;
  215. if (0 == index) {
  216. return this->initializeColorXform(info, fEncodedInfo.alpha(), fEncodedInfo.opaque())
  217. ? kSuccess : kInvalidConversion;
  218. }
  219. if (index < 0) {
  220. return kInvalidParameters;
  221. }
  222. if (options.fSubset) {
  223. // If we add support for this, we need to update the code that zeroes
  224. // a kRestoreBGColor frame.
  225. return kInvalidParameters;
  226. }
  227. if (index >= this->onGetFrameCount()) {
  228. return kIncompleteInput;
  229. }
  230. const auto* frameHolder = this->getFrameHolder();
  231. SkASSERT(frameHolder);
  232. const auto* frame = frameHolder->getFrame(index);
  233. SkASSERT(frame);
  234. const int requiredFrame = frame->getRequiredFrame();
  235. if (requiredFrame != kNoFrame) {
  236. if (options.fPriorFrame != kNoFrame) {
  237. // Check for a valid frame as a starting point. Alternatively, we could
  238. // treat an invalid frame as not providing one, but rejecting it will
  239. // make it easier to catch the mistake.
  240. if (options.fPriorFrame < requiredFrame || options.fPriorFrame >= index) {
  241. return kInvalidParameters;
  242. }
  243. const auto* prevFrame = frameHolder->getFrame(options.fPriorFrame);
  244. switch (prevFrame->getDisposalMethod()) {
  245. case SkCodecAnimation::DisposalMethod::kRestorePrevious:
  246. return kInvalidParameters;
  247. case SkCodecAnimation::DisposalMethod::kRestoreBGColor:
  248. // If a frame after the required frame is provided, there is no
  249. // need to clear, since it must be covered by the desired frame.
  250. if (options.fPriorFrame == requiredFrame) {
  251. SkIRect prevRect = prevFrame->frameRect();
  252. if (!zero_rect(info, pixels, rowBytes, this->dimensions(), prevRect)) {
  253. return kInternalError;
  254. }
  255. }
  256. break;
  257. default:
  258. break;
  259. }
  260. } else {
  261. Options prevFrameOptions(options);
  262. prevFrameOptions.fFrameIndex = requiredFrame;
  263. prevFrameOptions.fZeroInitialized = kNo_ZeroInitialized;
  264. const Result result = this->getPixels(info, pixels, rowBytes, &prevFrameOptions);
  265. if (result != kSuccess) {
  266. return result;
  267. }
  268. const auto* prevFrame = frameHolder->getFrame(requiredFrame);
  269. const auto disposalMethod = prevFrame->getDisposalMethod();
  270. if (disposalMethod == SkCodecAnimation::DisposalMethod::kRestoreBGColor) {
  271. auto prevRect = prevFrame->frameRect();
  272. if (!zero_rect(info, pixels, rowBytes, this->dimensions(), prevRect)) {
  273. return kInternalError;
  274. }
  275. }
  276. }
  277. }
  278. return this->initializeColorXform(info, frame->reportedAlpha(), !frame->hasAlpha())
  279. ? kSuccess : kInvalidConversion;
  280. }
  281. SkCodec::Result SkCodec::getPixels(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes,
  282. const Options* options) {
  283. SkImageInfo info = dstInfo;
  284. if (!info.colorSpace()) {
  285. info = info.makeColorSpace(SkColorSpace::MakeSRGB());
  286. }
  287. if (kUnknown_SkColorType == info.colorType()) {
  288. return kInvalidConversion;
  289. }
  290. if (nullptr == pixels) {
  291. return kInvalidParameters;
  292. }
  293. if (rowBytes < info.minRowBytes()) {
  294. return kInvalidParameters;
  295. }
  296. if (!this->rewindIfNeeded()) {
  297. return kCouldNotRewind;
  298. }
  299. // Default options.
  300. Options optsStorage;
  301. if (nullptr == options) {
  302. options = &optsStorage;
  303. } else {
  304. if (options->fSubset) {
  305. SkIRect subset(*options->fSubset);
  306. if (!this->onGetValidSubset(&subset) || subset != *options->fSubset) {
  307. // FIXME: How to differentiate between not supporting subset at all
  308. // and not supporting this particular subset?
  309. return kUnimplemented;
  310. }
  311. }
  312. }
  313. const Result frameIndexResult = this->handleFrameIndex(info, pixels, rowBytes,
  314. *options);
  315. if (frameIndexResult != kSuccess) {
  316. return frameIndexResult;
  317. }
  318. // FIXME: Support subsets somehow? Note that this works for SkWebpCodec
  319. // because it supports arbitrary scaling/subset combinations.
  320. if (!this->dimensionsSupported(info.dimensions())) {
  321. return kInvalidScale;
  322. }
  323. fDstInfo = info;
  324. fOptions = *options;
  325. // On an incomplete decode, the subclass will specify the number of scanlines that it decoded
  326. // successfully.
  327. int rowsDecoded = 0;
  328. const Result result = this->onGetPixels(info, pixels, rowBytes, *options, &rowsDecoded);
  329. // A return value of kIncompleteInput indicates a truncated image stream.
  330. // In this case, we will fill any uninitialized memory with a default value.
  331. // Some subclasses will take care of filling any uninitialized memory on
  332. // their own. They indicate that all of the memory has been filled by
  333. // setting rowsDecoded equal to the height.
  334. if ((kIncompleteInput == result || kErrorInInput == result) && rowsDecoded != info.height()) {
  335. // FIXME: (skbug.com/5772) fillIncompleteImage will fill using the swizzler's width, unless
  336. // there is a subset. In that case, it will use the width of the subset. From here, the
  337. // subset will only be non-null in the case of SkWebpCodec, but it treats the subset
  338. // differenty from the other codecs, and it needs to use the width specified by the info.
  339. // Set the subset to null so SkWebpCodec uses the correct width.
  340. fOptions.fSubset = nullptr;
  341. this->fillIncompleteImage(info, pixels, rowBytes, options->fZeroInitialized, info.height(),
  342. rowsDecoded);
  343. }
  344. return result;
  345. }
  346. SkCodec::Result SkCodec::startIncrementalDecode(const SkImageInfo& dstInfo, void* pixels,
  347. size_t rowBytes, const SkCodec::Options* options) {
  348. fStartedIncrementalDecode = false;
  349. SkImageInfo info = dstInfo;
  350. if (!info.colorSpace()) {
  351. info = info.makeColorSpace(SkColorSpace::MakeSRGB());
  352. }
  353. if (kUnknown_SkColorType == info.colorType()) {
  354. return kInvalidConversion;
  355. }
  356. if (nullptr == pixels) {
  357. return kInvalidParameters;
  358. }
  359. // FIXME: If the rows come after the rows of a previous incremental decode,
  360. // we might be able to skip the rewind, but only the implementation knows
  361. // that. (e.g. PNG will always need to rewind, since we called longjmp, but
  362. // a bottom-up BMP could skip rewinding if the new rows are above the old
  363. // rows.)
  364. if (!this->rewindIfNeeded()) {
  365. return kCouldNotRewind;
  366. }
  367. // Set options.
  368. Options optsStorage;
  369. if (nullptr == options) {
  370. options = &optsStorage;
  371. } else {
  372. if (options->fSubset) {
  373. SkIRect size = SkIRect::MakeSize(info.dimensions());
  374. if (!size.contains(*options->fSubset)) {
  375. return kInvalidParameters;
  376. }
  377. const int top = options->fSubset->top();
  378. const int bottom = options->fSubset->bottom();
  379. if (top < 0 || top >= info.height() || top >= bottom || bottom > info.height()) {
  380. return kInvalidParameters;
  381. }
  382. }
  383. }
  384. const Result frameIndexResult = this->handleFrameIndex(info, pixels, rowBytes,
  385. *options);
  386. if (frameIndexResult != kSuccess) {
  387. return frameIndexResult;
  388. }
  389. if (!this->dimensionsSupported(info.dimensions())) {
  390. return kInvalidScale;
  391. }
  392. fDstInfo = info;
  393. fOptions = *options;
  394. const Result result = this->onStartIncrementalDecode(info, pixels, rowBytes, fOptions);
  395. if (kSuccess == result) {
  396. fStartedIncrementalDecode = true;
  397. } else if (kUnimplemented == result) {
  398. // FIXME: This is temporarily necessary, until we transition SkCodec
  399. // implementations from scanline decoding to incremental decoding.
  400. // SkAndroidCodec will first attempt to use incremental decoding, but
  401. // will fall back to scanline decoding if incremental returns
  402. // kUnimplemented. rewindIfNeeded(), above, set fNeedsRewind to true
  403. // (after potentially rewinding), but we do not want the next call to
  404. // startScanlineDecode() to do a rewind.
  405. fNeedsRewind = false;
  406. }
  407. return result;
  408. }
  409. SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo,
  410. const SkCodec::Options* options) {
  411. // Reset fCurrScanline in case of failure.
  412. fCurrScanline = -1;
  413. SkImageInfo info = dstInfo;
  414. if (!info.colorSpace()) {
  415. info = info.makeColorSpace(SkColorSpace::MakeSRGB());
  416. }
  417. if (!this->rewindIfNeeded()) {
  418. return kCouldNotRewind;
  419. }
  420. // Set options.
  421. Options optsStorage;
  422. if (nullptr == options) {
  423. options = &optsStorage;
  424. } else if (options->fSubset) {
  425. SkIRect size = SkIRect::MakeSize(info.dimensions());
  426. if (!size.contains(*options->fSubset)) {
  427. return kInvalidInput;
  428. }
  429. // We only support subsetting in the x-dimension for scanline decoder.
  430. // Subsetting in the y-dimension can be accomplished using skipScanlines().
  431. if (options->fSubset->top() != 0 || options->fSubset->height() != info.height()) {
  432. return kInvalidInput;
  433. }
  434. }
  435. // Scanline decoding only supports decoding the first frame.
  436. if (options->fFrameIndex != 0) {
  437. return kUnimplemented;
  438. }
  439. // The void* dst and rowbytes in handleFrameIndex or only used for decoding prior
  440. // frames, which is not supported here anyway, so it is safe to pass nullptr/0.
  441. const Result frameIndexResult = this->handleFrameIndex(info, nullptr, 0, *options);
  442. if (frameIndexResult != kSuccess) {
  443. return frameIndexResult;
  444. }
  445. // FIXME: Support subsets somehow?
  446. if (!this->dimensionsSupported(info.dimensions())) {
  447. return kInvalidScale;
  448. }
  449. const Result result = this->onStartScanlineDecode(info, *options);
  450. if (result != SkCodec::kSuccess) {
  451. return result;
  452. }
  453. fCurrScanline = 0;
  454. fDstInfo = info;
  455. fOptions = *options;
  456. return kSuccess;
  457. }
  458. int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) {
  459. if (fCurrScanline < 0) {
  460. return 0;
  461. }
  462. SkASSERT(!fDstInfo.isEmpty());
  463. if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) {
  464. return 0;
  465. }
  466. const int linesDecoded = this->onGetScanlines(dst, countLines, rowBytes);
  467. if (linesDecoded < countLines) {
  468. this->fillIncompleteImage(this->dstInfo(), dst, rowBytes, this->options().fZeroInitialized,
  469. countLines, linesDecoded);
  470. }
  471. fCurrScanline += countLines;
  472. return linesDecoded;
  473. }
  474. bool SkCodec::skipScanlines(int countLines) {
  475. if (fCurrScanline < 0) {
  476. return false;
  477. }
  478. SkASSERT(!fDstInfo.isEmpty());
  479. if (countLines < 0 || fCurrScanline + countLines > fDstInfo.height()) {
  480. // Arguably, we could just skip the scanlines which are remaining,
  481. // and return true. We choose to return false so the client
  482. // can catch their bug.
  483. return false;
  484. }
  485. bool result = this->onSkipScanlines(countLines);
  486. fCurrScanline += countLines;
  487. return result;
  488. }
  489. int SkCodec::outputScanline(int inputScanline) const {
  490. SkASSERT(0 <= inputScanline && inputScanline < fEncodedInfo.height());
  491. return this->onOutputScanline(inputScanline);
  492. }
  493. int SkCodec::onOutputScanline(int inputScanline) const {
  494. switch (this->getScanlineOrder()) {
  495. case kTopDown_SkScanlineOrder:
  496. return inputScanline;
  497. case kBottomUp_SkScanlineOrder:
  498. return fEncodedInfo.height() - inputScanline - 1;
  499. default:
  500. // This case indicates an interlaced gif and is implemented by SkGifCodec.
  501. SkASSERT(false);
  502. return 0;
  503. }
  504. }
  505. void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t rowBytes,
  506. ZeroInitialized zeroInit, int linesRequested, int linesDecoded) {
  507. if (kYes_ZeroInitialized == zeroInit) {
  508. return;
  509. }
  510. const int linesRemaining = linesRequested - linesDecoded;
  511. SkSampler* sampler = this->getSampler(false);
  512. const int fillWidth = sampler ? sampler->fillWidth() :
  513. fOptions.fSubset ? fOptions.fSubset->width() :
  514. info.width() ;
  515. void* fillDst = this->getScanlineOrder() == kBottomUp_SkScanlineOrder ? dst :
  516. SkTAddOffset<void>(dst, linesDecoded * rowBytes);
  517. const auto fillInfo = info.makeWH(fillWidth, linesRemaining);
  518. SkSampler::Fill(fillInfo, fillDst, rowBytes, kNo_ZeroInitialized);
  519. }
  520. bool sk_select_xform_format(SkColorType colorType, bool forColorTable,
  521. skcms_PixelFormat* outFormat) {
  522. SkASSERT(outFormat);
  523. switch (colorType) {
  524. case kRGBA_8888_SkColorType:
  525. *outFormat = skcms_PixelFormat_RGBA_8888;
  526. break;
  527. case kBGRA_8888_SkColorType:
  528. *outFormat = skcms_PixelFormat_BGRA_8888;
  529. break;
  530. case kRGB_565_SkColorType:
  531. if (forColorTable) {
  532. #ifdef SK_PMCOLOR_IS_RGBA
  533. *outFormat = skcms_PixelFormat_RGBA_8888;
  534. #else
  535. *outFormat = skcms_PixelFormat_BGRA_8888;
  536. #endif
  537. break;
  538. }
  539. *outFormat = skcms_PixelFormat_BGR_565;
  540. break;
  541. case kRGBA_F16_SkColorType:
  542. *outFormat = skcms_PixelFormat_RGBA_hhhh;
  543. break;
  544. case kGray_8_SkColorType:
  545. *outFormat = skcms_PixelFormat_G_8;
  546. break;
  547. default:
  548. return false;
  549. }
  550. return true;
  551. }
  552. bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha encodedAlpha,
  553. bool srcIsOpaque) {
  554. fXformTime = kNo_XformTime;
  555. bool needsColorXform = false;
  556. if (this->usesColorXform() && dstInfo.colorSpace()) {
  557. dstInfo.colorSpace()->toProfile(&fDstProfile);
  558. if (kRGBA_F16_SkColorType == dstInfo.colorType()) {
  559. needsColorXform = true;
  560. } else {
  561. const auto* srcProfile = fEncodedInfo.profile();
  562. if (!srcProfile) {
  563. srcProfile = skcms_sRGB_profile();
  564. }
  565. if (!skcms_ApproximatelyEqualProfiles(srcProfile, &fDstProfile) ) {
  566. needsColorXform = true;
  567. }
  568. }
  569. }
  570. if (!this->conversionSupported(dstInfo, srcIsOpaque, needsColorXform)) {
  571. return false;
  572. }
  573. if (needsColorXform) {
  574. fXformTime = SkEncodedInfo::kPalette_Color != fEncodedInfo.color()
  575. || kRGBA_F16_SkColorType == dstInfo.colorType()
  576. ? kDecodeRow_XformTime : kPalette_XformTime;
  577. if (!sk_select_xform_format(dstInfo.colorType(), fXformTime == kPalette_XformTime,
  578. &fDstXformFormat)) {
  579. return false;
  580. }
  581. if (encodedAlpha == SkEncodedInfo::kUnpremul_Alpha
  582. && dstInfo.alphaType() == kPremul_SkAlphaType) {
  583. fDstXformAlphaFormat = skcms_AlphaFormat_PremulAsEncoded;
  584. } else {
  585. fDstXformAlphaFormat = skcms_AlphaFormat_Unpremul;
  586. }
  587. }
  588. return true;
  589. }
  590. void SkCodec::applyColorXform(void* dst, const void* src, int count) const {
  591. // It is okay for srcProfile to be null. This will use sRGB.
  592. const auto* srcProfile = fEncodedInfo.profile();
  593. SkAssertResult(skcms_Transform(src, fSrcXformFormat, skcms_AlphaFormat_Unpremul, srcProfile,
  594. dst, fDstXformFormat, fDstXformAlphaFormat, &fDstProfile,
  595. count));
  596. }
  597. std::vector<SkCodec::FrameInfo> SkCodec::getFrameInfo() {
  598. const int frameCount = this->getFrameCount();
  599. SkASSERT(frameCount >= 0);
  600. if (frameCount <= 0) {
  601. return std::vector<FrameInfo>{};
  602. }
  603. if (frameCount == 1 && !this->onGetFrameInfo(0, nullptr)) {
  604. // Not animated.
  605. return std::vector<FrameInfo>{};
  606. }
  607. std::vector<FrameInfo> result(frameCount);
  608. for (int i = 0; i < frameCount; ++i) {
  609. SkAssertResult(this->onGetFrameInfo(i, &result[i]));
  610. }
  611. return result;
  612. }
  613. const char* SkCodec::ResultToString(Result result) {
  614. switch (result) {
  615. case kSuccess:
  616. return "success";
  617. case kIncompleteInput:
  618. return "incomplete input";
  619. case kErrorInInput:
  620. return "error in input";
  621. case kInvalidConversion:
  622. return "invalid conversion";
  623. case kInvalidScale:
  624. return "invalid scale";
  625. case kInvalidParameters:
  626. return "invalid parameters";
  627. case kInvalidInput:
  628. return "invalid input";
  629. case kCouldNotRewind:
  630. return "could not rewind";
  631. case kInternalError:
  632. return "internal error";
  633. case kUnimplemented:
  634. return "unimplemented";
  635. default:
  636. SkASSERT(false);
  637. return "bogus result value";
  638. }
  639. }
  640. static SkIRect frame_rect_on_screen(SkIRect frameRect,
  641. const SkIRect& screenRect) {
  642. if (!frameRect.intersect(screenRect)) {
  643. return SkIRect::MakeEmpty();
  644. }
  645. return frameRect;
  646. }
  647. static bool independent(const SkFrame& frame) {
  648. return frame.getRequiredFrame() == SkCodec::kNoFrame;
  649. }
  650. static bool restore_bg(const SkFrame& frame) {
  651. return frame.getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestoreBGColor;
  652. }
  653. // As its name suggests, this method computes a frame's alpha (e.g. completely
  654. // opaque, unpremul, binary) and its required frame (a preceding frame that
  655. // this frame depends on, to draw the complete image at this frame's point in
  656. // the animation stream), and calls this frame's setter methods with that
  657. // computed information.
  658. //
  659. // A required frame of kNoFrame means that this frame is independent: drawing
  660. // the complete image at this frame's point in the animation stream does not
  661. // require first preparing the pixel buffer based on another frame. Instead,
  662. // drawing can start from an uninitialized pixel buffer.
  663. //
  664. // "Uninitialized" is from the SkCodec's caller's point of view. In the SkCodec
  665. // implementation, for independent frames, first party Skia code (in src/codec)
  666. // will typically fill the buffer with a uniform background color (e.g.
  667. // transparent black) before calling into third party codec-specific code (e.g.
  668. // libjpeg or libpng). Pixels outside of the frame's rect will remain this
  669. // background color after drawing this frame. For incomplete decodes, pixels
  670. // inside that rect may be (at least temporarily) set to that background color.
  671. // In an incremental decode, later passes may then overwrite that background
  672. // color.
  673. //
  674. // Determining kNoFrame or otherwise involves testing a number of conditions
  675. // sequentially. The first satisfied condition results in setting the required
  676. // frame to kNoFrame (an "INDx" condition) or to a non-negative frame number (a
  677. // "DEPx" condition), and the function returning early. Those "INDx" and "DEPx"
  678. // labels also map to comments in the function body.
  679. //
  680. // - IND1: this frame is the first frame.
  681. // - IND2: this frame fills out the whole image, and it is completely opaque
  682. // or it overwrites (not blends with) the previous frame.
  683. // - IND3: all preceding frames' disposals are kRestorePrevious.
  684. // - IND4: the prevFrame's disposal is kRestoreBGColor, and it fills out the
  685. // whole image or it is itself otherwise independent.
  686. // - DEP5: this frame reports alpha (it is not completely opaque) and it
  687. // blends with (not overwrites) the previous frame.
  688. // - IND6: this frame's rect covers the rects of all preceding frames back to
  689. // and including the most recent independent frame before this frame.
  690. // - DEP7: unconditional.
  691. //
  692. // The "prevFrame" variable initially points to the previous frame (also known
  693. // as the prior frame), but that variable may iterate further backwards over
  694. // the course of this computation.
  695. void SkFrameHolder::setAlphaAndRequiredFrame(SkFrame* frame) {
  696. const bool reportsAlpha = frame->reportedAlpha() != SkEncodedInfo::kOpaque_Alpha;
  697. const auto screenRect = SkIRect::MakeWH(fScreenWidth, fScreenHeight);
  698. const auto frameRect = frame_rect_on_screen(frame->frameRect(), screenRect);
  699. const int i = frame->frameId();
  700. if (0 == i) {
  701. frame->setHasAlpha(reportsAlpha || frameRect != screenRect);
  702. frame->setRequiredFrame(SkCodec::kNoFrame); // IND1
  703. return;
  704. }
  705. const bool blendWithPrevFrame = frame->getBlend() == SkCodecAnimation::Blend::kPriorFrame;
  706. if ((!reportsAlpha || !blendWithPrevFrame) && frameRect == screenRect) {
  707. frame->setHasAlpha(reportsAlpha);
  708. frame->setRequiredFrame(SkCodec::kNoFrame); // IND2
  709. return;
  710. }
  711. const SkFrame* prevFrame = this->getFrame(i-1);
  712. while (prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
  713. const int prevId = prevFrame->frameId();
  714. if (0 == prevId) {
  715. frame->setHasAlpha(true);
  716. frame->setRequiredFrame(SkCodec::kNoFrame); // IND3
  717. return;
  718. }
  719. prevFrame = this->getFrame(prevId - 1);
  720. }
  721. const bool clearPrevFrame = restore_bg(*prevFrame);
  722. auto prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect);
  723. if (clearPrevFrame) {
  724. if (prevFrameRect == screenRect || independent(*prevFrame)) {
  725. frame->setHasAlpha(true);
  726. frame->setRequiredFrame(SkCodec::kNoFrame); // IND4
  727. return;
  728. }
  729. }
  730. if (reportsAlpha && blendWithPrevFrame) {
  731. // Note: We could be more aggressive here. If prevFrame clears
  732. // to background color and covers its required frame (and that
  733. // frame is independent), prevFrame could be marked independent.
  734. // Would this extra complexity be worth it?
  735. frame->setRequiredFrame(prevFrame->frameId()); // DEP5
  736. frame->setHasAlpha(prevFrame->hasAlpha() || clearPrevFrame);
  737. return;
  738. }
  739. while (frameRect.contains(prevFrameRect)) {
  740. const int prevRequiredFrame = prevFrame->getRequiredFrame();
  741. if (prevRequiredFrame == SkCodec::kNoFrame) {
  742. frame->setRequiredFrame(SkCodec::kNoFrame); // IND6
  743. frame->setHasAlpha(true);
  744. return;
  745. }
  746. prevFrame = this->getFrame(prevRequiredFrame);
  747. prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect);
  748. }
  749. frame->setRequiredFrame(prevFrame->frameId()); // DEP7
  750. if (restore_bg(*prevFrame)) {
  751. frame->setHasAlpha(true);
  752. return;
  753. }
  754. SkASSERT(prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kKeep);
  755. frame->setHasAlpha(prevFrame->hasAlpha() || (reportsAlpha && !blendWithPrevFrame));
  756. }