| 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 |