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