/* * Copyright (C) 2013 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 com.android.rs.genimage; import android.content.Context; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLUtils; import android.opengl.GLES20; import android.opengl.GLSurfaceView; public class GenImage implements GLSurfaceView.Renderer { private Bitmap mTestImage; private Triangle mTriangle; private Bitmap loadBitmap(Context context, int resource) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; return BitmapFactory.decodeResource(context.getResources(), resource, options); } GenImage(Context context) { mTestImage = loadBitmap(context, R.drawable.test_pattern); } @Override public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Set the background frame color GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); mTriangle = new Triangle(mTestImage); } @Override public void onDrawFrame(GL10 unused) { // Draw background color GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); // Draw triangle mTriangle.draw(); } @Override public void onSurfaceChanged(GL10 unused, int width, int height) { // Adjust the viewport based on geometry changes, // such as screen rotation GLES20.glViewport(0, 0, 512, 512); } public static int loadShader(int type, String shaderCode){ // create a vertex shader type (GLES20.GL_VERTEX_SHADER) // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) int shader = GLES20.glCreateShader(type); // add the source code to the shader and compile it GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; } } class Triangle { int mTextureIDs[] = new int[1]; private final String vertexShaderCode = "varying vec2 vTex0;" + "varying vec2 vPos0;" + "attribute vec4 aPosition;" + "void main() {" + " gl_Position = aPosition;" + " vPos0 = aPosition.xy;" + " vTex0 = ((aPosition.xy + 1.0) * 0.6);" + //" vTex0 = (aPosition.xy * 1.7) + 0.5;" + "}"; private final String fragmentShaderCode = "precision mediump float;" + "varying vec2 vTex0;" + "varying vec2 vPos0;" + "uniform sampler2D uSamp;" + "void main() {" + " vec2 tc = vTex0;" + //" tc.x *= pow(vPos0.y + 1.0, 2.0);" + //" tc.y *= pow(vPos0.x + 1.0, 2.0);" + " vec4 c = texture2D(uSamp, tc);" + " c.a = 1.0;" + " gl_FragColor = c;" + "}"; private final FloatBuffer vertexBuffer; private final int mProgram; // number of coordinates per vertex in this array static float triangleCoords[] = { // in counterclockwise order: -1.0f, 1.0f, 0.0f, // top left -1.0f, -1.0f, 0.0f, // bottom left 1.0f, -1.0f, 0.0f, // bottom right -1.0f, 1.0f, 0.0f, // top left 1.0f, -1.0f, 0.0f, // bottom right 1.0f, 1.0f, 0.0f // top right }; FloatBuffer createFloatBuffer(float buf[]) { ByteBuffer bb = ByteBuffer.allocateDirect(buf.length * 4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(buf); fb.position(0); return fb; } public String setup(int key) { String s = new String(); int tmp; tmp = key % 2; key /= 2; if (tmp != 0) { s += "N"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); } else { s += "L"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); } tmp = key % 2; key /= 2; if (tmp != 0) { s += "N"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); } else { s += "L"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); } tmp = key % 3; key /= 3; switch(tmp) { case 0: s += "_CE"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); break; case 1: s += "_RE"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); break; case 2: s += "_MR"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_MIRRORED_REPEAT); break; } tmp = key % 3; key /= 3; switch(tmp) { case 0: s += "_CE"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); break; case 1: s += "_RE"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); break; case 2: s += "_MR"; GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_MIRRORED_REPEAT); break; } if (key > 0) done = true; return s; } public Triangle(Bitmap testImage) { vertexBuffer = createFloatBuffer(triangleCoords); // prepare shaders and OpenGL program int vertexShader = GenImage.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = GenImage.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program GLES20.glLinkProgram(mProgram); // create OpenGL program executables GLES20.glGenTextures(1, mTextureIDs, 0); // Bind to the texture in OpenGL GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIDs[0]); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, testImage, 0); } boolean done = false; int key = 0; public void draw() { GLES20.glActiveTexture(GLES20.GL_TEXTURE0); String ext = setup(key++); // Add program to OpenGL environment GLES20.glUseProgram(mProgram); int posA = GLES20.glGetAttribLocation(mProgram, "aPosition"); GLES20.glEnableVertexAttribArray(posA); GLES20.glVertexAttribPointer(posA, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer); int sampUni = GLES20.glGetUniformLocation(mProgram, "uSamp"); GLES20.glUniform1i(sampUni, 0); // Draw the triangle GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, triangleCoords.length / 3); if (!done) { IntBuffer ib = IntBuffer.allocate(512*512); ib.position(0); GLES20.glReadPixels(0,0, 512, 512, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ib); Bitmap bmp = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888); bmp.setPixels(ib.array(), 0, 512, 0, 0, 512, 512); try { String s = new String("/sdcard/imgs/RsSampImg_"); s += ext + ".png"; FileOutputStream out = new FileOutputStream(s); bmp.compress(Bitmap.CompressFormat.PNG, 95, out); out.close(); } catch (Exception e) { e.printStackTrace(); } bmp.recycle(); } } }