blob: c24bb548baaaa712b5c5286a34d188175414ff1d [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"
msarett1c8a5872015-07-07 08:50:01 -070016#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
msarette16b04a2015-04-15 07:32:19 -070017#include "SkJpegCodec.h"
msarett1c8a5872015-07-07 08:50:01 -070018#endif
scroggof24f2242015-03-03 08:59:20 -080019#include "SkStream.h"
scroggo6f5e6192015-06-18 12:53:43 -070020#include "SkWebpCodec.h"
scroggof24f2242015-03-03 08:59:20 -080021
msarett74114382015-03-16 11:55:18 -070022struct DecoderProc {
23 bool (*IsFormat)(SkStream*);
24 SkCodec* (*NewFromStream)(SkStream*);
25};
26
27static const DecoderProc gDecoderProcs[] = {
28 { SkPngCodec::IsPng, SkPngCodec::NewFromStream },
msarett1c8a5872015-07-07 08:50:01 -070029#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
msarette16b04a2015-04-15 07:32:19 -070030 { SkJpegCodec::IsJpeg, SkJpegCodec::NewFromStream },
msarett1c8a5872015-07-07 08:50:01 -070031#endif
scroggo6f5e6192015-06-18 12:53:43 -070032 { SkWebpCodec::IsWebp, SkWebpCodec::NewFromStream },
msarett8c8f22a2015-04-01 06:58:48 -070033 { SkGifCodec::IsGif, SkGifCodec::NewFromStream },
msarett9bde9182015-03-25 05:27:48 -070034 { SkIcoCodec::IsIco, SkIcoCodec::NewFromStream },
halcanarya096d7a2015-03-27 12:16:53 -070035 { SkBmpCodec::IsBmp, SkBmpCodec::NewFromStream },
36 { SkWbmpCodec::IsWbmp, SkWbmpCodec::NewFromStream }
msarett74114382015-03-16 11:55:18 -070037};
38
scroggof24f2242015-03-03 08:59:20 -080039SkCodec* SkCodec::NewFromStream(SkStream* stream) {
40 if (!stream) {
41 return NULL;
42 }
scroggo0a7e69c2015-04-03 07:22:22 -070043
44 SkAutoTDelete<SkStream> streamDeleter(stream);
msarett8c8f22a2015-04-01 06:58:48 -070045
scroggo0a7e69c2015-04-03 07:22:22 -070046 SkAutoTDelete<SkCodec> codec(NULL);
msarett74114382015-03-16 11:55:18 -070047 for (uint32_t i = 0; i < SK_ARRAY_COUNT(gDecoderProcs); i++) {
48 DecoderProc proc = gDecoderProcs[i];
49 const bool correctFormat = proc.IsFormat(stream);
50 if (!stream->rewind()) {
51 return NULL;
52 }
53 if (correctFormat) {
scroggo0a7e69c2015-04-03 07:22:22 -070054 codec.reset(proc.NewFromStream(streamDeleter.detach()));
msarett8c8f22a2015-04-01 06:58:48 -070055 break;
msarett74114382015-03-16 11:55:18 -070056 }
scroggof24f2242015-03-03 08:59:20 -080057 }
msarett8c8f22a2015-04-01 06:58:48 -070058
59 // Set the max size at 128 megapixels (512 MB for kN32).
60 // This is about 4x smaller than a test image that takes a few minutes for
61 // dm to decode and draw.
62 const int32_t maxSize = 1 << 27;
scroggo0a7e69c2015-04-03 07:22:22 -070063 if (codec && codec->getInfo().width() * codec->getInfo().height() > maxSize) {
msarett8c8f22a2015-04-01 06:58:48 -070064 SkCodecPrintf("Error: Image size too large, cannot decode.\n");
65 return NULL;
66 } else {
scroggo0a7e69c2015-04-03 07:22:22 -070067 return codec.detach();
msarett8c8f22a2015-04-01 06:58:48 -070068 }
scroggof24f2242015-03-03 08:59:20 -080069}
70
71SkCodec* SkCodec::NewFromData(SkData* data) {
72 if (!data) {
73 return NULL;
74 }
75 return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data)));
76}
77
78SkCodec::SkCodec(const SkImageInfo& info, SkStream* stream)
reed3ef71e32015-03-19 08:31:14 -070079 : INHERITED(info)
scroggof24f2242015-03-03 08:59:20 -080080 , fStream(stream)
81 , fNeedsRewind(false)
82{}
83
halcanarya096d7a2015-03-27 12:16:53 -070084SkCodec::RewindState SkCodec::rewindIfNeeded() {
scroggof24f2242015-03-03 08:59:20 -080085 // Store the value of fNeedsRewind so we can update it. Next read will
86 // require a rewind.
halcanarya096d7a2015-03-27 12:16:53 -070087 const bool needsRewind = fNeedsRewind;
scroggof24f2242015-03-03 08:59:20 -080088 fNeedsRewind = true;
halcanarya096d7a2015-03-27 12:16:53 -070089 if (!needsRewind) {
90 return kNoRewindNecessary_RewindState;
91 }
92 return fStream->rewind() ? kRewound_RewindState
93 : kCouldNotRewind_RewindState;
scroggof24f2242015-03-03 08:59:20 -080094}
scroggo05245902015-03-25 11:11:52 -070095
msarett9e43cab2015-04-29 07:38:43 -070096SkScanlineDecoder* SkCodec::getScanlineDecoder(const SkImageInfo& dstInfo, const Options* options,
97 SkPMColor ctable[], int* ctableCount) {
98
99 // Set options.
100 Options optsStorage;
101 if (NULL == options) {
102 options = &optsStorage;
103 }
104
105 fScanlineDecoder.reset(this->onGetScanlineDecoder(dstInfo, *options, ctable, ctableCount));
scroggo05245902015-03-25 11:11:52 -0700106 return fScanlineDecoder.get();
107}
msarett9e43cab2015-04-29 07:38:43 -0700108
109SkScanlineDecoder* SkCodec::getScanlineDecoder(const SkImageInfo& dstInfo) {
110 SkASSERT(kIndex_8_SkColorType != dstInfo.colorType());
111 if (kIndex_8_SkColorType == dstInfo.colorType()) {
112 return NULL;
113 }
114 return this->getScanlineDecoder(dstInfo, NULL, NULL, NULL);
115}