blob: eb29a24fa39593aa4c5598068571802bf8aab414 [file] [log] [blame]
Haoxiang Lib21a13e2019-06-18 13:16:28 -07001/*
2 * Copyright (C) 2017 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#include "TexWrapper.h"
17#include "glError.h"
18
19#include "log/log.h"
20
21#include <fcntl.h>
22#include <malloc.h>
23#include <png.h>
24
Haoxiang Lid2454a52019-06-18 13:23:12 -070025namespace android {
26namespace automotive {
27namespace evs {
28namespace support {
Haoxiang Lib21a13e2019-06-18 13:16:28 -070029
30/* Create an new empty GL texture that will be filled later */
31TexWrapper::TexWrapper() {
32 GLuint textureId;
33 glGenTextures(1, &textureId);
34 if (textureId <= 0) {
35 ALOGE("Didn't get a texture handle allocated: %s", getEGLError());
36 } else {
37 // Store the basic texture properties
38 id = textureId;
39 w = 0;
40 h = 0;
41 }
42}
43
44
45/* Wrap a texture that already allocated. The wrapper takes ownership. */
46TexWrapper::TexWrapper(GLuint textureId, unsigned width, unsigned height) {
47 // Store the basic texture properties
48 id = textureId;
49 w = width;
50 h = height;
51}
52
53
54TexWrapper::~TexWrapper() {
55 // Give the texture ID back
56 if (id > 0) {
57 glDeleteTextures(1, &id);
58 }
59 id = -1;
60}
61
62
63/* Factory to build TexWrapper objects from a given PNG file */
64TexWrapper* createTextureFromPng(const char * filename)
65{
66 // Open the PNG file
67 FILE *inputFile = fopen(filename, "rb");
68 if (inputFile == 0)
69 {
70 perror(filename);
71 return nullptr;
72 }
73
74 // Read the file header and validate that it is a PNG
75 static const int kSigSize = 8;
76 png_byte header[kSigSize] = {0};
77 fread(header, 1, kSigSize, inputFile);
78 if (png_sig_cmp(header, 0, kSigSize)) {
79 printf("%s is not a PNG.\n", filename);
80 fclose(inputFile);
81 return nullptr;
82 }
83
84 // Set up our control structure
85 png_structp pngControl = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
86 if (!pngControl)
87 {
88 printf("png_create_read_struct failed.\n");
89 fclose(inputFile);
90 return nullptr;
91 }
92
93 // Set up our image info structure
94 png_infop pngInfo = png_create_info_struct(pngControl);
95 if (!pngInfo)
96 {
97 printf("error: png_create_info_struct returned 0.\n");
98 png_destroy_read_struct(&pngControl, nullptr, nullptr);
99 fclose(inputFile);
100 return nullptr;
101 }
102
103 // Install an error handler
104 if (setjmp(png_jmpbuf(pngControl))) {
105 printf("libpng reported an error\n");
106 png_destroy_read_struct(&pngControl, &pngInfo, nullptr);
107 fclose(inputFile);
108 return nullptr;
109 }
110
111 // Set up the png reader and fetch the remaining bits of the header
112 png_init_io(pngControl, inputFile);
113 png_set_sig_bytes(pngControl, kSigSize);
114 png_read_info(pngControl, pngInfo);
115
116 // Get basic information about the PNG we're reading
117 int bitDepth;
118 int colorFormat;
119 png_uint_32 width;
120 png_uint_32 height;
121 png_get_IHDR(pngControl, pngInfo,
122 &width, &height,
123 &bitDepth, &colorFormat,
124 NULL, NULL, NULL);
125
126 GLint format;
127 switch(colorFormat)
128 {
129 case PNG_COLOR_TYPE_RGB:
130 format = GL_RGB;
131 break;
132 case PNG_COLOR_TYPE_RGB_ALPHA:
133 format = GL_RGBA;
134 break;
135 default:
136 printf("%s: Unknown libpng color format %d.\n", filename, colorFormat);
137 return nullptr;
138 }
139
140 // Refresh the values in the png info struct in case any transformation shave been applied.
141 png_read_update_info(pngControl, pngInfo);
142 int stride = png_get_rowbytes(pngControl, pngInfo);
143 stride += 3 - ((stride-1) % 4); // glTexImage2d requires rows to be 4-byte aligned
144
145 // Allocate storage for the pixel data
146 png_byte * buffer = (png_byte*)malloc(stride * height);
147 if (buffer == NULL)
148 {
149 printf("error: could not allocate memory for PNG image data\n");
150 png_destroy_read_struct(&pngControl, &pngInfo, nullptr);
151 fclose(inputFile);
152 return nullptr;
153 }
154
155 // libpng needs an array of pointers into the image data for each row
156 png_byte ** rowPointers = (png_byte**)malloc(height * sizeof(png_byte*));
157 if (rowPointers == NULL)
158 {
159 printf("Failed to allocate temporary row pointers\n");
160 png_destroy_read_struct(&pngControl, &pngInfo, nullptr);
161 free(buffer);
162 fclose(inputFile);
163 return nullptr;
164 }
165 for (unsigned int r = 0; r < height; r++)
166 {
167 rowPointers[r] = buffer + r*stride;
168 }
169
170
171 // Read in the actual image bytes
172 png_read_image(pngControl, rowPointers);
173 png_read_end(pngControl, nullptr);
174
175
176 // Set up the OpenGL texture to contain this image
177 GLuint textureId;
178 glGenTextures(1, &textureId);
179 glBindTexture(GL_TEXTURE_2D, textureId);
180
181 // Send the image data to GL
182 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
183
184 // Initialize the sampling properties (it seems the sample may not work if this isn't done)
185 // The user of this texture may very well want to set their own filtering, but we're going
186 // to pay the (minor) price of setting this up for them to avoid the dreaded "black image" if
187 // they forget.
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
190
191 // clean up
192 png_destroy_read_struct(&pngControl, &pngInfo, nullptr);
193 free(buffer);
194 free(rowPointers);
195 fclose(inputFile);
196
197 glBindTexture(GL_TEXTURE_2D, 0);
198
199
200 // Return the texture
201 return new TexWrapper(textureId, width, height);
202}
Haoxiang Lid2454a52019-06-18 13:23:12 -0700203
204} // namespace support
205} // namespace evs
206} // namespace automotive
207} // namespace android