// General headers.
#include <jni.h>
#include <android/log.h>
#include <vector>
#include <dlfcn.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

// OpenCV headers.
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

// OpenCL headers.
#include <CL/cl.h>

// Boost headers.
#include <boost/version.hpp>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>

#define TAG "SagivTechNative"
#define LOG(...) do {__android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__); printf(__VA_ARGS__); printf("\n"); } while (0)

extern "C" {

using namespace cv;

// OpenCL static global variables.
#define MAX_DEVICES 10
static bool oclPlatformInitialized = false;
static cl_platform_id oclPlatform_ = NULL;
static cl_device_id oclDevices_[MAX_DEVICES];
static cl_device_id oclDeviceId_ = 0;
static cl_context oclContext_ = NULL;
static cl_command_queue oclCommandQueue_ = NULL;
static cl_program oclProgram_ = NULL;
static cl_kernel oclKernel_ = NULL;
static cl_mem oclInput = NULL;
static cl_mem oclOutput = NULL;
static cl_event oclEvent;


// Boost thread function
void workerFunc()
{
    boost::posix_time::seconds workTime(3);
    LOG("Worker: Start");
    boost::this_thread::sleep(workTime);
    LOG("Worker: finished");
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// OpenCV functionality.
//////////////////////////////////////////////////////////////////////////////////////////////////

// OpenCV code to convert a cv::mat from BRGA to Gray.
JNIEXPORT jint JNICALL Java_com_example_sagivtechtemplate_SagivTechProcessingThread_OpenCVBgraToGray(
		JNIEnv *env, jobject obj, jlong pInputMatrix, jlong pOutputMatrix)
{
	// Boost test code to open a thread.
//	boost::thread workerThread(workerFunc);
//	LOG("Main thread waiting for worker");
//	workerThread.join();


	LOG("[OpenCVBgraToGray]: Start");
	Mat& matInput  = *(Mat*)pInputMatrix;
	Mat& matOutput  = *(Mat*)pOutputMatrix;

	cv::cvtColor(matInput, matOutput, CV_BGRA2GRAY);
	LOG("[OpenCVBgraToGray]: End");

	 return 0;
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// OpenCL functionality.
//////////////////////////////////////////////////////////////////////////////////////////////////
JNIEXPORT jint JNICALL Java_com_example_sagivtechtemplate_SagivTechProcessingThread_oclInitialize(JNIEnv *env, jobject obj, jint w, jint h, jobject kernel_code)
{
	jint err = 0;
	char sMessage[100];
	char sDeviceName[100];
	LOG("[oclInitialize]: Start");

	// Only initialize the OpenCL platform once
	if (!oclPlatformInitialized)
	{
		LOG("[oclInitialize]: Initializing the platform");

		err = clGetPlatformIDs(1, &oclPlatform_, NULL);
		err = clGetDeviceIDs(oclPlatform_, CL_DEVICE_TYPE_GPU, 1, &oclDeviceId_, NULL);

		err = clGetDeviceInfo(oclDeviceId_, CL_DEVICE_NAME, 100, sDeviceName, NULL);
		LOG("[oclInitialize]: %s", sDeviceName);

		oclContext_ 	 = clCreateContext(NULL, 1, &oclDeviceId_, NULL, NULL, &err);
		oclCommandQueue_ = clCreateCommandQueue(oclContext_, oclDeviceId_, 0, &err);

		char *kernelCode = (char *)env->GetDirectBufferAddress(kernel_code);
		const ::size_t iKernelTextLength = strlen(kernelCode);
		LOG("[oclInitialize]: Kernel size[%d]\ncode:\n %s", iKernelTextLength, kernelCode);

		LOG("[oclInitialize]: Calling clCreateProgramWithSource");
		oclProgram_ = clCreateProgramWithSource(oclContext_, 1, (const char**)&kernelCode, &iKernelTextLength, &err);
		LOG("[oclInitialize]: clCreateProgramWithSource returned: [%d]", err);

		char compilerOptions[1024];
		sprintf(compilerOptions, "-cl-fast-relaxed-math -cl-unsafe-math-optimizations -cl-finite-math-only -Werror");
		LOG("[oclInitialize]: Calling clBuildProgram with: [%s]", compilerOptions);
		err = clBuildProgram(oclProgram_, 0, NULL, (const char *)(&compilerOptions[0]), NULL, NULL);
		if (CL_SUCCESS != err)
		{
			::size_t len;
			char buffer[9000];
			clGetProgramBuildInfo(oclProgram_, oclDeviceId_, CL_PROGRAM_BUILD_LOG, 9000, buffer, &len);
			LOG("[oclInitialize]: Error building program: [%s]. error code: [%d]. iKernelTextLength[%d]", buffer, err, iKernelTextLength);
			return -1;
		}
		LOG("[oclInitialize]: Calling clCreateKernel");
		oclKernel_ = clCreateKernel(oclProgram_, "kernelSagivTechSample", &err);
		LOG("[oclInitialize]: clCreateKernel resulted: %d", err);

		LOG("[oclInitialize]:  Platform initialized");
		oclPlatformInitialized = true;
	}

	// Create the buffers inputs/outputs
	if (NULL != oclInput)
	{
		clReleaseMemObject(oclInput);
		clReleaseMemObject(oclOutput);
		oclInput 		= NULL;
		oclOutput		= NULL;
	}

	LOG("[oclInitialize]: Buffers size: [%d x %d]", w, h);
	oclInput  = clCreateBuffer(oclContext_, CL_MEM_READ_ONLY, (unsigned long int)(w * h * sizeof(int)), NULL, &err);
	LOG("[oclInitialize]: Input buffer created [%d]", err);
	oclOutput = clCreateBuffer(oclContext_, CL_MEM_READ_WRITE, (unsigned long int)(w * h * sizeof(int)), NULL, &err);
	LOG("[oclInitialize]: Output buffer created [%d]", err);

	LOG("[oclInitialize]: End");
	return 0;
}

JNIEXPORT jint JNICALL Java_com_example_sagivtechtemplate_SagivTechProcessingThread_oclRun(JNIEnv *env, jobject obj, jlong matInput, jobject outputBuffer)
{
	LOG("[oclRun]: Start");
	jint err = 0;
	Mat &input  = *(Mat*)matInput;
	void *output_ptr = env->GetDirectBufferAddress(outputBuffer);

	int w = input.cols;
	int h = input.rows;

	LOG("[oclRun]: Input: Channels: [%d], total[%d], w[%d], h[%d]", input.channels(), input.total(), w, h);

	LOG("[oclRun]: Copy host input -> Device");
	err = clEnqueueWriteBuffer(oclCommandQueue_, oclInput, CL_TRUE, 0, (unsigned long int)(w * h * sizeof(int)), (void *)input.data, 0, NULL, NULL);

	LOG("[oclRun]: Run kernel");

	const ::size_t globalWorkSize[2] = {w, h};
	const ::size_t localWorkSize = 1;

	int kernelParam = 0;
	err = clSetKernelArg(oclKernel_, kernelParam++, (unsigned long)sizeof(jint), &w);
	err = clSetKernelArg(oclKernel_, kernelParam++, (unsigned long)sizeof(jint), &h);
	err = clSetKernelArg(oclKernel_, kernelParam++, (unsigned long)sizeof(cl_mem), &oclInput);
	err = clSetKernelArg(oclKernel_, kernelParam++, (unsigned long)sizeof(cl_mem), &oclOutput);

	err = clEnqueueNDRangeKernel(oclCommandQueue_, oclKernel_, 2, NULL, &globalWorkSize[0], NULL, 0, NULL, &oclEvent);
	LOG("[oclRun]:clEnqueueNDRangeKernel result: [%d]", err);
	LOG("[oclRun]:Calling clFinish");
	clFlush(oclCommandQueue_);
	clFinish(oclCommandQueue_);

	LOG("[oclRun]:Copy device output -> Host");
	err = clEnqueueReadBuffer(oclCommandQueue_, oclOutput, CL_TRUE, 0, (unsigned long int)(w * h * sizeof(int)), output_ptr, 0, NULL, NULL);
	LOG("[oclRun]:End");
}

//////////////////////////////////////////////////////////////////////////////////////////////////
// Constant stretching functionality.
//////////////////////////////////////////////////////////////////////////////////////////////////

// OpenCV code to convert a cv::mat from BRGA to Gray.
JNIEXPORT jint JNICALL Java_com_example_sagivtechtemplate_SagivTechProcessingThread_CPUContrastStretching(
		JNIEnv *env, jobject obj, jlong pInputMatrix, jlong pOutputMatrix)
{
	LOG("[CPUContrastStretching]: Start");
	Mat& matInput  = *(Mat*)pInputMatrix;
	Mat& matOutput  = *(Mat*)pOutputMatrix;

//	normalize(matInput, matOutput, 10, 100, CV_MINMAX);

	int iMinVValue = INT_MAX;
	int iMaxVValue = -1;
	cv::cvtColor(matInput, matOutput, CV_BGR2HSV);
	for (int h = 0; h < matOutput.rows; h++) {
		for (int w = 0; w < matOutput.cols; w++) {
			Vec3b pixel = matOutput.at<Vec3b>(h, w);
			if (pixel[2] < iMinVValue)
				iMinVValue = pixel[2];
			if (pixel[2] > iMaxVValue)
				iMaxVValue = pixel[2];
			//pixel[2] = 0;
			//matOutput.at<Vec3b>(h, w) = pixel;
		}
	}
	LOG("[CPUContrastStretching]: Min V value [%d], Max V value [%d]", iMinVValue, iMaxVValue);

	//cv::cvtColor(matOutput, matOutput, CV_HSV2BGR);
	LOG("[CPUContrastStretching]: End");

	 return 0;
}


}

Legal Disclaimer:

You understand that when using the Site you may be exposed to content from a variety of sources, and that SagivTech is not responsible for the accuracy, usefulness, safety or intellectual property rights of, or relating to, such content and that such content does not express SagivTech’s opinion or endorsement of any subject matter and should not be relied upon as such. SagivTech and its affiliates accept no responsibility for any consequences whatsoever arising from use of such content. You acknowledge that any use of the content is at your own risk.