Fine scale the decoded result to match the desired sampleSize.

Bug: 27097032
Change-Id: Ie15a3116cdd6988524977e5390f6edbac224e502
This commit is contained in:
Anton Daubert
2016-03-07 17:30:20 +01:00
parent bf8f1cc3c0
commit 4e5ec34e98

View File

@@ -201,6 +201,26 @@ private:
const unsigned int mSize;
};
// Necessary for decodes when the native decoder cannot scale to appropriately match the sampleSize
// (for example, RAW). If the sampleSize divides evenly into the dimension, we require that the
// scale matches exactly. If sampleSize does not divide evenly, we allow the decoder to choose how
// best to round.
static bool needsFineScale(const int fullSize, const int decodedSize, const int sampleSize) {
if (fullSize % sampleSize == 0 && fullSize / sampleSize != decodedSize) {
return true;
} else if ((fullSize / sampleSize + 1) != decodedSize &&
(fullSize / sampleSize) != decodedSize) {
return true;
}
return false;
}
static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize,
const int sampleSize) {
return needsFineScale(fullSize.width(), decodedSize.width(), sampleSize) ||
needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
}
static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
// This function takes ownership of the input stream. Since the SkAndroidCodec
// will take ownership of the stream, we don't necessarily need to take ownership
@@ -250,7 +270,6 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
}
}
const bool willScale = scale != 1.0f;
// Create the codec.
NinePatchPeeker peeker;
@@ -269,15 +288,28 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
prefColorType = kN32_SkColorType;
}
// Determine the output size and return if the client only wants the size.
// Determine the output size.
SkISize size = codec->getSampledDimensions(sampleSize);
int scaledWidth = size.width();
int scaledHeight = size.height();
bool willScale = false;
// Apply a fine scaling step if necessary.
if (needsFineScale(codec->getInfo().dimensions(), size, sampleSize)) {
willScale = true;
scaledWidth = codec->getInfo().width() / sampleSize;
scaledHeight = codec->getInfo().height() / sampleSize;
}
// Set the options and return if the client only wants the size.
if (options != NULL) {
jstring mimeType = encodedFormatToString(env, codec->getEncodedFormat());
if (env->ExceptionCheck()) {
return nullObjectReturn("OOM in encodedFormatToString()");
}
env->SetIntField(options, gOptions_widthFieldID, size.width());
env->SetIntField(options, gOptions_heightFieldID, size.height());
env->SetIntField(options, gOptions_widthFieldID, scaledWidth);
env->SetIntField(options, gOptions_heightFieldID, scaledHeight);
env->SetObjectField(options, gOptions_mimeFieldID, mimeType);
if (onlyDecodeSize) {
@@ -285,6 +317,13 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
}
// Scale is necessary due to density differences.
if (scale != 1.0f) {
willScale = true;
scaledWidth = static_cast<int>(scaledWidth * scale + 0.5f);
scaledHeight = static_cast<int>(scaledHeight * scale + 0.5f);
}
android::Bitmap* reuseBitmap = nullptr;
unsigned int existingBufferSize = 0;
if (javaBitmap != NULL) {
@@ -381,13 +420,6 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
return nullObjectReturn("codec->getAndroidPixels() failed.");
}
int scaledWidth = size.width();
int scaledHeight = size.height();
if (willScale) {
scaledWidth = int(scaledWidth * scale + 0.5f);
scaledHeight = int(scaledHeight * scale + 0.5f);
}
jbyteArray ninePatchChunk = NULL;
if (peeker.mPatch != NULL) {
if (willScale) {