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