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// Extract histogram from image. 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterpacks.colorspace; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameValue; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Filter; 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Frame; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameBuffer2D; 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameType; 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.MffContext; 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.OutputPort; 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Signature; 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer; 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteOrder; 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.FloatBuffer; 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * ColorfulnessFilter takes in a particular Chroma histogram generated by NewChromaHistogramFilter 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * and compute the colorfulness based on the entropy in Hue space. 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic final class ColorfulnessFilter extends Filter { 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public ColorfulnessFilter(MffContext context, String name) { 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks super(context, name); 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Signature getSignature() { 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameType dataIn = FrameType.buffer2D(FrameType.ELEMENT_FLOAT32); 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Signature() 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addInputPort("histogram", Signature.PORT_REQUIRED, dataIn) 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .addOutputPort("score", Signature.PORT_REQUIRED, FrameType.single(float.class)) 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .disallowOtherPorts(); 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected void onProcess() { 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameBuffer2D histogramFrame = 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getConnectedInputPort("histogram").pullFrame().asFrameBuffer2D(); 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ByteBuffer byteBuffer = histogramFrame.lockBytes(Frame.MODE_READ); 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks byteBuffer.order(ByteOrder.nativeOrder()); 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FloatBuffer histogramBuffer = byteBuffer.asFloatBuffer(); 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks histogramBuffer.rewind(); 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Create a hue histogram from hue-saturation histogram 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int hueBins = histogramFrame.getWidth(); 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int saturationBins = histogramFrame.getHeight() - 1; 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float[] hueHistogram = new float[hueBins]; 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float total = 0; 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int r = 0; r < saturationBins; ++r) { 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float weight = (float) Math.pow(2, r); 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int c = 0; c < hueBins; c++) { 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float value = histogramBuffer.get() * weight; 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks hueHistogram[c] += value; 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks total += value; 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float colorful = 0f; 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int c = 0; c < hueBins; ++c) { 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float value = hueHistogram[c] / total; 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (value > 0f) { 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorful -= value * ((float) Math.log(value)); 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks colorful /= Math.log(2); 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks histogramFrame.unlock(); 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks OutputPort outPort = getConnectedOutputPort("score"); 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks FrameValue frameValue = outPort.fetchAvailableFrame(null).asFrameValue(); 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks frameValue.setValue(colorful); 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks outPort.pushFrame(frameValue); 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 94