aboutsummaryrefslogtreecommitdiff
path: root/evs/app/TexWrapper.cpp
diff options
context:
space:
mode:
authorScott Randolph <randolphs@google.com>2017-04-12 11:45:09 -0700
committerScott Randolph <randolphs@google.com>2017-05-02 17:08:33 -0700
commit150c580464a7a4d6b0ad3362f23f790ded65e7ab (patch)
tree3f66b23872f0336e87a025d6b77837149f33d814 /evs/app/TexWrapper.cpp
parentfd519152b4ca81a8635c3c94c8c1c4e5d0021719 (diff)
downloadCar-150c580464a7a4d6b0ad3362f23f790ded65e7ab.tar.gz
Rebuild EVS app with richer feature set
Adds support for additional data formats, multiple cameras, and lays the foundation for GL rendered overlays. Test: build and run on Gordon Peak with Logitech USB camera Change-Id: I60403361a91593d4e387df67a563522547efa981
Diffstat (limited to 'evs/app/TexWrapper.cpp')
-rw-r--r--evs/app/TexWrapper.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/evs/app/TexWrapper.cpp b/evs/app/TexWrapper.cpp
new file mode 100644
index 0000000000..7ec2191ff7
--- /dev/null
+++ b/evs/app/TexWrapper.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+#include "TexWrapper.h"
+#include "glError.h"
+
+#include "log/log.h"
+
+#include <fcntl.h>
+#include <malloc.h>
+#include <png.h>
+
+
+/* Create an new empty GL texture that will be filled later */
+TexWrapper::TexWrapper() {
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ if (textureId <= 0) {
+ ALOGE("Didn't get a texture handle allocated: %s", getEGLError());
+ } else {
+ // Store the basic texture properties
+ id = textureId;
+ w = 0;
+ h = 0;
+ }
+}
+
+
+/* Wrap a texture that already allocated. The wrapper takes ownership. */
+TexWrapper::TexWrapper(GLuint textureId, unsigned width, unsigned height) {
+ // Store the basic texture properties
+ id = textureId;
+ w = width;
+ h = height;
+}
+
+
+TexWrapper::~TexWrapper() {
+ // Give the texture ID back
+ if (id > 0) {
+ glDeleteTextures(1, &id);
+ }
+ id = -1;
+}
+
+
+/* Factory to build TexWrapper objects from a given PNG file */
+TexWrapper* createTextureFromPng(const char * filename)
+{
+ // Open the PNG file
+ FILE *inputFile = fopen(filename, "rb");
+ if (inputFile == 0)
+ {
+ perror(filename);
+ return nullptr;
+ }
+
+ // Read the file header and validate that it is a PNG
+ static const int kSigSize = 8;
+ png_byte header[kSigSize] = {0};
+ fread(header, 1, kSigSize, inputFile);
+ if (png_sig_cmp(header, 0, kSigSize)) {
+ printf("%s is not a PNG.\n", filename);
+ fclose(inputFile);
+ return nullptr;
+ }
+
+ // Set up our control structure
+ png_structp pngControl = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!pngControl)
+ {
+ printf("png_create_read_struct failed.\n");
+ fclose(inputFile);
+ return nullptr;
+ }
+
+ // Set up our image info structure
+ png_infop pngInfo = png_create_info_struct(pngControl);
+ if (!pngInfo)
+ {
+ printf("error: png_create_info_struct returned 0.\n");
+ png_destroy_read_struct(&pngControl, nullptr, nullptr);
+ fclose(inputFile);
+ return nullptr;
+ }
+
+ // Install an error handler
+ if (setjmp(png_jmpbuf(pngControl))) {
+ printf("libpng reported an error\n");
+ png_destroy_read_struct(&pngControl, &pngInfo, nullptr);
+ fclose(inputFile);
+ return nullptr;
+ }
+
+ // Set up the png reader and fetch the remaining bits of the header
+ png_init_io(pngControl, inputFile);
+ png_set_sig_bytes(pngControl, kSigSize);
+ png_read_info(pngControl, pngInfo);
+
+ // Get basic information about the PNG we're reading
+ int bitDepth;
+ int colorFormat;
+ png_uint_32 width;
+ png_uint_32 height;
+ png_get_IHDR(pngControl, pngInfo,
+ &width, &height,
+ &bitDepth, &colorFormat,
+ NULL, NULL, NULL);
+
+ GLint format;
+ switch(colorFormat)
+ {
+ case PNG_COLOR_TYPE_RGB:
+ format = GL_RGB;
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ format = GL_RGBA;
+ break;
+ default:
+ printf("%s: Unknown libpng color format %d.\n", filename, colorFormat);
+ return nullptr;
+ }
+
+ // Refresh the values in the png info struct in case any transformation shave been applied.
+ png_read_update_info(pngControl, pngInfo);
+ int stride = png_get_rowbytes(pngControl, pngInfo);
+ stride += 3 - ((stride-1) % 4); // glTexImage2d requires rows to be 4-byte aligned
+
+ // Allocate storage for the pixel data
+ png_byte * buffer = (png_byte*)malloc(stride * height);
+ if (buffer == NULL)
+ {
+ printf("error: could not allocate memory for PNG image data\n");
+ png_destroy_read_struct(&pngControl, &pngInfo, nullptr);
+ fclose(inputFile);
+ return nullptr;
+ }
+
+ // libpng needs an array of pointers into the image data for each row
+ png_byte ** rowPointers = (png_byte**)malloc(height * sizeof(png_byte*));
+ if (rowPointers == NULL)
+ {
+ printf("Failed to allocate temporary row pointers\n");
+ png_destroy_read_struct(&pngControl, &pngInfo, nullptr);
+ free(buffer);
+ fclose(inputFile);
+ return nullptr;
+ }
+ for (unsigned int r = 0; r < height; r++)
+ {
+ rowPointers[r] = buffer + r*stride;
+ }
+
+
+ // Read in the actual image bytes
+ png_read_image(pngControl, rowPointers);
+ png_read_end(pngControl, nullptr);
+
+
+ // Set up the OpenGL texture to contain this image
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ // Send the image data to GL
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+ // Initialize the sampling properties (it seems the sample may not work if this isn't done)
+ // The user of this texture may very well want to set their own filtering, but we're going
+ // to pay the (minor) price of setting this up for them to avoid the dreaded "black image" if
+ // they forget.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ // clean up
+ png_destroy_read_struct(&pngControl, &pngInfo, nullptr);
+ free(buffer);
+ free(rowPointers);
+ fclose(inputFile);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+
+ // Return the texture
+ return new TexWrapper(textureId, width, height);
+}