1/*
2 * Copyright (C) 2013 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
17package com.android.gallery3d.filtershow.info;
18
19import android.content.Context;
20import android.graphics.Bitmap;
21import android.graphics.Canvas;
22import android.graphics.Color;
23import android.graphics.Paint;
24import android.graphics.Path;
25import android.graphics.PorterDuff;
26import android.graphics.PorterDuffXfermode;
27import android.os.AsyncTask;
28import android.util.AttributeSet;
29import android.view.View;
30
31public class HistogramView extends View {
32
33    private Bitmap mBitmap;
34    private Paint mPaint = new Paint();
35    private int[] redHistogram = new int[256];
36    private int[] greenHistogram = new int[256];
37    private int[] blueHistogram = new int[256];
38    private Path mHistoPath = new Path();
39
40    class ComputeHistogramTask extends AsyncTask<Bitmap, Void, int[]> {
41        @Override
42        protected int[] doInBackground(Bitmap... params) {
43            int[] histo = new int[256 * 3];
44            Bitmap bitmap = params[0];
45            int w = bitmap.getWidth();
46            int h = bitmap.getHeight();
47            int[] pixels = new int[w * h];
48            bitmap.getPixels(pixels, 0, w, 0, 0, w, h);
49            for (int i = 0; i < w; i++) {
50                for (int j = 0; j < h; j++) {
51                    int index = j * w + i;
52                    int r = Color.red(pixels[index]);
53                    int g = Color.green(pixels[index]);
54                    int b = Color.blue(pixels[index]);
55                    histo[r]++;
56                    histo[256 + g]++;
57                    histo[512 + b]++;
58                }
59            }
60            return histo;
61        }
62
63        @Override
64        protected void onPostExecute(int[] result) {
65            System.arraycopy(result, 0, redHistogram, 0, 256);
66            System.arraycopy(result, 256, greenHistogram, 0, 256);
67            System.arraycopy(result, 512, blueHistogram, 0, 256);
68            invalidate();
69        }
70    }
71
72    public HistogramView(Context context, AttributeSet attrs) {
73        super(context, attrs);
74    }
75
76    public void setBitmap(Bitmap bitmap) {
77        mBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
78        new ComputeHistogramTask().execute(mBitmap);
79    }
80
81    private void drawHistogram(Canvas canvas, int[] histogram, int color, PorterDuff.Mode mode) {
82        int max = 0;
83        for (int i = 0; i < histogram.length; i++) {
84            if (histogram[i] > max) {
85                max = histogram[i];
86            }
87        }
88        float w = getWidth(); // - Spline.curveHandleSize();
89        float h = getHeight(); // - Spline.curveHandleSize() / 2.0f;
90        float dx = 0; // Spline.curveHandleSize() / 2.0f;
91        float wl = w / histogram.length;
92        float wh = h / max;
93
94        mPaint.reset();
95        mPaint.setAntiAlias(true);
96        mPaint.setARGB(100, 255, 255, 255);
97        mPaint.setStrokeWidth((int) Math.ceil(wl));
98
99        // Draw grid
100        mPaint.setStyle(Paint.Style.STROKE);
101        canvas.drawRect(dx, 0, dx + w, h, mPaint);
102        canvas.drawLine(dx + w / 3, 0, dx + w / 3, h, mPaint);
103        canvas.drawLine(dx + 2 * w / 3, 0, dx + 2 * w / 3, h, mPaint);
104
105        mPaint.setStyle(Paint.Style.FILL);
106        mPaint.setColor(color);
107        mPaint.setStrokeWidth(6);
108        mPaint.setXfermode(new PorterDuffXfermode(mode));
109        mHistoPath.reset();
110        mHistoPath.moveTo(dx, h);
111        boolean firstPointEncountered = false;
112        float prev = 0;
113        float last = 0;
114        for (int i = 0; i < histogram.length; i++) {
115            float x = i * wl + dx;
116            float l = histogram[i] * wh;
117            if (l != 0) {
118                float v = h - (l + prev) / 2.0f;
119                if (!firstPointEncountered) {
120                    mHistoPath.lineTo(x, h);
121                    firstPointEncountered = true;
122                }
123                mHistoPath.lineTo(x, v);
124                prev = l;
125                last = x;
126            }
127        }
128        mHistoPath.lineTo(last, h);
129        mHistoPath.lineTo(w, h);
130        mHistoPath.close();
131        canvas.drawPath(mHistoPath, mPaint);
132        mPaint.setStrokeWidth(2);
133        mPaint.setStyle(Paint.Style.STROKE);
134        mPaint.setARGB(255, 200, 200, 200);
135        canvas.drawPath(mHistoPath, mPaint);
136    }
137
138    public void onDraw(Canvas canvas) {
139        canvas.drawARGB(0, 0, 0, 0);
140        drawHistogram(canvas, redHistogram, Color.RED, PorterDuff.Mode.SCREEN);
141        drawHistogram(canvas, greenHistogram, Color.GREEN, PorterDuff.Mode.SCREEN);
142        drawHistogram(canvas, blueHistogram, Color.BLUE, PorterDuff.Mode.SCREEN);
143    }
144}
145