Home | History | Annotate | Download | only in cts
      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 android.renderscript.cts;
     18 
     19 import android.renderscript.Allocation;
     20 
     21 import android.renderscript.Byte2;
     22 import android.renderscript.Byte3;
     23 import android.renderscript.Byte4;
     24 
     25 import android.renderscript.Double2;
     26 import android.renderscript.Double3;
     27 import android.renderscript.Double4;
     28 
     29 import android.renderscript.Element;
     30 
     31 import android.renderscript.Float2;
     32 import android.renderscript.Float3;
     33 import android.renderscript.Float4;
     34 
     35 import android.renderscript.Int2;
     36 import android.renderscript.Int3;
     37 import android.renderscript.Int4;
     38 
     39 import android.renderscript.Long2;
     40 import android.renderscript.Long3;
     41 import android.renderscript.Long4;
     42 
     43 import android.renderscript.RSRuntimeException;
     44 
     45 import android.renderscript.Short2;
     46 import android.renderscript.Short3;
     47 import android.renderscript.Short4;
     48 
     49 import android.renderscript.Matrix4f;
     50 import android.renderscript.Script;
     51 
     52 import android.renderscript.Type;
     53 
     54 import android.renderscript.ScriptGroup;
     55 
     56 import android.renderscript.ScriptIntrinsicBlend;
     57 import android.renderscript.ScriptIntrinsicBlur;
     58 import android.renderscript.ScriptIntrinsicColorMatrix;
     59 import android.renderscript.ScriptIntrinsicConvolve3x3;
     60 import android.renderscript.ScriptIntrinsicConvolve5x5;
     61 import android.renderscript.ScriptIntrinsicLUT;
     62 import android.util.Log;
     63 
     64 public class ImageProcessingTest extends RSBaseCompute {
     65     private Allocation a1, a2;
     66 
     67     private final int MAX_RADIUS = 25;
     68     private final int dimX = 256;
     69 
     70     @Override
     71     protected void setUp() throws Exception {
     72         super.setUp();
     73 
     74         Type t = new Type.Builder(mRS, Element.U8_4(mRS)).setX(dimX).setY(dimX).create();
     75         a1 = Allocation.createTyped(mRS, t);
     76         a2 = Allocation.createTyped(mRS, t);
     77     }
     78 
     79     @Override
     80     protected void tearDown() throws Exception {
     81         a1.destroy();
     82         a2.destroy();
     83         super.tearDown();
     84     }
     85 
     86     public void testBlur() {
     87         ScriptIntrinsicBlur mBlur;
     88         mBlur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
     89 
     90         Allocation a1_copy, a2_copy;
     91         a1_copy = Allocation.createTyped(mRS, a1.getType());
     92         a2_copy = Allocation.createTyped(mRS, a2.getType());
     93 
     94         for (int i = 1; i < MAX_RADIUS; i++) {
     95 
     96             a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
     97 
     98             mBlur.setRadius(i);
     99             mBlur.setInput(a1_copy);
    100 
    101             mBlur.forEach(a2_copy);
    102 
    103             // validate
    104 
    105         }
    106 
    107         a1_copy.destroy();
    108         a2_copy.destroy();
    109         mBlur.destroy();
    110     }
    111 
    112     public void testBlend() {
    113         ScriptIntrinsicBlend mBlend;
    114         mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
    115         int w = 256;
    116         int h = 256;
    117         Allocation src = creatAllocation(w, h);
    118         Allocation dst = creatAllocation(w, h);
    119         byte[] srcData = new byte[w * h * 4];
    120         byte[] dstData = new byte[w * h * 4];
    121         byte[] resultData = new byte[w * h * 4];
    122         Script.LaunchOptions opt = new Script.LaunchOptions();
    123         // unclipped but with options
    124         for (int i = 0; i < 28; i++) {
    125             buildSrc(srcData, w, h);
    126             buildDst(dstData, w, h);
    127             src.copyFromUnchecked(srcData);
    128             dst.copyFromUnchecked(dstData);
    129 
    130             switch (i) {
    131                 case 0:
    132                     mBlend.forEachSrc(src, dst);
    133                     break;
    134                 case 1:
    135                     mBlend.forEachDst(src, dst);
    136                     break;
    137                 case 2:
    138                     mBlend.forEachSrcOver(src, dst);
    139                     break;
    140                 case 3:
    141                     mBlend.forEachDstOver(src, dst);
    142                     break;
    143                 case 4:
    144                     mBlend.forEachSrcIn(src, dst);
    145                     break;
    146                 case 5:
    147                     mBlend.forEachDstIn(src, dst);
    148                     break;
    149                 case 6:
    150                     mBlend.forEachSrcOut(src, dst);
    151                     break;
    152                 case 7:
    153                     mBlend.forEachDstOut(src, dst);
    154                     break;
    155                 case 8:
    156                     mBlend.forEachSrcAtop(src, dst);
    157                     break;
    158                 case 9:
    159                     mBlend.forEachDstAtop(src, dst);
    160                     break;
    161                 case 10:
    162                     mBlend.forEachXor(src, dst);
    163                     break;
    164                 case 11:
    165                     mBlend.forEachAdd(src, dst);
    166                     break;
    167                 case 12:
    168                     mBlend.forEachSubtract(src, dst);
    169                     break;
    170                 case 13:
    171                     mBlend.forEachMultiply(src, dst);
    172                     break;
    173                 case 14:
    174                     mBlend.forEachSrc(src, dst, opt);
    175                     break;
    176                 case 15:
    177                     mBlend.forEachDst(src, dst, opt);
    178                     break;
    179                 case 16:
    180                     mBlend.forEachSrcOver(src, dst, opt);
    181                     break;
    182                 case 17:
    183                     mBlend.forEachDstOver(src, dst, opt);
    184                     break;
    185                 case 18:
    186                     mBlend.forEachSrcIn(src, dst, opt);
    187                     break;
    188                 case 19:
    189                     mBlend.forEachDstIn(src, dst, opt);
    190                     break;
    191                 case 20:
    192                     mBlend.forEachSrcOut(src, dst, opt);
    193                     break;
    194                 case 21:
    195                     mBlend.forEachDstOut(src, dst, opt);
    196                     break;
    197                 case 22:
    198                     mBlend.forEachSrcAtop(src, dst, opt);
    199                     break;
    200                 case 23:
    201                     mBlend.forEachDstAtop(src, dst, opt);
    202                     break;
    203                 case 24:
    204                     mBlend.forEachXor(src, dst, opt);
    205                     break;
    206                 case 25:
    207                     mBlend.forEachAdd(src, dst, opt);
    208                     break;
    209                 case 26:
    210                     mBlend.forEachSubtract(src, dst, opt);
    211                     break;
    212                 case 27:
    213                     mBlend.forEachMultiply(src, dst, opt);
    214                     break;
    215             }
    216             dst.copyTo(resultData);
    217             String name = javaBlend(i%14, srcData, dstData);
    218             assertTrue(name, similar(resultData,dstData));
    219             Log.v("BlendUnit", name + " " + similar(resultData, dstData));
    220 
    221         }
    222 
    223         src.destroy();
    224         dst.destroy();
    225         mBlend.destroy();
    226     }
    227 
    228     // utility to create and allocation of a given dimension
    229     protected Allocation creatAllocation(int w, int h) {
    230         Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
    231         b.setX(w);
    232         b.setY(h);
    233         return  Allocation.createTyped(mRS, b.create(), Allocation.USAGE_SCRIPT);
    234     }
    235 
    236    // Compare two images ensuring returning false if error is greater than 2
    237    // so that it can  support integer and float non identical versions
    238     public boolean similar(byte[] a, byte[] b) {
    239         for (int i = 0; i < a.length; i++) {
    240             int v1 = 0xFF & a[i];
    241             int v2 = 0xFF & b[i];
    242             int error = Math.abs(v1 - v2);
    243             if (error > 2) {
    244                 return false;
    245             }
    246         }
    247         return true;
    248     }
    249     // Build a test pattern to be the source pattern designed to provide a wide range of values
    250     public void buildSrc(byte[] srcData, int width, int height) {
    251         for (int i = 0; i < srcData.length / 4; i++) {
    252             int x = i % width;
    253             int y = i / width;
    254             int d = (x - width / 2) * (x - width / 2) + (y - height / 2) * (y - height / 2);
    255             d = (255 * d) / ((width / 2) * (width / 2));
    256             d = (d > 255) ? 0 : d;
    257 
    258             srcData[i * 4 + 0] = (byte) d; // red
    259             srcData[i * 4 + 1] = (byte) d; // green
    260             srcData[i * 4 + 2] = (byte) 0; // blue
    261             srcData[i * 4 + 3] = (byte) y; // alpha
    262         }
    263     }
    264 
    265     // Build a test pattern to be the destination pattern designed to provide a wide range of values
    266     public void buildDst(byte[] dstData, int width, int height) {
    267         for (int i = 0; i < dstData.length / 4; i++) {
    268             int x = i % width;
    269             int y = i / width;
    270 
    271             dstData[i * 4 + 0] = (byte) 0; // red
    272             dstData[i * 4 + 1] = (byte) 0; // green
    273             dstData[i * 4 + 2] = (byte) y; // blue
    274             dstData[i * 4 + 3] = (byte) x; // alpha
    275         }
    276 
    277     }
    278 
    279     public String javaBlend(int type, byte[] src, byte[] dst) {
    280 
    281         for (int i = 0; i < dst.length; i += 4) {
    282             byte[] rgba = func[type].filter(src[i], src[i + 1], src[i + 2], src[i + 3],
    283                     dst[i], dst[i + 1], dst[i + 2], dst[i + 3]);
    284             dst[i] = rgba[0];
    285             dst[i + 1] = rgba[1];
    286             dst[i + 2] = rgba[2];
    287             dst[i + 3] = rgba[3];
    288         }
    289         return func[type].name;
    290     }
    291 
    292     // Base class for Java blend implementation supporting float and int implementations
    293 
    294     abstract class BlendFunc {
    295         float srcR, srcG, srcB, srcA;
    296         float dstR, dstG, dstB, dstA;
    297         int s_srcR, s_srcG, s_srcB, s_srcA;
    298         int s_dstR, s_dstG, s_dstB, s_dstA;
    299         byte[] rgba = new byte[4];
    300         String name;
    301 
    302         final int clamp(int c) {
    303             final int N = 255;
    304             c &= ~(c >> 31);
    305             c -= N;
    306             c &= (c >> 31);
    307             c += N;
    308             return c;
    309         }
    310 
    311         int pack(float a, float r, float g, float b) {
    312             int ia = clamp((int) (255 * a));
    313             int ir = clamp((int) (255 * r));
    314             int ig = clamp((int) (255 * g));
    315             int ib = clamp((int) (255 * b));
    316             rgba[0] = (byte) ir;
    317             rgba[1] = (byte) ig;
    318             rgba[2] = (byte) ib;
    319             rgba[3] = (byte) ia;
    320             return (ia << 24) | (ir << 16) | (ig << 8) | ib;
    321         }
    322 
    323         int pack(int a, int r, int g, int b) {
    324 
    325             rgba[0] = (byte) clamp(r);
    326             rgba[1] = (byte) clamp(g);
    327             rgba[2] = (byte) clamp(b);
    328             rgba[3] = (byte) clamp(a);
    329             return 0;
    330         }
    331 
    332         void unpackSrc(int src) {
    333             s_srcR = (0xFF & (src >> 16));
    334             s_srcG = (0xFF & (src >> 8));
    335             s_srcB = (0xFF & (src >> 0));
    336             s_srcA = (0xFF & (src >> 24));
    337             float scale = 1 / 255f;
    338 
    339             srcR = (0xFF & (src >> 16)) * scale;
    340             srcG = (0xFF & (src >> 8)) * scale;
    341             srcB = (0xFF & (src >> 0)) * scale;
    342             srcA = (0xFF & (src >> 24)) * scale;
    343         }
    344 
    345         void unpackDst(int dst) {
    346             float scale = 1 / 255f;
    347 
    348             s_dstR = (0xFF & (dst >> 16));
    349             s_dstG = (0xFF & (dst >> 8));
    350             s_dstB = (0xFF & (dst >> 0));
    351             s_dstA = (0xFF & (dst >> 24));
    352 
    353             dstR = (0xFF & (dst >> 16)) * scale;
    354             dstG = (0xFF & (dst >> 8)) * scale;
    355             dstB = (0xFF & (dst >> 0)) * scale;
    356             dstA = (0xFF & (dst >> 24)) * scale;
    357         }
    358 
    359         int filter(int scr, int dst) {
    360             unpackSrc(scr);
    361             unpackDst(dst);
    362             return blend();
    363         }
    364 
    365         byte[] filter(byte srcR, byte srcG, byte srcB, byte srcA,
    366                       byte dstR, byte dstG, byte dstB, byte dstA) {
    367             float scale = 1 / 255f;
    368             this.srcR = (0xFF & (srcR)) * scale;
    369             this.srcG = (0xFF & (srcG)) * scale;
    370             this.srcB = (0xFF & (srcB)) * scale;
    371             this.srcA = (0xFF & (srcA)) * scale;
    372 
    373             this.dstR = (0xFF & (dstR)) * scale;
    374             this.dstG = (0xFF & (dstG)) * scale;
    375             this.dstB = (0xFF & (dstB)) * scale;
    376             this.dstA = (0xFF & (dstA)) * scale;
    377             s_dstR = (0xFF & (dstR));
    378             s_dstG = (0xFF & (dstG));
    379             s_dstB = (0xFF & (dstB));
    380             s_dstA = (0xFF & (dstA));
    381 
    382             s_srcR = (0xFF & (srcR));
    383             s_srcG = (0xFF & (srcG));
    384             s_srcB = (0xFF & (srcB));
    385             s_srcA = (0xFF & (srcA));
    386 
    387             blend();
    388             return rgba;
    389         }
    390 
    391         abstract int blend();
    392     }
    393 
    394     BlendFunc blend_dstAtop = new BlendFunc() {
    395         // dst = dst.rgb * src.a + (1.0 - dst.a) * src.rgb
    396         // dst.a = src.a
    397         {
    398             name = "blend_dstAtop";
    399         }
    400 
    401         @Override
    402         int blend() {
    403             float r = (dstR * srcA + (1 - dstA) * srcR);
    404             float g = (dstG * srcA + (1 - dstA) * srcG);
    405             float b = (dstB * srcA + (1 - dstA) * srcB);
    406             float a = srcA;
    407 
    408             return pack(a, r, g, b);
    409         }
    410     };
    411     BlendFunc blend_dstIn = new BlendFunc() {
    412         // Sets dst = dst * src.a
    413         {
    414             name = "blend_dstIn";
    415         }
    416 
    417         @Override
    418         int blend() {
    419             float r = (dstR * srcA);
    420             float g = (dstG * srcA);
    421             float b = (dstB * srcA);
    422             float a = (dstA * srcA);
    423             return pack(a, r, g, b);
    424         }
    425     };
    426 
    427     BlendFunc blend_add = new BlendFunc() {
    428         // dst = dst + src
    429         {
    430             name = "blend_add";
    431         }
    432 
    433         @Override
    434         int blend() {
    435 
    436             int r = Math.min(s_dstR + s_srcR, 255);
    437             int g = Math.min(s_dstG + s_srcG, 255);
    438             int b = Math.min(s_dstB + s_srcB, 255);
    439             int a = Math.min(s_dstA + s_srcA, 255);
    440             return pack(a, r, g, b);
    441 
    442         }
    443     };
    444 
    445     BlendFunc blend_clear = new BlendFunc() {
    446         // Sets dst = {0, 0, 0, 0}
    447         {
    448             name = "blend_clear";
    449         }
    450 
    451         @Override
    452         int blend() {
    453             return pack(0, 0, 0, 0);
    454         }
    455     };
    456 
    457     BlendFunc blend_dst = new BlendFunc() {
    458         // Sets dst = dst
    459         {
    460             name = "blend_dst";
    461         }
    462 
    463         @Override
    464         int blend() {
    465             return pack(dstA, dstR, dstG, dstB);
    466         }
    467     };
    468 
    469     BlendFunc blend_dstOut = new BlendFunc() {
    470         // Sets dst = dst * (1.0 - src.a)
    471         {
    472             name = "blend_dstOut";
    473         }
    474 
    475         @Override
    476         int blend() {
    477             float r = (dstR * (1 - srcA));
    478             float g = (dstG * (1 - srcA));
    479             float b = (dstB * (1 - srcA));
    480             float a = (dstA * (1 - srcA));
    481             return pack(a, r, g, b);
    482         }
    483     };
    484     BlendFunc blend_dstOver = new BlendFunc() {
    485         // Sets dst = dst + src * (1.0 - dst.a)
    486         {
    487             name = "blend_dstOver";
    488         }
    489 
    490         @Override
    491         int blend() {
    492             float r = dstR + (srcR * (1 - dstA));
    493             float g = dstG + (srcG * (1 - dstA));
    494             float b = dstB + (srcB * (1 - dstA));
    495             float a = dstA + (srcA * (1 - dstA));
    496             return pack(a, r, g, b);
    497         }
    498     };
    499 
    500     BlendFunc blend_multiply = new BlendFunc() {
    501         // dst = dst * src
    502         {
    503             name = "blend_multiply";
    504         }
    505 
    506         @Override
    507         int blend() {
    508             float r = (srcR * dstR);
    509             float g = (srcG * dstG);
    510             float b = (srcB * dstB);
    511             float a = (srcA * dstA);
    512             return pack(a, r, g, b);
    513         }
    514     };
    515 
    516     BlendFunc blend_src = new BlendFunc() {
    517         // Sets dst =  src
    518         {
    519             name = "blend_src";
    520         }
    521 
    522         int blend() {
    523             return pack(srcA, srcR, srcG, srcB);
    524 
    525         }
    526     };
    527 
    528     BlendFunc blend_srcAtop = new BlendFunc() {
    529         // dst.rgb = src.rgb * dst.a + (1.0 - src.a) * dst.rgb
    530         // dst.a = dst.a
    531         {
    532             name = "blend_srcAtop";
    533         }
    534 
    535         @Override
    536         int blend() {
    537             float r = (srcR * dstA + (1 - srcA) * dstR);
    538             float g = (srcG * dstA + (1 - srcA) * dstG);
    539             float b = (srcB * dstA + (1 - srcA) * dstB);
    540             float a = (srcA * dstA + (1 - srcA) * dstA);
    541             return pack(a, r, g, b);
    542         }
    543     };
    544 
    545     BlendFunc blend_srcIn = new BlendFunc() {
    546         // dst = src * dst.a
    547         {
    548             name = "blend_srcIn";
    549         }
    550 
    551         @Override
    552         int blend() {
    553             float r = (srcR * dstA);
    554             float g = (srcG * dstA);
    555             float b = (srcB * dstA);
    556             float a = (srcA * dstA);
    557             ;
    558             return pack(a, r, g, b);
    559         }
    560     };
    561 
    562     BlendFunc blend_srcOut = new BlendFunc() {
    563         // Sets dst = src * (1.0 - dst.a)
    564         {
    565             name = "blend_srcOut";
    566         }
    567 
    568         @Override
    569         int blend() {
    570             float r = (srcR * (1 - dstA));
    571             float g = (srcG * (1 - dstA));
    572             float b = (srcB * (1 - dstA));
    573             float a = (srcA * (1 - dstA));
    574             ;
    575             return pack(a, r, g, b);
    576         }
    577     };
    578 
    579     BlendFunc blend_srcOver = new BlendFunc() {
    580         // Sets dst = src + dst * (1.0 - src.a)
    581         {
    582             name = "blend_srcOver";
    583         }
    584 
    585         @Override
    586         int blend() {
    587             float r = srcR + (dstR * (1 - srcA));
    588             float g = srcG + (dstG * (1 - srcA));
    589             float b = srcB + (dstB * (1 - srcA));
    590             float a = srcA + (dstA * (1 - srcA));
    591             return pack(a, r, g, b);
    592         }
    593     };
    594 
    595     BlendFunc blend_subtract = new BlendFunc() {
    596         // Sets dst =  dst - src
    597         {
    598             name = "blend_subtract";
    599         }
    600 
    601         @Override
    602         int blend() {
    603             float r = Math.max(dstR - srcR, 0);
    604             float g = Math.max(dstG - srcG, 0);
    605             float b = Math.max(dstB - srcB, 0);
    606             float a = Math.max(dstA - srcA, 0);
    607             return pack(a, r, g, b);
    608         }
    609     };
    610 
    611     // Porter/Duff xor compositing
    612     BlendFunc blend_pdxor = new BlendFunc() {
    613         // dst.rgb = src.rgb*(1-dst.a)+(1-src.a)*dst.rgb;
    614         // dst.a = src.a+dst.a - 2*src.a*dst.a
    615         {
    616             name = "blend_pdxor";
    617         }
    618 
    619         @Override
    620         int blend() {
    621             float r = srcR * (1 - dstA) + (dstR * (1 - srcA));
    622             float g = srcG * (1 - dstA) + (dstG * (1 - srcA));
    623             float b = srcB * (1 - dstA) + (dstB * (1 - srcA));
    624             float a = srcA + dstA - (2 * srcA * dstA);
    625             return pack(a, r, g, b);
    626         }
    627     };
    628 
    629     // NOT Porter/Duff xor compositing simple XOR
    630     BlendFunc blend_xor = new BlendFunc() {
    631         // Sets dst = {src.r ^ dst.r, src.g ^ dst.g, src.b ^ dst.b, src.a ^ dst.a}
    632         {
    633             name = "blend_xor";
    634         }
    635 
    636         @Override
    637         int blend() {
    638             float scale = 1 / 255f;
    639             float r = (((int) (dstR * 255)) ^ ((int) (srcR * 255))) * scale;
    640             float g = (((int) (dstG * 255)) ^ ((int) (srcG * 255))) * scale;
    641             float b = (((int) (dstB * 255)) ^ ((int) (srcB * 255))) * scale;
    642             float a = (((int) (dstA * 255)) ^ ((int) (srcA * 255))) * scale;
    643             return pack(a, r, g, b);
    644         }
    645     };
    646 
    647     BlendFunc[] func = {
    648             blend_src,
    649             blend_dst,
    650             blend_srcOver,
    651             blend_dstOver,
    652             blend_srcIn,
    653             blend_dstIn,
    654             blend_srcOut,
    655             blend_dstOut,
    656             blend_srcAtop,
    657             blend_dstAtop,
    658             blend_xor,
    659             blend_add,
    660             blend_subtract,
    661             blend_multiply,
    662     };
    663 
    664     public void testColorMatrix() {
    665         ScriptIntrinsicColorMatrix mColorMatrix;
    666         mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
    667 
    668         Allocation a1_copy, a2_copy;
    669         a1_copy = Allocation.createTyped(mRS, a1.getType());
    670         a2_copy = Allocation.createTyped(mRS, a2.getType());
    671 
    672         Matrix4f m = new Matrix4f();
    673         m.set(1, 0, 0.2f);
    674         m.set(1, 1, 0.9f);
    675         m.set(1, 2, 0.2f);
    676 
    677         //test greyscale
    678         mColorMatrix.setGreyscale();
    679 
    680         a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
    681         a2_copy.copy2DRangeFrom(0, 0, a2.getType().getX(), a2.getType().getY(), a2, 0, 0);
    682 
    683         mColorMatrix.forEach(a1_copy, a2_copy);
    684 
    685         //validate greyscale
    686 
    687 
    688         //test color matrix
    689         mColorMatrix.setColorMatrix(m);
    690 
    691         a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
    692         a2_copy.copy2DRangeFrom(0, 0, a2.getType().getX(), a2.getType().getY(), a2, 0, 0);
    693 
    694         mColorMatrix.forEach(a1_copy, a2_copy);
    695 
    696         a1_copy.destroy();
    697         a2_copy.destroy();
    698         mColorMatrix.destroy();
    699     }
    700 
    701     public void testConvolve3x3() {
    702         ScriptIntrinsicConvolve3x3 mConvolve3x3;
    703         mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
    704 
    705         Allocation a1_copy, a2_copy;
    706         a1_copy = Allocation.createTyped(mRS, a1.getType());
    707         a2_copy = Allocation.createTyped(mRS, a2.getType());
    708 
    709         a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
    710 
    711         float f[] = new float[9];
    712         f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
    713         f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
    714         f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
    715 
    716         mConvolve3x3.setCoefficients(f);
    717         mConvolve3x3.setInput(a1_copy);
    718         mConvolve3x3.forEach(a2_copy);
    719 
    720         a1_copy.destroy();
    721         a2_copy.destroy();
    722         mConvolve3x3.destroy();
    723     }
    724 
    725     public void testConvolve5x5() {
    726         ScriptIntrinsicConvolve5x5 mConvolve5x5;
    727         mConvolve5x5 = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
    728 
    729         Allocation a1_copy, a2_copy;
    730         a1_copy = Allocation.createTyped(mRS, a1.getType());
    731         a2_copy = Allocation.createTyped(mRS, a2.getType());
    732 
    733         a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
    734 
    735         float f[] = new float[25];
    736         f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
    737         f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
    738         f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
    739         f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
    740         f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
    741 
    742         mConvolve5x5.setCoefficients(f);
    743         mConvolve5x5.setInput(a1_copy);
    744         mConvolve5x5.forEach(a2_copy);
    745 
    746         a1_copy.destroy();
    747         a2_copy.destroy();
    748         mConvolve5x5.destroy();
    749     }
    750 
    751     public void testLUT() {
    752         ScriptIntrinsicLUT mLUT;
    753         mLUT = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
    754 
    755         Allocation a1_copy, a2_copy;
    756         a1_copy = Allocation.createTyped(mRS, a1.getType());
    757         a2_copy = Allocation.createTyped(mRS, a2.getType());
    758 
    759         a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
    760 
    761         for (int ct=0; ct < 256; ct++) {
    762             float f = ((float)ct) / 255.f;
    763 
    764             float r = f;
    765             if (r < 0.5f) {
    766                 r = 4.0f * r * r * r;
    767             } else {
    768                 r = 1.0f - r;
    769                 r = 1.0f - (4.0f * r * r * r);
    770             }
    771             mLUT.setRed(ct, (int)(r * 255.f + 0.5f));
    772 
    773             float g = f;
    774             if (g < 0.5f) {
    775                 g = 2.0f * g * g;
    776             } else {
    777                 g = 1.0f - g;
    778                 g = 1.0f - (2.0f * g * g);
    779             }
    780             mLUT.setGreen(ct, (int)(g * 255.f + 0.5f));
    781 
    782             float b = f * 0.5f + 0.25f;
    783             mLUT.setBlue(ct, (int)(b * 255.f + 0.5f));
    784         }
    785 
    786         mLUT.forEach(a1_copy, a2_copy);
    787 
    788         a1_copy.destroy();
    789         a2_copy.destroy();
    790         mLUT.destroy();
    791     }
    792 
    793     public void testScriptGroup() {
    794         ScriptGroup group;
    795 
    796         ScriptIntrinsicConvolve3x3 mConvolve3x3;
    797         ScriptIntrinsicColorMatrix mColorMatrix;
    798 
    799         mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
    800         mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
    801 
    802         Allocation a1_copy, a2_copy;
    803         a1_copy = Allocation.createTyped(mRS, a1.getType());
    804         a2_copy = Allocation.createTyped(mRS, a2.getType());
    805 
    806         a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
    807 
    808         float f[] = new float[9];
    809         f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
    810         f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
    811         f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
    812 
    813         mConvolve3x3.setCoefficients(f);
    814 
    815         Matrix4f m = new Matrix4f();
    816         m.set(1, 0, 0.2f);
    817         m.set(1, 1, 0.9f);
    818         m.set(1, 2, 0.2f);
    819         mColorMatrix.setColorMatrix(m);
    820 
    821         Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(dimX).setY(dimX).create();
    822 
    823         ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
    824         b.addKernel(mConvolve3x3.getKernelID());
    825         b.addKernel(mColorMatrix.getKernelID());
    826         b.addConnection(connect, mConvolve3x3.getKernelID(), mColorMatrix.getKernelID());
    827         group = b.create();
    828 
    829         mConvolve3x3.setInput(a1_copy);
    830         group.setOutput(mColorMatrix.getKernelID(), a2_copy);
    831         group.execute();
    832 
    833         // validate
    834 
    835         a1_copy.destroy();
    836         a2_copy.destroy();
    837         mConvolve3x3.destroy();
    838         mColorMatrix.destroy();
    839     }
    840 
    841 
    842 }
    843