blob: c8f235271c4393aa3fb208b49396b607131c7a7e [file] [log] [blame]
Marius Renn65953da2012-03-27 10:44:45 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "android/bitmap.h"
18
19#include "jni/jni_native_frame.h"
20#include "jni/jni_native_buffer.h"
21#include "jni/jni_util.h"
22
23#include "native/base/logging.h"
24#include "native/core/gl_frame.h"
25#include "native/core/native_frame.h"
26
27using android::filterfw::NativeFrame;
28using android::filterfw::GLFrame;
29
30typedef union {
31 uint32_t value;
32 uint8_t rgba[4];
33} Pixel;
34
35jboolean Java_android_filterfw_core_NativeFrame_nativeAllocate(JNIEnv* env,
36 jobject thiz,
37 jint size) {
38 return ToJBool(WrapObjectInJava(new NativeFrame(size), env, thiz, true));
39}
40
41jboolean Java_android_filterfw_core_NativeFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
42 return ToJBool(DeleteNativeObject<NativeFrame>(env, thiz));
43}
44
45jint Java_android_filterfw_core_NativeFrame_nativeIntSize(JNIEnv*, jclass) {
46 return sizeof(jint);
47}
48
49jint Java_android_filterfw_core_NativeFrame_nativeFloatSize(JNIEnv*, jclass) {
50 return sizeof(jfloat);
51}
52
53jboolean Java_android_filterfw_core_NativeFrame_setNativeData(JNIEnv* env,
54 jobject thiz,
55 jbyteArray data,
56 jint offset,
57 jint length) {
58 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
59 if (frame && data) {
60 jbyte* bytes = env->GetByteArrayElements(data, NULL);
61 if (bytes) {
62 const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(bytes + offset),
63 0,
64 length);
65 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
66 return ToJBool(success);
67 }
68 }
69 return JNI_FALSE;
70}
71
72jbyteArray Java_android_filterfw_core_NativeFrame_getNativeData(JNIEnv* env,
73 jobject thiz,
74 jint size) {
75 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
76 if (frame) {
77 const uint8_t* data = frame->Data();
78 if (!data || size > frame->Size())
79 return NULL;
80 jbyteArray result = env->NewByteArray(size);
81 env->SetByteArrayRegion(result, 0, size, reinterpret_cast<const jbyte*>(data));
82 return result;
83 }
84 return NULL;
85}
86
87jboolean Java_android_filterfw_core_NativeFrame_getNativeBuffer(JNIEnv* env,
88 jobject thiz,
89 jobject buffer) {
90 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
91 if (frame) {
92 char* data = reinterpret_cast<char*>(frame->MutableData());
93 return ToJBool(AttachDataToJBuffer(env, buffer, data, frame->Size()));
94 }
95 return JNI_FALSE;
96}
97
98jboolean Java_android_filterfw_core_NativeFrame_setNativeInts(JNIEnv* env,
99 jobject thiz,
100 jintArray ints) {
101 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
102 if (frame && ints) {
103 jint* int_ptr = env->GetIntArrayElements(ints, NULL);
104 const int length = env->GetArrayLength(ints);
105 if (int_ptr) {
106 const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(int_ptr),
107 0,
108 length * sizeof(jint));
109 env->ReleaseIntArrayElements(ints, int_ptr, JNI_ABORT);
110 return ToJBool(success);
111 }
112 }
113 return JNI_FALSE;
114}
115
116jintArray Java_android_filterfw_core_NativeFrame_getNativeInts(JNIEnv* env,
117 jobject thiz,
118 jint size) {
119 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
120 if (frame) {
121 const uint8_t* data = frame->Data();
122 if (!data || size > frame->Size() || (size % sizeof(jint)) != 0)
123 return NULL;
124 const int count = size / sizeof(jint);
125 jintArray result = env->NewIntArray(count);
126 env->SetIntArrayRegion(result, 0, count, reinterpret_cast<const jint*>(data));
127 return result;
128 }
129 return NULL;
130}
131
132jboolean Java_android_filterfw_core_NativeFrame_setNativeFloats(JNIEnv* env,
133 jobject thiz,
134 jfloatArray floats) {
135 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
136 if (frame && floats) {
137 jfloat* float_ptr = env->GetFloatArrayElements(floats, NULL);
138 const int length = env->GetArrayLength(floats);
139 if (float_ptr) {
140 const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(float_ptr),
141 0,
142 length * sizeof(jfloat));
143 env->ReleaseFloatArrayElements(floats, float_ptr, JNI_ABORT);
144 return ToJBool(success);
145 }
146 }
147 return JNI_FALSE;
148}
149
150jfloatArray Java_android_filterfw_core_NativeFrame_getNativeFloats(JNIEnv* env,
151 jobject thiz,
152 jint size) {
153 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
154 if (frame) {
155 const uint8_t* data = frame->Data();
156 if (!data || size > frame->Size() || (size % sizeof(jfloat)) != 0)
157 return NULL;
158 const int count = size / sizeof(jfloat);
159 jfloatArray result = env->NewFloatArray(count);
160 env->SetFloatArrayRegion(result, 0, count, reinterpret_cast<const jfloat*>(data));
161 return result;
162 }
163 return NULL;
164}
165
166jboolean Java_android_filterfw_core_NativeFrame_setNativeBitmap(JNIEnv* env,
167 jobject thiz,
168 jobject bitmap,
169 jint size,
170 jint bytes_per_sample) {
171 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
172 if (frame && bitmap) {
173 // Make sure frame size matches bitmap size
174 if ((size / 4) != (frame->Size() / bytes_per_sample)) {
175 ALOGE("Size mismatch in native setBitmap()!");
176 return JNI_FALSE;
177 }
178
179 Pixel* src_ptr;
180 const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&src_ptr));
Andrew Hsieheba82542012-12-12 11:27:44 +0800181 if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
Marius Renn65953da2012-03-27 10:44:45 -0700182 // Create destination pointers
183 uint8_t* dst_ptr = reinterpret_cast<uint8_t*>(frame->MutableData());
184 const uint8_t* end_ptr = dst_ptr + frame->Size();
185 switch (bytes_per_sample) {
186 case 1: { // RGBA -> GRAY
187 while (dst_ptr < end_ptr) {
188 const Pixel pixel = *(src_ptr++);
189 *(dst_ptr++) = (pixel.rgba[0] + pixel.rgba[1] + pixel.rgba[2]) / 3;
190 }
191 break;
192 }
193 case 3: { // RGBA -> RGB
194 while (dst_ptr < end_ptr) {
195 const Pixel pixel = *(src_ptr++);
196 *(dst_ptr++) = pixel.rgba[0];
197 *(dst_ptr++) = pixel.rgba[1];
198 *(dst_ptr++) = pixel.rgba[2];
199 }
200 break;
201 }
202 case 4: { // RGBA -> RGBA
203 memcpy(dst_ptr, src_ptr, frame->Size());
204 break;
205 }
206 default:
207 ALOGE("Unsupported bytes-per-pixel %d in setBitmap!", bytes_per_sample);
208 break;
209 }
Andrew Hsieheba82542012-12-12 11:27:44 +0800210 return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESULT_SUCCESS);
Marius Renn65953da2012-03-27 10:44:45 -0700211 }
212 }
213 return JNI_FALSE;
214}
215
216jboolean Java_android_filterfw_core_NativeFrame_getNativeBitmap(JNIEnv* env,
217 jobject thiz,
218 jobject bitmap,
219 jint size,
220 jint bytes_per_sample) {
221 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
222 if (frame && bitmap) {
223 Pixel* dst_ptr;
224 const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&dst_ptr));
Andrew Hsieheba82542012-12-12 11:27:44 +0800225 if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
Marius Renn65953da2012-03-27 10:44:45 -0700226 // Make sure frame size matches bitmap size
227 if ((size / 4) != (frame->Size() / bytes_per_sample)) {
228 ALOGE("Size mismatch in native getBitmap()!");
229 return JNI_FALSE;
230 }
231
232 const uint8_t* src_ptr = frame->Data();
233 const uint8_t* end_ptr = src_ptr + frame->Size();
234 switch (bytes_per_sample) {
235 case 1: { // GRAY -> RGBA
236 while (src_ptr < end_ptr) {
237 const uint8_t value = *(src_ptr++);
238 dst_ptr->rgba[0] = dst_ptr->rgba[1] = dst_ptr->rgba[2] = value;
239 dst_ptr->rgba[3] = 255;
240 ++dst_ptr;
241 }
242 break;
243 }
244 case 3: { // RGB -> RGBA
245 while (src_ptr < end_ptr) {
246 dst_ptr->rgba[0] = *(src_ptr++);
247 dst_ptr->rgba[1] = *(src_ptr++);
248 dst_ptr->rgba[2] = *(src_ptr++);
249 dst_ptr->rgba[3] = 255;
250 ++dst_ptr;
251 }
252 break;
253 }
254 case 4: { // RGBA -> RGBA
255 memcpy(dst_ptr, src_ptr, frame->Size());
256 break;
257 }
258 default:
259 ALOGE("Unsupported bytes-per-pixel %d in getBitmap!", bytes_per_sample);
260 break;
261 }
Andrew Hsieheba82542012-12-12 11:27:44 +0800262 return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESULT_SUCCESS);
Marius Renn65953da2012-03-27 10:44:45 -0700263 }
264 }
265 return JNI_FALSE;
266}
267
268jint Java_android_filterfw_core_NativeFrame_getNativeCapacity(JNIEnv* env, jobject thiz) {
269 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
270 return frame ? frame->Capacity() : -1;
271}
272
273jboolean Java_android_filterfw_core_NativeFrame_nativeCopyFromNative(JNIEnv* env,
274 jobject thiz,
275 jobject frame) {
276 NativeFrame* this_frame = ConvertFromJava<NativeFrame>(env, thiz);
277 NativeFrame* other_frame = ConvertFromJava<NativeFrame>(env, frame);
278 if (this_frame && other_frame) {
279 return ToJBool(this_frame->WriteData(other_frame->Data(), 0, other_frame->Size()));
280 }
281 return JNI_FALSE;
282}
283
284jboolean Java_android_filterfw_core_NativeFrame_nativeCopyFromGL(JNIEnv* env,
285 jobject thiz,
286 jobject frame) {
287 NativeFrame* this_frame = ConvertFromJava<NativeFrame>(env, thiz);
288 GLFrame* other_frame = ConvertFromJava<GLFrame>(env, frame);
289 if (this_frame && other_frame) {
290 return ToJBool(other_frame->CopyDataTo(this_frame->MutableData(), this_frame->Size()));
291 }
292 return JNI_FALSE;
293}