summaryrefslogtreecommitdiffstats
path: root/jni/feature_mos_jni.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'jni/feature_mos_jni.cpp')
-rw-r--r--jni/feature_mos_jni.cpp449
1 files changed, 449 insertions, 0 deletions
diff --git a/jni/feature_mos_jni.cpp b/jni/feature_mos_jni.cpp
new file mode 100644
index 0000000..680a913
--- /dev/null
+++ b/jni/feature_mos_jni.cpp
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+*
+ */
+#include <string.h>
+#include <jni.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <db_utilities_camera.h>
+
+#include <android/log.h>
+#define ANDROID_LOG_VERBOSE ANDROID_LOG_DEBUG
+#define LOG_TAG "CVJNI"
+#define LOGV(...) __android_log_print(ANDROID_LOG_SILENT, LOG_TAG, __VA_ARGS__)
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
+
+#include "mosaic/ImageUtils.h"
+#include "mosaic/AlignFeatures.h"
+#include "mosaic/Blend.h"
+#include "mosaic/Mosaic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char buffer[1024];
+
+const int MAX_FRAMES_HR = 100;
+const int MAX_FRAMES_LR = 200;
+
+static double mTx;
+
+enum { LR=0, HR, NR };
+int tWidth[NR];
+int tHeight[NR];
+int H2L_FACTOR = 4; // Can be 2
+
+ImageType tImage[NR][MAX_FRAMES_LR];// = {{ImageUtils::IMAGE_TYPE_NOIMAGE}}; // YVU24 format image
+Mosaic *mosaic[NR] = {NULL,NULL};
+ImageType resultYVU = ImageUtils::IMAGE_TYPE_NOIMAGE;
+ImageType resultBGR = ImageUtils::IMAGE_TYPE_NOIMAGE;
+float gTRS[10];
+
+int c;
+int ret;
+int width=0, height=0;
+int mosaicWidth=0, mosaicHeight=0;
+
+//int blendingType = Blend::BLEND_TYPE_FULL;
+//int blendingType = Blend::BLEND_TYPE_CYLPAN;
+int blendingType = Blend::BLEND_TYPE_HORZ;
+bool high_res = false;
+bool quarter_res[NR] = {false,false};
+float thresh_still[NR] = {5.0f,0.0f};
+
+JNIEXPORT jstring JNICALL Java_sri_ics_vt_SmartPhone_Mosaic_StringFromJNI( JNIEnv* env, jobject thiz )
+{
+ return (env)->NewStringUTF(buffer);
+}
+
+/* return current time in milliseconds*/
+
+#ifndef now_ms
+static double
+now_ms(void)
+{
+ //struct timespec res;
+ struct timeval res;
+ //clock_gettime(CLOCK_REALTIME, &res);
+ gettimeofday(&res, NULL);
+ return 1000.0*res.tv_sec + (double)res.tv_usec/1e3;
+}
+#endif
+
+
+static int frame_number_HR = 0;
+static int frame_number_LR = 0;
+
+int Init(int mID, int nmax)
+{
+ double t0, t1, time_c;
+
+ if(mosaic[mID]!=NULL)
+ {
+ delete mosaic[mID];
+ mosaic[mID] = NULL;
+ }
+
+ mosaic[mID] = new Mosaic();
+
+ t0 = now_ms();
+
+ // When processing higher than 720x480 video, process low-res at quarter resolution
+ if(tWidth[LR]>180)
+ quarter_res[LR] = true;
+
+
+ // Check for initialization and if not, initialize
+ if (!mosaic[mID]->isInitialized())
+ {
+ mosaic[mID]->initialize(blendingType, tWidth[mID], tHeight[mID], nmax, quarter_res[mID], thresh_still[mID]);
+ }
+
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGI("Init[%d]: %g ms [%d frames]",mID,time_c,nmax);
+ return 1;
+}
+
+void GenerateQuarterResImagePlanar(ImageType im, int input_w, int input_h, ImageType &out)
+{
+ ImageType imp;
+ ImageType outp;
+
+ int count = 0;
+ for (int j = 0; j < input_h; j+=4)
+ {
+ imp = im + j*input_w;
+ outp = out + (int)(j/4)*(int(input_w/4));
+
+ for (int i = 0; i < input_w; i+=4)
+ {
+ *outp++ = *(imp+i);
+ count++;
+ }
+ }
+ for (int j = input_h; j < 2*input_h; j+=4)
+ {
+ imp = im + j*input_w;
+ outp = out + (int)(j/4)*(int(input_w/4));
+
+ for (int i = 0; i < input_w; i+=4)
+ {
+ *outp++ = *(imp+i);
+ count++;
+ }
+ }
+ for (int j = 2*input_h; j < 3*input_h; j+=4)
+ {
+ imp = im + j*input_w;
+ outp = out + (int)(j/4)*(int(input_w/4));
+
+ for (int i = 0; i < input_w; i+=4)
+ {
+ *outp++ = *(imp+i);
+ count++;
+ }
+ }
+}
+
+int AddFrame(int mID, int k, float* trs1d)
+{
+ double t0, t1, time_c;
+ double trs[3][3];
+
+ t0 = now_ms();
+ int ret_code = mosaic[mID]->addFrame(tImage[mID][k]);
+
+ mosaic[mID]->getAligner()->getLastTRS(trs);
+
+ // LOGI("REG: %s",mosaic[mID]->getAligner()->getRegProfileString());
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGI("Align: %g ms",time_c);
+
+ if(trs1d!=NULL)
+ {
+
+ trs1d[0] = trs[0][0];
+ trs1d[1] = trs[0][1];
+ trs1d[2] = trs[0][2];
+ trs1d[3] = trs[1][0];
+ trs1d[4] = trs[1][1];
+ trs1d[5] = trs[1][2];
+ trs1d[6] = trs[2][0];
+ trs1d[7] = trs[2][1];
+ trs1d[8] = trs[2][2];
+ }
+
+ return ret_code;
+}
+
+void Finalize(int mID)
+{
+ double t0, t1, time_c;
+
+ t0 = now_ms();
+ // Create the mosaic
+ ret = mosaic[mID]->createMosaic();
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGI("CreateMosaic: %g ms",time_c);
+
+ // Get back the result
+ resultYVU = mosaic[mID]->getMosaic(mosaicWidth, mosaicHeight);
+}
+
+void YUV420toYVU24(ImageType yvu24, ImageType yuv420sp, int width, int height)
+{
+ int frameSize = width * height;
+
+ ImageType oyp = yvu24;
+ ImageType ovp = yvu24+frameSize;
+ ImageType oup = yvu24+frameSize+frameSize;
+
+ for (int j = 0, yp = 0; j < height; j++)
+ {
+ unsigned char u = 0, v = 0;
+ int uvp = frameSize + (j >> 1) * width;
+ for (int i = 0; i < width; i++, yp++)
+ {
+ *oyp++ = yuv420sp[yp];
+ //int y = (0xff & (int)yuv420sp[yp]) -16;
+ //yvu24p[yp] = (y<0)?0:y;
+
+ if ((i & 1) == 0)
+ {
+ v = yuv420sp[uvp++];
+ u = yuv420sp[uvp++];
+ }
+
+ *ovp++ = v;
+ *oup++ = u;
+ }
+ }
+}
+
+JNIEXPORT jboolean JNICALL Java_sri_ics_vt_SmartPhone_Mosaic_SetSourceImageDimensions(JNIEnv* env, jobject thiz, jint width, jint height)
+{
+ tWidth[HR] = width;
+ tHeight[HR] = height;
+ tWidth[LR] = int(width/H2L_FACTOR);
+ tHeight[LR] = int(height/H2L_FACTOR);
+
+ for(int i=0; i<MAX_FRAMES_LR; i++)
+ {
+ tImage[LR][i] = ImageUtils::allocateImage(tWidth[LR], tHeight[LR], ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
+ }
+ for(int i=0; i<MAX_FRAMES_HR; i++)
+ {
+ tImage[HR][i] = ImageUtils::allocateImage(tWidth[HR], tHeight[HR], ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
+ }
+ return 1;
+}
+
+
+JNIEXPORT jfloatArray JNICALL Java_sri_ics_vt_SmartPhone_Mosaic_SetSourceImage(JNIEnv* env, jobject thiz, jbyteArray photo_data)
+{
+ double t0, t1, time_c;
+ t0 = now_ms();
+
+ if(frame_number_HR<MAX_FRAMES_HR && frame_number_LR<MAX_FRAMES_LR)
+ {
+ jbyte *pixels = env->GetByteArrayElements(photo_data, 0);
+ YUV420toYVU24(tImage[HR][frame_number_HR], (ImageType)pixels, tWidth[HR], tHeight[HR]);
+
+ env->ReleaseByteArrayElements(photo_data, pixels, 0);
+
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGI("[%d] ReadImage: %g ms",frame_number_HR,time_c);
+
+ double last_tx = mTx;
+
+ t0 = now_ms();
+ GenerateQuarterResImagePlanar(tImage[HR][frame_number_HR], tWidth[HR], tHeight[HR], tImage[LR][frame_number_LR]);
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGI("[%d] HR->LR [%d]: %g ms",frame_number_HR,frame_number_LR,time_c);
+
+ int ret_code = AddFrame(LR,frame_number_LR,gTRS);
+
+ if(ret_code == Mosaic::MOSAIC_RET_OK)
+ {
+ frame_number_LR++;
+ frame_number_HR++;
+ }
+
+ }
+ else
+ {
+ gTRS[1] = gTRS[2] = gTRS[3] = gTRS[5] = gTRS[6] = gTRS[7] = 0.0f;
+ gTRS[0] = gTRS[4] = gTRS[8] = 1.0f;
+ }
+
+ gTRS[9] = frame_number_HR;
+
+ jfloatArray bytes = env->NewFloatArray(10);
+ if(bytes != 0)
+ {
+ env->SetFloatArrayRegion(bytes, 0, 10, (jfloat*) gTRS);
+ }
+ return bytes;
+}
+
+JNIEXPORT jboolean JNICALL Java_sri_ics_vt_SmartPhone_Mosaic_SetBlendingType(JNIEnv* env, jobject thiz, jint type)
+{
+ blendingType = int(type);
+
+ return 1;
+}
+
+JNIEXPORT jboolean JNICALL Java_sri_ics_vt_SmartPhone_Mosaic_Reset(JNIEnv* env, jobject thiz, jint type)
+{
+ frame_number_HR = 0;
+ frame_number_LR = 0;
+
+ blendingType = int(type);
+ Init(LR,MAX_FRAMES_LR);
+
+ return 1;
+}
+
+JNIEXPORT jboolean JNICALL Java_sri_ics_vt_SmartPhone_Mosaic_CreateMosaic(JNIEnv* env, jobject thiz, jboolean value)
+{
+ high_res = bool(value);
+
+ if(high_res)
+ {
+ Init(HR,frame_number_HR);
+ for(int k=0; k<frame_number_HR; k++)
+ {
+ AddFrame(HR,k,NULL);
+ LOGI("Added Frame [%d]",k);
+ }
+
+ Finalize(HR);
+ high_res = false;
+ }
+ else
+ {
+ Finalize(LR);
+ }
+
+ return 1;
+}
+JNIEXPORT jintArray JNICALL Java_sri_ics_vt_SmartPhone_Mosaic_GetFinalMosaic(JNIEnv* env, jobject thiz)
+{
+ int y,x;
+ int width = mosaicWidth;
+ int height = mosaicHeight;
+ int imageSize = width * height;
+
+ // Convert back to RGB24
+ resultBGR = ImageUtils::allocateImage(mosaicWidth, mosaicHeight, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
+ ImageUtils::yvu2bgr(resultBGR, resultYVU, mosaicWidth, mosaicHeight);
+
+ LOGI("MosBytes: %d, W = %d, H = %d", imageSize, width, height);
+
+ int* image = new int[imageSize];
+ int* dims = new int[2];
+
+ for(y=0; y<height; y++)
+ {
+ for(x=0; x<width; x++)
+ {
+ image[y*width+x] = (0xFF<<24) | (resultBGR[y*width*3+x*3+2]<<16)| (resultBGR[y*width*3+x*3+1]<<8)| (resultBGR[y*width*3+x*3]);
+ }
+ }
+
+ dims[0] = width;
+ dims[1] = height;
+
+ ImageUtils::freeImage(resultBGR);
+
+ jintArray bytes = env->NewIntArray(imageSize+2);
+ if (bytes == 0) {
+ LOGE("Error in creating the image.");
+ delete[] image;
+ return 0;
+ }
+ env->SetIntArrayRegion(bytes, 0, imageSize, (jint*) image);
+ env->SetIntArrayRegion(bytes, imageSize, 2, (jint*) dims);
+ delete[] image;
+ delete[] dims;
+ return bytes;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_sri_ics_vt_SmartPhone_Mosaic_GetFinalMosaicNV21(JNIEnv* env, jobject thiz)
+{
+ int y,x;
+ int width;
+ int height;
+
+ width = mosaicWidth;
+ height = mosaicHeight;
+
+ int imageSize = 1.5*width * height;
+
+ // Convert YVU to NV21 format in-place
+ ImageType V = resultYVU+mosaicWidth*mosaicHeight;
+ ImageType U = V+mosaicWidth*mosaicHeight;
+ for(int j=0; j<mosaicHeight; j++)
+ {
+ for(int i=0; i<mosaicWidth; i+=2)
+ {
+ V[j*mosaicWidth+i] = V[(2*j)*mosaicWidth+i]; // V
+ V[j*mosaicWidth+i+1] = U[(2*j)*mosaicWidth+i+1]; // U
+ }
+ }
+
+ LOGI("MosBytes: %d, W = %d, H = %d", imageSize, width, height);
+
+ unsigned char* dims = new unsigned char[8];
+
+ dims[0] = (unsigned char)(width >> 24);
+ dims[1] = (unsigned char)(width >> 16);
+ dims[2] = (unsigned char)(width >> 8);
+ dims[3] = (unsigned char)width;
+
+ dims[4] = (unsigned char)(height >> 24);
+ dims[5] = (unsigned char)(height >> 16);
+ dims[6] = (unsigned char)(height >> 8);
+ dims[7] = (unsigned char)height;
+
+ jbyteArray bytes = env->NewByteArray(imageSize+8);
+ if (bytes == 0) {
+ LOGE("Error in creating the image.");
+ ImageUtils::freeImage(resultYVU);
+ return 0;
+ }
+ env->SetByteArrayRegion(bytes, 0, imageSize, (jbyte*) resultYVU);
+ env->SetByteArrayRegion(bytes, imageSize, 8, (jbyte*) dims);
+ delete[] dims;
+ ImageUtils::freeImage(resultYVU);
+ return bytes;
+}
+
+#ifdef __cplusplus
+}
+#endif