1 /*
2  * Copyright (C) 2012 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 
17 package com.android.rs.levels;
18 
19 import android.app.Activity;
20 import android.graphics.Bitmap;
21 import android.graphics.BitmapFactory;
22 import android.graphics.Canvas;
23 import android.os.Bundle;
24 import android.renderscript.Matrix3f;
25 import android.util.Log;
26 import android.view.View;
27 import android.widget.ImageView;
28 import android.widget.SeekBar;
29 import android.widget.TextView;
30 
31 public class LevelsDalvikActivity extends Activity
32                                   implements SeekBar.OnSeekBarChangeListener {
33     private final String TAG = "Img";
34     private Bitmap mBitmapIn;
35     private Bitmap mBitmapOut;
36     private float mInBlack = 0.0f;
37     private SeekBar mInBlackSeekBar;
38     private float mOutBlack = 0.0f;
39     private SeekBar mOutBlackSeekBar;
40     private float mInWhite = 255.0f;
41     private SeekBar mInWhiteSeekBar;
42     private float mOutWhite = 255.0f;
43     private SeekBar mOutWhiteSeekBar;
44     private float mGamma = 1.0f;
45     private SeekBar mGammaSeekBar;
46     private float mSaturation = 1.0f;
47     private SeekBar mSaturationSeekBar;
48     private TextView mBenchmarkResult;
49     private ImageView mDisplayView;
50 
51     Matrix3f satMatrix = new Matrix3f();
52     float mInWMinInB;
53     float mOutWMinOutB;
54     float mOverInWMinInB;
55 
56     int mInPixels[];
57     int mOutPixels[];
58 
setLevels()59     private void setLevels() {
60         mInWMinInB = mInWhite - mInBlack;
61         mOutWMinOutB = mOutWhite - mOutBlack;
62         mOverInWMinInB = 1.f / mInWMinInB;
63     }
64 
setSaturation()65     private void setSaturation() {
66         float rWeight = 0.299f;
67         float gWeight = 0.587f;
68         float bWeight = 0.114f;
69         float oneMinusS = 1.0f - mSaturation;
70 
71         satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
72         satMatrix.set(0, 1, oneMinusS * rWeight);
73         satMatrix.set(0, 2, oneMinusS * rWeight);
74         satMatrix.set(1, 0, oneMinusS * gWeight);
75         satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
76         satMatrix.set(1, 2, oneMinusS * gWeight);
77         satMatrix.set(2, 0, oneMinusS * bWeight);
78         satMatrix.set(2, 1, oneMinusS * bWeight);
79         satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
80     }
81 
onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)82     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
83         if (fromUser) {
84             if (seekBar == mInBlackSeekBar) {
85                 mInBlack = (float)progress;
86                 setLevels();
87             } else if (seekBar == mOutBlackSeekBar) {
88                 mOutBlack = (float)progress;
89                 setLevels();
90             } else if (seekBar == mInWhiteSeekBar) {
91                 mInWhite = (float)progress + 127.0f;
92                 setLevels();
93             } else if (seekBar == mOutWhiteSeekBar) {
94                 mOutWhite = (float)progress + 127.0f;
95                 setLevels();
96             } else if (seekBar == mGammaSeekBar) {
97                 mGamma = (float)progress/100.0f;
98                 mGamma = Math.max(mGamma, 0.1f);
99                 mGamma = 1.0f / mGamma;
100             } else if (seekBar == mSaturationSeekBar) {
101                 mSaturation = (float)progress / 50.0f;
102                 setSaturation();
103             }
104 
105             filter();
106             mDisplayView.invalidate();
107         }
108     }
109 
onStartTrackingTouch(SeekBar seekBar)110     public void onStartTrackingTouch(SeekBar seekBar) {
111     }
112 
onStopTrackingTouch(SeekBar seekBar)113     public void onStopTrackingTouch(SeekBar seekBar) {
114     }
115 
116     @Override
onCreate(Bundle savedInstanceState)117     protected void onCreate(Bundle savedInstanceState) {
118         super.onCreate(savedInstanceState);
119         setContentView(R.layout.main);
120 
121         mBitmapIn = loadBitmap(R.drawable.city);
122         mBitmapOut = loadBitmap(R.drawable.city);
123 
124         mDisplayView = (ImageView) findViewById(R.id.display);
125         mDisplayView.setImageBitmap(mBitmapOut);
126 
127         mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
128         mInBlackSeekBar.setOnSeekBarChangeListener(this);
129         mInBlackSeekBar.setMax(128);
130         mInBlackSeekBar.setProgress(0);
131         mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
132         mOutBlackSeekBar.setOnSeekBarChangeListener(this);
133         mOutBlackSeekBar.setMax(128);
134         mOutBlackSeekBar.setProgress(0);
135 
136         mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
137         mInWhiteSeekBar.setOnSeekBarChangeListener(this);
138         mInWhiteSeekBar.setMax(128);
139         mInWhiteSeekBar.setProgress(128);
140         mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
141         mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
142         mOutWhiteSeekBar.setMax(128);
143         mOutWhiteSeekBar.setProgress(128);
144 
145         mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
146         mGammaSeekBar.setOnSeekBarChangeListener(this);
147         mGammaSeekBar.setMax(150);
148         mGammaSeekBar.setProgress(100);
149 
150         mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
151         mSaturationSeekBar.setOnSeekBarChangeListener(this);
152         mSaturationSeekBar.setProgress(50);
153 
154         mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
155         mBenchmarkResult.setText("Result: not run");
156 
157         mInPixels = new int[mBitmapIn.getHeight() * mBitmapIn.getWidth()];
158         mOutPixels = new int[mBitmapOut.getHeight() * mBitmapOut.getWidth()];
159         mBitmapIn.getPixels(mInPixels, 0, mBitmapIn.getWidth(), 0, 0,
160                             mBitmapIn.getWidth(), mBitmapIn.getHeight());
161 
162         setLevels();
163         setSaturation();
164         filter();
165     }
166 
loadBitmap(int resource)167     private Bitmap loadBitmap(int resource) {
168         final BitmapFactory.Options options = new BitmapFactory.Options();
169         options.inPreferredConfig = Bitmap.Config.ARGB_8888;
170         Bitmap b = BitmapFactory.decodeResource(getResources(), resource, options);
171         Bitmap b2 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), b.getConfig());
172         Canvas c = new Canvas(b2);
173         c.drawBitmap(b, 0, 0, null);
174         b.recycle();
175         return b2;
176     }
177 
178 
179 
filter()180     private void filter() {
181         final float[] m = satMatrix.getArray();
182 
183         for (int i=0; i < mInPixels.length; i++) {
184             float r = (float)(mInPixels[i] & 0xff);
185             float g = (float)((mInPixels[i] >> 8) & 0xff);
186             float b = (float)((mInPixels[i] >> 16) & 0xff);
187 
188             float tr = r * m[0] + g * m[3] + b * m[6];
189             float tg = r * m[1] + g * m[4] + b * m[7];
190             float tb = r * m[2] + g * m[5] + b * m[8];
191             r = tr;
192             g = tg;
193             b = tb;
194 
195             if (r < 0.f) r = 0.f;
196             if (r > 255.f) r = 255.f;
197             if (g < 0.f) g = 0.f;
198             if (g > 255.f) g = 255.f;
199             if (b < 0.f) b = 0.f;
200             if (b > 255.f) b = 255.f;
201 
202             r = (r - mInBlack) * mOverInWMinInB;
203             g = (g - mInBlack) * mOverInWMinInB;
204             b = (b - mInBlack) * mOverInWMinInB;
205 
206             if (mGamma != 1.0f) {
207                 r = (float)java.lang.Math.pow(r, mGamma);
208                 g = (float)java.lang.Math.pow(g, mGamma);
209                 b = (float)java.lang.Math.pow(b, mGamma);
210             }
211 
212             r = (r * mOutWMinOutB) + mOutBlack;
213             g = (g * mOutWMinOutB) + mOutBlack;
214             b = (b * mOutWMinOutB) + mOutBlack;
215 
216             if (r < 0.f) r = 0.f;
217             if (r > 255.f) r = 255.f;
218             if (g < 0.f) g = 0.f;
219             if (g > 255.f) g = 255.f;
220             if (b < 0.f) b = 0.f;
221             if (b > 255.f) b = 255.f;
222 
223             mOutPixels[i] = ((int)r) + (((int)g) << 8) + (((int)b) << 16)
224                             + (mInPixels[i] & 0xff000000);
225         }
226 
227         mBitmapOut.setPixels(mOutPixels, 0, mBitmapOut.getWidth(), 0, 0,
228                              mBitmapOut.getWidth(), mBitmapOut.getHeight());
229     }
230 
benchmark(View v)231     public void benchmark(View v) {
232         filter();
233         long t = java.lang.System.currentTimeMillis();
234         filter();
235         t = java.lang.System.currentTimeMillis() - t;
236         mDisplayView.invalidate();
237         mBenchmarkResult.setText("Result: " + t + " ms");
238     }
239 }
240