/* * 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 "histogram.h" #include <string.h> #include <jni.h> #include <unistd.h> #include <android/log.h> #include "imgprocutil.h" inline void addPixelToHistogram(unsigned char*& pImg, int* pHist, int numBins) { int R = *(pImg++); int G = *(pImg++); int B = *(pImg++); ++pImg; int i = getIntensityFast(R, G, B); int bin = clamp(0, static_cast<int>(static_cast<float>(i * numBins) / 255.0f), numBins - 1); ++pHist[bin]; } void Java_androidx_media_filterpacks_histogram_GrayHistogramFilter_extractHistogram( JNIEnv* env, jclass clazz, jobject imageBuffer, jobject maskBuffer, jobject histogramBuffer ) { unsigned char* pImg = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer)); int* pHist = static_cast<int*>(env->GetDirectBufferAddress(histogramBuffer)); int numPixels = env->GetDirectBufferCapacity(imageBuffer) / 4; // 4 bytes per pixel int numBins = env->GetDirectBufferCapacity(histogramBuffer); unsigned char* pMask = NULL; if(maskBuffer != NULL) { pMask = static_cast<unsigned char*>(env->GetDirectBufferAddress(maskBuffer)); } for(int i = 0; i < numBins; ++i) pHist[i] = 0; if(pMask == NULL) { for( ; numPixels > 0; --numPixels) { addPixelToHistogram(pImg, pHist, numBins); } } else { for( ; numPixels > 0; --numPixels) { if(*pMask == 0){ pMask += 4; pImg += 4; // Note that otherwise addPixelToHistogram advances pImg by 4 continue; } pMask += 4; addPixelToHistogram(pImg, pHist, numBins); } } } void Java_androidx_media_filterpacks_histogram_ChromaHistogramFilter_extractChromaHistogram( JNIEnv* env, jclass clazz, jobject imageBuffer, jobject histogramBuffer, jint hBins, jint sBins) { unsigned char* pixelIn = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer)); float* histOut = static_cast<float*>(env->GetDirectBufferAddress(histogramBuffer)); int numPixels = env->GetDirectBufferCapacity(imageBuffer) / 4; // 4 bytes per pixel for (int i = 0; i < hBins * sBins; ++i) histOut[i] = 0.0f; int h, s, v; float hScaler = hBins / 256.0f; float sScaler = sBins / 256.0f; for( ; numPixels > 0; --numPixels) { h = *(pixelIn++); s = *(pixelIn++); v = *(pixelIn++); pixelIn++; int index = static_cast<int>(s * sScaler) * hBins + static_cast<int>(h * hScaler); histOut[index] += 1.0f; } } void Java_androidx_media_filterpacks_histogram_NewChromaHistogramFilter_extractChromaHistogram( JNIEnv* env, jclass clazz, jobject imageBuffer, jobject histogramBuffer, jint hueBins, jint saturationBins, jint valueBins, jint saturationThreshold, jint valueThreshold) { unsigned char* pixelIn = static_cast<unsigned char*>(env->GetDirectBufferAddress(imageBuffer)); float* histOut = static_cast<float*>(env->GetDirectBufferAddress(histogramBuffer)); int numPixels = env->GetDirectBufferCapacity(imageBuffer) / 4; // 4 bytes per pixel // TODO: add check on the size of histOut for (int i = 0; i < (hueBins * saturationBins + valueBins); ++i) { histOut[i] = 0.0f; } for( ; numPixels > 0; --numPixels) { int h = *(pixelIn++); int s = *(pixelIn++); int v = *(pixelIn++); pixelIn++; // If a pixel that is either too dark (less than valueThreshold) or colorless // (less than saturationThreshold), if will be put in a 1-D value histogram instead. int index; if (s > saturationThreshold && v > valueThreshold) { int sIndex = s * saturationBins / 256; // Shifting hue index by 0.5 such that peaks of red, yellow, green, cyan, blue, pink // will be at the center of some bins. int hIndex = ((h * hueBins + 128) / 256) % hueBins; index = sIndex * hueBins + hIndex; } else { index = hueBins * saturationBins + (v * valueBins / 256); } histOut[index] += 1.0f; } }