BitmapRegionDecoder.cpp revision ed79ff0026a44741237a6eb5e3810dbf5d765154
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"
205827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger#include "SkData.h"
216b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkImageEncoder.h"
226b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "GraphicsJNI.h"
236b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkUtils.h"
246b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkTemplates.h"
256b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkPixelRef.h"
266b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "SkStream.h"
276b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "BitmapFactory.h"
286b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "AutoDecodeCancel.h"
296b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h"
306b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "Utils.h"
31a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes#include "JNIHelp.h"
326b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
336b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <android_runtime/AndroidRuntime.h>
346b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "android_util_Binder.h"
356b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "android_nio_utils.h"
366b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h"
376b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
386b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <binder/Parcel.h>
396b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <jni.h>
40b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/Asset.h>
416b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <sys/stat.h>
426b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
436b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#if 0
446b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    #define TRACE_BITMAP(code)  code
456b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#else
466b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    #define TRACE_BITMAP(code)
476b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#endif
486b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
496b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenusing namespace android;
506b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
515827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenbergerclass SkBitmapRegionDecoder {
525827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenbergerpublic:
535827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    SkBitmapRegionDecoder(SkImageDecoder* decoder, int width, int height) {
545827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger        fDecoder = decoder;
555827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger        fWidth = width;
565827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger        fHeight = height;
575827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    }
585827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    ~SkBitmapRegionDecoder() {
595827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger        SkDELETE(fDecoder);
605827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    }
615827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger
625827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect,
635827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger                      SkBitmap::Config pref, int sampleSize) {
645827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger        fDecoder->setSampleSize(sampleSize);
655827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger        return fDecoder->decodeRegion(bitmap, rect, pref);
665827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    }
675827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger
685827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    SkImageDecoder* getDecoder() const { return fDecoder; }
695827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    int getWidth() const { return fWidth; }
705827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    int getHeight() const { return fHeight; }
715827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger
725827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenbergerprivate:
735827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    SkImageDecoder* fDecoder;
745827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    int fWidth;
755827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    int fHeight;
765827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger};
775827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger
78ed79ff0026a44741237a6eb5e3810dbf5d765154Derek Sollenbergerstatic jobject createBitmapRegionDecoder(JNIEnv* env, SkStreamRewindable* stream) {
796b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
806b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    int width, height;
816b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    if (NULL == decoder) {
826b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        doThrowIOE(env, "Image format not supported");
836b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        return nullObjectReturn("SkImageDecoder::Factory returned null");
846b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    }
856b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
86e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env);
876b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    decoder->setAllocator(javaAllocator);
886b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    javaAllocator->unref();
896b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
906b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    if (!decoder->buildTileIndex(stream, &width, &height)) {
916b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        char msg[100];
926b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder",
936b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                decoder->getFormatName());
946b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        doThrowIOE(env, msg);
955827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger        SkDELETE(decoder);
966b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        return nullObjectReturn("decoder->buildTileIndex returned false");
976b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    }
986b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
995827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    SkBitmapRegionDecoder *bm = new SkBitmapRegionDecoder(decoder, width, height);
1006b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    return GraphicsJNI::createBitmapRegionDecoder(env, bm);
1016b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
1026b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1036b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeNewInstanceFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
1046b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                                     int offset, int length, jboolean isShareable) {
1056b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    /*  If isShareable we could decide to just wrap the java array and
1066b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        share it, but that means adding a globalref to the java array object
1076b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        For now we just always copy the array's data if isShareable.
1086b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen     */
1096b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    AutoJavaByteArray ar(env, byteArray);
110ed79ff0026a44741237a6eb5e3810dbf5d765154Derek Sollenberger    SkMemoryStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true);
1115827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger
1125827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    jobject brd = createBitmapRegionDecoder(env, stream);
1135827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    SkSafeUnref(stream); // the decoder now holds a reference
1145827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    return brd;
1156b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
1166b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1176b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz,
1186b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                                          jobject fileDescriptor, jboolean isShareable) {
1196b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
1206b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
121a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes    jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
1225827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger
1236b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    struct stat fdStat;
1246b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    if (fstat(descriptor, &fdStat) == -1) {
1256b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        doThrowIOE(env, "broken file descriptor");
1266b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        return nullObjectReturn("fstat return -1");
1276b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    }
1286b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1295827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    SkAutoTUnref<SkData> data(SkData::NewFromFD(descriptor));
1305827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    SkMemoryStream* stream = new SkMemoryStream(data);
1316b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1325827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    jobject brd = createBitmapRegionDecoder(env, stream);
1335827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    SkSafeUnref(stream); // the decoder now holds a reference
1345827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    return brd;
1356b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
1366b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1376b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
1386b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                                  jobject is,       // InputStream
1396b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                                  jbyteArray storage, // byte[]
1406b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                                  jboolean isShareable) {
1415827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    jobject brd = NULL;
142ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III    // for now we don't allow shareable with java inputstreams
143c7797525084ba0ea441e394aa0a2ba35d6ff3320Leon Scroggins III    SkStreamRewindable* stream = CopyJavaInputStream(env, is, storage);
1446b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1456b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    if (stream) {
146ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III        brd = createBitmapRegionDecoder(env, stream);
147ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III        stream->unref(); // the decoder now holds a reference
1486b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    }
1495827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    return brd;
1506b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
1516b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1526b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
1536b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                                 jint native_asset, // Asset
1546b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                                 jboolean isShareable) {
1556b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    Asset* asset = reinterpret_cast<Asset*>(native_asset);
156ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III    SkAutoTUnref<SkMemoryStream> stream(CopyAssetToStream(asset));
157ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III    if (NULL == stream.get()) {
158ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III        return NULL;
159ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III    }
1605827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger
161ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III    jobject brd = createBitmapRegionDecoder(env, stream.get());
162ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III    // The decoder now holds a reference to stream.
1635827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger    return brd;
1646b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
1656b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1666b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen/*
1676b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * nine patch not supported
1686b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen *
1696b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * purgeable not supported
1706b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * reportSizeToVM not supported
1716b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen */
1726b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd,
173f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin                                int start_x, int start_y, int width, int height, jobject options) {
174f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    jobject tileBitmap = NULL;
1756b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    SkImageDecoder *decoder = brd->getDecoder();
1766b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    int sampleSize = 1;
1776b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
1786b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    bool doDither = true;
179953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen    bool preferQualityOverSpeed = false;
1801abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik    bool requireUnpremultiplied = false;
1816b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1826b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    if (NULL != options) {
1836b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
1846b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        // initialize these, in case we fail later on
1856b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        env->SetIntField(options, gOptions_widthFieldID, -1);
1866b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        env->SetIntField(options, gOptions_heightFieldID, -1);
1876b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        env->SetObjectField(options, gOptions_mimeFieldID, 0);
1886b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1896b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
1906b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig);
1916b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        doDither = env->GetBooleanField(options, gOptions_ditherFieldID);
192953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen        preferQualityOverSpeed = env->GetBooleanField(options,
193953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen                gOptions_preferQualityOverSpeedFieldID);
194f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin        // Get the bitmap for re-use if it exists.
195f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin        tileBitmap = env->GetObjectField(options, gOptions_bitmapFieldID);
1962cc409ae52a2a50f54195579a000e98f403de9beLeon Scroggins III        requireUnpremultiplied = !env->GetBooleanField(options, gOptions_premultipliedFieldID);
1976b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    }
1986b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
1996b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    decoder->setDitherImage(doDither);
200953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen    decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
2011abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik    decoder->setRequireUnpremultipliedColors(requireUnpremultiplied);
2021abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik    AutoDecoderCancel adc(options, decoder);
2036b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2046b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    // To fix the race condition in case "requestCancelDecode"
2056b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    // happens earlier than AutoDecoderCancel object is added
2066b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    // to the gAutoDecoderCancelMutex linked list.
2076b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
2086b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        return nullObjectReturn("gOptions_mCancelID");;
2096b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    }
2106b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2116b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    SkIRect region;
2126b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    region.fLeft = start_x;
2136b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    region.fTop = start_y;
2146b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    region.fRight = start_x + width;
2156b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    region.fBottom = start_y + height;
216f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    SkBitmap* bitmap = NULL;
217f5b43bdc6231df8b646d5bbb215e639230f37260Mike Klein    SkAutoTDelete<SkBitmap> adb;
218f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin
219f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    if (tileBitmap != NULL) {
220f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin        // Re-use bitmap.
221f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin        bitmap = GraphicsJNI::getNativeBitmap(env, tileBitmap);
222f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    }
223f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    if (bitmap == NULL) {
224f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin        bitmap = new SkBitmap;
225f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin        adb.reset(bitmap);
226f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    }
2276b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2286b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    if (!brd->decodeRegion(bitmap, region, prefConfig, sampleSize)) {
2296b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        return nullObjectReturn("decoder->decodeRegion returned false");
2306b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    }
2316b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2326b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    // update options (if any)
2336b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    if (NULL != options) {
2346b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        env->SetIntField(options, gOptions_widthFieldID, bitmap->width());
2356b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        env->SetIntField(options, gOptions_heightFieldID, bitmap->height());
2366b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        // TODO: set the mimeType field with the data from the codec.
2376b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        // but how to reuse a set of strings, rather than allocating new one
2386b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        // each time?
2396b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        env->SetObjectField(options, gOptions_mimeFieldID,
2406b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen                            getMimeTypeString(env, decoder->getFormat()));
2416b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    }
2426b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
243f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    if (tileBitmap != NULL) {
244f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin        return tileBitmap;
245f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    }
2466b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
247f970c2e6de52ef0da91c3c8f3b48a44303d0eb73Owen Lin    // detach bitmap from its autodeleter, since we want to own it now
248f5b43bdc6231df8b646d5bbb215e639230f37260Mike Klein    adb.detach();
249e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
250afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy    JavaPixelAllocator* allocator = (JavaPixelAllocator*) decoder->getAllocator();
251afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy    jbyteArray buff = allocator->getStorageObjAndReset();
2521abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik
2531abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik    int bitmapCreateFlags = 0;
2541abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik    if (!requireUnpremultiplied) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied;
2551abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik    return GraphicsJNI::createBitmap(env, bitmap, buff, bitmapCreateFlags, NULL, NULL, -1);
2566b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
2576b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2586b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
2596b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    return brd->getHeight();
2606b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
2616b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2626b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic int nativeGetWidth(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
2636b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    return brd->getWidth();
2646b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
2656b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2666b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic void nativeClean(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
2676b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    delete brd;
2686b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
2696b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2706b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen///////////////////////////////////////////////////////////////////////////////
2716b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2726b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#include <android_runtime/AndroidRuntime.h>
2736b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2746b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenstatic JNINativeMethod gBitmapRegionDecoderMethods[] = {
2756b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    {   "nativeDecodeRegion",
2766b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
2776b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        (void*)nativeDecodeRegion},
2786b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2796b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    {   "nativeGetHeight", "(I)I", (void*)nativeGetHeight},
2806b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2816b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    {   "nativeGetWidth", "(I)I", (void*)nativeGetWidth},
2826b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2836b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    {   "nativeClean", "(I)V", (void*)nativeClean},
2846b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2856b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    {   "nativeNewInstance",
2866b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        "([BIIZ)Landroid/graphics/BitmapRegionDecoder;",
2876b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        (void*)nativeNewInstanceFromByteArray
2886b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    },
2896b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2906b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    {   "nativeNewInstance",
2916b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        "(Ljava/io/InputStream;[BZ)Landroid/graphics/BitmapRegionDecoder;",
2926b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        (void*)nativeNewInstanceFromStream
2936b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    },
2946b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
2956b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    {   "nativeNewInstance",
2966b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        "(Ljava/io/FileDescriptor;Z)Landroid/graphics/BitmapRegionDecoder;",
2976b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        (void*)nativeNewInstanceFromFileDescriptor
2986b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    },
2996b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
3006b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    {   "nativeNewInstance",
3016b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        "(IZ)Landroid/graphics/BitmapRegionDecoder;",
3026b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen        (void*)nativeNewInstanceFromAsset
3036b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    },
3046b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen};
3056b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
3066b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen#define kClassPathName  "android/graphics/BitmapRegionDecoder"
3076b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen
3086b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chenint register_android_graphics_BitmapRegionDecoder(JNIEnv* env)
3096b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen{
3106b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
3116b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen            gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods));
3126b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen}
313