1/* 2 * Copyright (C) 2013 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 17package com.android.rs.genimage; 18 19import android.content.Context; 20 21import java.io.FileOutputStream; 22import java.nio.ByteBuffer; 23import java.nio.IntBuffer; 24import java.nio.ByteOrder; 25import java.nio.FloatBuffer; 26 27import android.graphics.Bitmap; 28import android.graphics.BitmapFactory; 29 30import javax.microedition.khronos.egl.EGLConfig; 31import javax.microedition.khronos.opengles.GL10; 32import android.opengl.GLUtils; 33 34import android.opengl.GLES20; 35import android.opengl.GLSurfaceView; 36 37public class GenImage implements GLSurfaceView.Renderer { 38 private Bitmap mTestImage; 39 40 private Triangle mTriangle; 41 42 43 private Bitmap loadBitmap(Context context, int resource) { 44 final BitmapFactory.Options options = new BitmapFactory.Options(); 45 options.inPreferredConfig = Bitmap.Config.ARGB_8888; 46 return BitmapFactory.decodeResource(context.getResources(), resource, options); 47 } 48 49 GenImage(Context context) { 50 51 mTestImage = loadBitmap(context, R.drawable.test_pattern); 52 53 } 54 55 @Override 56 public void onSurfaceCreated(GL10 unused, EGLConfig config) { 57 58 // Set the background frame color 59 GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 60 61 mTriangle = new Triangle(mTestImage); 62 } 63 64 @Override 65 public void onDrawFrame(GL10 unused) { 66 67 // Draw background color 68 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 69 70 // Draw triangle 71 mTriangle.draw(); 72 } 73 74 @Override 75 public void onSurfaceChanged(GL10 unused, int width, int height) { 76 // Adjust the viewport based on geometry changes, 77 // such as screen rotation 78 GLES20.glViewport(0, 0, 512, 512); 79 } 80 81 public static int loadShader(int type, String shaderCode){ 82 83 // create a vertex shader type (GLES20.GL_VERTEX_SHADER) 84 // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) 85 int shader = GLES20.glCreateShader(type); 86 87 // add the source code to the shader and compile it 88 GLES20.glShaderSource(shader, shaderCode); 89 GLES20.glCompileShader(shader); 90 91 return shader; 92 } 93 94} 95 96 97 98class Triangle { 99 int mTextureIDs[] = new int[1]; 100 101 private final String vertexShaderCode = 102 "varying vec2 vTex0;" + 103 "varying vec2 vPos0;" + 104 "attribute vec4 aPosition;" + 105 "void main() {" + 106 " gl_Position = aPosition;" + 107 " vPos0 = aPosition.xy;" + 108 " vTex0 = ((aPosition.xy + 1.0) * 0.6);" + 109 //" vTex0 = (aPosition.xy * 1.7) + 0.5;" + 110 "}"; 111 112 private final String fragmentShaderCode = 113 "precision mediump float;" + 114 "varying vec2 vTex0;" + 115 "varying vec2 vPos0;" + 116 "uniform sampler2D uSamp;" + 117 "void main() {" + 118 " vec2 tc = vTex0;" + 119 //" tc.x *= pow(vPos0.y + 1.0, 2.0);" + 120 //" tc.y *= pow(vPos0.x + 1.0, 2.0);" + 121 " vec4 c = texture2D(uSamp, tc);" + 122 " c.a = 1.0;" + 123 " gl_FragColor = c;" + 124 "}"; 125 126 private final FloatBuffer vertexBuffer; 127 private final int mProgram; 128 129 // number of coordinates per vertex in this array 130 static float triangleCoords[] = { // in counterclockwise order: 131 -1.0f, 1.0f, 0.0f, // top left 132 -1.0f, -1.0f, 0.0f, // bottom left 133 1.0f, -1.0f, 0.0f, // bottom right 134 135 -1.0f, 1.0f, 0.0f, // top left 136 1.0f, -1.0f, 0.0f, // bottom right 137 1.0f, 1.0f, 0.0f // top right 138 }; 139 140 FloatBuffer createFloatBuffer(float buf[]) { 141 ByteBuffer bb = ByteBuffer.allocateDirect(buf.length * 4); 142 bb.order(ByteOrder.nativeOrder()); 143 FloatBuffer fb = bb.asFloatBuffer(); 144 fb.put(buf); 145 fb.position(0); 146 return fb; 147 } 148 149 public String setup(int key) { 150 String s = new String(); 151 int tmp; 152 153 tmp = key % 2; 154 key /= 2; 155 if (tmp != 0) { 156 s += "N"; 157 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 158 } else { 159 s += "L"; 160 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 161 } 162 163 tmp = key % 2; 164 key /= 2; 165 if (tmp != 0) { 166 s += "N"; 167 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 168 } else { 169 s += "L"; 170 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 171 } 172 173 tmp = key % 3; 174 key /= 3; 175 switch(tmp) { 176 case 0: 177 s += "_CE"; 178 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 179 break; 180 case 1: 181 s += "_RE"; 182 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); 183 break; 184 case 2: 185 s += "_MR"; 186 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_MIRRORED_REPEAT); 187 break; 188 } 189 190 tmp = key % 3; 191 key /= 3; 192 switch(tmp) { 193 case 0: 194 s += "_CE"; 195 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 196 break; 197 case 1: 198 s += "_RE"; 199 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); 200 break; 201 case 2: 202 s += "_MR"; 203 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_MIRRORED_REPEAT); 204 break; 205 } 206 207 if (key > 0) done = true; 208 return s; 209 } 210 211 public Triangle(Bitmap testImage) { 212 vertexBuffer = createFloatBuffer(triangleCoords); 213 214 // prepare shaders and OpenGL program 215 int vertexShader = GenImage.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); 216 int fragmentShader = GenImage.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); 217 218 mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program 219 GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program 220 GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program 221 GLES20.glLinkProgram(mProgram); // create OpenGL program executables 222 223 GLES20.glGenTextures(1, mTextureIDs, 0); 224 225 // Bind to the texture in OpenGL 226 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIDs[0]); 227 GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, testImage, 0); 228 } 229 230 boolean done = false; 231 int key = 0; 232 233 public void draw() { 234 GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 235 String ext = setup(key++); 236 237 // Add program to OpenGL environment 238 GLES20.glUseProgram(mProgram); 239 240 int posA = GLES20.glGetAttribLocation(mProgram, "aPosition"); 241 GLES20.glEnableVertexAttribArray(posA); 242 GLES20.glVertexAttribPointer(posA, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer); 243 244 int sampUni = GLES20.glGetUniformLocation(mProgram, "uSamp"); 245 GLES20.glUniform1i(sampUni, 0); 246 247 // Draw the triangle 248 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, triangleCoords.length / 3); 249 250 if (!done) { 251 IntBuffer ib = IntBuffer.allocate(512*512); 252 ib.position(0); 253 GLES20.glReadPixels(0,0, 512, 512, GLES20.GL_RGBA, 254 GLES20.GL_UNSIGNED_BYTE, ib); 255 256 Bitmap bmp = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888); 257 bmp.setPixels(ib.array(), 0, 512, 0, 0, 512, 512); 258 259 try { 260 String s = new String("/sdcard/imgs/RsSampImg_"); 261 s += ext + ".png"; 262 FileOutputStream out = new FileOutputStream(s); 263 bmp.compress(Bitmap.CompressFormat.PNG, 95, out); 264 out.close(); 265 } catch (Exception e) { 266 e.printStackTrace(); 267 } 268 bmp.recycle(); 269 } 270 } 271} 272