BitmapRegionDecoder.cpp revision 6b849e2123be98eb2a1a25b8abf0b13a279ce952
16b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen/* 26b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * Copyright (C) 2010 The Android Open Source Project 36b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * 46b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License"); 56b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * you may not use this file except in compliance with the License. 66b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * You may obtain a copy of the License at 76b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * 86b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * http://www.apache.org/licenses/LICENSE-2.0 96b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * 106b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * Unless required by applicable law or agreed to in writing, software 116b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS, 126b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * See the License for the specific language governing permissions and 146b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * limitations under the License. 156b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen */ 166b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 176b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#define LOG_TAG "BitmapRegionDecoder" 186b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 196b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkBitmap.h" 206b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkImageEncoder.h" 216b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "GraphicsJNI.h" 226b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkUtils.h" 236b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkTemplates.h" 246b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkPixelRef.h" 256b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkStream.h" 266b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "BitmapFactory.h" 276b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "AutoDecodeCancel.h" 286b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkBitmapRegionDecoder.h" 296b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h" 306b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "Utils.h" 316b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 326b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <android_runtime/AndroidRuntime.h> 336b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "android_util_Binder.h" 346b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "android_nio_utils.h" 356b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h" 366b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 376b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <binder/Parcel.h> 386b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <jni.h> 396b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <utils/Asset.h> 406b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <sys/stat.h> 416b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 426b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jclass gFileDescriptor_class; 436b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jfieldID gFileDescriptor_descriptor; 446b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 456b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#if 0 466b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen #define TRACE_BITMAP(code) code 476b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#else 486b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen #define TRACE_BITMAP(code) 496b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#endif 506b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 516b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenusing namespace android; 526b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 536b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic SkMemoryStream* buildSkMemoryStream(SkStream *stream) { 546b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen size_t bufferSize = 4096; 556b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen size_t streamLen = 0; 566b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen size_t len; 576b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen char* data = (char*)sk_malloc_throw(bufferSize); 586b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 596b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen while ((len = stream->read(data + streamLen, 606b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen bufferSize - streamLen)) != 0) { 616b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen streamLen += len; 626b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (streamLen == bufferSize) { 636b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen bufferSize *= 2; 646b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen data = (char*)sk_realloc_throw(data, bufferSize); 656b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 666b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 676b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen data = (char*)sk_realloc_throw(data, streamLen); 686b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkMemoryStream* streamMem = new SkMemoryStream(); 696b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen streamMem->setMemoryOwned(data, streamLen); 706b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return streamMem; 716b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 726b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 736b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) { 746b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkImageDecoder* decoder = SkImageDecoder::Factory(stream); 756b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen int width, height; 766b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (NULL == decoder) { 776b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen doThrowIOE(env, "Image format not supported"); 786b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return nullObjectReturn("SkImageDecoder::Factory returned null"); 796b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 806b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 816b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env, true); 826b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen decoder->setAllocator(javaAllocator); 836b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env); 846b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen decoder->setReporter(javaMemoryReporter); 856b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen javaAllocator->unref(); 866b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen javaMemoryReporter->unref(); 876b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 886b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (!decoder->buildTileIndex(stream, &width, &height)) { 896b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen char msg[100]; 906b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder", 916b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen decoder->getFormatName()); 926b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen doThrowIOE(env, msg); 936b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return nullObjectReturn("decoder->buildTileIndex returned false"); 946b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 956b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 966b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkBitmapRegionDecoder *bm = new SkBitmapRegionDecoder(decoder, width, height); 976b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 986b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return GraphicsJNI::createBitmapRegionDecoder(env, bm); 996b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 1006b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1016b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeNewInstanceFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray, 1026b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen int offset, int length, jboolean isShareable) { 1036b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen /* If isShareable we could decide to just wrap the java array and 1046b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen share it, but that means adding a globalref to the java array object 1056b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen For now we just always copy the array's data if isShareable. 1066b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen */ 1076b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen AutoJavaByteArray ar(env, byteArray); 1086b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true); 1096b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return doBuildTileIndex(env, stream); 1106b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 1116b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1126b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz, 1136b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jobject fileDescriptor, jboolean isShareable) { 1146b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen NPE_CHECK_RETURN_ZERO(env, fileDescriptor); 1156b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1166b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jint descriptor = env->GetIntField(fileDescriptor, 1176b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen gFileDescriptor_descriptor); 1186b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkStream *stream = NULL; 1196b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen struct stat fdStat; 1206b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen int newFD; 1216b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (fstat(descriptor, &fdStat) == -1) { 1226b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen doThrowIOE(env, "broken file descriptor"); 1236b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return nullObjectReturn("fstat return -1"); 1246b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 1256b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1266b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (isShareable && 1276b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen S_ISREG(fdStat.st_mode) && 1286b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen (newFD = ::dup(descriptor)) != -1) { 1296b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkFDStream* fdStream = new SkFDStream(newFD, true); 1306b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (!fdStream->isValid()) { 1316b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen fdStream->unref(); 1326b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return NULL; 1336b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 1346b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen stream = fdStream; 1356b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } else { 1366b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkFDStream* fdStream = new SkFDStream(descriptor, false); 1376b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (!fdStream->isValid()) { 1386b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen fdStream->unref(); 1396b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return NULL; 1406b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 1416b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen stream = buildSkMemoryStream(fdStream); 1426b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen fdStream->unref(); 1436b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 1446b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1456b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen /* Restore our offset when we leave, so we can be called more than once 1466b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen with the same descriptor. This is only required if we didn't dup the 1476b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen file descriptor, but it is OK to do it all the time. 1486b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen */ 1496b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen AutoFDSeek as(descriptor); 1506b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1516b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return doBuildTileIndex(env, stream); 1526b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 1536b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1546b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz, 1556b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jobject is, // InputStream 1566b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jbyteArray storage, // byte[] 1576b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jboolean isShareable) { 1586b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jobject largeBitmap = NULL; 1596b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024); 1606b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1616b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (stream) { 1626b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // for now we don't allow shareable with java inputstreams 1636b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkMemoryStream *mStream = buildSkMemoryStream(stream); 1646b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen largeBitmap = doBuildTileIndex(env, mStream); 1656b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen stream->unref(); 1666b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 1676b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return largeBitmap; 1686b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 1696b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1706b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz, 1716b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jint native_asset, // Asset 1726b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jboolean isShareable) { 1736b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkStream* stream, *assStream; 1746b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen Asset* asset = reinterpret_cast<Asset*>(native_asset); 1756b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen assStream = new AssetStreamAdaptor(asset); 1766b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen stream = buildSkMemoryStream(assStream); 1776b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen assStream->unref(); 1786b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return doBuildTileIndex(env, stream); 1796b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 1806b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1816b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen/* 1826b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * nine patch not supported 1836b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * 1846b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * purgeable not supported 1856b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * reportSizeToVM not supported 1866b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen */ 1876b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd, 1886b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen int start_x, int start_y, int width, int height, jobject options) { 1896b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkImageDecoder *decoder = brd->getDecoder(); 1906b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen int sampleSize = 1; 1916b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkBitmap::Config prefConfig = SkBitmap::kNo_Config; 1926b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen bool doDither = true; 1936b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 1946b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (NULL != options) { 1956b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); 1966b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // initialize these, in case we fail later on 1976b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen env->SetIntField(options, gOptions_widthFieldID, -1); 1986b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen env->SetIntField(options, gOptions_heightFieldID, -1); 1996b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen env->SetObjectField(options, gOptions_mimeFieldID, 0); 2006b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2016b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen jobject jconfig = env->GetObjectField(options, gOptions_configFieldID); 2026b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig); 2036b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen doDither = env->GetBooleanField(options, gOptions_ditherFieldID); 2046b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 2056b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2066b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen decoder->setDitherImage(doDither); 2076b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkBitmap* bitmap = new SkBitmap; 2086b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkAutoTDelete<SkBitmap> adb(bitmap); 2096b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen AutoDecoderCancel adc(options, decoder); 2106b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2116b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // To fix the race condition in case "requestCancelDecode" 2126b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // happens earlier than AutoDecoderCancel object is added 2136b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // to the gAutoDecoderCancelMutex linked list. 2146b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) { 2156b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return nullObjectReturn("gOptions_mCancelID");; 2166b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 2176b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2186b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkIRect region; 2196b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen region.fLeft = start_x; 2206b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen region.fTop = start_y; 2216b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen region.fRight = start_x + width; 2226b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen region.fBottom = start_y + height; 2236b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2246b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (!brd->decodeRegion(bitmap, region, prefConfig, sampleSize)) { 2256b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return nullObjectReturn("decoder->decodeRegion returned false"); 2266b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 2276b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2286b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // update options (if any) 2296b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen if (NULL != options) { 2306b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen env->SetIntField(options, gOptions_widthFieldID, bitmap->width()); 2316b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen env->SetIntField(options, gOptions_heightFieldID, bitmap->height()); 2326b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // TODO: set the mimeType field with the data from the codec. 2336b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // but how to reuse a set of strings, rather than allocating new one 2346b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // each time? 2356b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen env->SetObjectField(options, gOptions_mimeFieldID, 2366b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen getMimeTypeString(env, decoder->getFormat())); 2376b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen } 2386b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2396b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // detach bitmap from its autotdeleter, since we want to own it now 2406b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen adb.detach(); 2416b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2426b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen SkPixelRef* pr; 2436b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen pr = bitmap->pixelRef(); 2446b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // promise we will never change our pixels (great for sharing and pictures) 2456b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen pr->setImmutable(); 2466b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen // now create the java bitmap 2476b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return GraphicsJNI::createBitmap(env, bitmap, false, NULL); 2486b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 2496b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2506b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { 2516b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return brd->getHeight(); 2526b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 2536b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2546b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic int nativeGetWidth(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { 2556b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return brd->getWidth(); 2566b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 2576b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2586b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic void nativeClean(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { 2596b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen delete brd; 2606b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 2616b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2626b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen/////////////////////////////////////////////////////////////////////////////// 2636b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2646b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <android_runtime/AndroidRuntime.h> 2656b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2666b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic JNINativeMethod gBitmapRegionDecoderMethods[] = { 2676b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen { "nativeDecodeRegion", 2686b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;", 2696b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen (void*)nativeDecodeRegion}, 2706b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2716b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen { "nativeGetHeight", "(I)I", (void*)nativeGetHeight}, 2726b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2736b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen { "nativeGetWidth", "(I)I", (void*)nativeGetWidth}, 2746b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2756b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen { "nativeClean", "(I)V", (void*)nativeClean}, 2766b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2776b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen { "nativeNewInstance", 2786b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen "([BIIZ)Landroid/graphics/BitmapRegionDecoder;", 2796b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen (void*)nativeNewInstanceFromByteArray 2806b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen }, 2816b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2826b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen { "nativeNewInstance", 2836b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen "(Ljava/io/InputStream;[BZ)Landroid/graphics/BitmapRegionDecoder;", 2846b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen (void*)nativeNewInstanceFromStream 2856b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen }, 2866b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2876b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen { "nativeNewInstance", 2886b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen "(Ljava/io/FileDescriptor;Z)Landroid/graphics/BitmapRegionDecoder;", 2896b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen (void*)nativeNewInstanceFromFileDescriptor 2906b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen }, 2916b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2926b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen { "nativeNewInstance", 2936b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen "(IZ)Landroid/graphics/BitmapRegionDecoder;", 2946b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen (void*)nativeNewInstanceFromAsset 2956b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen }, 2966b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}; 2976b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 2986b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#define kClassPathName "android/graphics/BitmapRegionDecoder" 2996b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen 3006b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenint register_android_graphics_BitmapRegionDecoder(JNIEnv* env); 3016b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenint register_android_graphics_BitmapRegionDecoder(JNIEnv* env) 3026b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen{ 3036b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen return android::AndroidRuntime::registerNativeMethods(env, kClassPathName, 3046b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods)); 3056b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen} 306