| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.renderscript.cts; |
| |
| import android.renderscript.Allocation; |
| |
| import android.renderscript.Byte2; |
| import android.renderscript.Byte3; |
| import android.renderscript.Byte4; |
| |
| import android.renderscript.Double2; |
| import android.renderscript.Double3; |
| import android.renderscript.Double4; |
| |
| import android.renderscript.Element; |
| |
| import android.renderscript.Float2; |
| import android.renderscript.Float3; |
| import android.renderscript.Float4; |
| |
| import android.renderscript.Int2; |
| import android.renderscript.Int3; |
| import android.renderscript.Int4; |
| |
| import android.renderscript.Long2; |
| import android.renderscript.Long3; |
| import android.renderscript.Long4; |
| |
| import android.renderscript.RSRuntimeException; |
| |
| import android.renderscript.Short2; |
| import android.renderscript.Short3; |
| import android.renderscript.Short4; |
| |
| import android.renderscript.Matrix4f; |
| import android.renderscript.Script; |
| |
| import android.renderscript.Type; |
| |
| import android.renderscript.ScriptGroup; |
| |
| import android.renderscript.ScriptIntrinsicBlend; |
| import android.renderscript.ScriptIntrinsicBlur; |
| import android.renderscript.ScriptIntrinsicColorMatrix; |
| import android.renderscript.ScriptIntrinsicConvolve3x3; |
| import android.renderscript.ScriptIntrinsicConvolve5x5; |
| import android.renderscript.ScriptIntrinsicLUT; |
| import android.util.Log; |
| |
| public class ImageProcessingTest extends RSBaseCompute { |
| private Allocation a1, a2; |
| |
| private final int MAX_RADIUS = 25; |
| private final int dimX = 256; |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| |
| Type t = new Type.Builder(mRS, Element.U8_4(mRS)).setX(dimX).setY(dimX).create(); |
| a1 = Allocation.createTyped(mRS, t); |
| a2 = Allocation.createTyped(mRS, t); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| a1.destroy(); |
| a2.destroy(); |
| super.tearDown(); |
| } |
| |
| public void testBlur() { |
| ScriptIntrinsicBlur mBlur; |
| mBlur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS)); |
| |
| Allocation a1_copy, a2_copy; |
| a1_copy = Allocation.createTyped(mRS, a1.getType()); |
| a2_copy = Allocation.createTyped(mRS, a2.getType()); |
| |
| for (int i = 1; i < MAX_RADIUS; i++) { |
| |
| a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0); |
| |
| mBlur.setRadius(i); |
| mBlur.setInput(a1_copy); |
| |
| mBlur.forEach(a2_copy); |
| |
| // validate |
| |
| } |
| |
| a1_copy.destroy(); |
| a2_copy.destroy(); |
| mBlur.destroy(); |
| } |
| |
| public void testBlend() { |
| ScriptIntrinsicBlend mBlend; |
| mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS)); |
| int w = 256; |
| int h = 256; |
| Allocation src = creatAllocation(w, h); |
| Allocation dst = creatAllocation(w, h); |
| byte[] srcData = new byte[w * h * 4]; |
| byte[] dstData = new byte[w * h * 4]; |
| byte[] resultData = new byte[w * h * 4]; |
| |
| for (int i = 0; i < 14; i++) { |
| buildSrc(srcData, w, h); |
| buildDst(dstData, w, h); |
| src.copyFromUnchecked(srcData); |
| dst.copyFromUnchecked(dstData); |
| |
| switch (i) { |
| case 0: |
| mBlend.forEachSrc(src, dst); |
| break; |
| case 1: |
| mBlend.forEachDst(src, dst); |
| break; |
| case 2: |
| mBlend.forEachSrcOver(src, dst); |
| break; |
| case 3: |
| mBlend.forEachDstOver(src, dst); |
| break; |
| case 4: |
| mBlend.forEachSrcIn(src, dst); |
| break; |
| case 5: |
| mBlend.forEachDstIn(src, dst); |
| break; |
| case 6: |
| mBlend.forEachSrcOut(src, dst); |
| break; |
| case 7: |
| mBlend.forEachDstOut(src, dst); |
| break; |
| case 8: |
| mBlend.forEachSrcAtop(src, dst); |
| break; |
| case 9: |
| mBlend.forEachDstAtop(src, dst); |
| break; |
| case 10: |
| mBlend.forEachXor(src, dst); |
| break; |
| case 11: |
| mBlend.forEachAdd(src, dst); |
| break; |
| case 12: |
| mBlend.forEachSubtract(src, dst); |
| break; |
| case 13: |
| mBlend.forEachMultiply(src, dst); |
| break; |
| } |
| dst.copyTo(resultData); |
| String name = javaBlend(i, srcData, dstData, 0, w, 0, h, w); |
| assertTrue(name, similar(resultData,dstData)); |
| Log.v("BlendUnit", name + " " + similar(resultData, dstData)); |
| } |
| |
| // Do the same but passing LaunchOptions |
| int xStart = 10; |
| int xEnd = 20; |
| int yStart = 3; |
| int yEnd = 6; |
| Script.LaunchOptions opt = new Script.LaunchOptions(); |
| opt.setX(xStart, xEnd).setY(yStart, yEnd); |
| for (int i = 0; i < 14; i++) { |
| buildSrc(srcData, w, h); |
| buildDst(dstData, w, h); |
| src.copyFromUnchecked(srcData); |
| dst.copyFromUnchecked(dstData); |
| switch (i) { |
| case 0: |
| mBlend.forEachSrc(src, dst, opt); |
| break; |
| case 1: |
| mBlend.forEachDst(src, dst, opt); |
| break; |
| case 2: |
| mBlend.forEachSrcOver(src, dst, opt); |
| break; |
| case 3: |
| mBlend.forEachDstOver(src, dst, opt); |
| break; |
| case 4: |
| mBlend.forEachSrcIn(src, dst, opt); |
| break; |
| case 5: |
| mBlend.forEachDstIn(src, dst, opt); |
| break; |
| case 6: |
| mBlend.forEachSrcOut(src, dst, opt); |
| break; |
| case 7: |
| mBlend.forEachDstOut(src, dst, opt); |
| break; |
| case 8: |
| mBlend.forEachSrcAtop(src, dst, opt); |
| break; |
| case 9: |
| mBlend.forEachDstAtop(src, dst, opt); |
| break; |
| case 10: |
| mBlend.forEachXor(src, dst, opt); |
| break; |
| case 11: |
| mBlend.forEachAdd(src, dst, opt); |
| break; |
| case 12: |
| mBlend.forEachSubtract(src, dst, opt); |
| break; |
| case 13: |
| mBlend.forEachMultiply(src, dst, opt); |
| break; |
| } |
| dst.copyTo(resultData); |
| String name = javaBlend(i, srcData, dstData, xStart, xEnd, yStart, yEnd, w); |
| assertTrue(name, similar(resultData,dstData)); |
| Log.v("BlendUnit", name + " " + similar(resultData, dstData)); |
| |
| } |
| |
| src.destroy(); |
| dst.destroy(); |
| mBlend.destroy(); |
| } |
| |
| // utility to create and allocation of a given dimension |
| protected Allocation creatAllocation(int w, int h) { |
| Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS)); |
| b.setX(w); |
| b.setY(h); |
| return Allocation.createTyped(mRS, b.create(), Allocation.USAGE_SCRIPT); |
| } |
| |
| // Compare two images ensuring returning false if error is greater than 2 |
| // so that it can support integer and float non identical versions |
| public boolean similar(byte[] a, byte[] b) { |
| for (int i = 0; i < a.length; i++) { |
| int v1 = 0xFF & a[i]; |
| int v2 = 0xFF & b[i]; |
| int error = Math.abs(v1 - v2); |
| if (error > 2) { |
| return false; |
| } |
| } |
| return true; |
| } |
| // Build a test pattern to be the source pattern designed to provide a wide range of values |
| public void buildSrc(byte[] srcData, int width, int height) { |
| for (int i = 0; i < srcData.length / 4; i++) { |
| int x = i % width; |
| int y = i / width; |
| int d = (x - width / 2) * (x - width / 2) + (y - height / 2) * (y - height / 2); |
| d = (255 * d) / ((width / 2) * (width / 2)); |
| d = (d > 255) ? 0 : d; |
| |
| srcData[i * 4 + 0] = (byte) d; // red |
| srcData[i * 4 + 1] = (byte) d; // green |
| srcData[i * 4 + 2] = (byte) 0; // blue |
| srcData[i * 4 + 3] = (byte) y; // alpha |
| } |
| // Manually set a few known problematic values. |
| // These created problems for SRC_OVER, SRC_ATOP |
| srcData[0] = 230 - 256; |
| srcData[1] = 200 - 256; |
| srcData[2] = 210 - 256; |
| srcData[3] = 7; |
| |
| // These created problems for DST_OVER, DST_ATOP, |
| srcData[4] = 230 - 255; |
| srcData[5] = 200 - 256; |
| srcData[6] = 210 - 256; |
| srcData[7] = 245 - 256; |
| } |
| |
| // Build a test pattern to be the destination pattern designed to provide a wide range of values |
| public void buildDst(byte[] dstData, int width, int height) { |
| for (int i = 0; i < dstData.length / 4; i++) { |
| int x = i % width; |
| int y = i / width; |
| |
| dstData[i * 4 + 0] = (byte) 0; // red |
| dstData[i * 4 + 1] = (byte) 0; // green |
| dstData[i * 4 + 2] = (byte) y; // blue |
| dstData[i * 4 + 3] = (byte) x; // alpha |
| } |
| // Manually set a few known problematic values |
| dstData[0] = 170 - 256; |
| dstData[1] = 180 - 256; |
| dstData[2] = 230 - 256; |
| dstData[3] = 245 - 256; |
| |
| dstData[4] = 170 - 256; |
| dstData[5] = 180 - 256; |
| dstData[6] = 230 - 256; |
| dstData[7] = 9; |
| } |
| |
| public String javaBlend(int type, byte[] src, byte[] dst, int xStart, int xEnd, int yStart, int yEnd, int width) { |
| for (int y = yStart; y < yEnd; y++) { |
| for (int x = xStart; x < xEnd; x++) { |
| int i = (y * width + x) * 4; |
| byte[] rgba = func[type].filter(src[i], src[i + 1], src[i + 2], src[i + 3], |
| dst[i], dst[i + 1], dst[i + 2], dst[i + 3]); |
| dst[i] = rgba[0]; |
| dst[i + 1] = rgba[1]; |
| dst[i + 2] = rgba[2]; |
| dst[i + 3] = rgba[3]; |
| } |
| } |
| return func[type].name; |
| } |
| |
| // Base class for Java blend implementation supporting float and int implementations |
| |
| abstract class BlendFunc { |
| float srcR, srcG, srcB, srcA; |
| float dstR, dstG, dstB, dstA; |
| int s_srcR, s_srcG, s_srcB, s_srcA; |
| int s_dstR, s_dstG, s_dstB, s_dstA; |
| byte[] rgba = new byte[4]; |
| String name; |
| |
| final int clamp(int c) { |
| final int N = 255; |
| c &= ~(c >> 31); |
| c -= N; |
| c &= (c >> 31); |
| c += N; |
| return c; |
| } |
| |
| int pack(float a, float r, float g, float b) { |
| int ia = clamp((int) (255 * a)); |
| int ir = clamp((int) (255 * r)); |
| int ig = clamp((int) (255 * g)); |
| int ib = clamp((int) (255 * b)); |
| rgba[0] = (byte) ir; |
| rgba[1] = (byte) ig; |
| rgba[2] = (byte) ib; |
| rgba[3] = (byte) ia; |
| return (ia << 24) | (ir << 16) | (ig << 8) | ib; |
| } |
| |
| int pack(int a, int r, int g, int b) { |
| |
| rgba[0] = (byte) clamp(r); |
| rgba[1] = (byte) clamp(g); |
| rgba[2] = (byte) clamp(b); |
| rgba[3] = (byte) clamp(a); |
| return 0; |
| } |
| |
| void unpackSrc(int src) { |
| s_srcR = (0xFF & (src >> 16)); |
| s_srcG = (0xFF & (src >> 8)); |
| s_srcB = (0xFF & (src >> 0)); |
| s_srcA = (0xFF & (src >> 24)); |
| float scale = 1 / 255f; |
| |
| srcR = (0xFF & (src >> 16)) * scale; |
| srcG = (0xFF & (src >> 8)) * scale; |
| srcB = (0xFF & (src >> 0)) * scale; |
| srcA = (0xFF & (src >> 24)) * scale; |
| } |
| |
| void unpackDst(int dst) { |
| float scale = 1 / 255f; |
| |
| s_dstR = (0xFF & (dst >> 16)); |
| s_dstG = (0xFF & (dst >> 8)); |
| s_dstB = (0xFF & (dst >> 0)); |
| s_dstA = (0xFF & (dst >> 24)); |
| |
| dstR = (0xFF & (dst >> 16)) * scale; |
| dstG = (0xFF & (dst >> 8)) * scale; |
| dstB = (0xFF & (dst >> 0)) * scale; |
| dstA = (0xFF & (dst >> 24)) * scale; |
| } |
| |
| int filter(int scr, int dst) { |
| unpackSrc(scr); |
| unpackDst(dst); |
| return blend(); |
| } |
| |
| byte[] filter(byte srcR, byte srcG, byte srcB, byte srcA, |
| byte dstR, byte dstG, byte dstB, byte dstA) { |
| float scale = 1 / 255f; |
| this.srcR = (0xFF & (srcR)) * scale; |
| this.srcG = (0xFF & (srcG)) * scale; |
| this.srcB = (0xFF & (srcB)) * scale; |
| this.srcA = (0xFF & (srcA)) * scale; |
| |
| this.dstR = (0xFF & (dstR)) * scale; |
| this.dstG = (0xFF & (dstG)) * scale; |
| this.dstB = (0xFF & (dstB)) * scale; |
| this.dstA = (0xFF & (dstA)) * scale; |
| s_dstR = (0xFF & (dstR)); |
| s_dstG = (0xFF & (dstG)); |
| s_dstB = (0xFF & (dstB)); |
| s_dstA = (0xFF & (dstA)); |
| |
| s_srcR = (0xFF & (srcR)); |
| s_srcG = (0xFF & (srcG)); |
| s_srcB = (0xFF & (srcB)); |
| s_srcA = (0xFF & (srcA)); |
| |
| blend(); |
| return rgba; |
| } |
| |
| abstract int blend(); |
| } |
| |
| BlendFunc blend_dstAtop = new BlendFunc() { |
| // dst = dst.rgb * src.a + (1.0 - dst.a) * src.rgb |
| // dst.a = src.a |
| { |
| name = "blend_dstAtop"; |
| } |
| |
| @Override |
| int blend() { |
| float r = (dstR * srcA + (1 - dstA) * srcR); |
| float g = (dstG * srcA + (1 - dstA) * srcG); |
| float b = (dstB * srcA + (1 - dstA) * srcB); |
| float a = srcA; |
| |
| return pack(a, r, g, b); |
| } |
| }; |
| BlendFunc blend_dstIn = new BlendFunc() { |
| // Sets dst = dst * src.a |
| { |
| name = "blend_dstIn"; |
| } |
| |
| @Override |
| int blend() { |
| float r = (dstR * srcA); |
| float g = (dstG * srcA); |
| float b = (dstB * srcA); |
| float a = (dstA * srcA); |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| BlendFunc blend_add = new BlendFunc() { |
| // dst = dst + src |
| { |
| name = "blend_add"; |
| } |
| |
| @Override |
| int blend() { |
| |
| int r = Math.min(s_dstR + s_srcR, 255); |
| int g = Math.min(s_dstG + s_srcG, 255); |
| int b = Math.min(s_dstB + s_srcB, 255); |
| int a = Math.min(s_dstA + s_srcA, 255); |
| return pack(a, r, g, b); |
| |
| } |
| }; |
| |
| BlendFunc blend_clear = new BlendFunc() { |
| // Sets dst = {0, 0, 0, 0} |
| { |
| name = "blend_clear"; |
| } |
| |
| @Override |
| int blend() { |
| return pack(0, 0, 0, 0); |
| } |
| }; |
| |
| BlendFunc blend_dst = new BlendFunc() { |
| // Sets dst = dst |
| { |
| name = "blend_dst"; |
| } |
| |
| @Override |
| int blend() { |
| return pack(dstA, dstR, dstG, dstB); |
| } |
| }; |
| |
| BlendFunc blend_dstOut = new BlendFunc() { |
| // Sets dst = dst * (1.0 - src.a) |
| { |
| name = "blend_dstOut"; |
| } |
| |
| @Override |
| int blend() { |
| float r = (dstR * (1 - srcA)); |
| float g = (dstG * (1 - srcA)); |
| float b = (dstB * (1 - srcA)); |
| float a = (dstA * (1 - srcA)); |
| return pack(a, r, g, b); |
| } |
| }; |
| BlendFunc blend_dstOver = new BlendFunc() { |
| // Sets dst = dst + src * (1.0 - dst.a) |
| { |
| name = "blend_dstOver"; |
| } |
| |
| @Override |
| int blend() { |
| float r = dstR + (srcR * (1 - dstA)); |
| float g = dstG + (srcG * (1 - dstA)); |
| float b = dstB + (srcB * (1 - dstA)); |
| float a = dstA + (srcA * (1 - dstA)); |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| BlendFunc blend_multiply = new BlendFunc() { |
| // dst = dst * src |
| { |
| name = "blend_multiply"; |
| } |
| |
| @Override |
| int blend() { |
| float r = (srcR * dstR); |
| float g = (srcG * dstG); |
| float b = (srcB * dstB); |
| float a = (srcA * dstA); |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| BlendFunc blend_src = new BlendFunc() { |
| // Sets dst = src |
| { |
| name = "blend_src"; |
| } |
| |
| int blend() { |
| return pack(srcA, srcR, srcG, srcB); |
| |
| } |
| }; |
| |
| BlendFunc blend_srcAtop = new BlendFunc() { |
| // dst.rgb = src.rgb * dst.a + (1.0 - src.a) * dst.rgb |
| // dst.a = dst.a |
| { |
| name = "blend_srcAtop"; |
| } |
| |
| @Override |
| int blend() { |
| float r = (srcR * dstA + (1 - srcA) * dstR); |
| float g = (srcG * dstA + (1 - srcA) * dstG); |
| float b = (srcB * dstA + (1 - srcA) * dstB); |
| float a = (srcA * dstA + (1 - srcA) * dstA); |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| BlendFunc blend_srcIn = new BlendFunc() { |
| // dst = src * dst.a |
| { |
| name = "blend_srcIn"; |
| } |
| |
| @Override |
| int blend() { |
| float r = (srcR * dstA); |
| float g = (srcG * dstA); |
| float b = (srcB * dstA); |
| float a = (srcA * dstA); |
| ; |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| BlendFunc blend_srcOut = new BlendFunc() { |
| // Sets dst = src * (1.0 - dst.a) |
| { |
| name = "blend_srcOut"; |
| } |
| |
| @Override |
| int blend() { |
| float r = (srcR * (1 - dstA)); |
| float g = (srcG * (1 - dstA)); |
| float b = (srcB * (1 - dstA)); |
| float a = (srcA * (1 - dstA)); |
| ; |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| BlendFunc blend_srcOver = new BlendFunc() { |
| // Sets dst = src + dst * (1.0 - src.a) |
| { |
| name = "blend_srcOver"; |
| } |
| |
| @Override |
| int blend() { |
| float r = srcR + (dstR * (1 - srcA)); |
| float g = srcG + (dstG * (1 - srcA)); |
| float b = srcB + (dstB * (1 - srcA)); |
| float a = srcA + (dstA * (1 - srcA)); |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| BlendFunc blend_subtract = new BlendFunc() { |
| // Sets dst = dst - src |
| { |
| name = "blend_subtract"; |
| } |
| |
| @Override |
| int blend() { |
| float r = Math.max(dstR - srcR, 0); |
| float g = Math.max(dstG - srcG, 0); |
| float b = Math.max(dstB - srcB, 0); |
| float a = Math.max(dstA - srcA, 0); |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| // Porter/Duff xor compositing |
| BlendFunc blend_pdxor = new BlendFunc() { |
| // dst.rgb = src.rgb*(1-dst.a)+(1-src.a)*dst.rgb; |
| // dst.a = src.a+dst.a - 2*src.a*dst.a |
| { |
| name = "blend_pdxor"; |
| } |
| |
| @Override |
| int blend() { |
| float r = srcR * (1 - dstA) + (dstR * (1 - srcA)); |
| float g = srcG * (1 - dstA) + (dstG * (1 - srcA)); |
| float b = srcB * (1 - dstA) + (dstB * (1 - srcA)); |
| float a = srcA + dstA - (2 * srcA * dstA); |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| // NOT Porter/Duff xor compositing simple XOR |
| BlendFunc blend_xor = new BlendFunc() { |
| // Sets dst = {src.r ^ dst.r, src.g ^ dst.g, src.b ^ dst.b, src.a ^ dst.a} |
| { |
| name = "blend_xor"; |
| } |
| |
| @Override |
| int blend() { |
| float scale = 1 / 255f; |
| float r = (((int) (dstR * 255)) ^ ((int) (srcR * 255))) * scale; |
| float g = (((int) (dstG * 255)) ^ ((int) (srcG * 255))) * scale; |
| float b = (((int) (dstB * 255)) ^ ((int) (srcB * 255))) * scale; |
| float a = (((int) (dstA * 255)) ^ ((int) (srcA * 255))) * scale; |
| return pack(a, r, g, b); |
| } |
| }; |
| |
| BlendFunc[] func = { |
| blend_src, |
| blend_dst, |
| blend_srcOver, |
| blend_dstOver, |
| blend_srcIn, |
| blend_dstIn, |
| blend_srcOut, |
| blend_dstOut, |
| blend_srcAtop, |
| blend_dstAtop, |
| blend_xor, |
| blend_add, |
| blend_subtract, |
| blend_multiply, |
| }; |
| |
| public void testColorMatrix() { |
| ScriptIntrinsicColorMatrix mColorMatrix; |
| mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS)); |
| |
| Allocation a1_copy, a2_copy; |
| a1_copy = Allocation.createTyped(mRS, a1.getType()); |
| a2_copy = Allocation.createTyped(mRS, a2.getType()); |
| |
| Matrix4f m = new Matrix4f(); |
| m.set(1, 0, 0.2f); |
| m.set(1, 1, 0.9f); |
| m.set(1, 2, 0.2f); |
| |
| //test greyscale |
| mColorMatrix.setGreyscale(); |
| |
| a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0); |
| a2_copy.copy2DRangeFrom(0, 0, a2.getType().getX(), a2.getType().getY(), a2, 0, 0); |
| |
| mColorMatrix.forEach(a1_copy, a2_copy); |
| |
| //validate greyscale |
| |
| |
| //test color matrix |
| mColorMatrix.setColorMatrix(m); |
| |
| a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0); |
| a2_copy.copy2DRangeFrom(0, 0, a2.getType().getX(), a2.getType().getY(), a2, 0, 0); |
| |
| mColorMatrix.forEach(a1_copy, a2_copy); |
| |
| a1_copy.destroy(); |
| a2_copy.destroy(); |
| mColorMatrix.destroy(); |
| } |
| |
| public void testConvolve3x3() { |
| ScriptIntrinsicConvolve3x3 mConvolve3x3; |
| mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS)); |
| |
| Allocation a1_copy, a2_copy; |
| a1_copy = Allocation.createTyped(mRS, a1.getType()); |
| a2_copy = Allocation.createTyped(mRS, a2.getType()); |
| |
| a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0); |
| |
| float f[] = new float[9]; |
| f[0] = 0.f; f[1] = -1.f; f[2] = 0.f; |
| f[3] = -1.f; f[4] = 5.f; f[5] = -1.f; |
| f[6] = 0.f; f[7] = -1.f; f[8] = 0.f; |
| |
| mConvolve3x3.setCoefficients(f); |
| mConvolve3x3.setInput(a1_copy); |
| mConvolve3x3.forEach(a2_copy); |
| |
| a1_copy.destroy(); |
| a2_copy.destroy(); |
| mConvolve3x3.destroy(); |
| } |
| |
| public void testConvolve5x5() { |
| ScriptIntrinsicConvolve5x5 mConvolve5x5; |
| mConvolve5x5 = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS)); |
| |
| Allocation a1_copy, a2_copy; |
| a1_copy = Allocation.createTyped(mRS, a1.getType()); |
| a2_copy = Allocation.createTyped(mRS, a2.getType()); |
| |
| a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0); |
| |
| float f[] = new float[25]; |
| f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f; |
| f[5] = -3.f; f[6] = 0.f; f[7] = 6.f; f[8] = 0.f; f[9] = -3.f; |
| f[10]= -4.f; f[11]= 6.f; f[12]= 20.f; f[13]= 6.f; f[14]= -4.f; |
| f[15]= -3.f; f[16]= 0.f; f[17]= 6.f; f[18]= 0.f; f[19]= -3.f; |
| f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f; |
| |
| mConvolve5x5.setCoefficients(f); |
| mConvolve5x5.setInput(a1_copy); |
| mConvolve5x5.forEach(a2_copy); |
| |
| a1_copy.destroy(); |
| a2_copy.destroy(); |
| mConvolve5x5.destroy(); |
| } |
| |
| public void testLUT() { |
| ScriptIntrinsicLUT mLUT; |
| mLUT = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS)); |
| |
| Allocation a1_copy, a2_copy; |
| a1_copy = Allocation.createTyped(mRS, a1.getType()); |
| a2_copy = Allocation.createTyped(mRS, a2.getType()); |
| |
| a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0); |
| |
| for (int ct=0; ct < 256; ct++) { |
| float f = ((float)ct) / 255.f; |
| |
| float r = f; |
| if (r < 0.5f) { |
| r = 4.0f * r * r * r; |
| } else { |
| r = 1.0f - r; |
| r = 1.0f - (4.0f * r * r * r); |
| } |
| mLUT.setRed(ct, (int)(r * 255.f + 0.5f)); |
| |
| float g = f; |
| if (g < 0.5f) { |
| g = 2.0f * g * g; |
| } else { |
| g = 1.0f - g; |
| g = 1.0f - (2.0f * g * g); |
| } |
| mLUT.setGreen(ct, (int)(g * 255.f + 0.5f)); |
| |
| float b = f * 0.5f + 0.25f; |
| mLUT.setBlue(ct, (int)(b * 255.f + 0.5f)); |
| } |
| |
| mLUT.forEach(a1_copy, a2_copy); |
| |
| a1_copy.destroy(); |
| a2_copy.destroy(); |
| mLUT.destroy(); |
| } |
| |
| public void testScriptGroup() { |
| ScriptGroup group; |
| |
| ScriptIntrinsicConvolve3x3 mConvolve3x3; |
| ScriptIntrinsicColorMatrix mColorMatrix; |
| |
| mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS)); |
| mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS)); |
| |
| Allocation a1_copy, a2_copy; |
| a1_copy = Allocation.createTyped(mRS, a1.getType()); |
| a2_copy = Allocation.createTyped(mRS, a2.getType()); |
| |
| a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0); |
| |
| float f[] = new float[9]; |
| f[0] = 0.f; f[1] = -1.f; f[2] = 0.f; |
| f[3] = -1.f; f[4] = 5.f; f[5] = -1.f; |
| f[6] = 0.f; f[7] = -1.f; f[8] = 0.f; |
| |
| mConvolve3x3.setCoefficients(f); |
| |
| Matrix4f m = new Matrix4f(); |
| m.set(1, 0, 0.2f); |
| m.set(1, 1, 0.9f); |
| m.set(1, 2, 0.2f); |
| mColorMatrix.setColorMatrix(m); |
| |
| Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(dimX).setY(dimX).create(); |
| |
| ScriptGroup.Builder b = new ScriptGroup.Builder(mRS); |
| b.addKernel(mConvolve3x3.getKernelID()); |
| b.addKernel(mColorMatrix.getKernelID()); |
| b.addConnection(connect, mConvolve3x3.getKernelID(), mColorMatrix.getKernelID()); |
| group = b.create(); |
| |
| mConvolve3x3.setInput(a1_copy); |
| group.setOutput(mColorMatrix.getKernelID(), a2_copy); |
| group.execute(); |
| |
| // validate |
| |
| a1_copy.destroy(); |
| a2_copy.destroy(); |
| mConvolve3x3.destroy(); |
| mColorMatrix.destroy(); |
| } |
| |
| |
| } |