ImageFilterRS.java revision 7706e506dc74fa634a69b9ce8c7e5e2c457f01fc
1a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard/*
2a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * Copyright (C) 2012 The Android Open Source Project
3a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard *
4a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * Licensed under the Apache License, Version 2.0 (the "License");
5a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * you may not use this file except in compliance with the License.
6a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * You may obtain a copy of the License at
7a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard *
8a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard *      http://www.apache.org/licenses/LICENSE-2.0
9a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard *
10a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * Unless required by applicable law or agreed to in writing, software
11a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * distributed under the License is distributed on an "AS IS" BASIS,
12a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * See the License for the specific language governing permissions and
14a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard * limitations under the License.
15a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard */
16a9f280f938b5fd5891c5cfe0999f8f1d4945d7a1nicolasroard
175448bf8095483574649afcc2add7f153670c7450nicolasroardpackage com.android.gallery3d.filtershow.filters;
185448bf8095483574649afcc2add7f153670c7450nicolasroard
195448bf8095483574649afcc2add7f153670c7450nicolasroardimport android.app.Activity;
205448bf8095483574649afcc2add7f153670c7450nicolasroardimport android.graphics.Bitmap;
21a64051696e46fb5d5e1c76e53ac95a4feba18585Tim Murrayimport android.support.v8.renderscript.*;
225448bf8095483574649afcc2add7f153670c7450nicolasroardimport android.util.Log;
23a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murrayimport com.android.gallery3d.R;
245448bf8095483574649afcc2add7f153670c7450nicolasroard
254e6c07b71b269ee3fe7f6fa455bc540238df9dedJohn Hofordpublic abstract class ImageFilterRS extends ImageFilter {
265448bf8095483574649afcc2add7f153670c7450nicolasroard    private final String LOGTAG = "ImageFilterRS";
275448bf8095483574649afcc2add7f153670c7450nicolasroard
285448bf8095483574649afcc2add7f153670c7450nicolasroard    private static RenderScript mRS = null;
295448bf8095483574649afcc2add7f153670c7450nicolasroard    protected static Allocation mInPixelsAllocation;
305448bf8095483574649afcc2add7f153670c7450nicolasroard    protected static Allocation mOutPixelsAllocation;
315448bf8095483574649afcc2add7f153670c7450nicolasroard    private static android.content.res.Resources mResources = null;
3257eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard    private static Bitmap sOldBitmap = null;
3357eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard    private Bitmap mOldBitmap = null;
345448bf8095483574649afcc2add7f153670c7450nicolasroard
357706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    private boolean mResourcesLoaded = false;
367706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard
3757eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard    private final Bitmap.Config mBitmapConfig = Bitmap.Config.ARGB_8888;
3857eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard
39b01a32825018cfb79f2c965c1c3e3e25b5131229nicolasroard    public void resetBitmap() {
40b01a32825018cfb79f2c965c1c3e3e25b5131229nicolasroard        mOldBitmap = null;
41b01a32825018cfb79f2c965c1c3e3e25b5131229nicolasroard    }
42b01a32825018cfb79f2c965c1c3e3e25b5131229nicolasroard
4399baf61387ab1ef15bb9db5fa3b2b55591e87059John Hoford    public void prepare(Bitmap bitmap, float scaleFactor, int quality) {
4457eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard        if (sOldBitmap == null
4557eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard                || (bitmap.getWidth() != sOldBitmap.getWidth())
4657eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard                || (bitmap.getHeight() != sOldBitmap.getHeight())) {
4757eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard            if (mInPixelsAllocation != null) {
4857eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard                mInPixelsAllocation.destroy();
490f8047fe826a84829ab37bc7cd24c8a4dea0db64Ruben Brunk                mInPixelsAllocation = null;
5057eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard            }
5157eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard            if (mOutPixelsAllocation != null) {
5257eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard                mOutPixelsAllocation.destroy();
530f8047fe826a84829ab37bc7cd24c8a4dea0db64Ruben Brunk                mOutPixelsAllocation = null;
5457eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard            }
5557eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard            Bitmap bitmapBuffer = bitmap.copy(mBitmapConfig, true);
563df4f831396ffbc11e4bbee0b6150794e8e44e0bnicolasroard            mOutPixelsAllocation = Allocation.createFromBitmap(mRS, bitmapBuffer,
573df4f831396ffbc11e4bbee0b6150794e8e44e0bnicolasroard                    Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
5857eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard            mInPixelsAllocation = Allocation.createTyped(mRS,
5957eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard                    mOutPixelsAllocation.getType());
6057eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard            sOldBitmap = bitmap;
6163a7dac01d394523799939596b960cb03321798dJohn Hoford        }
6257eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard        mInPixelsAllocation.copyFrom(bitmap);
637706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard        if (mOldBitmap != sOldBitmap || !isResourcesLoaded()) {
647706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard            freeResources();
6599baf61387ab1ef15bb9db5fa3b2b55591e87059John Hoford            createFilter(mResources, scaleFactor, quality);
6657eedfd99676913f575b1f76e3a874026d1ddf7cnicolasroard            mOldBitmap = sOldBitmap;
677706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard            setResourcesLoaded(true);
6863a7dac01d394523799939596b960cb03321798dJohn Hoford        }
695448bf8095483574649afcc2add7f153670c7450nicolasroard    }
705448bf8095483574649afcc2add7f153670c7450nicolasroard
717706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    abstract public void createFilter(android.content.res.Resources res,
727706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard            float scaleFactor, int quality);
735448bf8095483574649afcc2add7f153670c7450nicolasroard
747706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    abstract public void runFilter();
755448bf8095483574649afcc2add7f153670c7450nicolasroard
765448bf8095483574649afcc2add7f153670c7450nicolasroard    public void update(Bitmap bitmap) {
775448bf8095483574649afcc2add7f153670c7450nicolasroard        mOutPixelsAllocation.copyTo(bitmap);
785448bf8095483574649afcc2add7f153670c7450nicolasroard    }
795448bf8095483574649afcc2add7f153670c7450nicolasroard
8081eb9976f967d9b3faa1749a8ab29d1743cf347dnicolasroard    @Override
8199baf61387ab1ef15bb9db5fa3b2b55591e87059John Hoford    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
825448bf8095483574649afcc2add7f153670c7450nicolasroard        if (bitmap == null) {
8381eb9976f967d9b3faa1749a8ab29d1743cf347dnicolasroard            return bitmap;
845448bf8095483574649afcc2add7f153670c7450nicolasroard        }
855448bf8095483574649afcc2add7f153670c7450nicolasroard        try {
8699baf61387ab1ef15bb9db5fa3b2b55591e87059John Hoford            prepare(bitmap, scaleFactor, quality);
875448bf8095483574649afcc2add7f153670c7450nicolasroard            runFilter();
885448bf8095483574649afcc2add7f153670c7450nicolasroard            update(bitmap);
895448bf8095483574649afcc2add7f153670c7450nicolasroard        } catch (android.renderscript.RSIllegalArgumentException e) {
905448bf8095483574649afcc2add7f153670c7450nicolasroard            Log.e(LOGTAG, "Illegal argument? " + e);
915448bf8095483574649afcc2add7f153670c7450nicolasroard        } catch (android.renderscript.RSRuntimeException e) {
925448bf8095483574649afcc2add7f153670c7450nicolasroard            Log.e(LOGTAG, "RS runtime exception ? " + e);
93b17b1b0758799914fbad5f4a3afae71ce58891fcRuben Brunk        } catch (java.lang.OutOfMemoryError e) {
94b17b1b0758799914fbad5f4a3afae71ce58891fcRuben Brunk            // Many of the renderscript filters allocated large (>16Mb resources) in order to apply.
95b17b1b0758799914fbad5f4a3afae71ce58891fcRuben Brunk            System.gc();
96b17b1b0758799914fbad5f4a3afae71ce58891fcRuben Brunk            displayLowMemoryToast();
97b17b1b0758799914fbad5f4a3afae71ce58891fcRuben Brunk            Log.e(LOGTAG, "not enough memory for filter " + getName(), e);
985448bf8095483574649afcc2add7f153670c7450nicolasroard        }
9981eb9976f967d9b3faa1749a8ab29d1743cf347dnicolasroard        return bitmap;
1005448bf8095483574649afcc2add7f153670c7450nicolasroard    }
1015448bf8095483574649afcc2add7f153670c7450nicolasroard
1025448bf8095483574649afcc2add7f153670c7450nicolasroard    public static RenderScript getRenderScriptContext() {
1035448bf8095483574649afcc2add7f153670c7450nicolasroard        return mRS;
1045448bf8095483574649afcc2add7f153670c7450nicolasroard    }
1055448bf8095483574649afcc2add7f153670c7450nicolasroard
1065448bf8095483574649afcc2add7f153670c7450nicolasroard    public static void setRenderScriptContext(Activity context) {
1077921e124d57759d6f0887a42ddc360d923e60cddTim Murray        if (mRS == null) {
1087921e124d57759d6f0887a42ddc360d923e60cddTim Murray            mRS = RenderScript.create(context);
1097921e124d57759d6f0887a42ddc360d923e60cddTim Murray        }
1105448bf8095483574649afcc2add7f153670c7450nicolasroard        mResources = context.getResources();
111588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard        if (mInPixelsAllocation != null) {
112588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard            mInPixelsAllocation.destroy();
113588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard            mInPixelsAllocation = null;
114588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard        }
115588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard        if (mOutPixelsAllocation != null) {
116588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard            mOutPixelsAllocation.destroy();
117588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard            mOutPixelsAllocation = null;
118588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard        }
119588c30c74178bc399b043a5401f0c1f93ae22378nicolasroard        sOldBitmap = null;
1205448bf8095483574649afcc2add7f153670c7450nicolasroard    }
1215448bf8095483574649afcc2add7f153670c7450nicolasroard
122a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray    public Allocation convertRGBAtoA(Bitmap bitmap) {
123a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        Type.Builder tb_a8 = new Type.Builder(mRS, Element.U8(mRS));
124a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        ScriptC_grey greyConvert = new ScriptC_grey(mRS, mResources, R.raw.grey);
125a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray
126a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        Allocation bitmapTemp = Allocation.createFromBitmap(mRS, bitmap);
127a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray
128a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        if (bitmapTemp.getType().getElement().isCompatible(Element.U8(mRS))) {
129a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray            return bitmapTemp;
130a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        }
131a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray
132a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        tb_a8.setX(bitmapTemp.getType().getX());
133a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        tb_a8.setY(bitmapTemp.getType().getY());
134a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        Allocation bitmapAlloc = Allocation.createTyped(mRS, tb_a8.create());
135a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        greyConvert.forEach_RGBAtoA(bitmapTemp, bitmapAlloc);
136a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray
137a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray        return bitmapAlloc;
1387706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    }
139a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray
1407706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    public boolean isResourcesLoaded() {
1417706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard        return mResourcesLoaded;
142a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray    }
143a7723fb08098c0c7682b02cf459cafa3792a4ce4Tim Murray
1447706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    public void setResourcesLoaded(boolean resourcesLoaded) {
1457706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard        mResourcesLoaded = resourcesLoaded;
1467706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    }
1477706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard
1487706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    abstract protected void resetAllocations();
1497706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard
1507706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    public void freeResources() {
1517706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard        if (!isResourcesLoaded()) {
1527706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard            return;
1537706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard        }
1547706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard        resetAllocations();
1557706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard        setResourcesLoaded(false);
1567706e506dc74fa634a69b9ce8c7e5e2c457f01fcnicolasroard    }
1575448bf8095483574649afcc2add7f153670c7450nicolasroard}
158