feat(android): add native bitmap utils
This commit is contained in:
parent
44bff1992a
commit
05d46111b7
|
@ -56,8 +56,9 @@ public final class Mynteye implements Runnable {
|
||||||
startBackgroundThread();
|
startBackgroundThread();
|
||||||
|
|
||||||
mDevice.configStreamRequest(request);
|
mDevice.configStreamRequest(request);
|
||||||
mDevice.enableMotionDatas(Integer.MAX_VALUE);
|
//mDevice.enableMotionDatas(Integer.MAX_VALUE);
|
||||||
mDevice.start(Source.ALL);
|
//mDevice.start(Source.ALL);
|
||||||
|
mDevice.start(Source.VIDEO_STREAMING);
|
||||||
|
|
||||||
mBackgroundHandler.post(this);
|
mBackgroundHandler.post(this);
|
||||||
}
|
}
|
||||||
|
@ -91,12 +92,14 @@ public final class Mynteye implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Timber.i("get motions");
|
//Timber.i("get motions");
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
ArrayList<MotionData> datas = mDevice.getMotionDatas();
|
ArrayList<MotionData> datas = mDevice.getMotionDatas();
|
||||||
if (mOnMotionDataReceiveListener != null) {
|
if (mOnMotionDataReceiveListener != null) {
|
||||||
mOnMotionDataReceiveListener.onMotionDataReceive(datas, mBackgroundHandler);
|
mOnMotionDataReceiveListener.onMotionDataReceive(datas, mBackgroundHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (mOpened) mBackgroundHandler.post(this);
|
if (mOpened) mBackgroundHandler.post(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import com.slightech.mynteye.usb.CameraDialog;
|
||||||
import com.slightech.mynteye.usb.USBMonitor;
|
import com.slightech.mynteye.usb.USBMonitor;
|
||||||
import com.slightech.mynteye.usb.USBMonitor.OnDeviceConnectListener;
|
import com.slightech.mynteye.usb.USBMonitor.OnDeviceConnectListener;
|
||||||
import com.slightech.mynteye.usb.USBMonitor.UsbControlBlock;
|
import com.slightech.mynteye.usb.USBMonitor.UsbControlBlock;
|
||||||
|
import com.slightech.mynteye.util.BitmapUtils;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -166,51 +167,8 @@ public class MainActivity extends BaseActivity implements CameraDialog.CameraDia
|
||||||
private void actionOpen(final Runnable completeEvent) {
|
private void actionOpen(final Runnable completeEvent) {
|
||||||
if (completeEvent != null) completeEvent.run();
|
if (completeEvent != null) completeEvent.run();
|
||||||
CameraDialog.showDialog(this);
|
CameraDialog.showDialog(this);
|
||||||
/*
|
|
||||||
if (!RootUtils.isRooted()) {
|
|
||||||
if (completeEvent != null) completeEvent.run();
|
|
||||||
alert("Warning", "Root denied :(");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RootUtils.requestAccessible(ok -> {
|
|
||||||
if (completeEvent != null) completeEvent.run();
|
|
||||||
if (ok) {
|
|
||||||
toast("Root granted :)");
|
|
||||||
showDevices();
|
|
||||||
} else {
|
|
||||||
alert("Warning", "There are no devices accessible.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
private void showDevices() {
|
|
||||||
ArrayList<DeviceUsbInfo> infos = Device.query();
|
|
||||||
if (infos.isEmpty()) {
|
|
||||||
alert("Warning", "There are no devices :(");
|
|
||||||
} else {
|
|
||||||
ArrayList<String> items = new ArrayList<>();
|
|
||||||
for (DeviceUsbInfo info : infos) {
|
|
||||||
items.add(String.format(Locale.getDefault(), "%d, %s, SN: %s",
|
|
||||||
info.getIndex(), info.getName(), info.getSn()));
|
|
||||||
}
|
|
||||||
|
|
||||||
AlertDialog dialog = new AlertDialog.Builder(this)
|
|
||||||
.setTitle("Devices")
|
|
||||||
.create();
|
|
||||||
ListView listView = new ListView(this);
|
|
||||||
listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items));
|
|
||||||
listView.setOnItemClickListener((parent, view, position, id) -> {
|
|
||||||
dialog.dismiss();
|
|
||||||
openDevice(infos.get(position));
|
|
||||||
});
|
|
||||||
dialog.setView(listView);
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private void openDevice(DeviceUsbInfo info) {
|
private void openDevice(DeviceUsbInfo info) {
|
||||||
mMynteye = new Mynteye(info);
|
mMynteye = new Mynteye(info);
|
||||||
ArrayList<StreamRequest> requests = mMynteye.getStreamRequests();
|
ArrayList<StreamRequest> requests = mMynteye.getStreamRequests();
|
||||||
|
@ -256,15 +214,9 @@ public class MainActivity extends BaseActivity implements CameraDialog.CameraDia
|
||||||
//Timber.i("onStreamLeftReceive");
|
//Timber.i("onStreamLeftReceive");
|
||||||
Frame frame = data.frame();
|
Frame frame = data.frame();
|
||||||
if (mLeftBitmap == null) {
|
if (mLeftBitmap == null) {
|
||||||
Bitmap.Config config;
|
mLeftBitmap = Bitmap.createBitmap(frame.width(), frame.height(), Bitmap.Config.ARGB_8888);
|
||||||
switch (frame.format()) {
|
|
||||||
case GREY: config = Bitmap.Config.ALPHA_8; break;
|
|
||||||
case RGB888: config = Bitmap.Config.ARGB_8888; break;
|
|
||||||
default: Timber.e("Unaccepted stream format"); return;
|
|
||||||
}
|
|
||||||
mLeftBitmap = Bitmap.createBitmap(frame.width(), frame.height(), config);
|
|
||||||
}
|
}
|
||||||
mLeftBitmap.copyPixelsFromBuffer(ByteBuffer.wrap(frame.data()));
|
BitmapUtils.copyPixels(frame, mLeftBitmap);
|
||||||
mLeftImageView.post(() -> mLeftImageView.setImageBitmap(mLeftBitmap));
|
mLeftImageView.post(() -> mLeftImageView.setImageBitmap(mLeftBitmap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,15 +225,9 @@ public class MainActivity extends BaseActivity implements CameraDialog.CameraDia
|
||||||
//Timber.i("onStreamRightReceive");
|
//Timber.i("onStreamRightReceive");
|
||||||
Frame frame = data.frame();
|
Frame frame = data.frame();
|
||||||
if (mRightBitmap == null) {
|
if (mRightBitmap == null) {
|
||||||
Bitmap.Config config;
|
mRightBitmap = Bitmap.createBitmap(frame.width(), frame.height(), Bitmap.Config.ARGB_8888);
|
||||||
switch (frame.format()) {
|
|
||||||
case GREY: config = Bitmap.Config.ALPHA_8; break;
|
|
||||||
case RGB888: config = Bitmap.Config.ARGB_8888; break;
|
|
||||||
default: Timber.e("Unaccepted stream format"); return;
|
|
||||||
}
|
|
||||||
mRightBitmap = Bitmap.createBitmap(frame.width(), frame.height(), config);
|
|
||||||
}
|
}
|
||||||
mRightBitmap.copyPixelsFromBuffer(ByteBuffer.wrap(frame.data()));
|
BitmapUtils.copyPixels(frame, mRightBitmap);
|
||||||
mRightImageView.post(() -> mRightImageView.setImageBitmap(mRightBitmap));
|
mRightImageView.post(() -> mRightImageView.setImageBitmap(mRightBitmap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,10 @@ endif()
|
||||||
|
|
||||||
find_library(log-lib log)
|
find_library(log-lib log)
|
||||||
|
|
||||||
|
## jnigraphics
|
||||||
|
|
||||||
|
find_library(jnigraphics-lib jnigraphics)
|
||||||
|
|
||||||
## djinni_jni
|
## djinni_jni
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
@ -115,6 +119,7 @@ endforeach()
|
||||||
|
|
||||||
add_library(mynteye_jni SHARED
|
add_library(mynteye_jni SHARED
|
||||||
${DJINNI_DIR}/support-lib/jni/djinni_main.cpp
|
${DJINNI_DIR}/support-lib/jni/djinni_main.cpp
|
||||||
|
${CPP_DIR}/mynteye/impl/util/jni_util.cpp
|
||||||
${MYNTEYE_JNI_SRCS}
|
${MYNTEYE_JNI_SRCS}
|
||||||
)
|
)
|
||||||
target_link_libraries(mynteye_jni ${log-lib} djinni_jni mynteye mynteye_internal)
|
target_link_libraries(mynteye_jni ${log-lib} ${jnigraphics-lib} djinni_jni mynteye mynteye_internal)
|
||||||
|
|
|
@ -39,6 +39,10 @@ class FrameImpl : public Frame {
|
||||||
return std::vector<uint8_t>(frame_->data(), frame_->data() + frame_->size());
|
return std::vector<uint8_t>(frame_->data(), frame_->data() + frame_->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frame_t RawFrame() const {
|
||||||
|
return frame_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
frame_t frame_;
|
frame_t frame_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
#include <android/bitmap.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#ifndef LOG_TAG
|
||||||
|
#define LOG_TAG "native"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LOGI(...) \
|
||||||
|
((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
|
||||||
|
#define LOGW(...) \
|
||||||
|
((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
|
||||||
|
#define LOGE(...) \
|
||||||
|
((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||||
|
|
||||||
|
#include "NativeFrame.hpp"
|
||||||
|
|
||||||
|
#include "frame_impl.hpp"
|
||||||
|
|
||||||
|
// BitmapUtils
|
||||||
|
|
||||||
|
// RGBA
|
||||||
|
typedef struct {
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t a;
|
||||||
|
} rgba_t;
|
||||||
|
|
||||||
|
void copyPixelsGray(std::uint8_t *from, rgba_t *to, uint32_t n);
|
||||||
|
void copyPixelsBGR3(std::uint8_t *from, rgba_t *to, uint32_t n);
|
||||||
|
void copyPixelsRGB3(std::uint8_t *from, rgba_t *to, uint32_t n);
|
||||||
|
|
||||||
|
void copyPixels(mynteye_jni::FrameImpl::frame_t from, rgba_t *to,
|
||||||
|
const AndroidBitmapInfo &info) {
|
||||||
|
if (info.width != from->width() || info.height != from->height()) {
|
||||||
|
LOGE("Frame size is not same");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t n = info.width * info.height;
|
||||||
|
switch (from->format()) {
|
||||||
|
case MYNTEYE_NAMESPACE::Format::GREY:
|
||||||
|
copyPixelsGray(from->data(), to, n);
|
||||||
|
return;
|
||||||
|
case MYNTEYE_NAMESPACE::Format::BGR888:
|
||||||
|
copyPixelsBGR3(from->data(), to, n);
|
||||||
|
return;
|
||||||
|
case MYNTEYE_NAMESPACE::Format::RGB888:
|
||||||
|
copyPixelsRGB3(from->data(), to, n);
|
||||||
|
return;
|
||||||
|
case MYNTEYE_NAMESPACE::Format::YUYV:
|
||||||
|
default:
|
||||||
|
LOGE("Frame format is not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CJNIEXPORT void JNICALL Java_com_slightech_mynteye_util_BitmapUtils_copyPixels(
|
||||||
|
JNIEnv *env, jclass clazz, jobject j_frame, jobject bitmap) {
|
||||||
|
auto frame = ::djinni_generated::NativeFrame::toCpp(env, j_frame);
|
||||||
|
// LOGI("frame format: %dx%d", frame->Width(), frame->Height());
|
||||||
|
auto frame_raw = std::dynamic_pointer_cast<mynteye_jni::FrameImpl>(frame)->RawFrame();
|
||||||
|
|
||||||
|
AndroidBitmapInfo info;
|
||||||
|
int result;
|
||||||
|
if ((result = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
|
||||||
|
LOGE("AndroidBitmap_getInfo() failed, error=%d", result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
|
||||||
|
LOGE("Bitmap format is not RGBA_8888!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pixels;
|
||||||
|
if ((result = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
|
||||||
|
LOGE("AndroidBitmap_lockPixels() failed, error=%d", result);
|
||||||
|
}
|
||||||
|
rgba_t *rgba_pixels = static_cast<rgba_t*>(pixels);
|
||||||
|
|
||||||
|
copyPixels(frame_raw, rgba_pixels, info);
|
||||||
|
|
||||||
|
AndroidBitmap_unlockPixels(env, bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyPixelsGray(std::uint8_t *from, rgba_t *to, uint32_t n) {
|
||||||
|
for (uint32_t i = 0; i < n; ++i) {
|
||||||
|
std::uint8_t &gray = from[i];
|
||||||
|
rgba_t &rgba = to[i];
|
||||||
|
rgba.r = gray;
|
||||||
|
rgba.g = gray;
|
||||||
|
rgba.b = gray;
|
||||||
|
rgba.a = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyPixelsBGR3(std::uint8_t *from, rgba_t *to, uint32_t n) {
|
||||||
|
for (uint32_t i = 0; i < n; ++i) {
|
||||||
|
std::uint8_t *bgr = from + (i*3);
|
||||||
|
rgba_t &rgba = to[i];
|
||||||
|
rgba.r = *(bgr + 2);
|
||||||
|
rgba.g = *(bgr + 1);
|
||||||
|
rgba.b = *(bgr);
|
||||||
|
rgba.a = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyPixelsRGB3(std::uint8_t *from, rgba_t *to, uint32_t n) {
|
||||||
|
for (uint32_t i = 0; i < n; ++i) {
|
||||||
|
std::uint8_t *rgb = from + (i*3);
|
||||||
|
rgba_t &rgba = to[i];
|
||||||
|
rgba.r = *(rgb);
|
||||||
|
rgba.g = *(rgb + 1);
|
||||||
|
rgba.b = *(rgb + 2);
|
||||||
|
rgba.a = 255;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.slightech.mynteye.util;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import com.slightech.mynteye.Frame;
|
||||||
|
|
||||||
|
public class BitmapUtils {
|
||||||
|
|
||||||
|
public static native void copyPixels(Frame from, Bitmap to);
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user