blob: 93db0e58eec0aea9c0b4d80354b671f1c80a225b [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"
scroggo6f5e6192015-06-18 12:53:43 -070018#include "SkWebpCodec.h"
scroggof24f2242015-03-03 08:59:20 -080019
msarett74114382015-03-16 11:55:18 -070020struct DecoderProc {
21 bool (*IsFormat)(SkStream*);
22 SkCodec* (*NewFromStream)(SkStream*);
23};
24
25static const DecoderProc gDecoderProcs[] = {
26 { SkPngCodec::IsPng, SkPngCodec::NewFromStream },
msarette16b04a2015-04-15 07:32:19 -070027 { SkJpegCodec::IsJpeg, SkJpegCodec::NewFromStream },
scroggo6f5e6192015-06-18 12:53:43 -070028 { SkWebpCodec::IsWebp, SkWebpCodec::NewFromStream },
msarett8c8f22a2015-04-01 06:58:48 -070029 { SkGifCodec::IsGif, SkGifCodec::NewFromStream },
msarett9bde9182015-03-25 05:27:48 -070030 { SkIcoCodec::IsIco, SkIcoCodec::NewFromStream },
halcanarya096d7a2015-03-27 12:16:53 -070031 { SkBmpCodec::IsBmp, SkBmpCodec::NewFromStream },
32 { SkWbmpCodec::IsWbmp, SkWbmpCodec::NewFromStream }
msarett74114382015-03-16 11:55:18 -070033};
34
scroggof24f2242015-03-03 08:59:20 -080035SkCodec* SkCodec::NewFromStream(SkStream* stream) {
36 if (!stream) {
37 return NULL;
38 }
scroggo0a7e69c2015-04-03 07:22:22 -070039
40 SkAutoTDelete<SkStream> streamDeleter(stream);
msarett8c8f22a2015-04-01 06:58:48 -070041
scroggo0a7e69c2015-04-03 07:22:22 -070042 SkAutoTDelete<SkCodec> codec(NULL);
msarett74114382015-03-16 11:55:18 -070043 for (uint32_t i = 0; i < SK_ARRAY_COUNT(gDecoderProcs); i++) {
44 DecoderProc proc = gDecoderProcs[i];
45 const bool correctFormat = proc.IsFormat(stream);
46 if (!stream->rewind()) {
47 return NULL;
48 }
49 if (correctFormat) {
scroggo0a7e69c2015-04-03 07:22:22 -070050 codec.reset(proc.NewFromStream(streamDeleter.detach()));
msarett8c8f22a2015-04-01 06:58:48 -070051 break;
msarett74114382015-03-16 11:55:18 -070052 }
scroggof24f2242015-03-03 08:59:20 -080053 }
msarett8c8f22a2015-04-01 06:58:48 -070054
55 // Set the max size at 128 megapixels (512 MB for kN32).
56 // This is about 4x smaller than a test image that takes a few minutes for
57 // dm to decode and draw.
58 const int32_t maxSize = 1 << 27;
scroggo0a7e69c2015-04-03 07:22:22 -070059 if (codec && codec->getInfo().width() * codec->getInfo().height() > maxSize) {
msarett8c8f22a2015-04-01 06:58:48 -070060 SkCodecPrintf("Error: Image size too large, cannot decode.\n");
61 return NULL;
62 } else {
scroggo0a7e69c2015-04-03 07:22:22 -070063 return codec.detach();
msarett8c8f22a2015-04-01 06:58:48 -070064 }
scroggof24f2242015-03-03 08:59:20 -080065}
66
67SkCodec* SkCodec::NewFromData(SkData* data) {
68 if (!data) {
69 return NULL;
70 }
71 return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data)));
72}
73
74SkCodec::SkCodec(const SkImageInfo& info, SkStream* stream)
reed3ef71e32015-03-19 08:31:14 -070075 : INHERITED(info)
scroggof24f2242015-03-03 08:59:20 -080076 , fStream(stream)
77 , fNeedsRewind(false)
78{}
79
halcanarya096d7a2015-03-27 12:16:53 -070080SkCodec::RewindState SkCodec::rewindIfNeeded() {
scroggof24f2242015-03-03 08:59:20 -080081 // Store the value of fNeedsRewind so we can update it. Next read will
82 // require a rewind.
halcanarya096d7a2015-03-27 12:16:53 -070083 const bool needsRewind = fNeedsRewind;
scroggof24f2242015-03-03 08:59:20 -080084 fNeedsRewind = true;
halcanarya096d7a2015-03-27 12:16:53 -070085 if (!needsRewind) {
86 return kNoRewindNecessary_RewindState;
87 }
88 return fStream->rewind() ? kRewound_RewindState
89 : kCouldNotRewind_RewindState;
scroggof24f2242015-03-03 08:59:20 -080090}
scroggo05245902015-03-25 11:11:52 -070091
msarett9e43cab2015-04-29 07:38:43 -070092SkScanlineDecoder* SkCodec::getScanlineDecoder(const SkImageInfo& dstInfo, const Options* options,
93 SkPMColor ctable[], int* ctableCount) {
94
95 // Set options.
96 Options optsStorage;
97 if (NULL == options) {
98 options = &optsStorage;
99 }
100
101 fScanlineDecoder.reset(this->onGetScanlineDecoder(dstInfo, *options, ctable, ctableCount));
scroggo05245902015-03-25 11:11:52 -0700102 return fScanlineDecoder.get();
103}
msarett9e43cab2015-04-29 07:38:43 -0700104
105SkScanlineDecoder* SkCodec::getScanlineDecoder(const SkImageInfo& dstInfo) {
106 SkASSERT(kIndex_8_SkColorType != dstInfo.colorType());
107 if (kIndex_8_SkColorType == dstInfo.colorType()) {
108 return NULL;
109 }
110 return this->getScanlineDecoder(dstInfo, NULL, NULL, NULL);
111}