125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen/* 225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * Copyright (C) 2010 The Android Open Source Project 325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * 425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License"); 525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * you may not use this file except in compliance with the License. 625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * You may obtain a copy of the License at 725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * 825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * http://www.apache.org/licenses/LICENSE-2.0 925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * 1025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * Unless required by applicable law or agreed to in writing, software 1125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS, 1225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * See the License for the specific language governing permissions and 1425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * limitations under the License. 1525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen */ 1625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 1725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#define LOG_TAG "BitmapRegionDecoder" 1825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 1925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkBitmap.h" 2025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkImageEncoder.h" 2125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "GraphicsJNI.h" 2225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkUtils.h" 2325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkTemplates.h" 2425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkPixelRef.h" 2525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkStream.h" 2625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "BitmapFactory.h" 2725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "AutoDecodeCancel.h" 2825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "SkBitmapRegionDecoder.h" 2925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h" 3025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "Utils.h" 3125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 3225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <android_runtime/AndroidRuntime.h> 3325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "android_util_Binder.h" 3425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "android_nio_utils.h" 3525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h" 3625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 3725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <binder/Parcel.h> 3825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <jni.h> 3925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <utils/Asset.h> 4025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <sys/stat.h> 4125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 4225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jclass gFileDescriptor_class; 4325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jfieldID gFileDescriptor_descriptor; 4425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 4525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#if 0 4625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen #define TRACE_BITMAP(code) code 4725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#else 4825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen #define TRACE_BITMAP(code) 4925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#endif 5025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 5125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenusing namespace android; 5225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 5325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic SkMemoryStream* buildSkMemoryStream(SkStream *stream) { 5425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen size_t bufferSize = 4096; 5525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen size_t streamLen = 0; 5625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen size_t len; 5725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen char* data = (char*)sk_malloc_throw(bufferSize); 5825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 5925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen while ((len = stream->read(data + streamLen, 6025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen bufferSize - streamLen)) != 0) { 6125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen streamLen += len; 6225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (streamLen == bufferSize) { 6325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen bufferSize *= 2; 6425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen data = (char*)sk_realloc_throw(data, bufferSize); 6525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 6625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 6725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen data = (char*)sk_realloc_throw(data, streamLen); 6825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 6925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkMemoryStream* streamMem = new SkMemoryStream(); 7025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen streamMem->setMemoryOwned(data, streamLen); 7125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return streamMem; 7225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 7325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 7425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) { 7525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkImageDecoder* decoder = SkImageDecoder::Factory(stream); 7625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen int width, height; 7725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (NULL == decoder) { 7825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen doThrowIOE(env, "Image format not supported"); 7925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return nullObjectReturn("SkImageDecoder::Factory returned null"); 8025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 8125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 8225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env, true); 8325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen decoder->setAllocator(javaAllocator); 8425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env); 8525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen decoder->setReporter(javaMemoryReporter); 8625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen javaAllocator->unref(); 8725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen javaMemoryReporter->unref(); 8825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 8925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (!decoder->buildTileIndex(stream, &width, &height)) { 9025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen char msg[100]; 9125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder", 9225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen decoder->getFormatName()); 9325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen doThrowIOE(env, msg); 9425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return nullObjectReturn("decoder->buildTileIndex returned false"); 9525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 9625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 9725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkBitmapRegionDecoder *bm = new SkBitmapRegionDecoder(decoder, width, height); 9825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 9925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return GraphicsJNI::createBitmapRegionDecoder(env, bm); 10025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 10125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 10225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeNewInstanceFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray, 10325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen int offset, int length, jboolean isShareable) { 10425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen /* If isShareable we could decide to just wrap the java array and 10525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen share it, but that means adding a globalref to the java array object 10625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen For now we just always copy the array's data if isShareable. 10725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen */ 10825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen AutoJavaByteArray ar(env, byteArray); 10925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true); 11025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return doBuildTileIndex(env, stream); 11125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 11225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 11325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz, 11425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jobject fileDescriptor, jboolean isShareable) { 11525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen NPE_CHECK_RETURN_ZERO(env, fileDescriptor); 11625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 11725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jint descriptor = env->GetIntField(fileDescriptor, 11825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen gFileDescriptor_descriptor); 11925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkStream *stream = NULL; 12025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen struct stat fdStat; 12125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen int newFD; 12225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (fstat(descriptor, &fdStat) == -1) { 12325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen doThrowIOE(env, "broken file descriptor"); 12425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return nullObjectReturn("fstat return -1"); 12525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 12625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 12725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (isShareable && 12825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen S_ISREG(fdStat.st_mode) && 12925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen (newFD = ::dup(descriptor)) != -1) { 13025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkFDStream* fdStream = new SkFDStream(newFD, true); 13125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (!fdStream->isValid()) { 13225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen fdStream->unref(); 13325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return NULL; 13425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 13525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen stream = fdStream; 13625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } else { 13725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen /* Restore our offset when we leave, so we can be called more than once 13825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen with the same descriptor. This is only required if we didn't dup the 13925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen file descriptor, but it is OK to do it all the time. 14025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen */ 14125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen AutoFDSeek as(descriptor); 14225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 14325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkFDStream* fdStream = new SkFDStream(descriptor, false); 14425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (!fdStream->isValid()) { 14525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen fdStream->unref(); 14625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return NULL; 14725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 14825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen stream = buildSkMemoryStream(fdStream); 14925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen fdStream->unref(); 15025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 15125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 15225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return doBuildTileIndex(env, stream); 15325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 15425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 15525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz, 15625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jobject is, // InputStream 15725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jbyteArray storage, // byte[] 15825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jboolean isShareable) { 15925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jobject largeBitmap = NULL; 16025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024); 16125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 16225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (stream) { 16325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // for now we don't allow shareable with java inputstreams 16425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkMemoryStream *mStream = buildSkMemoryStream(stream); 16525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen largeBitmap = doBuildTileIndex(env, mStream); 16625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen stream->unref(); 16725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 16825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return largeBitmap; 16925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 17025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 17125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz, 17225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jint native_asset, // Asset 17325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jboolean isShareable) { 17425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkStream* stream, *assStream; 17525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen Asset* asset = reinterpret_cast<Asset*>(native_asset); 17625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen assStream = new AssetStreamAdaptor(asset); 17725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen stream = buildSkMemoryStream(assStream); 17825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen assStream->unref(); 17925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return doBuildTileIndex(env, stream); 18025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 18125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 18225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen/* 18325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * nine patch not supported 18425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * 18525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * purgeable not supported 18625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen * reportSizeToVM not supported 18725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen */ 18825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd, 18925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen int start_x, int start_y, int width, int height, jobject options) { 19025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkImageDecoder *decoder = brd->getDecoder(); 19125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen int sampleSize = 1; 19225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkBitmap::Config prefConfig = SkBitmap::kNo_Config; 19325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen bool doDither = true; 19425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen bool preferQualityOverSpeed = false; 19525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 19625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (NULL != options) { 19725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); 19825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // initialize these, in case we fail later on 19925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen env->SetIntField(options, gOptions_widthFieldID, -1); 20025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen env->SetIntField(options, gOptions_heightFieldID, -1); 20125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen env->SetObjectField(options, gOptions_mimeFieldID, 0); 20225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 20325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jobject jconfig = env->GetObjectField(options, gOptions_configFieldID); 20425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig); 20525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen doDither = env->GetBooleanField(options, gOptions_ditherFieldID); 20625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen preferQualityOverSpeed = env->GetBooleanField(options, 20725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen gOptions_preferQualityOverSpeedFieldID); 20825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 20925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 21025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen decoder->setDitherImage(doDither); 21125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen decoder->setPreferQualityOverSpeed(preferQualityOverSpeed); 21225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkBitmap* bitmap = new SkBitmap; 21325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkAutoTDelete<SkBitmap> adb(bitmap); 21425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen AutoDecoderCancel adc(options, decoder); 21525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 21625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // To fix the race condition in case "requestCancelDecode" 21725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // happens earlier than AutoDecoderCancel object is added 21825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // to the gAutoDecoderCancelMutex linked list. 21925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) { 22025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return nullObjectReturn("gOptions_mCancelID");; 22125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 22225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 22325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkIRect region; 22425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen region.fLeft = start_x; 22525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen region.fTop = start_y; 22625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen region.fRight = start_x + width; 22725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen region.fBottom = start_y + height; 22825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 22925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (!brd->decodeRegion(bitmap, region, prefConfig, sampleSize)) { 23025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return nullObjectReturn("decoder->decodeRegion returned false"); 23125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 23225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 23325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // update options (if any) 23425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen if (NULL != options) { 23525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen env->SetIntField(options, gOptions_widthFieldID, bitmap->width()); 23625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen env->SetIntField(options, gOptions_heightFieldID, bitmap->height()); 23725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // TODO: set the mimeType field with the data from the codec. 23825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // but how to reuse a set of strings, rather than allocating new one 23925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // each time? 24025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen env->SetObjectField(options, gOptions_mimeFieldID, 24125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen getMimeTypeString(env, decoder->getFormat())); 24225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen } 24325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 24425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // detach bitmap from its autotdeleter, since we want to own it now 24525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen adb.detach(); 24625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 24725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkPixelRef* pr; 24825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen pr = bitmap->pixelRef(); 24925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // promise we will never change our pixels (great for sharing and pictures) 25025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen pr->setImmutable(); 25125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen // now create the java bitmap 25225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return GraphicsJNI::createBitmap(env, bitmap, false, NULL); 25325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 25425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 25525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { 25625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return brd->getHeight(); 25725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 25825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 25925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic int nativeGetWidth(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { 26025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return brd->getWidth(); 26125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 26225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 26325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic void nativeClean(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { 26425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen delete brd; 26525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 26625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 26725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen/////////////////////////////////////////////////////////////////////////////// 26825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 26925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#include <android_runtime/AndroidRuntime.h> 27025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 27125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic JNINativeMethod gBitmapRegionDecoderMethods[] = { 27225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen { "nativeDecodeRegion", 27325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;", 27425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen (void*)nativeDecodeRegion}, 27525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 27625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen { "nativeGetHeight", "(I)I", (void*)nativeGetHeight}, 27725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 27825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen { "nativeGetWidth", "(I)I", (void*)nativeGetWidth}, 27925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 28025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen { "nativeClean", "(I)V", (void*)nativeClean}, 28125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 28225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen { "nativeNewInstance", 28325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen "([BIIZ)Landroid/graphics/BitmapRegionDecoder;", 28425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen (void*)nativeNewInstanceFromByteArray 28525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen }, 28625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 28725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen { "nativeNewInstance", 28825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen "(Ljava/io/InputStream;[BZ)Landroid/graphics/BitmapRegionDecoder;", 28925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen (void*)nativeNewInstanceFromStream 29025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen }, 29125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 29225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen { "nativeNewInstance", 29325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen "(Ljava/io/FileDescriptor;Z)Landroid/graphics/BitmapRegionDecoder;", 29425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen (void*)nativeNewInstanceFromFileDescriptor 29525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen }, 29625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 29725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen { "nativeNewInstance", 29825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen "(IZ)Landroid/graphics/BitmapRegionDecoder;", 29925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen (void*)nativeNewInstanceFromAsset 30025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen }, 30125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen}; 30225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 30325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen#define kClassPathName "android/graphics/BitmapRegionDecoder" 30425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 30525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jclass make_globalref(JNIEnv* env, const char classname[]) { 30625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jclass c = env->FindClass(classname); 30725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkASSERT(c); 30825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return (jclass)env->NewGlobalRef(c); 30925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 31025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 31125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenstatic jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, 31225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen const char fieldname[], const char type[]) { 31325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen jfieldID id = env->GetFieldID(clazz, fieldname, type); 31425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen SkASSERT(id); 31525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return id; 31625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 31725bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 31825bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenint register_android_graphics_BitmapRegionDecoder(JNIEnv* env); 31925bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chenint register_android_graphics_BitmapRegionDecoder(JNIEnv* env) 32025bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen{ 32125bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen 32225bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor"); 32325bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I"); 32425bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen return android::AndroidRuntime::registerNativeMethods(env, kClassPathName, 32525bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods)); 32625bce3a673afef6a7858270afae4395b4ab53de3Wei-Ta Chen} 327