diff options
author | Scott Randolph <randolphs@google.com> | 2017-04-12 11:45:09 -0700 |
---|---|---|
committer | Scott Randolph <randolphs@google.com> | 2017-05-02 17:08:33 -0700 |
commit | 150c580464a7a4d6b0ad3362f23f790ded65e7ab (patch) | |
tree | 3f66b23872f0336e87a025d6b77837149f33d814 /evs/app/TexWrapper.cpp | |
parent | fd519152b4ca81a8635c3c94c8c1c4e5d0021719 (diff) | |
download | Car-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.cpp | 198 |
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); +} |