1 /***************************************************************************
2 *
3 * Copyright (C) 2018 Advanced Driver Information Technology Joint Venture GmbH
4 *
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ****************************************************************************/
19 #include "TextureLoader.h"
20
TextureLoader()21 TextureLoader::TextureLoader(){
22 ;
23 }
24
25 // source: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/
loadBMP(const char * imagePath)26 bool TextureLoader::loadBMP(const char * imagePath) {
27 // Data read from the header of the BMP file
28 const unsigned char headerSize = 54; // Each BMP file begins by a 54-bytes header
29 unsigned char header[headerSize];
30 GLsizei width, height;
31 uint16_t pixelSizeBits;
32 uint8_t pixelSizeBytes;
33 // imageSize == width*height*pixelSize, because each pixel consists of pixelSize bytes (red, green and blue)
34 unsigned int imageSize;
35 unsigned char * data;
36 FILE * file = fopen(imagePath,"rb");
37 if (!file) {
38 //cout << "Image file could not be opened: " << imagePath << endl;
39 return false;
40 }
41 if (fread(header, 1, headerSize, file) != headerSize) {
42 cout << "Not a correct BMP file (could not read the header): " << imagePath << endl;
43 fclose(file);
44 return false;
45 }
46 if (header[0]!='B' || header[1]!='M' ) {
47 cout << "Not a correct BMP file (wrong header format) :" << imagePath << endl;
48 fclose(file);
49 return false;
50 }
51 // Read fields from the BMP file header
52 imageSize = *(int*)(header + 0x22);
53 width = *(GLsizei*)(header + 0x12);
54 height = *(GLsizei*)(header + 0x16);
55 pixelSizeBits = *(uint16_t*)(header + 0x1C);
56 pixelSizeBytes = pixelSizeBits / 8;
57
58 if ((pixelSizeBits != 24) and (pixelSizeBits != 32)) {
59 cout << "unsupported pixel size of " << pixelSizeBits << " bits" << endl;
60 fclose(file);
61 return false;
62 }
63
64 // calculate the image size if there is no information in the header
65 if (imageSize==0) {
66 imageSize=width*height*pixelSizeBytes;
67 }
68
69 data = new unsigned char [imageSize];
70 fread(data,1,imageSize,file);
71 fclose(file);
72
73 if (pixelSizeBits == 32) {
74 // BMP files with an alpha channel use ABGR format for storing pixels
75 // OpenGLES does not have an ABGR format specifier
76 // therefore change pixel format from ABGR to RGBA
77 for (long long i = 0; i < width*height; i++) {
78 unsigned char a = data[i*pixelSizeBytes + 0];
79 unsigned char b = data[i*pixelSizeBytes + 1];
80 unsigned char g = data[i*pixelSizeBytes + 2];
81 unsigned char r = data[i*pixelSizeBytes + 3];
82 data[i*pixelSizeBytes] = r;
83 data[i*pixelSizeBytes + 1] = g;
84 data[i*pixelSizeBytes + 2] = b;
85 data[i*pixelSizeBytes + 3] = a;
86 }
87 } else if (pixelSizeBits == 24) {
88 for (long long i = 0; i < width*height; i++) {
89 unsigned char b = data[i*pixelSizeBytes];
90 unsigned char g = data[i*pixelSizeBytes + 1];
91 unsigned char r = data[i*pixelSizeBytes + 2];
92 data[i*pixelSizeBytes] = r;
93 data[i*pixelSizeBytes + 1] = g;
94 data[i*pixelSizeBytes + 2] = b;
95 }
96 }
97
98 bool loaded = loadArray(data, width, height, pixelSizeBits);
99 delete[] data;
100 return loaded;
101 }
102
103 // This function loads an array with image data
loadArray(void * data,unsigned int width,unsigned int height,unsigned int pixelSizeBits)104 bool TextureLoader::loadArray(void * data, unsigned int width, unsigned int height, unsigned int pixelSizeBits) {
105 if (loaded)
106 // don't load the thexture if a texture was already loaded for this object
107 return false;
108 else
109 loaded = true;
110 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
111 glGenTextures(1, &textureID);
112 glBindTexture(GL_TEXTURE_2D, textureID);
113 if (pixelSizeBits == 32) {
114 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
115 glEnable(GL_BLEND);
116 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
117 } else if (pixelSizeBits == 24) {
118 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
119 glEnable(GL_BLEND);
120 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
121 }
122 glGenerateMipmap(GL_TEXTURE_2D);
123 // set texture parameters
124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
125 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
128 return loaded;
129 }
130
getId()131 GLuint TextureLoader::getId() {
132 return textureID;
133 }
134