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 "histogram.h" 20 21#include <string.h> 22#include <jni.h> 23#include <unistd.h> 24#include <android/log.h> 25 26#include "imgprocutil.h" 27 28inline void addPixelToHistogram(unsigned char*& pImg, int* pHist, int numBins) { 29 int R = *(pImg++); 30 int G = *(pImg++); 31 int B = *(pImg++); 32 ++pImg; 33 int i = getIntensityFast(R, G, B); 34 int bin = clamp(0, static_cast<int>(static_cast<float>(i * numBins) / 255.0f), numBins - 1); 35 ++pHist[bin]; 36} 37 38void Java_androidx_media_filterpacks_histogram_GrayHistogramFilter_extractHistogram( 39 JNIEnv* env, jclass clazz, jobject imageBuffer, jobject maskBuffer, jobject histogramBuffer ) 40{ 41 unsigned char* pImg = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer)); 42 int* pHist = static_cast<int*>(env->GetDirectBufferAddress(histogramBuffer)); 43 int numPixels = env->GetDirectBufferCapacity(imageBuffer) / 4; // 4 bytes per pixel 44 int numBins = env->GetDirectBufferCapacity(histogramBuffer); 45 46 unsigned char* pMask = NULL; 47 if(maskBuffer != NULL) { 48 pMask = static_cast<unsigned char*>(env->GetDirectBufferAddress(maskBuffer)); 49 } 50 51 for(int i = 0; i < numBins; ++i) pHist[i] = 0; 52 53 if(pMask == NULL) { 54 for( ; numPixels > 0; --numPixels) { 55 addPixelToHistogram(pImg, pHist, numBins); 56 } 57 } else { 58 for( ; numPixels > 0; --numPixels) { 59 if(*pMask == 0){ 60 pMask += 4; 61 pImg += 4; // Note that otherwise addPixelToHistogram advances pImg by 4 62 continue; 63 } 64 pMask += 4; 65 addPixelToHistogram(pImg, pHist, numBins); 66 } 67 } 68} 69 70void Java_androidx_media_filterpacks_histogram_ChromaHistogramFilter_extractChromaHistogram( 71 JNIEnv* env, jclass clazz, jobject imageBuffer, jobject histogramBuffer, jint hBins, jint sBins) 72{ 73 unsigned char* pixelIn = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer)); 74 float* histOut = static_cast<float*>(env->GetDirectBufferAddress(histogramBuffer)); 75 int numPixels = env->GetDirectBufferCapacity(imageBuffer) / 4; // 4 bytes per pixel 76 77 for (int i = 0; i < hBins * sBins; ++i) histOut[i] = 0.0f; 78 79 int h, s, v; 80 float hScaler = hBins / 256.0f; 81 float sScaler = sBins / 256.0f; 82 for( ; numPixels > 0; --numPixels) { 83 h = *(pixelIn++); 84 s = *(pixelIn++); 85 v = *(pixelIn++); 86 pixelIn++; 87 88 int index = static_cast<int>(s * sScaler) * hBins + static_cast<int>(h * hScaler); 89 histOut[index] += 1.0f; 90 } 91} 92 93void Java_androidx_media_filterpacks_histogram_NewChromaHistogramFilter_extractChromaHistogram( 94 JNIEnv* env, jclass clazz, jobject imageBuffer, jobject histogramBuffer, 95 jint hueBins, jint saturationBins, jint valueBins, 96 jint saturationThreshold, jint valueThreshold) { 97 unsigned char* pixelIn = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer)); 98 float* histOut = static_cast<float*>(env->GetDirectBufferAddress(histogramBuffer)); 99 int numPixels = env->GetDirectBufferCapacity(imageBuffer) / 4; // 4 bytes per pixel 100 101 // TODO: add check on the size of histOut 102 for (int i = 0; i < (hueBins * saturationBins + valueBins); ++i) { 103 histOut[i] = 0.0f; 104 } 105 106 for( ; numPixels > 0; --numPixels) { 107 int h = *(pixelIn++); 108 int s = *(pixelIn++); 109 int v = *(pixelIn++); 110 111 pixelIn++; 112 // If a pixel that is either too dark (less than valueThreshold) or colorless 113 // (less than saturationThreshold), if will be put in a 1-D value histogram instead. 114 115 int index; 116 if (s > saturationThreshold && v > valueThreshold) { 117 int sIndex = s * saturationBins / 256; 118 119 // Shifting hue index by 0.5 such that peaks of red, yellow, green, cyan, blue, pink 120 // will be at the center of some bins. 121 int hIndex = ((h * hueBins + 128) / 256) % hueBins; 122 index = sIndex * hueBins + hIndex; 123 } else { 124 index = hueBins * saturationBins + (v * valueBins / 256); 125 } 126 histOut[index] += 1.0f; 127 } 128} 129