115 lines
4.1 KiB
C++
115 lines
4.1 KiB
C++
/*
|
|
* Copyright (C) 2012 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.
|
|
*/
|
|
|
|
// Native function to extract histogram from image (handed down as ByteBuffer).
|
|
|
|
#include "sobeloperator.h"
|
|
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <jni.h>
|
|
#include <unistd.h>
|
|
#include <android/log.h>
|
|
|
|
#include "imgprocutil.h"
|
|
|
|
/*
|
|
* Perform 1d convolution on 3 channel image either horizontally or vertically.
|
|
* Parameters:
|
|
* inputHead: pointer to input image
|
|
* length: the length of image in the chosen axis.
|
|
* fragments: number of lines of the image in the chosen axis.
|
|
* step: the 1d pixel distance between adjacent pixels in the chosen axis.
|
|
* shift: the 1d pixel distance between adjacent lines in the chosen axis.
|
|
* filter: pointer to 1d filter
|
|
* halfSize: the length of filter is supposed to be (2 * halfSize + 1)
|
|
* outputHead: pointer to output image
|
|
*/
|
|
|
|
void computeGradient(unsigned char* dataPtr, int width, int height, short* gxPtr, short* gyPtr) {
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
const int left = (j > 0)? -4 : 0;
|
|
const int right = (j < width - 1) ? 4 : 0;
|
|
const int curr = (i * width + j) * 4;
|
|
const int above = (i > 0) ? curr - 4 * width : curr;
|
|
const int below = (i < height - 1) ? curr + 4 * width : curr;
|
|
const int offset = (i * width + j) * 3;
|
|
for (int c = 0; c < 3; c++) {
|
|
*(gxPtr + offset + c) =
|
|
(*(dataPtr + curr + c + right) - *(dataPtr + curr + c + left)) * 2 +
|
|
*(dataPtr + above + c + right) - *(dataPtr + above + c + left) +
|
|
*(dataPtr + below + c + right) - *(dataPtr + below + c + left);
|
|
*(gyPtr + offset + c) =
|
|
(*(dataPtr + c + below) - *(dataPtr + c + above)) * 2 +
|
|
*(dataPtr + left + c + below) - *(dataPtr + left + c + above) +
|
|
*(dataPtr + right + c + below) - *(dataPtr + right + c + above);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
jboolean Java_androidx_media_filterpacks_image_SobelFilter_sobelOperator(
|
|
JNIEnv* env, jclass clazz, jint width, jint height, jobject imageBuffer,
|
|
jobject magBuffer, jobject dirBuffer) {
|
|
|
|
if (imageBuffer == 0) {
|
|
return JNI_FALSE;
|
|
}
|
|
unsigned char* srcPtr = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer));
|
|
unsigned char* magPtr = (magBuffer == 0) ?
|
|
0 : static_cast<unsigned char*>(env->GetDirectBufferAddress(magBuffer));
|
|
unsigned char* dirPtr = (dirBuffer == 0) ?
|
|
0 : static_cast<unsigned char*>(env->GetDirectBufferAddress(dirBuffer));
|
|
|
|
int numPixels = width * height;
|
|
// TODO: avoid creating and deleting these buffers within this native function.
|
|
short* gxPtr = new short[3 * numPixels];
|
|
short* gyPtr = new short[3 * numPixels];
|
|
computeGradient(srcPtr, width, height, gxPtr, gyPtr);
|
|
|
|
for (int i = 0; i < numPixels; ++i) {
|
|
for (int c = 0; c < 3; c++) {
|
|
int gx = static_cast<int>(*(gxPtr + 3 * i + c) / 8 + 127.5);
|
|
int gy = static_cast<int>(*(gyPtr + 3 * i + c) / 8 + 127.5);
|
|
|
|
// emulate arithmetic in GPU.
|
|
gx = 2 * gx - 255;
|
|
gy = 2 * gy - 255;
|
|
if (magPtr != 0) {
|
|
double value = sqrt(gx * gx + gy * gy);
|
|
*(magPtr + 4 * i + c) = static_cast<unsigned char>(value);
|
|
}
|
|
if (dirPtr != 0) {
|
|
*(dirPtr + 4 * i + c) = static_cast<unsigned char>(
|
|
(atan(static_cast<double>(gy)/static_cast<double>(gx)) + 3.14) / 6.28);
|
|
}
|
|
}
|
|
//setting alpha change to 1.0 (255)
|
|
if (magPtr != 0) {
|
|
*(magPtr + 4 * i + 3) = 255;
|
|
}
|
|
if (dirPtr != 0) {
|
|
*(dirPtr + 4 * i + 3) = 255;
|
|
}
|
|
}
|
|
|
|
delete[] gxPtr;
|
|
delete[] gyPtr;
|
|
|
|
return JNI_TRUE;
|
|
}
|