1860af325f2030a03c526e8551a85230d17df7b15nicolasroard/* 2860af325f2030a03c526e8551a85230d17df7b15nicolasroard * Copyright (C) 2013 The Android Open Source Project 3860af325f2030a03c526e8551a85230d17df7b15nicolasroard * 4860af325f2030a03c526e8551a85230d17df7b15nicolasroard * Licensed under the Apache License, Version 2.0 (the "License"); 5860af325f2030a03c526e8551a85230d17df7b15nicolasroard * you may not use this file except in compliance with the License. 6860af325f2030a03c526e8551a85230d17df7b15nicolasroard * You may obtain a copy of the License at 7860af325f2030a03c526e8551a85230d17df7b15nicolasroard * 8860af325f2030a03c526e8551a85230d17df7b15nicolasroard * http://www.apache.org/licenses/LICENSE-2.0 9860af325f2030a03c526e8551a85230d17df7b15nicolasroard * 10860af325f2030a03c526e8551a85230d17df7b15nicolasroard * Unless required by applicable law or agreed to in writing, software 11860af325f2030a03c526e8551a85230d17df7b15nicolasroard * distributed under the License is distributed on an "AS IS" BASIS, 12860af325f2030a03c526e8551a85230d17df7b15nicolasroard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13860af325f2030a03c526e8551a85230d17df7b15nicolasroard * See the License for the specific language governing permissions and 14860af325f2030a03c526e8551a85230d17df7b15nicolasroard * limitations under the License. 15860af325f2030a03c526e8551a85230d17df7b15nicolasroard */ 16860af325f2030a03c526e8551a85230d17df7b15nicolasroard 17860af325f2030a03c526e8551a85230d17df7b15nicolasroardpackage com.android.gallery3d.filtershow.info; 18860af325f2030a03c526e8551a85230d17df7b15nicolasroard 19860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.content.Context; 20860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.graphics.Bitmap; 21860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.graphics.Canvas; 22860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.graphics.Color; 23860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.graphics.Paint; 24860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.graphics.Path; 25860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.graphics.PorterDuff; 26860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.graphics.PorterDuffXfermode; 27860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.os.AsyncTask; 28860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.util.AttributeSet; 29860af325f2030a03c526e8551a85230d17df7b15nicolasroardimport android.view.View; 30860af325f2030a03c526e8551a85230d17df7b15nicolasroard 31860af325f2030a03c526e8551a85230d17df7b15nicolasroardpublic class HistogramView extends View { 32860af325f2030a03c526e8551a85230d17df7b15nicolasroard 33860af325f2030a03c526e8551a85230d17df7b15nicolasroard private Bitmap mBitmap; 34b203968cc53015d9c51b790a56cca638be77818dnicolasroard private Paint mPaint = new Paint(); 35b203968cc53015d9c51b790a56cca638be77818dnicolasroard private int[] redHistogram = new int[256]; 36b203968cc53015d9c51b790a56cca638be77818dnicolasroard private int[] greenHistogram = new int[256]; 37b203968cc53015d9c51b790a56cca638be77818dnicolasroard private int[] blueHistogram = new int[256]; 38b203968cc53015d9c51b790a56cca638be77818dnicolasroard private Path mHistoPath = new Path(); 39860af325f2030a03c526e8551a85230d17df7b15nicolasroard 40860af325f2030a03c526e8551a85230d17df7b15nicolasroard class ComputeHistogramTask extends AsyncTask<Bitmap, Void, int[]> { 41860af325f2030a03c526e8551a85230d17df7b15nicolasroard @Override 42860af325f2030a03c526e8551a85230d17df7b15nicolasroard protected int[] doInBackground(Bitmap... params) { 43860af325f2030a03c526e8551a85230d17df7b15nicolasroard int[] histo = new int[256 * 3]; 44860af325f2030a03c526e8551a85230d17df7b15nicolasroard Bitmap bitmap = params[0]; 45860af325f2030a03c526e8551a85230d17df7b15nicolasroard int w = bitmap.getWidth(); 46860af325f2030a03c526e8551a85230d17df7b15nicolasroard int h = bitmap.getHeight(); 47860af325f2030a03c526e8551a85230d17df7b15nicolasroard int[] pixels = new int[w * h]; 48860af325f2030a03c526e8551a85230d17df7b15nicolasroard bitmap.getPixels(pixels, 0, w, 0, 0, w, h); 49860af325f2030a03c526e8551a85230d17df7b15nicolasroard for (int i = 0; i < w; i++) { 50860af325f2030a03c526e8551a85230d17df7b15nicolasroard for (int j = 0; j < h; j++) { 51860af325f2030a03c526e8551a85230d17df7b15nicolasroard int index = j * w + i; 52860af325f2030a03c526e8551a85230d17df7b15nicolasroard int r = Color.red(pixels[index]); 53860af325f2030a03c526e8551a85230d17df7b15nicolasroard int g = Color.green(pixels[index]); 54860af325f2030a03c526e8551a85230d17df7b15nicolasroard int b = Color.blue(pixels[index]); 55860af325f2030a03c526e8551a85230d17df7b15nicolasroard histo[r]++; 56860af325f2030a03c526e8551a85230d17df7b15nicolasroard histo[256 + g]++; 57860af325f2030a03c526e8551a85230d17df7b15nicolasroard histo[512 + b]++; 58860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 59860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 60860af325f2030a03c526e8551a85230d17df7b15nicolasroard return histo; 61860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 62860af325f2030a03c526e8551a85230d17df7b15nicolasroard 63860af325f2030a03c526e8551a85230d17df7b15nicolasroard @Override 64860af325f2030a03c526e8551a85230d17df7b15nicolasroard protected void onPostExecute(int[] result) { 65860af325f2030a03c526e8551a85230d17df7b15nicolasroard System.arraycopy(result, 0, redHistogram, 0, 256); 66860af325f2030a03c526e8551a85230d17df7b15nicolasroard System.arraycopy(result, 256, greenHistogram, 0, 256); 67860af325f2030a03c526e8551a85230d17df7b15nicolasroard System.arraycopy(result, 512, blueHistogram, 0, 256); 68860af325f2030a03c526e8551a85230d17df7b15nicolasroard invalidate(); 69860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 70860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 71860af325f2030a03c526e8551a85230d17df7b15nicolasroard 72860af325f2030a03c526e8551a85230d17df7b15nicolasroard public HistogramView(Context context, AttributeSet attrs) { 73860af325f2030a03c526e8551a85230d17df7b15nicolasroard super(context, attrs); 74860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 75860af325f2030a03c526e8551a85230d17df7b15nicolasroard 76860af325f2030a03c526e8551a85230d17df7b15nicolasroard public void setBitmap(Bitmap bitmap) { 77860af325f2030a03c526e8551a85230d17df7b15nicolasroard mBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); 78860af325f2030a03c526e8551a85230d17df7b15nicolasroard new ComputeHistogramTask().execute(mBitmap); 79860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 80860af325f2030a03c526e8551a85230d17df7b15nicolasroard 81860af325f2030a03c526e8551a85230d17df7b15nicolasroard private void drawHistogram(Canvas canvas, int[] histogram, int color, PorterDuff.Mode mode) { 82860af325f2030a03c526e8551a85230d17df7b15nicolasroard int max = 0; 83860af325f2030a03c526e8551a85230d17df7b15nicolasroard for (int i = 0; i < histogram.length; i++) { 84860af325f2030a03c526e8551a85230d17df7b15nicolasroard if (histogram[i] > max) { 85860af325f2030a03c526e8551a85230d17df7b15nicolasroard max = histogram[i]; 86860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 87860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 88b203968cc53015d9c51b790a56cca638be77818dnicolasroard float w = getWidth(); // - Spline.curveHandleSize(); 89b203968cc53015d9c51b790a56cca638be77818dnicolasroard float h = getHeight(); // - Spline.curveHandleSize() / 2.0f; 90b203968cc53015d9c51b790a56cca638be77818dnicolasroard float dx = 0; // Spline.curveHandleSize() / 2.0f; 91860af325f2030a03c526e8551a85230d17df7b15nicolasroard float wl = w / histogram.length; 927321f1d82c7b72b491bf7c20b03e3491cb91fcabnicolasroard float wh = h / max; 93b203968cc53015d9c51b790a56cca638be77818dnicolasroard 94b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.reset(); 95b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setAntiAlias(true); 96b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setARGB(100, 255, 255, 255); 97b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setStrokeWidth((int) Math.ceil(wl)); 98860af325f2030a03c526e8551a85230d17df7b15nicolasroard 99860af325f2030a03c526e8551a85230d17df7b15nicolasroard // Draw grid 100b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setStyle(Paint.Style.STROKE); 101b203968cc53015d9c51b790a56cca638be77818dnicolasroard canvas.drawRect(dx, 0, dx + w, h, mPaint); 102b203968cc53015d9c51b790a56cca638be77818dnicolasroard canvas.drawLine(dx + w / 3, 0, dx + w / 3, h, mPaint); 103b203968cc53015d9c51b790a56cca638be77818dnicolasroard canvas.drawLine(dx + 2 * w / 3, 0, dx + 2 * w / 3, h, mPaint); 104860af325f2030a03c526e8551a85230d17df7b15nicolasroard 105b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setStyle(Paint.Style.FILL); 106b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setColor(color); 107b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setStrokeWidth(6); 108b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setXfermode(new PorterDuffXfermode(mode)); 109b203968cc53015d9c51b790a56cca638be77818dnicolasroard mHistoPath.reset(); 110b203968cc53015d9c51b790a56cca638be77818dnicolasroard mHistoPath.moveTo(dx, h); 111860af325f2030a03c526e8551a85230d17df7b15nicolasroard boolean firstPointEncountered = false; 112860af325f2030a03c526e8551a85230d17df7b15nicolasroard float prev = 0; 113860af325f2030a03c526e8551a85230d17df7b15nicolasroard float last = 0; 114860af325f2030a03c526e8551a85230d17df7b15nicolasroard for (int i = 0; i < histogram.length; i++) { 115860af325f2030a03c526e8551a85230d17df7b15nicolasroard float x = i * wl + dx; 116860af325f2030a03c526e8551a85230d17df7b15nicolasroard float l = histogram[i] * wh; 117860af325f2030a03c526e8551a85230d17df7b15nicolasroard if (l != 0) { 118860af325f2030a03c526e8551a85230d17df7b15nicolasroard float v = h - (l + prev) / 2.0f; 119860af325f2030a03c526e8551a85230d17df7b15nicolasroard if (!firstPointEncountered) { 120b203968cc53015d9c51b790a56cca638be77818dnicolasroard mHistoPath.lineTo(x, h); 121860af325f2030a03c526e8551a85230d17df7b15nicolasroard firstPointEncountered = true; 122860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 123b203968cc53015d9c51b790a56cca638be77818dnicolasroard mHistoPath.lineTo(x, v); 124860af325f2030a03c526e8551a85230d17df7b15nicolasroard prev = l; 125860af325f2030a03c526e8551a85230d17df7b15nicolasroard last = x; 126860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 127860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 128b203968cc53015d9c51b790a56cca638be77818dnicolasroard mHistoPath.lineTo(last, h); 129b203968cc53015d9c51b790a56cca638be77818dnicolasroard mHistoPath.lineTo(w, h); 130b203968cc53015d9c51b790a56cca638be77818dnicolasroard mHistoPath.close(); 131b203968cc53015d9c51b790a56cca638be77818dnicolasroard canvas.drawPath(mHistoPath, mPaint); 132b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setStrokeWidth(2); 133b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setStyle(Paint.Style.STROKE); 134b203968cc53015d9c51b790a56cca638be77818dnicolasroard mPaint.setARGB(255, 200, 200, 200); 135b203968cc53015d9c51b790a56cca638be77818dnicolasroard canvas.drawPath(mHistoPath, mPaint); 136860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 137860af325f2030a03c526e8551a85230d17df7b15nicolasroard 138860af325f2030a03c526e8551a85230d17df7b15nicolasroard public void onDraw(Canvas canvas) { 139860af325f2030a03c526e8551a85230d17df7b15nicolasroard canvas.drawARGB(0, 0, 0, 0); 140860af325f2030a03c526e8551a85230d17df7b15nicolasroard drawHistogram(canvas, redHistogram, Color.RED, PorterDuff.Mode.SCREEN); 141860af325f2030a03c526e8551a85230d17df7b15nicolasroard drawHistogram(canvas, greenHistogram, Color.GREEN, PorterDuff.Mode.SCREEN); 142860af325f2030a03c526e8551a85230d17df7b15nicolasroard drawHistogram(canvas, blueHistogram, Color.BLUE, PorterDuff.Mode.SCREEN); 143860af325f2030a03c526e8551a85230d17df7b15nicolasroard } 144860af325f2030a03c526e8551a85230d17df7b15nicolasroard} 145