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