/* The contents of this file are subject to the Mozilla Public License Version 1.1 (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.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is collection of files collectively known as Open Camera. The Initial Developer of the Original Code is Almalence Inc. Portions created by Initial Developer are Copyright (C) 2013 by Almalence Inc. All Rights Reserved. */ package com.almalence.plugins.capture.night; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; import javax.microedition.khronos.opengles.GL11Ext; import android.content.Context; import android.util.Log; /* <!-- +++ import com.almalence.opencam_plus.ApplicationScreen; +++ --> */ // <!-- -+- import com.almalence.opencam.ApplicationScreen; //-+- --> import com.almalence.util.ImageConversion; /** * This class is an object representation of a Square containing the vertex * information and drawing functionality, which is called by the renderer. * * @author Savas Ziplies (nea/INsanityDesign) */ public class GLCameraPreview { /** The buffer holding the vertices */ private FloatBuffer vertexBuffer; /** The initial vertex definition */ private float[] vertices = { -1.0f, -1.0f, 0.0f, // Bottom Left 1.0f, -1.0f, 0.0f, // Bottom Right -1.0f, 0.5f, 0.0f, // Top Left 1.0f, 0.5f, 0.0f // Top Right }; /** buffer holding the texture coordinates */ private FloatBuffer textureBuffer; /** Our texture pointer */ private float[] texture = { // Mapping coordinates for the vertices 0.0f, 0.0f, // top left (V2) 0.0f, 1.0f, // bottom left (V1) 1.0f, 0.0f, // top right (V4) 1.0f, 1.0f // bottom right (V3) }; /** The texture pointer */ private int[] textures = new int[1]; private byte[] out; private int surfaceWidth; private int surfaceHeight; private int previewWidth; private int previewHeight; private int previewHalfWidth; private int previewHalfHeight; private int textureHeight; private int textureWidth; private int[] cropRect; public void setSurfaceSize(int width, int height) { // Log.d("GLCameraPreview", "Surface size = " + width + " x " + height); surfaceWidth = width; surfaceHeight = height; out = null; vertexBuffer.clear(); vertices = new float[] { -height / 2.0f, -width / 2.0f, 0.0f, // Bottom // Left height / 2.0f, -width / 2.0f, 0.0f, // Bottom Right -height / 2.0f, width / 2.0f, 0.0f, // Top Left height / 2.0f, width / 2.0f, 0.0f // Top Right }; vertexBuffer.put(vertices); vertexBuffer.position(0); } /** * The Square constructor. * * Initiate the buffers. */ public GLCameraPreview(Context context) { ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4); byteBuf.order(ByteOrder.nativeOrder()); vertexBuffer = byteBuf.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); byteBuf = ByteBuffer.allocateDirect(texture.length * 4); byteBuf.order(ByteOrder.nativeOrder()); textureBuffer = byteBuf.asFloatBuffer(); textureBuffer.put(texture); textureBuffer.position(0); } public void generateGLTexture(GL10 gl) { // Generate one texture pointer... gl.glGenTextures(1, textures, 0); // ...and bind it to our array gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); // Create Nearest Filtered Texture gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT); previewWidth = ApplicationScreen.getPreviewWidth(); previewHeight = ApplicationScreen.getPreviewHeight(); // Log.d("GLCameraPreview", "Preview size from ApplicationScreen = " + previewWidth + " x " + previewHeight); textureWidth = 512; textureHeight = 512; previewHalfWidth = textureWidth; previewHalfHeight = textureHeight; cropRect = new int[] { 0, previewHalfWidth, previewHalfHeight, -previewHalfWidth }; } /** * Load the textures * * @param gl * - The GL Context * @param context * - The Activity context */ public void loadGLTexture(GL10 gl, byte[] yuv_data, Context context) { int out_len = previewHalfWidth * previewHalfHeight * 3; if (out == null) out = new byte[out_len]; else if (out.length < out_len) out = new byte[out_len]; ImageConversion.convertNV21toGL(yuv_data, out, previewWidth, previewHeight, previewHalfWidth, previewHalfHeight); // ...and bind it to our array gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGB, textureWidth, textureHeight, 0, GL10.GL_RGB, GL10.GL_UNSIGNED_BYTE, ByteBuffer.wrap(out)); ((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect, 0); ((GL11Ext) gl).glDrawTexiOES(0, 0, 0, surfaceWidth, surfaceHeight); } /** * The object own drawing function. Called from the renderer to redraw this * instance with possible changes in values. * * @param gl * - The GL context */ public void draw(GL10 gl, byte[] yuv_data, Context context) { if (yuv_data != null && context != null && cropRect != null) this.loadGLTexture(gl, yuv_data, context); else { Log.i("NIGHT CAMERA DEBUG", "GLCameraPreview.draw finished. rgb_data = null || context = null || cropRect = null"); return; } // bind the previously generated texture gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); // Point to our buffers gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Set the face rotation // Point to our vertex buffer gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); // Draw the vertices as triangle strip gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3); // Disable the client state before leaving gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); } }