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
setUp()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
tearDown()80     protected void tearDown() throws Exception {
81         a1.destroy();
82         a2.destroy();
83         super.tearDown();
84     }
85 
testBlur()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 
testBlend()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
creatAllocation(int w, int h)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
similar(byte[] a, byte[] b)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
buildSrc(byte[] srcData, int width, int height)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
buildDst(byte[] dstData, int width, int height)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 
javaBlend(int type, byte[] src, byte[] dst)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 
clamp(int c)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 
pack(float a, float r, float g, float b)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 
pack(int a, int r, int g, int b)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 
unpackSrc(int src)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 
unpackDst(int dst)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 
filter(int scr, int dst)359         int filter(int scr, int dst) {
360             unpackSrc(scr);
361             unpackDst(dst);
362             return blend();
363         }
364 
filter(byte srcR, byte srcG, byte srcB, byte srcA, byte dstR, byte dstG, byte dstB, byte dstA)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 
blend()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 
testColorMatrix()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 
testConvolve3x3()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 
testConvolve5x5()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 
testLUT()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 
testScriptGroup()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