OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCodecPriv.h" | 8 #include "SkCodecPriv.h" |
9 #include "SkScaledCodec.h" | 9 #include "SkScaledCodec.h" |
10 #include "SkStream.h" | 10 #include "SkStream.h" |
(...skipping 26 matching lines...) Expand all Loading... | |
37 return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data))); | 37 return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data))); |
38 } | 38 } |
39 | 39 |
40 SkScaledCodec::SkScaledCodec(SkScanlineDecoder* scanlineDecoder) | 40 SkScaledCodec::SkScaledCodec(SkScanlineDecoder* scanlineDecoder) |
41 : INHERITED(scanlineDecoder->getInfo(), NULL) | 41 : INHERITED(scanlineDecoder->getInfo(), NULL) |
42 , fScanlineDecoder(scanlineDecoder) | 42 , fScanlineDecoder(scanlineDecoder) |
43 {} | 43 {} |
44 | 44 |
45 SkScaledCodec::~SkScaledCodec() {} | 45 SkScaledCodec::~SkScaledCodec() {} |
46 | 46 |
47 // returns a scaled dimension based on the original dimension and the sampleSize | |
48 // NOTE: we round down here for scaled dimension to match the behavior of SkImag eDecoder | |
49 static int get_scaled_dimension(int srcDimension, int sampleSize) { | |
50 if (sampleSize > srcDimension) { | |
51 return 1; | |
52 } | |
53 return srcDimension / sampleSize; | |
54 } | |
55 | |
56 static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& na tiveDims, | 47 static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& na tiveDims, |
57 const SkISize& scaledCodecDims, float desi redScale) { | 48 const SkISize& scaledCodecDims, float desi redScale) { |
58 if (nativeDims == scaledCodecDims) { | 49 if (nativeDims == scaledCodecDims) { |
59 // does not matter which to return if equal. Return here to skip below c alculations | 50 // does not matter which to return if equal. Return here to skip below c alculations |
60 return nativeDims; | 51 return nativeDims; |
61 } | 52 } |
62 float idealWidth = origDims.width() * desiredScale; | 53 float idealWidth = origDims.width() * desiredScale; |
63 float idealHeight = origDims.height() * desiredScale; | 54 float idealHeight = origDims.height() * desiredScale; |
64 | 55 |
65 // calculate difference between native dimensions and ideal dimensions | 56 // calculate difference between native dimensions and ideal dimensions |
(...skipping 25 matching lines...) Expand all Loading... | |
91 // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ... | 82 // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ... |
92 SkISize scaledCodecDimensions; | 83 SkISize scaledCodecDimensions; |
93 if (desiredScale > 0.5f) { | 84 if (desiredScale > 0.5f) { |
94 // sampleSize = 1 | 85 // sampleSize = 1 |
95 scaledCodecDimensions = fScanlineDecoder->getInfo().dimensions(); | 86 scaledCodecDimensions = fScanlineDecoder->getInfo().dimensions(); |
96 } | 87 } |
97 // sampleSize determines the step size between samples | 88 // sampleSize determines the step size between samples |
98 // Ex: sampleSize = 2, sample every second pixel in x and y directions | 89 // Ex: sampleSize = 2, sample every second pixel in x and y directions |
99 int sampleSize = int(1 / desiredScale); | 90 int sampleSize = int(1 / desiredScale); |
100 | 91 |
101 int scaledWidth = get_scaled_dimension(this->getInfo().width(), sampleSize); | 92 int scaledWidth = SkScaledCodec::GetScaledDimension(this->getInfo().width(), sampleSize); |
102 int scaledHeight = get_scaled_dimension(this->getInfo().height(), sampleSize ); | 93 int scaledHeight = SkScaledCodec::GetScaledDimension(this->getInfo().height( ), sampleSize); |
103 | 94 |
104 // Return the calculated output dimensions for the given scale | 95 // Return the calculated output dimensions for the given scale |
105 scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight); | 96 scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight); |
106 | 97 |
107 return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions , | 98 return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions , |
108 scaledCodecDimensions, desiredScale); | 99 scaledCodecDimensions, desiredScale); |
109 } | 100 } |
110 | 101 |
111 // check if scaling to dstInfo size from srcInfo size using sampleSize is possib le | 102 // check if scaling to dstInfo size from srcInfo size using sampleSize is possib le |
112 static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& src Info, | 103 static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& src Info, |
113 int* sampleX, int* sampleY) { | 104 int* sampleX, int* sampleY) { |
114 SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, sampleX, sampleY); | 105 SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, sampleX, sampleY); |
115 const int dstWidth = dstInfo.width(); | 106 const int dstWidth = dstInfo.width(); |
116 const int dstHeight = dstInfo.height(); | 107 const int dstHeight = dstInfo.height(); |
117 const int srcWidth = srcInfo.width(); | 108 const int srcWidth = srcInfo.width(); |
118 const int srcHeight = srcInfo.height(); | 109 const int srcHeight = srcInfo.height(); |
119 // only support down sampling, not up sampling | 110 // only support down sampling, not up sampling |
120 if (dstWidth > srcWidth || dstHeight > srcHeight) { | 111 if (dstWidth > srcWidth || dstHeight > srcHeight) { |
121 return false; | 112 return false; |
122 } | 113 } |
123 // check that srcWidth is scaled down by an integer value | 114 // check that srcWidth is scaled down by an integer value |
124 if (get_scaled_dimension(srcWidth, *sampleX) != dstWidth) { | 115 if (SkScaledCodec::GetScaledDimension(srcWidth, *sampleX) != dstWidth) { |
125 return false; | 116 return false; |
126 } | 117 } |
127 // check that src height is scaled down by an integer value | 118 // check that src height is scaled down by an integer value |
128 if (get_scaled_dimension(srcHeight, *sampleY) != dstHeight) { | 119 if (SkScaledCodec::GetScaledDimension(srcHeight, *sampleY) != dstHeight) { |
129 return false; | 120 return false; |
130 } | 121 } |
131 // sampleX and sampleY should be equal unless the original sampleSize reques ted was larger | 122 // sampleX and sampleY should be equal unless the original sampleSize reques ted was larger |
132 // than srcWidth or srcHeight. If so, the result of this is dstWidth or dstH eight = 1. | 123 // than srcWidth or srcHeight. If so, the result of this is dstWidth or dstH eight = 1. |
133 // This functionality allows for tall thin images to still be scaled down by scaling factors. | 124 // This functionality allows for tall thin images to still be scaled down by scaling factors. |
134 if (*sampleX != *sampleY){ | 125 if (*sampleX != *sampleY){ |
135 if (1 != dstWidth && 1 != dstHeight) { | 126 if (1 != dstWidth && 1 != dstHeight) { |
136 return false; | 127 return false; |
137 } | 128 } |
138 } | 129 } |
139 return true; | 130 return true; |
140 } | 131 } |
141 | 132 |
133 // returns a scaled dimension based on the original dimension and the sampleSize | |
134 // NOTE: we round down here for scaled dimension to match the behavior of SkImag eDecoder | |
135 inline int SkScaledCodec::GetScaledDimension(int srcDimension, int sampleSize) { | |
136 if (sampleSize > srcDimension) { | |
137 return 1; | |
138 } | |
139 return srcDimension / sampleSize; | |
140 } | |
141 | |
142 inline int SkScaledCodec::GetStartCoord(int sampleFactor) { | 142 inline int SkScaledCodec::GetStartCoord(int sampleFactor) { |
143 return sampleFactor / 2; | 143 return sampleFactor / 2; |
144 } | 144 } |
145 | 145 |
146 inline int SkScaledCodec::GetDstCoord(int srcCoord, int sampleFactor) { | 146 inline int SkScaledCodec::GetDstCoord(int srcCoord, int sampleFactor) { |
147 return srcCoord / sampleFactor; | 147 return srcCoord / sampleFactor; |
148 } | 148 } |
149 | 149 |
150 bool SkScaledCodec::IsCoordNecessary(int srcCoord, int sampleFactor, int scaledD im) { | 150 bool SkScaledCodec::IsCoordNecessary(int srcCoord, int sampleFactor, int scaledD im) { |
151 // Get the first coordinate that we want to keep | 151 // Get the first coordinate that we want to keep |
(...skipping 30 matching lines...) Expand all Loading... | |
182 // allows for tall thin images to still be scaled down by scaling factors. | 182 // allows for tall thin images to still be scaled down by scaling factors. |
183 | 183 |
184 if (sampleX != sampleY){ | 184 if (sampleX != sampleY){ |
185 if (1 != dstWidth && 1 != dstHeight) { | 185 if (1 != dstWidth && 1 != dstHeight) { |
186 | 186 |
187 // rounding during onGetScaledDimensions can cause different sampleS izes | 187 // rounding during onGetScaledDimensions can cause different sampleS izes |
188 // Ex: srcWidth = 79, srcHeight = 20, sampleSize = 10 | 188 // Ex: srcWidth = 79, srcHeight = 20, sampleSize = 10 |
189 // dstWidth = 7, dstHeight = 2, sampleX = 79/7 = 11, sampleY = 20/2 = 10 | 189 // dstWidth = 7, dstHeight = 2, sampleX = 79/7 = 11, sampleY = 20/2 = 10 |
190 // correct for this rounding by comparing width to sampleY and heigh t to sampleX | 190 // correct for this rounding by comparing width to sampleY and heigh t to sampleX |
191 | 191 |
192 if (get_scaled_dimension(srcWidth, sampleY) == dstWidth) { | 192 if (SkScaledCodec::GetScaledDimension(srcWidth, sampleY) == dstWidth ) { |
193 sampleX = sampleY; | 193 sampleX = sampleY; |
194 } else if (get_scaled_dimension(srcHeight, sampleX) == dstHeight) { | 194 } else if (SkScaledCodec::GetScaledDimension(srcHeight, sampleX) == dstHeight) { |
195 sampleY = sampleX; | 195 sampleY = sampleX; |
196 } | 196 } |
197 } | 197 } |
198 } | 198 } |
199 | 199 |
200 if (sampleXPtr) { | 200 if (sampleXPtr) { |
201 *sampleXPtr = sampleX; | 201 *sampleXPtr = sampleX; |
202 } | 202 } |
203 if (sampleYPtr) { | 203 if (sampleYPtr) { |
204 *sampleYPtr = sampleY; | 204 *sampleYPtr = sampleY; |
205 } | 205 } |
206 } | 206 } |
207 | 207 |
208 // TODO: Implement subsetting in onGetPixels which works when and when not sampl ing | 208 // TODO: Implement subsetting in onGetPixels which works when and when not sampl ing |
209 | 209 |
210 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst, | 210 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst, |
211 size_t rowBytes, const Options& optio ns, | 211 size_t rowBytes, const Options& optio ns, |
212 SkPMColor ctable[], int* ctableCount) { | 212 SkPMColor ctable[], int* ctableCount) { |
213 | 213 |
214 if (options.fSubset) { | 214 if (options.fSubset) { |
215 // Subsets are not supported. | 215 // Subsets are not supported. |
216 return kUnimplemented; | 216 return kUnimplemented; |
217 } | 217 } |
218 | 218 |
219 Result result = fScanlineDecoder->start(requestedInfo, &options, ctable, cta bleCount); | 219 Result result = fScanlineDecoder->start(requestedInfo, &options, ctable, cta bleCount); |
220 if (kSuccess == result) { | 220 if (kSuccess == result) { |
221 // native decode supported | 221 // native decode supported |
222 return fScanlineDecoder->getScanlines(dst, requestedInfo.height(), rowBy tes); | 222 return fScanlineDecoder->getScanlines(dst, requestedInfo.height(), rowBy tes); |
msarett
2015/08/24 23:20:13
I need to add a switch statement here.
Interlaced
| |
223 } | 223 } |
224 | 224 |
225 if (kInvalidScale != result) { | 225 if (kInvalidScale != result) { |
226 // no scaling requested | 226 // no scaling requested |
227 return result; | 227 return result; |
228 } | 228 } |
229 | 229 |
230 // scaling requested | 230 // scaling requested |
231 int sampleX; | 231 int sampleX; |
232 int sampleY; | 232 int sampleY; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 storagePtr += sampleY * rowBytes; | 302 storagePtr += sampleY * rowBytes; |
303 dst = SkTAddOffset<void>(dst, rowBytes); | 303 dst = SkTAddOffset<void>(dst, rowBytes); |
304 } | 304 } |
305 return kSuccess; | 305 return kSuccess; |
306 } | 306 } |
307 default: | 307 default: |
308 SkASSERT(false); | 308 SkASSERT(false); |
309 return kUnimplemented; | 309 return kUnimplemented; |
310 } | 310 } |
311 } | 311 } |
OLD | NEW |