Skip to content

Commit 49b77c5

Browse files
author
AndroidDeveloperLB
committed
Initial commit
0 parents  commit 49b77c5

30 files changed

+579
-0
lines changed

.classpath

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
4+
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
5+
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
6+
<classpathentry kind="src" path="gen"/>
7+
<classpathentry kind="src" path="src"/>
8+
<classpathentry kind="output" path="bin/classes"/>
9+
</classpath>

.cproject

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
3+
<storageModule moduleId="org.eclipse.cdt.core.settings">
4+
<cconfiguration id="com.android.toolchain.gcc.57546648">
5+
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.android.toolchain.gcc.57546648" moduleId="org.eclipse.cdt.core.settings" name="Default">
6+
<externalSettings/>
7+
<extensions>
8+
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
9+
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
10+
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
11+
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
12+
<extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
13+
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
14+
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
15+
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
16+
</extensions>
17+
</storageModule>
18+
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
19+
<configuration artifactName="${ProjName}" buildProperties="" description="" id="com.android.toolchain.gcc.57546648" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
20+
<folderInfo id="com.android.toolchain.gcc.57546648.1077372323" name="/" resourcePath="">
21+
<toolChain id="com.android.toolchain.gcc.658165108" name="com.android.toolchain.gcc" superClass="com.android.toolchain.gcc">
22+
<targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="com.android.targetPlatform.1261067781" isAbstract="false" superClass="com.android.targetPlatform"/>
23+
<builder id="com.android.builder.1819182102" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Android Builder" superClass="com.android.builder">
24+
<outputEntries>
25+
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="obj"/>
26+
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="libs"/>
27+
</outputEntries>
28+
</builder>
29+
<tool id="com.android.gcc.compiler.1081164407" name="Android GCC Compiler" superClass="com.android.gcc.compiler">
30+
<inputType id="com.android.gcc.inputType.849779005" superClass="com.android.gcc.inputType"/>
31+
</tool>
32+
</toolChain>
33+
</folderInfo>
34+
<sourceEntries>
35+
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="jni"/>
36+
</sourceEntries>
37+
</configuration>
38+
</storageModule>
39+
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
40+
</cconfiguration>
41+
</storageModule>
42+
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
43+
<project id="JniBitmapStorageTest.null.1781276221" name="JniBitmapStorageTest"/>
44+
</storageModule>
45+
<storageModule moduleId="org.eclipse.cdt.core.pathentry"/>
46+
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
47+
<storageModule moduleId="scannerConfiguration">
48+
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
49+
<scannerConfigBuildInfo instanceId="com.android.toolchain.gcc.57546648;com.android.toolchain.gcc.57546648.1077372323;com.android.gcc.compiler.1081164407;com.android.gcc.inputType.849779005">
50+
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.android.AndroidPerProjectProfile"/>
51+
</scannerConfigBuildInfo>
52+
</storageModule>
53+
<storageModule moduleId="refreshScope"/>
54+
</cproject>

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/obj
2+
/bin
3+
/gen

.project

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>JniBitmapOperationsTest</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
10+
<triggers>clean,full,incremental,</triggers>
11+
<arguments>
12+
</arguments>
13+
</buildCommand>
14+
<buildCommand>
15+
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
16+
<arguments>
17+
</arguments>
18+
</buildCommand>
19+
<buildCommand>
20+
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
21+
<arguments>
22+
</arguments>
23+
</buildCommand>
24+
<buildCommand>
25+
<name>org.eclipse.jdt.core.javabuilder</name>
26+
<arguments>
27+
</arguments>
28+
</buildCommand>
29+
<buildCommand>
30+
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
31+
<arguments>
32+
</arguments>
33+
</buildCommand>
34+
<buildCommand>
35+
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
36+
<triggers>full,incremental,</triggers>
37+
<arguments>
38+
</arguments>
39+
</buildCommand>
40+
</buildSpec>
41+
<natures>
42+
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
43+
<nature>org.eclipse.jdt.core.javanature</nature>
44+
<nature>org.eclipse.cdt.core.cnature</nature>
45+
<nature>org.eclipse.cdt.core.ccnature</nature>
46+
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
47+
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
48+
</natures>
49+
</projectDescription>

AndroidManifest.xml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.jni.bitmap_operations" android:versionCode="1"
4+
android:versionName="1.0">
5+
6+
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" />
7+
8+
<application android:allowBackup="true" android:icon="@drawable/ic_launcher"
9+
android:label="@string/app_name" android:theme="@style/AppTheme">
10+
<activity android:name="com.jni.bitmap_operations.MainActivity"
11+
android:label="@string/app_name">
12+
<intent-filter>
13+
<action android:name="android.intent.action.MAIN" />
14+
15+
<category android:name="android.intent.category.LAUNCHER" />
16+
</intent-filter>
17+
</activity>
18+
</application>
19+
20+
</manifest>

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
AndroidJniBitmapOperations
2+
==========================
3+
4+
Allows to perform various simple operations on bitmaps via JNI , while also providing some protection against OOM using the native Java environment on Android
5+
6+
This library is currently fully based on a post I've made on StackOverflow here:
7+
http://stackoverflow.com/questions/18250951/jni-bitmap-operations-for-helping-to-avoid-oom-when-using-large-images/18250952?noredirect=1
8+
9+
Please read all of its notes.

ic_launcher-web.png

50.2 KB
Loading

jni/Android.mk

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
LOCAL_PATH := $(call my-dir)
2+
3+
#bitmap operations module
4+
include $(CLEAR_VARS)
5+
6+
LOCAL_MODULE := JniBitmapOperations
7+
LOCAL_SRC_FILES := JniBitmapOperations.cpp
8+
LOCAL_LDLIBS := -llog
9+
LOCAL_LDFLAGS += -ljnigraphics
10+
11+
include $(BUILD_SHARED_LIBRARY)
12+
APP_OPTIM := debug
13+
LOCAL_CFLAGS := -g
14+
15+
#if you need to add more module, do the same as the one we started with (the one with the CLEAR_VARS)

jni/JniBitmapOperations.cpp

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#include <jni.h>
2+
#include <jni.h>
3+
#include <android/log.h>
4+
#include <stdio.h>
5+
#include <android/bitmap.h>
6+
#include <cstring>
7+
#include <unistd.h>
8+
9+
#define LOG_TAG "DEBUG"
10+
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
11+
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
12+
13+
extern "C"
14+
{
15+
JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap);
16+
JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle);
17+
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle);
18+
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle);
19+
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom);
20+
}
21+
22+
class JniBitmap
23+
{
24+
public:
25+
uint32_t* _storedBitmapPixels;
26+
AndroidBitmapInfo _bitmapInfo;
27+
JniBitmap()
28+
{
29+
_storedBitmapPixels = NULL;
30+
}
31+
};
32+
33+
/**crops the bitmap within to be smaller. note that no validations are done*/ //
34+
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom)
35+
{
36+
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
37+
if (jniBitmap->_storedBitmapPixels == NULL)
38+
return;
39+
uint32_t* previousData = jniBitmap->_storedBitmapPixels;
40+
uint32_t oldWidth = jniBitmap->_bitmapInfo.width;
41+
uint32_t newWidth = right - left, newHeight = bottom - top;
42+
uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
43+
uint32_t* whereToGet = previousData + left + top * oldWidth;
44+
uint32_t* whereToPut = newBitmapPixels;
45+
for (int y = top; y < bottom; ++y)
46+
{
47+
memcpy(whereToPut, whereToGet, sizeof(uint32_t) * newWidth);
48+
whereToGet += oldWidth;
49+
whereToPut += newWidth;
50+
}
51+
//done copying , so replace old data with new one
52+
delete[] previousData;
53+
jniBitmap->_storedBitmapPixels = newBitmapPixels;
54+
jniBitmap->_bitmapInfo.width = newWidth;
55+
jniBitmap->_bitmapInfo.height = newHeight;
56+
}
57+
58+
/**rotates the inner bitmap data by 90 degress counter clock wise*/ //
59+
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle)
60+
{
61+
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
62+
if (jniBitmap->_storedBitmapPixels == NULL)
63+
return;
64+
uint32_t* previousData = jniBitmap->_storedBitmapPixels;
65+
AndroidBitmapInfo bitmapInfo = jniBitmap->_bitmapInfo;
66+
uint32_t* newBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
67+
int whereToPut = 0;
68+
// X.. ...
69+
// ...>...
70+
// ... X..
71+
for (int x = bitmapInfo.width - 1; x >= 0; --x)
72+
for (int y = 0; y < bitmapInfo.height; ++y)
73+
{
74+
uint32_t pixel = previousData[bitmapInfo.width * y + x];
75+
newBitmapPixels[whereToPut++] = pixel;
76+
}
77+
delete[] previousData;
78+
jniBitmap->_storedBitmapPixels = newBitmapPixels;
79+
uint32_t temp = bitmapInfo.width;
80+
bitmapInfo.width = bitmapInfo.height;
81+
bitmapInfo.height = temp;
82+
}
83+
84+
/**free bitmap*/ //
85+
JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle)
86+
{
87+
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
88+
if (jniBitmap->_storedBitmapPixels == NULL)
89+
return;
90+
delete[] jniBitmap->_storedBitmapPixels;
91+
jniBitmap->_storedBitmapPixels = NULL;
92+
delete jniBitmap;
93+
}
94+
95+
/**restore java bitmap (from JNI data)*/ //
96+
JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle)
97+
{
98+
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
99+
if (jniBitmap->_storedBitmapPixels == NULL)
100+
{
101+
LOGD("no bitmap data was stored. returning null...");
102+
return NULL;
103+
}
104+
//
105+
//creating a new bitmap to put the pixels into it - using Bitmap Bitmap.createBitmap (int width, int height, Bitmap.Config config) :
106+
//
107+
//LOGD("creating new bitmap...");
108+
jclass bitmapCls = env->FindClass("android/graphics/Bitmap");
109+
jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
110+
jstring configName = env->NewStringUTF("ARGB_8888");
111+
jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
112+
jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
113+
jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass, valueOfBitmapConfigFunction, configName);
114+
jobject newBitmap = env->CallStaticObjectMethod(bitmapCls, createBitmapFunction, jniBitmap->_bitmapInfo.height, jniBitmap->_bitmapInfo.width, bitmapConfig);
115+
//
116+
// putting the pixels into the new bitmap:
117+
//
118+
int ret;
119+
void* bitmapPixels;
120+
if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &bitmapPixels)) < 0)
121+
{
122+
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
123+
return NULL;
124+
}
125+
uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels;
126+
int pixelsCount = jniBitmap->_bitmapInfo.height * jniBitmap->_bitmapInfo.width;
127+
memcpy(newBitmapPixels, jniBitmap->_storedBitmapPixels, sizeof(uint32_t) * pixelsCount);
128+
AndroidBitmap_unlockPixels(env, newBitmap);
129+
//LOGD("returning the new bitmap");
130+
return newBitmap;
131+
}
132+
133+
/**store java bitmap as JNI data*/ //
134+
JNIEXPORT jobject JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap)
135+
{
136+
AndroidBitmapInfo bitmapInfo;
137+
uint32_t* storedBitmapPixels = NULL;
138+
//LOGD("reading bitmap info...");
139+
int ret;
140+
if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0)
141+
{
142+
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
143+
return NULL;
144+
}
145+
LOGD("width:%d height:%d stride:%d", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride);
146+
if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
147+
{
148+
LOGE("Bitmap format is not RGBA_8888!");
149+
return NULL;
150+
}
151+
//
152+
//read pixels of bitmap into native memory :
153+
//
154+
//LOGD("reading bitmap pixels...");
155+
void* bitmapPixels;
156+
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0)
157+
{
158+
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
159+
return NULL;
160+
}
161+
uint32_t* src = (uint32_t*) bitmapPixels;
162+
storedBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
163+
int pixelsCount = bitmapInfo.height * bitmapInfo.width;
164+
memcpy(storedBitmapPixels, src, sizeof(uint32_t) * pixelsCount);
165+
AndroidBitmap_unlockPixels(env, bitmap);
166+
JniBitmap *jniBitmap = new JniBitmap();
167+
jniBitmap->_bitmapInfo = bitmapInfo;
168+
jniBitmap->_storedBitmapPixels = storedBitmapPixels;
169+
return env->NewDirectByteBuffer(jniBitmap, 0);
170+
}
171+

libs/android-support-v4.jar

473 KB
Binary file not shown.
17.1 KB
Binary file not shown.

lint.xml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<lint>
3+
</lint>

proguard-project.txt

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# To enable ProGuard in your project, edit project.properties
2+
# to define the proguard.config property as described in that file.
3+
#
4+
# Add project specific ProGuard rules here.
5+
# By default, the flags in this file are appended to flags specified
6+
# in ${sdk.dir}/tools/proguard/proguard-android.txt
7+
# You can edit the include path and order by changing the ProGuard
8+
# include property in project.properties.
9+
#
10+
# For more details, see
11+
# http://developer.android.com/guide/developing/tools/proguard.html
12+
13+
# Add any project specific keep options here:
14+
15+
# If your project uses WebView with JS, uncomment the following
16+
# and specify the fully qualified class name to the JavaScript interface
17+
# class:
18+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19+
# public *;
20+
#}

project.properties

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# This file is automatically generated by Android Tools.
2+
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3+
#
4+
# This file must be checked in Version Control Systems.
5+
#
6+
# To customize properties used by the Ant build system edit
7+
# "ant.properties", and override values to adapt the script to your
8+
# project structure.
9+
#
10+
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11+
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12+
13+
# Project target.
14+
target=android-18

res/drawable-hdpi/ic_launcher.png

7.48 KB
Loading

res/drawable-mdpi/ic_launcher.png

3.69 KB
Loading

res/drawable-xhdpi/ic_launcher.png

12.2 KB
Loading

res/drawable-xxhdpi/ic_launcher.png

24.2 KB
Loading

res/layout/activity_main.xml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
3+
android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin"
4+
android:paddingLeft="@dimen/activity_horizontal_margin"
5+
android:paddingRight="@dimen/activity_horizontal_margin"
6+
android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity">
7+
8+
9+
</RelativeLayout>

res/menu/main.xml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
2+
3+
<item
4+
android:id="@+id/action_settings"
5+
android:orderInCategory="100"
6+
android:showAsAction="never"
7+
android:title="@string/action_settings"/>
8+
9+
</menu>

0 commit comments

Comments
 (0)