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