ImageProcessingActivity.java revision 586f3b5d32c0464a4e69c92f89865eea672ab665
1d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy/*
2d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * Copyright (C) 2009 The Android Open Source Project
3d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy *
4d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * you may not use this file except in compliance with the License.
6d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * You may obtain a copy of the License at
7d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy *
8d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy *
10d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * Unless required by applicable law or agreed to in writing, software
11d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * See the License for the specific language governing permissions and
14d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy * limitations under the License.
15d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy */
16d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
17d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guypackage com.android.rs.image;
18d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
19d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.app.Activity;
20d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.os.Bundle;
21d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.graphics.BitmapFactory;
22d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.graphics.Bitmap;
23d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.graphics.Canvas;
24d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.renderscript.ScriptC;
25d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.renderscript.RenderScript;
26d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.renderscript.Type;
27d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.renderscript.Allocation;
28d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.renderscript.Element;
29d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.renderscript.Script;
30d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.view.SurfaceView;
31d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.view.SurfaceHolder;
32d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.widget.ImageView;
33d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guyimport android.widget.SeekBar;
34586f3b5d32c0464a4e69c92f89865eea672ab665Jason Samsimport java.lang.Math;
35d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
36d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guypublic class ImageProcessingActivity extends Activity implements SurfaceHolder.Callback {
37d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Bitmap mBitmap;
38d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Params mParams;
39d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Script.Invokable mInvokable;
40586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams    private int[] mInData;
41d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private int[] mOutData;
42d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
43d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    @SuppressWarnings({"FieldCanBeLocal"})
44d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private RenderScript mRS;
45d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    @SuppressWarnings({"FieldCanBeLocal"})
46d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Type mParamsType;
47d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    @SuppressWarnings({"FieldCanBeLocal"})
48d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Allocation mParamsAllocation;
49d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    @SuppressWarnings({"FieldCanBeLocal"})
50d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Type mPixelType;
51d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    @SuppressWarnings({"FieldCanBeLocal"})
52d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Allocation mInPixelsAllocation;
53d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    @SuppressWarnings({"FieldCanBeLocal"})
54d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Allocation mOutPixelsAllocation;
55d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
56d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private SurfaceView mSurfaceView;
57d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private ImageView mDisplayView;
58d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
59d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    static class Params {
60d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public int inWidth;
61d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public int outWidth;
62d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public int inHeight;
63d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public int outHeight;
64d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
65d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public float threshold;
66d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
67718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams
68d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    static class Pixel {
69d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public byte a;
70d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public byte r;
71d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public byte g;
72d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public byte b;
73d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
74d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
75d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    class FilterCallback extends RenderScript.RSMessage {
76d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        private Runnable mAction = new Runnable() {
77d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            public void run() {
78d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                mOutPixelsAllocation.readData(mOutData);
79d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0,
80d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                        mParams.outWidth, mParams.outHeight);
81d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                mDisplayView.invalidate();
82d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            }
83718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        };
84d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
85d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        @Override
86d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        public void run() {
87d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            mSurfaceView.removeCallbacks(mAction);
88d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            mSurfaceView.post(mAction);
89d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        }
90d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
91d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
92586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams    private void javaFilter() {
93586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        long t = java.lang.System.currentTimeMillis();
94586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        int count = mParams.inWidth * mParams.inHeight;
95586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        float threshold = mParams.threshold * 255.f;
96586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams
97586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        for (int i = 0; i < count; i++) {
98586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams            final float r = (float)((mInData[i] >> 0) & 0xff);
99586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams            final float g = (float)((mInData[i] >> 8) & 0xff);
100586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams            final float b = (float)((mInData[i] >> 16) & 0xff);
101586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams
102586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams            final float luminance = 0.2125f * r +
103586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                              0.7154f * g +
104586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                              0.0721f * b;
105586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams            if (luminance > threshold) {
106586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                mOutData[i] = mInData[i];
107586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams            } else {
108586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                mOutData[i] = mInData[i] & 0xff000000;
109586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams            }
110586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        }
111586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams
112586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        t = java.lang.System.currentTimeMillis() - t;
113586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams
114586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        android.util.Log.v("Img", "frame time ms " + t);
115586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams    }
116586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams
117d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    @Override
118d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    protected void onCreate(Bundle savedInstanceState) {
119d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        super.onCreate(savedInstanceState);
120d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        setContentView(R.layout.main);
121d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
122d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mBitmap = loadBitmap(R.drawable.data);
123d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
124d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
125d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mSurfaceView.getHolder().addCallback(this);
126d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
127d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mDisplayView = (ImageView) findViewById(R.id.display);
128d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mDisplayView.setImageBitmap(mBitmap);
129d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
130d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        ((SeekBar) findViewById(R.id.threshold)).setOnSeekBarChangeListener(
131d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                new SeekBar.OnSeekBarChangeListener() {
132d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
133d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                if (fromUser) {
134d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                    mParams.threshold = progress / 100.0f;
135d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                    mParamsAllocation.data(mParams);
136586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams
137586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                    if (false) {
138586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                        mInvokable.execute();
139586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                    } else {
140586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                        javaFilter();
141586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                        mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0,
142586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                                mParams.outWidth, mParams.outHeight);
143586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                        mDisplayView.invalidate();
144586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams                    }
145d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                }
146d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            }
147d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
148d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            public void onStartTrackingTouch(SeekBar seekBar) {
149d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            }
150d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
151d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            public void onStopTrackingTouch(SeekBar seekBar) {
152d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy            }
153d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        });
154d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
155d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
156d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    public void surfaceCreated(SurfaceHolder holder) {
157d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mParams = createParams();
158d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mInvokable = createScript();
159d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
160d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mInvokable.execute();
161d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
162d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
163d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
164d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
165d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
166d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    public void surfaceDestroyed(SurfaceHolder holder) {
167d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
168718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams
169d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Script.Invokable createScript() {
170704ff64b099406bb328898a7443921f22dbffd6dJason Sams        mRS = RenderScript.create();
171d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mRS.mMessageCallback = new FilterCallback();
172d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
173d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mParamsType = Type.createFromClass(mRS, Params.class, 1, "Parameters");
174d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mParamsAllocation = Allocation.createTyped(mRS, mParamsType);
175d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mParamsAllocation.data(mParams);
176d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
177d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        final int pixelCount = mParams.inWidth * mParams.inHeight;
178d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
179d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mPixelType = Type.createFromClass(mRS, Pixel.class, 1, "Pixel");
180718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        mInPixelsAllocation = Allocation.createSized(mRS,
181718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams                Element.createUser(mRS, Element.DataType.SIGNED_32),
182d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                pixelCount);
183718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        mOutPixelsAllocation = Allocation.createSized(mRS,
184718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams                Element.createUser(mRS, Element.DataType.SIGNED_32),
185d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy                pixelCount);
186d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
187586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        mInData = new int[pixelCount];
188586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        mBitmap.getPixels(mInData, 0, mParams.inWidth, 0, 0, mParams.inWidth, mParams.inHeight);
189586f3b5d32c0464a4e69c92f89865eea672ab665Jason Sams        mInPixelsAllocation.data(mInData);
190d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
191d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mOutData = new int[pixelCount];
192d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        mOutPixelsAllocation.data(mOutData);
193718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams
194d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        ScriptC.Builder sb = new ScriptC.Builder(mRS);
195d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        sb.setType(mParamsType, "Params", 0);
196d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        sb.setType(mPixelType, "InPixel", 1);
197d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        sb.setType(mPixelType, "OutPixel", 2);
198d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        sb.setType(true, 2);
199d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        Script.Invokable invokable = sb.addInvokable("main");
200d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        sb.setScript(getResources(), R.raw.threshold);
201704ff64b099406bb328898a7443921f22dbffd6dJason Sams        //sb.setRoot(true);
202d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
203d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        ScriptC script = sb.create();
204d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        script.bindAllocation(mParamsAllocation, 0);
205d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        script.bindAllocation(mInPixelsAllocation, 1);
206d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        script.bindAllocation(mOutPixelsAllocation, 2);
207d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
208d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        return invokable;
209d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
210d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
211d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Params createParams() {
212d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        final Params params = new Params();
213d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        params.inWidth = params.outWidth = mBitmap.getWidth();
214d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        params.inHeight = params.outHeight = mBitmap.getHeight();
215d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        params.threshold = 0.5f;
216d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        return params;
217d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
218d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
219d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private Bitmap loadBitmap(int resource) {
220d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        final BitmapFactory.Options options = new BitmapFactory.Options();
221d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
222d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        return copyBitmap(BitmapFactory.decodeResource(getResources(), resource, options));
223d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
224d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy
225d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    private static Bitmap copyBitmap(Bitmap source) {
226d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        Bitmap b = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
227d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        Canvas c = new Canvas(b);
228d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        c.drawBitmap(source, 0, 0, null);
229d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        source.recycle();
230d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy        return b;
231d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy    }
232d7fa122dfed376cd9c60eac516e2730acf23f3ddRomain Guy}
233