ImageCurves.java revision 15a056e3cc1970bc0b99dba71df8222ba0345859
10d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 20d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroardpackage com.android.gallery3d.filtershow.ui; 30d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 40d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroardimport android.content.Context; 53992ae6cf1cbb7b57a22d8287c40451558408335nicolasroardimport android.graphics.Bitmap; 60d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroardimport android.graphics.Canvas; 73992ae6cf1cbb7b57a22d8287c40451558408335nicolasroardimport android.graphics.Color; 80d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroardimport android.graphics.Paint; 90d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroardimport android.graphics.Path; 103992ae6cf1cbb7b57a22d8287c40451558408335nicolasroardimport android.graphics.PorterDuff; 113992ae6cf1cbb7b57a22d8287c40451558408335nicolasroardimport android.graphics.PorterDuffXfermode; 123992ae6cf1cbb7b57a22d8287c40451558408335nicolasroardimport android.os.AsyncTask; 130d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroardimport android.util.AttributeSet; 140d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroardimport android.view.MotionEvent; 150d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 16c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroardimport com.android.gallery3d.R; 1792e2341248e99c691f38820503984bc5e2f18811nicolasroardimport com.android.gallery3d.filtershow.filters.ImageFilterCurves; 1892e2341248e99c691f38820503984bc5e2f18811nicolasroardimport com.android.gallery3d.filtershow.imageshow.ImageSlave; 1992e2341248e99c691f38820503984bc5e2f18811nicolasroardimport com.android.gallery3d.filtershow.presets.ImagePreset; 2092e2341248e99c691f38820503984bc5e2f18811nicolasroard 215448bf8095483574649afcc2add7f153670c7450nicolasroardpublic class ImageCurves extends ImageSlave { 220d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 230d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard private static final String LOGTAG = "ImageCurves"; 240d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard Paint gPaint = new Paint(); 250d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard Path gPathSpline = new Path(); 263992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard 27c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard private int mCurrentCurveIndex = Spline.RGB; 280d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard private boolean mDidAddPoint = false; 290d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard private boolean mDidDelete = false; 300d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard private ControlPoint mCurrentControlPoint = null; 313992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard private ImagePreset mLastPreset = null; 323992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int[] redHistogram = new int[256]; 333992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int[] greenHistogram = new int[256]; 343992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int[] blueHistogram = new int[256]; 353992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard Path gHistoPath = new Path(); 360d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 37c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard boolean mDoingTouchMove = false; 38c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard 390d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard public ImageCurves(Context context) { 400d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard super(context); 410d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard resetCurve(); 420d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 430d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 440d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard public ImageCurves(Context context, AttributeSet attrs) { 450d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard super(context, attrs); 460d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard resetCurve(); 470d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 480d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 493992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard public void nextChannel() { 503992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard mCurrentCurveIndex = ((mCurrentCurveIndex + 1) % 4); 513992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard invalidate(); 523992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 533992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard 5492e2341248e99c691f38820503984bc5e2f18811nicolasroard @Override 550d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard public boolean showTitle() { 560d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard return false; 570d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 580d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 59d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard private ImageFilterCurves curves() { 605448bf8095483574649afcc2add7f153670c7450nicolasroard if (getMaster() != null) { 610d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard String filterName = getFilterName(); 62d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard return (ImageFilterCurves) getImagePreset().getFilter(filterName); 630d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 64d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard return null; 65d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard } 66d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard 67d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard private Spline getSpline(int index) { 68d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard return curves().getSpline(index); 690d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 700d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 7192e2341248e99c691f38820503984bc5e2f18811nicolasroard @Override 7292e2341248e99c691f38820503984bc5e2f18811nicolasroard public void resetParameter() { 7392e2341248e99c691f38820503984bc5e2f18811nicolasroard super.resetParameter(); 7492e2341248e99c691f38820503984bc5e2f18811nicolasroard resetCurve(); 753992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard mLastPreset = null; 763992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard invalidate(); 7792e2341248e99c691f38820503984bc5e2f18811nicolasroard } 7892e2341248e99c691f38820503984bc5e2f18811nicolasroard 790d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard public void resetCurve() { 80d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard if (getMaster() != null && curves() != null) { 81d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard curves().reset(); 82d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard updateCachedImage(); 830d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 840d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 850d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 8692e2341248e99c691f38820503984bc5e2f18811nicolasroard @Override 870d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard public void onDraw(Canvas canvas) { 880d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard super.onDraw(canvas); 890d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 900d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard gPaint.setAntiAlias(true); 910d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 923992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (getImagePreset() != mLastPreset) { 933992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard new ComputeHistogramTask().execute(mFilteredImage); 943992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard mLastPreset = getImagePreset(); 950d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 960d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 9715a056e3cc1970bc0b99dba71df8222ba0345859nicolasroard if (curves() == null) { 9815a056e3cc1970bc0b99dba71df8222ba0345859nicolasroard return; 9915a056e3cc1970bc0b99dba71df8222ba0345859nicolasroard } 10015a056e3cc1970bc0b99dba71df8222ba0345859nicolasroard 1013992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.RED) { 1023992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard drawHistogram(canvas, redHistogram, Color.RED, PorterDuff.Mode.SCREEN); 1033992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 1043992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.GREEN) { 1053992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard drawHistogram(canvas, greenHistogram, Color.GREEN, PorterDuff.Mode.SCREEN); 1063992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 1073992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.BLUE) { 1083992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard drawHistogram(canvas, blueHistogram, Color.BLUE, PorterDuff.Mode.SCREEN); 1093992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 1103992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard // We only display the other channels curves when showing the RGB curve 1113992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (mCurrentCurveIndex == Spline.RGB) { 1123992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard for (int i = 0; i < 4; i++) { 113d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard Spline spline = getSpline(i); 1143992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (i != mCurrentCurveIndex && !spline.isOriginal()) { 1153992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard // And we only display a curve if it has more than two 1163992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard // points 117c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard spline.draw(canvas, Spline.colorForCurve(i), getWidth(), 118c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard getHeight(), false, mDoingTouchMove); 1193992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 1200d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1210d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1223992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard // ...but we always display the current curve. 123d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard getSpline(mCurrentCurveIndex) 1243992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard .draw(canvas, Spline.colorForCurve(mCurrentCurveIndex), getWidth(), getHeight(), 125c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard true, mDoingTouchMove); 1263992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard drawToast(canvas); 1270d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 1280d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1290d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 1300d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard private int pickControlPoint(float x, float y) { 1310d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard int pick = 0; 132d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard Spline spline = getSpline(mCurrentCurveIndex); 133d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard float px = spline.getPoint(0).x; 134d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard float py = spline.getPoint(0).y; 1350d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard double delta = Math.sqrt((px - x) * (px - x) + (py - y) * (py - y)); 136d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard for (int i = 1; i < spline.getNbPoints(); i++) { 137d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard px = spline.getPoint(i).x; 138d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard py = spline.getPoint(i).y; 1390d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard double currentDelta = Math.sqrt((px - x) * (px - x) + (py - y) 1400d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard * (py - y)); 1410d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard if (currentDelta < delta) { 1420d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard delta = currentDelta; 1430d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard pick = i; 1440d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1450d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1460d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 1470d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard if (!mDidAddPoint && (delta * getWidth() > 100) 148d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard && (spline.getNbPoints() < 10)) { 1490d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard return -1; 1500d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1510d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 1523992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard return pick; 1530d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1540d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 1550d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard private String getFilterName() { 1563992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard return "Curves"; 1570d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1580d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 1590d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard @Override 1600d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard public synchronized boolean onTouchEvent(MotionEvent e) { 1610d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard float posX = e.getX() / getWidth(); 1623992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float posY = e.getY(); 1633992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float margin = Spline.curveHandleSize() / 2; 1643992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (posY < margin) { 1653992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard posY = margin; 1663992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 1673992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (posY > getHeight() - margin) { 1683992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard posY = getHeight() - margin; 1693992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 1703992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard posY = (posY - margin) / (getHeight() - 2 * margin); 1710d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 1720d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard if (e.getActionMasked() == MotionEvent.ACTION_UP) { 1730d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard mCurrentControlPoint = null; 174d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard updateCachedImage(); 1750d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard mDidAddPoint = false; 1760d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard if (mDidDelete) { 1770d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard mDidDelete = false; 1780d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 179c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard mDoingTouchMove = false; 1800d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard return true; 1810d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 182c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard mDoingTouchMove = true; 1830d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 1840d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard if (mDidDelete) { 1850d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard return true; 1860d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1870d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 188d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard Spline spline = getSpline(mCurrentCurveIndex); 1890d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard int pick = pickControlPoint(posX, posY); 1900d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard if (mCurrentControlPoint == null) { 1910d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard if (pick == -1) { 1920d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard mCurrentControlPoint = new ControlPoint(posX, posY); 193d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard spline.addPoint(mCurrentControlPoint); 1940d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard mDidAddPoint = true; 1950d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } else { 196d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard mCurrentControlPoint = spline.getPoint(pick); 1970d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1980d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 1993992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard 200d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard if (spline.isPointContained(posX, pick)) { 2013992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard mCurrentControlPoint.x = posX; 2023992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard mCurrentControlPoint.y = posY; 203c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard spline.didMovePoint(mCurrentControlPoint); 204c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard } else if (pick != -1 && spline.getNbPoints() > 2) { 205d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard spline.deletePoint(pick); 2063992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard mDidDelete = true; 2070d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 208d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard updateCachedImage(); 2090d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard return true; 2100d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 2110d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 212d7899c56b8df278dfd6720ae11eadc2f89fe8094nicolasroard public synchronized void updateCachedImage() { 2130d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard // update image 2140d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard if (getImagePreset() != null) { 2150d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard mImageLoader.resetImageForPreset(getImagePreset(), this); 2160d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard invalidate(); 2170d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 2180d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard } 2190d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard 2203992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard class ComputeHistogramTask extends AsyncTask<Bitmap, Void, int[]> { 2213992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard @Override 2223992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard protected int[] doInBackground(Bitmap... params) { 2233992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int[] histo = new int[256 * 3]; 2243992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard Bitmap bitmap = params[0]; 2253992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int w = bitmap.getWidth(); 2263992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int h = bitmap.getHeight(); 2273992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int[] pixels = new int[w * h]; 2283992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard bitmap.getPixels(pixels, 0, w, 0, 0, w, h); 2293992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard for (int i = 0; i < w; i++) { 2303992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard for (int j = 0; j < h; j++) { 2313992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int index = j * w + i; 2323992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int r = Color.red(pixels[index]); 2333992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int g = Color.green(pixels[index]); 2343992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int b = Color.blue(pixels[index]); 2353992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard histo[r]++; 2363992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard histo[256 + g]++; 2373992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard histo[512 + b]++; 2383992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2393992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2403992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard return histo; 2413992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2423992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard 2433992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard @Override 2443992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard protected void onPostExecute(int[] result) { 2453992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard System.arraycopy(result, 0, redHistogram, 0, 256); 2463992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard System.arraycopy(result, 256, greenHistogram, 0, 256); 2473992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard System.arraycopy(result, 512, blueHistogram, 0, 256); 2483992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard invalidate(); 2493992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2503992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2513992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard 2523992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard private void drawHistogram(Canvas canvas, int[] histogram, int color, PorterDuff.Mode mode) { 2533992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard int max = 0; 2543992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard for (int i = 0; i < histogram.length; i++) { 2553992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (histogram[i] > max) { 2563992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard max = histogram[i]; 2573992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2583992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2593992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float w = getWidth(); 2603992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float h = getHeight(); 2613992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float wl = w / histogram.length; 2623992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float wh = (0.3f * h) / max; 2633992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard Paint paint = new Paint(); 2643992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard paint.setARGB(100, 255, 255, 255); 2653992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard paint.setStrokeWidth((int) Math.ceil(wl)); 2663992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard 2673992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard Paint paint2 = new Paint(); 2683992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard paint2.setColor(color); 2693992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard paint2.setStrokeWidth(6); 2703992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard paint2.setXfermode(new PorterDuffXfermode(mode)); 2713992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard gHistoPath.reset(); 2723992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard gHistoPath.moveTo(0, h); 2733992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard boolean firstPointEncountered = false; 2743992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float prev = 0; 2753992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float last = 0; 2763992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard for (int i = 0; i < histogram.length; i++) { 2773992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float x = i * wl; 2783992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float l = histogram[i] * wh; 2793992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (l != 0) { 2803992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard float v = h - (l + prev) / 2.0f; 2813992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard if (!firstPointEncountered) { 2823992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard gHistoPath.lineTo(x, h); 2833992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard firstPointEncountered = true; 2843992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2853992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard gHistoPath.lineTo(x, v); 2863992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard prev = l; 2873992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard last = x; 2883992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2893992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 2903992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard gHistoPath.lineTo(last, h); 2913992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard gHistoPath.lineTo(w, h); 2923992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard gHistoPath.close(); 2933992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard canvas.drawPath(gHistoPath, paint2); 2943992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard paint2.setStrokeWidth(2); 2953992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard paint2.setStyle(Paint.Style.STROKE); 2963992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard paint2.setARGB(255, 200, 200, 200); 2973992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard canvas.drawPath(gHistoPath, paint2); 2983992ae6cf1cbb7b57a22d8287c40451558408335nicolasroard } 299c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard 300c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard public void setChannel(int itemId) { 301c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard switch (itemId) { 302c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard case R.id.curve_menu_rgb: { 303c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard mCurrentCurveIndex = Spline.RGB; 304c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard break; 305c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard } 306c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard case R.id.curve_menu_red: { 307c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard mCurrentCurveIndex = Spline.RED; 308c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard break; 309c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard } 310c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard case R.id.curve_menu_green: { 311c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard mCurrentCurveIndex = Spline.GREEN; 312c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard break; 313c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard } 314c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard case R.id.curve_menu_blue: { 315c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard mCurrentCurveIndex = Spline.BLUE; 316c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard break; 317c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard } 318c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard } 319c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard invalidate(); 320c5590eb1a20b112e67e4c43684790587f844fc6bnicolasroard } 3210d7cdf8e763fb65c32bfad65245b3753deb75737nicolasroard} 322