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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 | 46 |
47 // returns a scaled dimension based on the original dimension and the sampleSize | 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 | 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) { | 49 static int get_scaled_dimension(int srcDimension, int sampleSize) { |
50 if (sampleSize > srcDimension) { | 50 if (sampleSize > srcDimension) { |
51 return 1; | 51 return 1; |
52 } | 52 } |
53 return srcDimension / sampleSize; | 53 return srcDimension / sampleSize; |
54 } | 54 } |
55 | 55 |
56 static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& na
tiveDims, | 56 static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& na
tiveDims, |
57 const SkISize& scaledCodecDims, float desi
redScale) { | 57 const SkISize& scaledCodecDims, float desi
redScale) { |
58 if (nativeDims == scaledCodecDims) { | 58 if (nativeDims == scaledCodecDims) { |
59 // does not matter which to return if equal. Return here to skip below c
alculations | 59 // does not matter which to return if equal. Return here to skip below c
alculations |
60 return nativeDims; | 60 return nativeDims; |
61 } | 61 } |
62 float idealWidth = origDims.width() * desiredScale; | 62 float idealWidth = origDims.width() * desiredScale; |
63 float idealHeight = origDims.height() * desiredScale; | 63 float idealHeight = origDims.height() * desiredScale; |
64 | 64 |
65 // calculate difference between native dimensions and ideal dimensions | 65 // calculate difference between native dimensions and ideal dimensions |
66 float nativeWDiff = SkTAbs(idealWidth - nativeDims.width()); | 66 float nativeWDiff = SkTAbs(idealWidth - nativeDims.width()); |
67 float nativeHDiff = SkTAbs(idealHeight - nativeDims.height()); | 67 float nativeHDiff = SkTAbs(idealHeight - nativeDims.height()); |
68 float nativeDiff = (nativeWDiff + nativeHDiff) / 2; | 68 float nativeDiff = nativeWDiff + nativeHDiff; |
| 69 |
| 70 // Native scaling is preferred to sampling. If we can scale natively to |
| 71 // within one of the ideal value, we should choose to scale natively. |
| 72 if (nativeWDiff < 1.0f && nativeHDiff < 1.0f) { |
| 73 return nativeDims; |
| 74 } |
69 | 75 |
70 // calculate difference between scaledCodec dimensions and ideal dimensions | 76 // calculate difference between scaledCodec dimensions and ideal dimensions |
71 float scaledCodecWDiff = SkTAbs(idealWidth - scaledCodecDims.width()); | 77 float scaledCodecWDiff = SkTAbs(idealWidth - scaledCodecDims.width()); |
72 float scaledCodecHDiff = SkTAbs(idealHeight - scaledCodecDims.height()); | 78 float scaledCodecHDiff = SkTAbs(idealHeight - scaledCodecDims.height()); |
73 float scaledCodecDiff = (scaledCodecWDiff + scaledCodecHDiff) / 2; | 79 float scaledCodecDiff = scaledCodecWDiff + scaledCodecHDiff; |
74 | 80 |
75 // return dimensions closest to ideal dimensions. | 81 // return dimensions closest to ideal dimensions. |
76 // If the differences are equal, return nativeDims, as native scaling is mor
e efficient. | 82 // If the differences are equal, return nativeDims, as native scaling is mor
e efficient. |
77 return nativeDiff > scaledCodecDiff ? scaledCodecDims : nativeDims; | 83 return nativeDiff > scaledCodecDiff ? scaledCodecDims : nativeDims; |
| 84 } |
78 | 85 |
79 } | |
80 /* | 86 /* |
81 * Return a valid set of output dimensions for this decoder, given an input scal
e | 87 * Return a valid set of output dimensions for this decoder, given an input scal
e |
82 */ | 88 */ |
83 SkISize SkScaledCodec::onGetScaledDimensions(float desiredScale) const { | 89 SkISize SkScaledCodec::onGetScaledDimensions(float desiredScale) const { |
84 SkISize nativeDimensions = fScanlineDecoder->getScaledDimensions(desiredScal
e); | 90 SkISize nativeDimensions = fScanlineDecoder->getScaledDimensions(desiredScal
e); |
85 // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ... | 91 // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ... |
86 SkISize scaledCodecDimensions; | 92 SkISize scaledCodecDimensions; |
87 if (desiredScale > 0.5f) { | 93 if (desiredScale > 0.5f) { |
88 // sampleSize = 1 | 94 // sampleSize = 1 |
89 scaledCodecDimensions = fScanlineDecoder->getInfo().dimensions(); | 95 scaledCodecDimensions = fScanlineDecoder->getInfo().dimensions(); |
90 } | 96 } |
91 // sampleSize determines the step size between samples | 97 // sampleSize determines the step size between samples |
92 // Ex: sampleSize = 2, sample every second pixel in x and y directions | 98 // Ex: sampleSize = 2, sample every second pixel in x and y directions |
93 int sampleSize = int(1 / desiredScale); | 99 int sampleSize = int(1 / desiredScale); |
94 | 100 |
95 int scaledWidth = get_scaled_dimension(this->getInfo().width(), sampleSize); | 101 int scaledWidth = get_scaled_dimension(this->getInfo().width(), sampleSize); |
96 int scaledHeight = get_scaled_dimension(this->getInfo().height(), sampleSize
); | 102 int scaledHeight = get_scaled_dimension(this->getInfo().height(), sampleSize
); |
97 | 103 |
98 // Return the calculated output dimensions for the given scale | 104 // Return the calculated output dimensions for the given scale |
99 scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight); | 105 scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight); |
100 | 106 |
101 return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions
, | 107 return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions
, |
102 scaledCodecDimensions, desiredScale); | 108 scaledCodecDimensions, desiredScale); |
103 } | 109 } |
104 | 110 |
105 // check if scaling to dstInfo size from srcInfo size using sampleSize is possib
le | 111 // check if scaling to dstInfo size from srcInfo size using sampleSize is possib
le |
106 static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& src
Info, | 112 static bool scaling_supported(const SkImageInfo& dstInfo, const SkImageInfo& src
Info, |
107 int* sampleX, int* sampleY) { | 113 int* sampleX, int* sampleY) { |
108 SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, sampleX, sampleY); | 114 SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, sampleX, sampleY); |
109 const int dstWidth = dstInfo.width(); | 115 const int dstWidth = dstInfo.width(); |
110 const int dstHeight = dstInfo.height(); | 116 const int dstHeight = dstInfo.height(); |
111 const int srcWidth = srcInfo.width(); | 117 const int srcWidth = srcInfo.width(); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 result = fScanlineDecoder->skipScanlines(sampleY - 1); | 258 result = fScanlineDecoder->skipScanlines(sampleY - 1); |
253 if (kSuccess != result) { | 259 if (kSuccess != result) { |
254 return result; | 260 return result; |
255 } | 261 } |
256 } | 262 } |
257 dst = SkTAddOffset<void>(dst, rowBytes); | 263 dst = SkTAddOffset<void>(dst, rowBytes); |
258 } | 264 } |
259 } | 265 } |
260 return kSuccess; | 266 return kSuccess; |
261 } | 267 } |
OLD | NEW |