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