blob: 85f2414ecbf8a700a40aa2f87bcf6d54a1baef0e [file] [log] [blame]
scroggof24f2242015-03-03 08:59:20 -08001/*
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
8#include "SkCodec.h"
9#include "SkData.h"
msarett74114382015-03-16 11:55:18 -070010#include "SkCodec_libbmp.h"
msarett8c8f22a2015-04-01 06:58:48 -070011#include "SkCodec_libgif.h"
msarett9bde9182015-03-25 05:27:48 -070012#include "SkCodec_libico.h"
scroggof24f2242015-03-03 08:59:20 -080013#include "SkCodec_libpng.h"
halcanarya096d7a2015-03-27 12:16:53 -070014#include "SkCodec_wbmp.h"
msarett8c8f22a2015-04-01 06:58:48 -070015#include "SkCodecPriv.h"
msarette16b04a2015-04-15 07:32:19 -070016#include "SkJpegCodec.h"
scroggof24f2242015-03-03 08:59:20 -080017#include "SkStream.h"
18
msarett74114382015-03-16 11:55:18 -070019struct DecoderProc {
20 bool (*IsFormat)(SkStream*);
21 SkCodec* (*NewFromStream)(SkStream*);
22};
23
24static const DecoderProc gDecoderProcs[] = {
25 { SkPngCodec::IsPng, SkPngCodec::NewFromStream },
msarette16b04a2015-04-15 07:32:19 -070026 { SkJpegCodec::IsJpeg, SkJpegCodec::NewFromStream },
msarett8c8f22a2015-04-01 06:58:48 -070027 { SkGifCodec::IsGif, SkGifCodec::NewFromStream },
msarett9bde9182015-03-25 05:27:48 -070028 { SkIcoCodec::IsIco, SkIcoCodec::NewFromStream },
halcanarya096d7a2015-03-27 12:16:53 -070029 { SkBmpCodec::IsBmp, SkBmpCodec::NewFromStream },
30 { SkWbmpCodec::IsWbmp, SkWbmpCodec::NewFromStream }
msarett74114382015-03-16 11:55:18 -070031};
32
scroggof24f2242015-03-03 08:59:20 -080033SkCodec* SkCodec::NewFromStream(SkStream* stream) {
34 if (!stream) {
35 return NULL;
36 }
scroggo0a7e69c2015-04-03 07:22:22 -070037
38 SkAutoTDelete<SkStream> streamDeleter(stream);
msarett8c8f22a2015-04-01 06:58:48 -070039
scroggo0a7e69c2015-04-03 07:22:22 -070040 SkAutoTDelete<SkCodec> codec(NULL);
msarett74114382015-03-16 11:55:18 -070041 for (uint32_t i = 0; i < SK_ARRAY_COUNT(gDecoderProcs); i++) {
42 DecoderProc proc = gDecoderProcs[i];
43 const bool correctFormat = proc.IsFormat(stream);
44 if (!stream->rewind()) {
45 return NULL;
46 }
47 if (correctFormat) {
scroggo0a7e69c2015-04-03 07:22:22 -070048 codec.reset(proc.NewFromStream(streamDeleter.detach()));
msarett8c8f22a2015-04-01 06:58:48 -070049 break;
msarett74114382015-03-16 11:55:18 -070050 }
scroggof24f2242015-03-03 08:59:20 -080051 }
msarett8c8f22a2015-04-01 06:58:48 -070052
53 // Set the max size at 128 megapixels (512 MB for kN32).
54 // This is about 4x smaller than a test image that takes a few minutes for
55 // dm to decode and draw.
56 const int32_t maxSize = 1 << 27;
scroggo0a7e69c2015-04-03 07:22:22 -070057 if (codec && codec->getInfo().width() * codec->getInfo().height() > maxSize) {
msarett8c8f22a2015-04-01 06:58:48 -070058 SkCodecPrintf("Error: Image size too large, cannot decode.\n");
59 return NULL;
60 } else {
scroggo0a7e69c2015-04-03 07:22:22 -070061 return codec.detach();
msarett8c8f22a2015-04-01 06:58:48 -070062 }
scroggof24f2242015-03-03 08:59:20 -080063}
64
65SkCodec* SkCodec::NewFromData(SkData* data) {
66 if (!data) {
67 return NULL;
68 }
69 return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data)));
70}
71
72SkCodec::SkCodec(const SkImageInfo& info, SkStream* stream)
reed3ef71e32015-03-19 08:31:14 -070073 : INHERITED(info)
halcanaryb880d7f2015-03-26 06:29:03 -070074#ifdef SK_SUPPORT_LEGACY_BOOL_ONGETINFO
reed3ef71e32015-03-19 08:31:14 -070075 , fInfo(info)
halcanaryb880d7f2015-03-26 06:29:03 -070076#endif
scroggof24f2242015-03-03 08:59:20 -080077 , fStream(stream)
78 , fNeedsRewind(false)
79{}
80
halcanarya096d7a2015-03-27 12:16:53 -070081SkCodec::RewindState SkCodec::rewindIfNeeded() {
scroggof24f2242015-03-03 08:59:20 -080082 // Store the value of fNeedsRewind so we can update it. Next read will
83 // require a rewind.
halcanarya096d7a2015-03-27 12:16:53 -070084 const bool needsRewind = fNeedsRewind;
scroggof24f2242015-03-03 08:59:20 -080085 fNeedsRewind = true;
halcanarya096d7a2015-03-27 12:16:53 -070086 if (!needsRewind) {
87 return kNoRewindNecessary_RewindState;
88 }
89 return fStream->rewind() ? kRewound_RewindState
90 : kCouldNotRewind_RewindState;
scroggof24f2242015-03-03 08:59:20 -080091}
scroggo05245902015-03-25 11:11:52 -070092
msarett9e43cab2015-04-29 07:38:43 -070093SkScanlineDecoder* SkCodec::getScanlineDecoder(const SkImageInfo& dstInfo, const Options* options,
94 SkPMColor ctable[], int* ctableCount) {
95
96 // Set options.
97 Options optsStorage;
98 if (NULL == options) {
99 options = &optsStorage;
100 }
101
102 fScanlineDecoder.reset(this->onGetScanlineDecoder(dstInfo, *options, ctable, ctableCount));
scroggo05245902015-03-25 11:11:52 -0700103 return fScanlineDecoder.get();
104}
msarett9e43cab2015-04-29 07:38:43 -0700105
106SkScanlineDecoder* SkCodec::getScanlineDecoder(const SkImageInfo& dstInfo) {
107 SkASSERT(kIndex_8_SkColorType != dstInfo.colorType());
108 if (kIndex_8_SkColorType == dstInfo.colorType()) {
109 return NULL;
110 }
111 return this->getScanlineDecoder(dstInfo, NULL, NULL, NULL);
112}