blob: 1a11a193e0d5624f4eafcb965c797311fd3ec195 [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) {
George Burgess IV315c9362016-11-01 16:06:39 -070038 std::unique_ptr<NativeFrame> frame(new NativeFrame(size));
39 return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
Marius Renn65953da2012-03-27 10:44:45 -070040}
41
42jboolean Java_android_filterfw_core_NativeFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
43 return ToJBool(DeleteNativeObject<NativeFrame>(env, thiz));
44}
45
46jint Java_android_filterfw_core_NativeFrame_nativeIntSize(JNIEnv*, jclass) {
47 return sizeof(jint);
48}
49
50jint Java_android_filterfw_core_NativeFrame_nativeFloatSize(JNIEnv*, jclass) {
51 return sizeof(jfloat);
52}
53
54jboolean Java_android_filterfw_core_NativeFrame_setNativeData(JNIEnv* env,
55 jobject thiz,
56 jbyteArray data,
57 jint offset,
58 jint length) {
59 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
60 if (frame && data) {
61 jbyte* bytes = env->GetByteArrayElements(data, NULL);
62 if (bytes) {
63 const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(bytes + offset),
64 0,
65 length);
66 env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
67 return ToJBool(success);
68 }
69 }
70 return JNI_FALSE;
71}
72
73jbyteArray Java_android_filterfw_core_NativeFrame_getNativeData(JNIEnv* env,
74 jobject thiz,
75 jint size) {
76 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
77 if (frame) {
78 const uint8_t* data = frame->Data();
79 if (!data || size > frame->Size())
80 return NULL;
81 jbyteArray result = env->NewByteArray(size);
82 env->SetByteArrayRegion(result, 0, size, reinterpret_cast<const jbyte*>(data));
83 return result;
84 }
85 return NULL;
86}
87
88jboolean Java_android_filterfw_core_NativeFrame_getNativeBuffer(JNIEnv* env,
89 jobject thiz,
90 jobject buffer) {
91 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
92 if (frame) {
93 char* data = reinterpret_cast<char*>(frame->MutableData());
94 return ToJBool(AttachDataToJBuffer(env, buffer, data, frame->Size()));
95 }
96 return JNI_FALSE;
97}
98
99jboolean Java_android_filterfw_core_NativeFrame_setNativeInts(JNIEnv* env,
100 jobject thiz,
101 jintArray ints) {
102 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
103 if (frame && ints) {
104 jint* int_ptr = env->GetIntArrayElements(ints, NULL);
105 const int length = env->GetArrayLength(ints);
106 if (int_ptr) {
107 const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(int_ptr),
108 0,
109 length * sizeof(jint));
110 env->ReleaseIntArrayElements(ints, int_ptr, JNI_ABORT);
111 return ToJBool(success);
112 }
113 }
114 return JNI_FALSE;
115}
116
117jintArray Java_android_filterfw_core_NativeFrame_getNativeInts(JNIEnv* env,
118 jobject thiz,
119 jint size) {
120 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
121 if (frame) {
122 const uint8_t* data = frame->Data();
123 if (!data || size > frame->Size() || (size % sizeof(jint)) != 0)
124 return NULL;
125 const int count = size / sizeof(jint);
126 jintArray result = env->NewIntArray(count);
127 env->SetIntArrayRegion(result, 0, count, reinterpret_cast<const jint*>(data));
128 return result;
129 }
130 return NULL;
131}
132
133jboolean Java_android_filterfw_core_NativeFrame_setNativeFloats(JNIEnv* env,
134 jobject thiz,
135 jfloatArray floats) {
136 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
137 if (frame && floats) {
138 jfloat* float_ptr = env->GetFloatArrayElements(floats, NULL);
139 const int length = env->GetArrayLength(floats);
140 if (float_ptr) {
141 const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(float_ptr),
142 0,
143 length * sizeof(jfloat));
144 env->ReleaseFloatArrayElements(floats, float_ptr, JNI_ABORT);
145 return ToJBool(success);
146 }
147 }
148 return JNI_FALSE;
149}
150
151jfloatArray Java_android_filterfw_core_NativeFrame_getNativeFloats(JNIEnv* env,
152 jobject thiz,
153 jint size) {
154 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
155 if (frame) {
156 const uint8_t* data = frame->Data();
157 if (!data || size > frame->Size() || (size % sizeof(jfloat)) != 0)
158 return NULL;
159 const int count = size / sizeof(jfloat);
160 jfloatArray result = env->NewFloatArray(count);
161 env->SetFloatArrayRegion(result, 0, count, reinterpret_cast<const jfloat*>(data));
162 return result;
163 }
164 return NULL;
165}
166
167jboolean Java_android_filterfw_core_NativeFrame_setNativeBitmap(JNIEnv* env,
168 jobject thiz,
169 jobject bitmap,
170 jint size,
171 jint bytes_per_sample) {
172 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
173 if (frame && bitmap) {
174 // Make sure frame size matches bitmap size
175 if ((size / 4) != (frame->Size() / bytes_per_sample)) {
176 ALOGE("Size mismatch in native setBitmap()!");
177 return JNI_FALSE;
178 }
179
180 Pixel* src_ptr;
181 const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&src_ptr));
Andrew Hsieheba82542012-12-12 11:27:44 +0800182 if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
Marius Renn65953da2012-03-27 10:44:45 -0700183 // Create destination pointers
184 uint8_t* dst_ptr = reinterpret_cast<uint8_t*>(frame->MutableData());
185 const uint8_t* end_ptr = dst_ptr + frame->Size();
186 switch (bytes_per_sample) {
187 case 1: { // RGBA -> GRAY
188 while (dst_ptr < end_ptr) {
189 const Pixel pixel = *(src_ptr++);
190 *(dst_ptr++) = (pixel.rgba[0] + pixel.rgba[1] + pixel.rgba[2]) / 3;
191 }
192 break;
193 }
194 case 3: { // RGBA -> RGB
195 while (dst_ptr < end_ptr) {
196 const Pixel pixel = *(src_ptr++);
197 *(dst_ptr++) = pixel.rgba[0];
198 *(dst_ptr++) = pixel.rgba[1];
199 *(dst_ptr++) = pixel.rgba[2];
200 }
201 break;
202 }
203 case 4: { // RGBA -> RGBA
204 memcpy(dst_ptr, src_ptr, frame->Size());
205 break;
206 }
207 default:
208 ALOGE("Unsupported bytes-per-pixel %d in setBitmap!", bytes_per_sample);
209 break;
210 }
Andrew Hsieheba82542012-12-12 11:27:44 +0800211 return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESULT_SUCCESS);
Marius Renn65953da2012-03-27 10:44:45 -0700212 }
213 }
214 return JNI_FALSE;
215}
216
217jboolean Java_android_filterfw_core_NativeFrame_getNativeBitmap(JNIEnv* env,
218 jobject thiz,
219 jobject bitmap,
220 jint size,
221 jint bytes_per_sample) {
222 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
223 if (frame && bitmap) {
224 Pixel* dst_ptr;
225 const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&dst_ptr));
Andrew Hsieheba82542012-12-12 11:27:44 +0800226 if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
Marius Renn65953da2012-03-27 10:44:45 -0700227 // Make sure frame size matches bitmap size
228 if ((size / 4) != (frame->Size() / bytes_per_sample)) {
229 ALOGE("Size mismatch in native getBitmap()!");
230 return JNI_FALSE;
231 }
232
233 const uint8_t* src_ptr = frame->Data();
234 const uint8_t* end_ptr = src_ptr + frame->Size();
235 switch (bytes_per_sample) {
236 case 1: { // GRAY -> RGBA
237 while (src_ptr < end_ptr) {
238 const uint8_t value = *(src_ptr++);
239 dst_ptr->rgba[0] = dst_ptr->rgba[1] = dst_ptr->rgba[2] = value;
240 dst_ptr->rgba[3] = 255;
241 ++dst_ptr;
242 }
243 break;
244 }
245 case 3: { // RGB -> RGBA
246 while (src_ptr < end_ptr) {
247 dst_ptr->rgba[0] = *(src_ptr++);
248 dst_ptr->rgba[1] = *(src_ptr++);
249 dst_ptr->rgba[2] = *(src_ptr++);
250 dst_ptr->rgba[3] = 255;
251 ++dst_ptr;
252 }
253 break;
254 }
255 case 4: { // RGBA -> RGBA
256 memcpy(dst_ptr, src_ptr, frame->Size());
257 break;
258 }
259 default:
260 ALOGE("Unsupported bytes-per-pixel %d in getBitmap!", bytes_per_sample);
261 break;
262 }
Andrew Hsieheba82542012-12-12 11:27:44 +0800263 return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESULT_SUCCESS);
Marius Renn65953da2012-03-27 10:44:45 -0700264 }
265 }
266 return JNI_FALSE;
267}
268
269jint Java_android_filterfw_core_NativeFrame_getNativeCapacity(JNIEnv* env, jobject thiz) {
270 NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
271 return frame ? frame->Capacity() : -1;
272}
273
274jboolean Java_android_filterfw_core_NativeFrame_nativeCopyFromNative(JNIEnv* env,
275 jobject thiz,
276 jobject frame) {
277 NativeFrame* this_frame = ConvertFromJava<NativeFrame>(env, thiz);
278 NativeFrame* other_frame = ConvertFromJava<NativeFrame>(env, frame);
279 if (this_frame && other_frame) {
280 return ToJBool(this_frame->WriteData(other_frame->Data(), 0, other_frame->Size()));
281 }
282 return JNI_FALSE;
283}
284
285jboolean Java_android_filterfw_core_NativeFrame_nativeCopyFromGL(JNIEnv* env,
286 jobject thiz,
287 jobject frame) {
288 NativeFrame* this_frame = ConvertFromJava<NativeFrame>(env, thiz);
289 GLFrame* other_frame = ConvertFromJava<GLFrame>(env, frame);
290 if (this_frame && other_frame) {
291 return ToJBool(other_frame->CopyDataTo(this_frame->MutableData(), this_frame->Size()));
292 }
293 return JNI_FALSE;
294}