blob: 086caf2d8129f30e00de197802e2358ff24a2a99 [file] [log] [blame]
msarett3d9d7a72015-10-21 10:27:10 -07001/*
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 "SkAndroidCodec.h"
9#include "SkCodec.h"
10#include "SkCodecPriv.h"
11#include "SkSampledCodec.h"
12#include "SkWebpAdapterCodec.h"
13
14static bool is_valid_sample_size(int sampleSize) {
15 // FIXME: As Leon has mentioned elsewhere, surely there is also a maximum sampleSize?
16 return sampleSize > 0;
17}
18
19SkAndroidCodec::SkAndroidCodec(const SkImageInfo& info)
20 : fInfo(info)
21{}
22
23SkAndroidCodec* SkAndroidCodec::NewFromStream(SkStream* stream) {
24 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
25 if (nullptr == codec) {
26 return nullptr;
27 }
28
29 switch (codec->getEncodedFormat()) {
30 case kWEBP_SkEncodedFormat:
31 return new SkWebpAdapterCodec((SkWebpCodec*) codec.detach());
32 case kPNG_SkEncodedFormat:
33 case kJPEG_SkEncodedFormat:
34 return new SkSampledCodec(codec.detach());
35 default:
36 // FIXME: SkSampledCodec is temporarily disabled for other formats
37 // while focusing on the formats that are supported by
38 // BitmapRegionDecoder.
39 return nullptr;
40 }
41}
42
43SkAndroidCodec* SkAndroidCodec::NewFromData(SkData* data) {
44 if (!data) {
45 return nullptr;
46 }
47
48 return NewFromStream(new SkMemoryStream(data));
49}
50
51SkISize SkAndroidCodec::getSampledDimensions(int sampleSize) const {
52 if (!is_valid_sample_size(sampleSize)) {
53 return SkISize::Make(0, 0);
54 }
55
scroggo501b7342015-11-03 07:55:11 -080056 // Fast path for when we are not scaling.
57 if (1 == sampleSize) {
58 return fInfo.dimensions();
59 }
60
msarett3d9d7a72015-10-21 10:27:10 -070061 return this->onGetSampledDimensions(sampleSize);
62}
63
64bool SkAndroidCodec::getSupportedSubset(SkIRect* desiredSubset) const {
65 if (!desiredSubset || !is_valid_subset(*desiredSubset, fInfo.dimensions())) {
66 return false;
67 }
68
69 return this->onGetSupportedSubset(desiredSubset);
70}
71
72SkISize SkAndroidCodec::getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const {
73 if (!is_valid_sample_size(sampleSize)) {
74 return SkISize::Make(0, 0);
75 }
76
77 // We require that the input subset is a subset that is supported by SkAndroidCodec.
78 // We test this by calling getSupportedSubset() and verifying that no modifications
79 // are made to the subset.
80 SkIRect copySubset = subset;
81 if (!this->getSupportedSubset(&copySubset) || copySubset != subset) {
82 return SkISize::Make(0, 0);
83 }
84
scroggo501b7342015-11-03 07:55:11 -080085 // If the subset is the entire image, for consistency, use getSampledDimensions().
msarett3d9d7a72015-10-21 10:27:10 -070086 if (fInfo.dimensions() == subset.size()) {
scroggo501b7342015-11-03 07:55:11 -080087 return this->getSampledDimensions(sampleSize);
msarett3d9d7a72015-10-21 10:27:10 -070088 }
89
90 // This should perhaps call a virtual function, but currently both of our subclasses
91 // want the same implementation.
92 return SkISize::Make(get_scaled_dimension(subset.width(), sampleSize),
93 get_scaled_dimension(subset.height(), sampleSize));
94}
95
96SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& info, void* pixels,
97 size_t rowBytes, AndroidOptions* options) {
98 if (!pixels) {
99 return SkCodec::kInvalidParameters;
100 }
101 if (rowBytes < info.minRowBytes()) {
102 return SkCodec::kInvalidParameters;
103 }
104
105 AndroidOptions defaultOptions;
106 if (!options) {
107 options = &defaultOptions;
108 } else if (options->fSubset) {
109 if (!is_valid_subset(*options->fSubset, fInfo.dimensions())) {
110 return SkCodec::kInvalidParameters;
111 }
scroggo501b7342015-11-03 07:55:11 -0800112
113 if (SkIRect::MakeSize(fInfo.dimensions()) == *options->fSubset) {
114 // The caller wants the whole thing, rather than a subset. Modify
115 // the AndroidOptions passed to onGetAndroidPixels to not specify
116 // a subset.
117 defaultOptions = *options;
118 defaultOptions.fSubset = nullptr;
119 options = &defaultOptions;
120 }
msarett3d9d7a72015-10-21 10:27:10 -0700121 }
122
123 return this->onGetAndroidPixels(info, pixels, rowBytes, *options);
124}
125
126SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& info, void* pixels,
127 size_t rowBytes) {
128 return this->getAndroidPixels(info, pixels, rowBytes, nullptr);
129}