blob: 3e5ebe185091488cc45ec5bea0c65d70ca7e0578 [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
msarettb46e5e22015-07-30 11:36:40 -07008#include "SkBmpCodec.h"
scroggof24f2242015-03-03 08:59:20 -08009#include "SkCodec.h"
10#include "SkData.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)
scroggoeb602a52015-07-09 08:16:03 -070079 : fInfo(info)
scroggof24f2242015-03-03 08:59:20 -080080 , fStream(stream)
81 , fNeedsRewind(false)
82{}
83
scroggo9b2cdbf42015-07-10 12:07:02 -070084SkCodec::~SkCodec() {}
scroggoeb602a52015-07-09 08:16:03 -070085
scroggob427db12015-08-12 07:24:13 -070086bool SkCodec::rewindIfNeeded() {
scroggof24f2242015-03-03 08:59:20 -080087 // Store the value of fNeedsRewind so we can update it. Next read will
88 // require a rewind.
halcanarya096d7a2015-03-27 12:16:53 -070089 const bool needsRewind = fNeedsRewind;
scroggof24f2242015-03-03 08:59:20 -080090 fNeedsRewind = true;
halcanarya096d7a2015-03-27 12:16:53 -070091 if (!needsRewind) {
scroggob427db12015-08-12 07:24:13 -070092 return true;
halcanarya096d7a2015-03-27 12:16:53 -070093 }
scroggob427db12015-08-12 07:24:13 -070094
95 if (!fStream->rewind()) {
96 return false;
97 }
98
99 return this->onRewind();
scroggof24f2242015-03-03 08:59:20 -0800100}
scroggo05245902015-03-25 11:11:52 -0700101
scroggoeb602a52015-07-09 08:16:03 -0700102SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
103 const Options* options, SkPMColor ctable[], int* ctableCount) {
104 if (kUnknown_SkColorType == info.colorType()) {
105 return kInvalidConversion;
106 }
107 if (NULL == pixels) {
108 return kInvalidParameters;
109 }
110 if (rowBytes < info.minRowBytes()) {
111 return kInvalidParameters;
112 }
113
114 if (kIndex_8_SkColorType == info.colorType()) {
115 if (NULL == ctable || NULL == ctableCount) {
116 return kInvalidParameters;
117 }
118 } else {
119 if (ctableCount) {
120 *ctableCount = 0;
121 }
122 ctableCount = NULL;
123 ctable = NULL;
124 }
125
126 // Default options.
127 Options optsStorage;
128 if (NULL == options) {
129 options = &optsStorage;
130 }
131 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ctable, ctableCount);
132
133 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) {
134 SkASSERT(*ctableCount >= 0 && *ctableCount <= 256);
135 }
136 return result;
137}
138
139SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
scroggoeb602a52015-07-09 08:16:03 -0700140 return this->getPixels(info, pixels, rowBytes, NULL, NULL, NULL);
141}