blob: 86c067558f0d9b857d86ee8ce98f141fe852b416 [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:
msarett33c76232015-11-16 13:43:40 -080034 case kWBMP_SkEncodedFormat:
msarett887e18e2015-11-17 08:46:02 -080035 case kBMP_SkEncodedFormat:
msarett5af4e0b2015-11-17 11:18:03 -080036 case kGIF_SkEncodedFormat:
msarett3d9d7a72015-10-21 10:27:10 -070037 return new SkSampledCodec(codec.detach());
38 default:
39 // FIXME: SkSampledCodec is temporarily disabled for other formats
40 // while focusing on the formats that are supported by
41 // BitmapRegionDecoder.
42 return nullptr;
43 }
44}
45
46SkAndroidCodec* SkAndroidCodec::NewFromData(SkData* data) {
47 if (!data) {
48 return nullptr;
49 }
50
51 return NewFromStream(new SkMemoryStream(data));
52}
53
54SkISize SkAndroidCodec::getSampledDimensions(int sampleSize) const {
55 if (!is_valid_sample_size(sampleSize)) {
56 return SkISize::Make(0, 0);
57 }
58
scroggo501b7342015-11-03 07:55:11 -080059 // Fast path for when we are not scaling.
60 if (1 == sampleSize) {
61 return fInfo.dimensions();
62 }
63
msarett3d9d7a72015-10-21 10:27:10 -070064 return this->onGetSampledDimensions(sampleSize);
65}
66
67bool SkAndroidCodec::getSupportedSubset(SkIRect* desiredSubset) const {
68 if (!desiredSubset || !is_valid_subset(*desiredSubset, fInfo.dimensions())) {
69 return false;
70 }
71
72 return this->onGetSupportedSubset(desiredSubset);
73}
74
75SkISize SkAndroidCodec::getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const {
76 if (!is_valid_sample_size(sampleSize)) {
77 return SkISize::Make(0, 0);
78 }
79
80 // We require that the input subset is a subset that is supported by SkAndroidCodec.
81 // We test this by calling getSupportedSubset() and verifying that no modifications
82 // are made to the subset.
83 SkIRect copySubset = subset;
84 if (!this->getSupportedSubset(&copySubset) || copySubset != subset) {
85 return SkISize::Make(0, 0);
86 }
87
scroggo501b7342015-11-03 07:55:11 -080088 // If the subset is the entire image, for consistency, use getSampledDimensions().
msarett3d9d7a72015-10-21 10:27:10 -070089 if (fInfo.dimensions() == subset.size()) {
scroggo501b7342015-11-03 07:55:11 -080090 return this->getSampledDimensions(sampleSize);
msarett3d9d7a72015-10-21 10:27:10 -070091 }
92
93 // This should perhaps call a virtual function, but currently both of our subclasses
94 // want the same implementation.
95 return SkISize::Make(get_scaled_dimension(subset.width(), sampleSize),
96 get_scaled_dimension(subset.height(), sampleSize));
97}
98
99SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& info, void* pixels,
scroggoe95a0682015-11-04 04:31:12 -0800100 size_t rowBytes, const AndroidOptions* options) {
msarett3d9d7a72015-10-21 10:27:10 -0700101 if (!pixels) {
102 return SkCodec::kInvalidParameters;
103 }
104 if (rowBytes < info.minRowBytes()) {
105 return SkCodec::kInvalidParameters;
106 }
107
108 AndroidOptions defaultOptions;
109 if (!options) {
110 options = &defaultOptions;
111 } else if (options->fSubset) {
112 if (!is_valid_subset(*options->fSubset, fInfo.dimensions())) {
113 return SkCodec::kInvalidParameters;
114 }
scroggo501b7342015-11-03 07:55:11 -0800115
116 if (SkIRect::MakeSize(fInfo.dimensions()) == *options->fSubset) {
117 // The caller wants the whole thing, rather than a subset. Modify
118 // the AndroidOptions passed to onGetAndroidPixels to not specify
119 // a subset.
120 defaultOptions = *options;
121 defaultOptions.fSubset = nullptr;
122 options = &defaultOptions;
123 }
msarett3d9d7a72015-10-21 10:27:10 -0700124 }
125
126 return this->onGetAndroidPixels(info, pixels, rowBytes, *options);
127}
128
129SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& info, void* pixels,
130 size_t rowBytes) {
131 return this->getAndroidPixels(info, pixels, rowBytes, nullptr);
132}