1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2012 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// Native function to extract histogram from image (handed down as ByteBuffer). 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "sobeloperator.h" 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include <math.h> 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include <string.h> 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include <jni.h> 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include <unistd.h> 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include <android/log.h> 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "imgprocutil.h" 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Perform 1d convolution on 3 channel image either horizontally or vertically. 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Parameters: 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * inputHead: pointer to input image 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * length: the length of image in the chosen axis. 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * fragments: number of lines of the image in the chosen axis. 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * step: the 1d pixel distance between adjacent pixels in the chosen axis. 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * shift: the 1d pixel distance between adjacent lines in the chosen axis. 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * filter: pointer to 1d filter 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * halfSize: the length of filter is supposed to be (2 * halfSize + 1) 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * outputHead: pointer to output image 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksvoid computeGradient(unsigned char* dataPtr, int width, int height, short* gxPtr, short* gyPtr) { 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < height; i++) { 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int j = 0; j < width; j++) { 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks const int left = (j > 0)? -4 : 0; 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks const int right = (j < width - 1) ? 4 : 0; 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks const int curr = (i * width + j) * 4; 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks const int above = (i > 0) ? curr - 4 * width : curr; 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks const int below = (i < height - 1) ? curr + 4 * width : curr; 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks const int offset = (i * width + j) * 3; 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int c = 0; c < 3; c++) { 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(gxPtr + offset + c) = 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (*(dataPtr + curr + c + right) - *(dataPtr + curr + c + left)) * 2 + 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(dataPtr + above + c + right) - *(dataPtr + above + c + left) + 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(dataPtr + below + c + right) - *(dataPtr + below + c + left); 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(gyPtr + offset + c) = 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (*(dataPtr + c + below) - *(dataPtr + c + above)) * 2 + 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(dataPtr + left + c + below) - *(dataPtr + left + c + above) + 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(dataPtr + right + c + below) - *(dataPtr + right + c + above); 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksjboolean Java_androidx_media_filterpacks_image_SobelFilter_sobelOperator( 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks JNIEnv* env, jclass clazz, jint width, jint height, jobject imageBuffer, 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks jobject magBuffer, jobject dirBuffer) { 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (imageBuffer == 0) { 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return JNI_FALSE; 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks unsigned char* srcPtr = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer)); 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks unsigned char* magPtr = (magBuffer == 0) ? 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 0 : static_cast<unsigned char*>(env->GetDirectBufferAddress(magBuffer)); 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks unsigned char* dirPtr = (dirBuffer == 0) ? 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 0 : static_cast<unsigned char*>(env->GetDirectBufferAddress(dirBuffer)); 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int numPixels = width * height; 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // TODO: avoid creating and deleting these buffers within this native function. 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks short* gxPtr = new short[3 * numPixels]; 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks short* gyPtr = new short[3 * numPixels]; 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks computeGradient(srcPtr, width, height, gxPtr, gyPtr); 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks unsigned char* mag = magPtr; 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks unsigned char* dir = dirPtr; 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < numPixels; ++i) { 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int c = 0; c < 3; c++) { 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int gx = static_cast<int>(*(gxPtr + 3 * i + c) / 8 + 127.5); 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int gy = static_cast<int>(*(gyPtr + 3 * i + c) / 8 + 127.5); 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // emulate arithmetic in GPU. 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks gx = 2 * gx - 255; 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks gy = 2 * gy - 255; 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (magPtr != 0) { 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks double value = sqrt(gx * gx + gy * gy); 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(magPtr + 4 * i + c) = static_cast<unsigned char>(value); 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (dirPtr != 0) { 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(dirPtr + 4 * i + c) = static_cast<unsigned char>( 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (atan(static_cast<double>(gy)/static_cast<double>(gx)) + 3.14) / 6.28); 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks //setting alpha change to 1.0 (255) 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (magPtr != 0) { 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(magPtr + 4 * i + 3) = 255; 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (dirPtr != 0) { 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *(dirPtr + 4 * i + 3) = 255; 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks delete[] gxPtr; 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks delete[] gyPtr; 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return JNI_TRUE; 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 117