165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "android/bitmap.h"
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "jni/jni_native_frame.h"
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "jni/jni_native_buffer.h"
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "jni/jni_util.h"
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "native/base/logging.h"
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "native/core/gl_frame.h"
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "native/core/native_frame.h"
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennusing android::filterfw::NativeFrame;
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennusing android::filterfw::GLFrame;
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renntypedef union {
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    uint32_t value;
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    uint8_t  rgba[4];
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} Pixel;
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_nativeAllocate(JNIEnv* env,
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                               jobject thiz,
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                               jint size) {
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return ToJBool(WrapObjectInJava(new NativeFrame(size), env, thiz, true));
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return ToJBool(DeleteNativeObject<NativeFrame>(env, thiz));
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjint Java_android_filterfw_core_NativeFrame_nativeIntSize(JNIEnv*, jclass) {
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return sizeof(jint);
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjint Java_android_filterfw_core_NativeFrame_nativeFloatSize(JNIEnv*, jclass) {
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return sizeof(jfloat);
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_setNativeData(JNIEnv* env,
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                              jobject thiz,
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                              jbyteArray data,
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                              jint offset,
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                              jint length) {
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame && data) {
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    jbyte* bytes = env->GetByteArrayElements(data, NULL);
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (bytes) {
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(bytes + offset),
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                            0,
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                            length);
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return ToJBool(success);
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return JNI_FALSE;
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennjbyteArray Java_android_filterfw_core_NativeFrame_getNativeData(JNIEnv* env,
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jobject thiz,
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jint size) {
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame) {
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const uint8_t* data = frame->Data();
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (!data || size > frame->Size())
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return NULL;
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    jbyteArray result = env->NewByteArray(size);
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    env->SetByteArrayRegion(result, 0, size, reinterpret_cast<const jbyte*>(data));
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return result;
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return NULL;
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_getNativeBuffer(JNIEnv* env,
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jobject thiz,
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jobject buffer) {
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame) {
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    char* data = reinterpret_cast<char*>(frame->MutableData());
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return ToJBool(AttachDataToJBuffer(env, buffer, data, frame->Size()));
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return JNI_FALSE;
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_setNativeInts(JNIEnv* env,
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                              jobject thiz,
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                              jintArray ints) {
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame && ints) {
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    jint* int_ptr = env->GetIntArrayElements(ints, NULL);
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const int length = env->GetArrayLength(ints);
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (int_ptr) {
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(int_ptr),
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                            0,
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                            length * sizeof(jint));
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      env->ReleaseIntArrayElements(ints, int_ptr, JNI_ABORT);
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return ToJBool(success);
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return JNI_FALSE;
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennjintArray Java_android_filterfw_core_NativeFrame_getNativeInts(JNIEnv* env,
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                               jobject thiz,
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                               jint size) {
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame) {
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const uint8_t* data = frame->Data();
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (!data || size > frame->Size() || (size % sizeof(jint)) != 0)
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return NULL;
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const int count = size / sizeof(jint);
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    jintArray result = env->NewIntArray(count);
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    env->SetIntArrayRegion(result, 0, count, reinterpret_cast<const jint*>(data));
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return result;
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return NULL;
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_setNativeFloats(JNIEnv* env,
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jobject thiz,
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jfloatArray floats) {
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame && floats) {
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    jfloat* float_ptr = env->GetFloatArrayElements(floats, NULL);
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const int length = env->GetArrayLength(floats);
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (float_ptr) {
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(float_ptr),
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                            0,
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                            length * sizeof(jfloat));
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      env->ReleaseFloatArrayElements(floats, float_ptr, JNI_ABORT);
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return ToJBool(success);
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return JNI_FALSE;
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennjfloatArray Java_android_filterfw_core_NativeFrame_getNativeFloats(JNIEnv* env,
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                   jobject thiz,
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                   jint size) {
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame) {
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const uint8_t* data = frame->Data();
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (!data || size > frame->Size() || (size % sizeof(jfloat)) != 0)
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return NULL;
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const int count = size / sizeof(jfloat);
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    jfloatArray result = env->NewFloatArray(count);
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    env->SetFloatArrayRegion(result, 0, count, reinterpret_cast<const jfloat*>(data));
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return result;
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return NULL;
16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_setNativeBitmap(JNIEnv* env,
16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jobject thiz,
16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jobject bitmap,
16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jint size,
17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jint bytes_per_sample) {
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame && bitmap) {
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Make sure frame size matches bitmap size
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if ((size / 4) != (frame->Size() / bytes_per_sample)) {
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ALOGE("Size mismatch in native setBitmap()!");
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return JNI_FALSE;
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    Pixel* src_ptr;
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&src_ptr));
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (result == ANDROID_BITMAP_RESUT_SUCCESS) {
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      // Create destination pointers
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      uint8_t* dst_ptr = reinterpret_cast<uint8_t*>(frame->MutableData());
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      const uint8_t* end_ptr = dst_ptr + frame->Size();
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      switch (bytes_per_sample) {
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        case 1: { // RGBA -> GRAY
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          while (dst_ptr < end_ptr) {
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            const Pixel pixel = *(src_ptr++);
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            *(dst_ptr++) = (pixel.rgba[0] + pixel.rgba[1] + pixel.rgba[2]) / 3;
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          }
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          break;
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        case 3: { // RGBA -> RGB
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          while (dst_ptr < end_ptr) {
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            const Pixel pixel = *(src_ptr++);
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            *(dst_ptr++) = pixel.rgba[0];
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            *(dst_ptr++) = pixel.rgba[1];
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            *(dst_ptr++) = pixel.rgba[2];
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          }
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          break;
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        case 4: { // RGBA -> RGBA
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          memcpy(dst_ptr, src_ptr, frame->Size());
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          break;
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        default:
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          ALOGE("Unsupported bytes-per-pixel %d in setBitmap!", bytes_per_sample);
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          break;
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESUT_SUCCESS);
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return JNI_FALSE;
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_getNativeBitmap(JNIEnv* env,
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jobject thiz,
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jobject bitmap,
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jint size,
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                jint bytes_per_sample) {
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (frame && bitmap) {
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    Pixel* dst_ptr;
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&dst_ptr));
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (result == ANDROID_BITMAP_RESUT_SUCCESS) {
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      // Make sure frame size matches bitmap size
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if ((size / 4) != (frame->Size() / bytes_per_sample)) {
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("Size mismatch in native getBitmap()!");
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return JNI_FALSE;
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      const uint8_t* src_ptr = frame->Data();
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      const uint8_t* end_ptr = src_ptr + frame->Size();
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      switch (bytes_per_sample) {
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        case 1: { // GRAY -> RGBA
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          while (src_ptr < end_ptr) {
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            const uint8_t value = *(src_ptr++);
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            dst_ptr->rgba[0] = dst_ptr->rgba[1] = dst_ptr->rgba[2] = value;
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            dst_ptr->rgba[3] = 255;
24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            ++dst_ptr;
24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          }
24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          break;
24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        case 3: { // RGB -> RGBA
24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          while (src_ptr < end_ptr) {
24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            dst_ptr->rgba[0] = *(src_ptr++);
24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            dst_ptr->rgba[1] = *(src_ptr++);
24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            dst_ptr->rgba[2] = *(src_ptr++);
24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            dst_ptr->rgba[3] = 255;
25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            ++dst_ptr;
25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          }
25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          break;
25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        case 4: { // RGBA -> RGBA
25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          memcpy(dst_ptr, src_ptr, frame->Size());
25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          break;
25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        default:
25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          ALOGE("Unsupported bytes-per-pixel %d in getBitmap!", bytes_per_sample);
26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          break;
26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESUT_SUCCESS);
26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return JNI_FALSE;
26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjint Java_android_filterfw_core_NativeFrame_getNativeCapacity(JNIEnv* env, jobject thiz) {
26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* frame = ConvertFromJava<NativeFrame>(env, thiz);
27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return frame ? frame->Capacity() : -1;
27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_nativeCopyFromNative(JNIEnv* env,
27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                     jobject thiz,
27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                     jobject frame) {
27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* this_frame = ConvertFromJava<NativeFrame>(env, thiz);
27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* other_frame = ConvertFromJava<NativeFrame>(env, frame);
27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (this_frame && other_frame) {
27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return ToJBool(this_frame->WriteData(other_frame->Data(), 0, other_frame->Size()));
28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return JNI_FALSE;
28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_NativeFrame_nativeCopyFromGL(JNIEnv* env,
28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                 jobject thiz,
28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                 jobject frame) {
28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  NativeFrame* this_frame = ConvertFromJava<NativeFrame>(env, thiz);
28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLFrame* other_frame = ConvertFromJava<GLFrame>(env, frame);
28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (this_frame && other_frame) {
29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return ToJBool(other_frame->CopyDataTo(this_frame->MutableData(), this_frame->Size()));
29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return JNI_FALSE;
29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
294