1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Native function to extract histogram from image (handed down as ByteBuffer). 18 19 #include "sobeloperator.h" 20 21 #include <math.h> 22 #include <string.h> 23 #include <jni.h> 24 #include <unistd.h> 25 #include <android/log.h> 26 27 #include "imgprocutil.h" 28 29 /* 30 * Perform 1d convolution on 3 channel image either horizontally or vertically. 31 * Parameters: 32 * inputHead: pointer to input image 33 * length: the length of image in the chosen axis. 34 * fragments: number of lines of the image in the chosen axis. 35 * step: the 1d pixel distance between adjacent pixels in the chosen axis. 36 * shift: the 1d pixel distance between adjacent lines in the chosen axis. 37 * filter: pointer to 1d filter 38 * halfSize: the length of filter is supposed to be (2 * halfSize + 1) 39 * outputHead: pointer to output image 40 */ 41 42 void computeGradient(unsigned char* dataPtr, int width, int height, short* gxPtr, short* gyPtr) { 43 for (int i = 0; i < height; i++) { 44 for (int j = 0; j < width; j++) { 45 const int left = (j > 0)? -4 : 0; 46 const int right = (j < width - 1) ? 4 : 0; 47 const int curr = (i * width + j) * 4; 48 const int above = (i > 0) ? curr - 4 * width : curr; 49 const int below = (i < height - 1) ? curr + 4 * width : curr; 50 const int offset = (i * width + j) * 3; 51 for (int c = 0; c < 3; c++) { 52 *(gxPtr + offset + c) = 53 (*(dataPtr + curr + c + right) - *(dataPtr + curr + c + left)) * 2 + 54 *(dataPtr + above + c + right) - *(dataPtr + above + c + left) + 55 *(dataPtr + below + c + right) - *(dataPtr + below + c + left); 56 *(gyPtr + offset + c) = 57 (*(dataPtr + c + below) - *(dataPtr + c + above)) * 2 + 58 *(dataPtr + left + c + below) - *(dataPtr + left + c + above) + 59 *(dataPtr + right + c + below) - *(dataPtr + right + c + above); 60 } 61 } 62 } 63 } 64 65 jboolean Java_androidx_media_filterpacks_image_SobelFilter_sobelOperator( 66 JNIEnv* env, jclass clazz, jint width, jint height, jobject imageBuffer, 67 jobject magBuffer, jobject dirBuffer) { 68 69 if (imageBuffer == 0) { 70 return JNI_FALSE; 71 } 72 unsigned char* srcPtr = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer)); 73 unsigned char* magPtr = (magBuffer == 0) ? 74 0 : static_cast<unsigned char*>(env->GetDirectBufferAddress(magBuffer)); 75 unsigned char* dirPtr = (dirBuffer == 0) ? 76 0 : static_cast<unsigned char*>(env->GetDirectBufferAddress(dirBuffer)); 77 78 int numPixels = width * height; 79 // TODO: avoid creating and deleting these buffers within this native function. 80 short* gxPtr = new short[3 * numPixels]; 81 short* gyPtr = new short[3 * numPixels]; 82 computeGradient(srcPtr, width, height, gxPtr, gyPtr); 83 84 for (int i = 0; i < numPixels; ++i) { 85 for (int c = 0; c < 3; c++) { 86 int gx = static_cast<int>(*(gxPtr + 3 * i + c) / 8 + 127.5); 87 int gy = static_cast<int>(*(gyPtr + 3 * i + c) / 8 + 127.5); 88 89 // emulate arithmetic in GPU. 90 gx = 2 * gx - 255; 91 gy = 2 * gy - 255; 92 if (magPtr != 0) { 93 double value = sqrt(gx * gx + gy * gy); 94 *(magPtr + 4 * i + c) = static_cast<unsigned char>(value); 95 } 96 if (dirPtr != 0) { 97 *(dirPtr + 4 * i + c) = static_cast<unsigned char>( 98 (atan(static_cast<double>(gy)/static_cast<double>(gx)) + 3.14) / 6.28); 99 } 100 } 101 //setting alpha change to 1.0 (255) 102 if (magPtr != 0) { 103 *(magPtr + 4 * i + 3) = 255; 104 } 105 if (dirPtr != 0) { 106 *(dirPtr + 4 * i + 3) = 255; 107 } 108 } 109 110 delete[] gxPtr; 111 delete[] gyPtr; 112 113 return JNI_TRUE; 114 } 115