Mali OpenCL SDK v1.1.0
 All Classes Files Functions Variables Macros Pages
image.cpp
Go to the documentation of this file.
1 /*
2  * This confidential and proprietary software may be used only as
3  * authorised by a licensing agreement from ARM Limited
4  * (C) COPYRIGHT 2013 ARM Limited
5  * ALL RIGHTS RESERVED
6  * The entire notice above must be reproduced on all authorised
7  * copies and copies may only be made to the extent permitted
8  * by a licensing agreement from ARM Limited.
9  */
10 
11 #include "image.h"
12 #include <fstream>
13 #include <iostream>
14 
15 using namespace std;
16 
17 bool saveToBitmap(string filename, int width, int height, const unsigned char* imageData)
18 {
19  /* Try and open the file for writing. */
20  fstream imageFile(filename.c_str(), ios::out);
21  if(!imageFile.is_open())
22  {
23  cerr << "Unable to open " << filename << ". " << __FILE__ << ":"<< __LINE__ << endl;
24  return false;
25  }
26 
27  /* Magic header bits come from the bitmap specification. */
28  const struct bitmapMagic magic = { {0x42, 0x4d} };
29  struct bitmapHeader header;
30  struct bitmapInformationHeader informationHeader;
31 
32  /*
33  * Each row of the data must be padded to a multiple of 4 bytes according to the bitmap specification.
34  * This method uses three bytes per pixel (hence the width * 3).
35  * Then we increase the padding until it is divisible by 4.
36  */
37  int paddedWidth = width * 3;
38  while((paddedWidth % 4) != 0)
39  {
40  paddedWidth++;
41  }
42 
43  /* Setup the bitmap header. */
44  header.fileSize = sizeof(magic) + sizeof(header) + sizeof(informationHeader) + paddedWidth * height;
45  header.creator1 = 0;
46  header.creator2 = 0;
47  header.offset = sizeof(magic) + sizeof(header) + sizeof(informationHeader);
48 
49  /* Setup the bitmap information header. */
50  informationHeader.size = sizeof(informationHeader);
51  informationHeader.width = width;
52  informationHeader.height = height;
53  informationHeader.numberOfColorPlanes = 1;
54  informationHeader.bitsPerPixel = 24;
55  informationHeader.compressionType = 0;
56  informationHeader.rawBitmapSize = paddedWidth * height;
57  informationHeader.horizontalResolution = 2835;
58  informationHeader.verticalResolution = 2835;
59  informationHeader.numberOfColors = 0;
60  informationHeader.numberOfImportantColors = 0;
61 
62  /* Try to write the header data. */
63  if(imageFile.write((char*)&magic, sizeof(magic)).bad() ||
64  imageFile.write((char*)&header, sizeof(header)).bad() ||
65  imageFile.write((char*)&informationHeader, sizeof(informationHeader)).bad())
66  {
67  cerr << "Failed to write bitmap header. " << __FILE__ << ":"<< __LINE__ << endl;
68  if (imageFile.is_open())
69  {
70  imageFile.close();
71  }
72  return false;
73  }
74 
75  for (int y = height - 1; y >= 0; y--)
76  {
77  for (int x = 0; x < width; x++)
78  {
79  /* The pixels lie in RGB order in memory, we need to store them in BGR order. */
80  unsigned char rgb[3];
81  rgb[2] = imageData[3 * (y * informationHeader.width + x) + 0];
82  rgb[1] = imageData[3 * (y * informationHeader.width + x) + 1];
83  rgb[0] = imageData[3 * (y * informationHeader.width + x) + 2];
84 
85  if(imageFile.write((char*)&rgb, 3).bad())
86  {
87  if (imageFile.is_open())
88  {
89  imageFile.close();
90  }
91  return false;
92  }
93  }
94  /*
95  * At the end of the row, write out blank bytes to ensure the row length is
96  * a multiple of 4 bytes (part of the bitmap specification).
97  */
98  for (int x = width * 3; x < paddedWidth; x++)
99  {
100  char b = 0;
101  if(imageFile.write(&b, 1).bad())
102  {
103  if (imageFile.is_open())
104  {
105  imageFile.close();
106  }
107  return false;
108  }
109  }
110  }
111 
112  return true;
113 }
114 
115 bool loadFromBitmap(const string filename, int* const width, int* const height, unsigned char **imageData)
116 {
117  /* Try and open the file for reading. */
118  ifstream imageFile(filename.c_str(), ios::in);
119  if(!imageFile.is_open())
120  {
121  cerr << "Unable to open " << filename << ". " << __FILE__ << ":"<< __LINE__ << endl;
122  return false;
123  }
124 
125  /*
126  * Read and check the headers to make sure we support the type of bitmap passed in.
127  */
128  struct bitmapMagic magic;
129  struct bitmapHeader header;
130  struct bitmapInformationHeader informationHeader;
131 
132  if (imageFile.read((char*)&magic, sizeof(magic)).bad() || magic.magic[0] != 0x42 || magic.magic[1] != 0x4d)
133  {
134  /* Not a valid BMP file header */
135  cerr << "Not a valid BMP file header. " << __FILE__ << ":"<< __LINE__ << endl;
136  if (imageFile.is_open())
137  {
138  imageFile.close();
139  }
140  return false;
141  }
142 
143  /* 54 is the standard size of a bitmap header. */
144  if (imageFile.read((char*)&header, sizeof(header)).bad() || header.offset != 54)
145  {
146  /* Not a supported BMP format */
147  cerr << "Not a supported BMP format. " << __FILE__ << ":"<< __LINE__ << endl;
148  if (imageFile.is_open())
149  {
150  imageFile.close();
151  }
152  return false;
153  }
154 
155  if (imageFile.read((char*)&informationHeader, sizeof(informationHeader)).bad() || informationHeader.compressionType != 0 || informationHeader.bitsPerPixel != 24)
156  {
157  /* We only support uncompressed 24-bits per pixel RGB */
158  cerr << "We only support uncompressed 24-bits per pixel RGB. " << __FILE__ << ":"<< __LINE__ << endl;
159  if (imageFile.is_open())
160  {
161  imageFile.close();
162  }
163  return false;
164  }
165 
166  int row_delta;
167  int first_row;
168  int after_last_row;
169  if (informationHeader.height > 0)
170  {
171  /* The image is stored upside down in memory */
172  row_delta = -1;
173  first_row = informationHeader.height - 1;
174  after_last_row = -1;
175  }
176  else
177  {
178  informationHeader.height = -informationHeader.height;
179  row_delta = 1;
180  first_row = 0;
181  after_last_row = informationHeader.height;
182  }
183 
184  /* Calculate the paddle of the image to skip it when reading the buffer. */
185  int paddedWidth = informationHeader.width * 3;
186  while((paddedWidth % 4) != 0)
187  {
188  paddedWidth++;
189  }
190 
191  /* 24-bits per pixel means 3 bytes of data per pixel. */
192  int size = 3 * paddedWidth * informationHeader.height;
193  *imageData = new unsigned char[size];
194  unsigned char* readBuffer = new unsigned char[size];
195 
196  /* Try to read in the image data. */
197  if (imageFile.read((char*)readBuffer, size).bad())
198  {
199  cerr << "Error reading main image data. " << __FILE__ << ":"<< __LINE__ << endl;
200  if (imageFile.is_open())
201  {
202  imageFile.close();
203  }
204  if (readBuffer != NULL)
205  {
206  delete [] readBuffer;
207  }
208  return false;
209  }
210 
211  int readBufferIndex = 0;
212  /* Loop throught the image data and store it at the output data location. */
213  for (int y = first_row; y != after_last_row; y += row_delta)
214  {
215  for (int x = 0; x < informationHeader.width; x++)
216  {
217  /* The pixels lie in BGR order, we need to resort them into RGB */
218  (*imageData)[3 * (y * informationHeader.width + x) + 0] = readBuffer[readBufferIndex + 2];
219  (*imageData)[3 * (y * informationHeader.width + x) + 1] = readBuffer[readBufferIndex + 1];
220  (*imageData)[3 * (y * informationHeader.width + x) + 2] = readBuffer[readBufferIndex + 0];
221 
222  readBufferIndex += 3;
223  }
224  /* Skip padding. */
225  readBufferIndex += paddedWidth - (informationHeader.width * 3);
226  }
227 
228  *width = informationHeader.width;
229  *height = informationHeader.height;
230 
231  if (imageFile.is_open())
232  {
233  imageFile.close();
234  }
235  if (readBuffer != NULL)
236  {
237  delete [] readBuffer;
238  }
239 
240  return true;
241 }
242 
243 bool luminanceToRGB(const unsigned char* luminanceData, unsigned char* rgbData, int width, int height)
244 {
245  if (luminanceData == NULL)
246  {
247  cerr << "luminanceData cannot be NULL. " << __FILE__ << ":"<< __LINE__ << endl;
248  return false;
249  }
250 
251  if (rgbData == NULL)
252  {
253  cerr << "rgbData cannot be NULL. " << __FILE__ << ":"<< __LINE__ << endl;
254  return false;
255  }
256 
257  for (int n = width * height - 1; n >= 0; --n)
258  {
259  unsigned char d = luminanceData[n];
260  rgbData[3 * n + 0] = d;
261  rgbData[3 * n + 1] = d;
262  rgbData[3 * n + 2] = d;
263  }
264  return true;
265 }
266 
267 bool RGBToLuminance(const unsigned char* const rgbData, unsigned char* const luminanceData, int width, int height)
268 {
269  if (rgbData == NULL)
270  {
271  cerr << "rgbData cannot be NULL. " << __FILE__ << ":"<< __LINE__ << endl;
272  return false;
273  }
274 
275  if (luminanceData == NULL)
276  {
277  cerr << "luminanceData cannot be NULL. " << __FILE__ << ":"<< __LINE__ << endl;
278  return false;
279  }
280 
281  for (int n = width * height - 1; n >= 0; --n)
282  {
283  float r = rgbData[3 * n + 0];
284  float g = rgbData[3 * n + 1];
285  float b = rgbData[3 * n + 2];
286  luminanceData[n] = (unsigned char) (0.2126f * r + 0.7152f * g + 0.0722f * b);
287  }
288  return true;
289 }
290 
291 bool RGBToRGBA(const unsigned char* const rgbData, unsigned char* const rgbaData, int width, int height)
292 {
293  if (rgbData == NULL)
294  {
295  cerr << "rgbData cannot be NULL. " << __FILE__ << ":"<< __LINE__ << endl;
296  return false;
297  }
298 
299  if (rgbaData == NULL)
300  {
301  cerr << "rgbaData cannot be NULL. " << __FILE__ << ":"<< __LINE__ << endl;
302  return false;
303  }
304 
305  for (int n = 0; n < width * height; n++)
306  {
307  /* Copy the RGB components directly. */
308  rgbaData[4 * n + 0] = rgbData[3 * n + 0];
309  rgbaData[4 * n + 1] = rgbData[3 * n + 1];
310  rgbaData[4 * n + 2] = rgbData[3 * n + 2];
311 
312  /* Set the alpha channel to 255 (fully opaque). */
313  rgbaData[4 * n + 3] = (unsigned char)255;
314  }
315  return true;
316 }
317 
318 bool RGBAToRGB(const unsigned char* const rgbaData, unsigned char* const rgbData, int width, int height)
319 {
320  if (rgbaData == NULL)
321  {
322  cerr << "rgbaData cannot be NULL. " << __FILE__ << ":"<< __LINE__ << endl;
323  return false;
324  }
325 
326  if (rgbData == NULL)
327  {
328  cerr << "rgbData cannot be NULL. " << __FILE__ << ":"<< __LINE__ << endl;
329  return false;
330  }
331 
332  for (int n = 0; n < width * height; n++)
333  {
334  /* Copy the RGB components but throw away the alpha channel. */
335  rgbData[3 * n + 0] = rgbaData[4 * n + 0];
336  rgbData[3 * n + 1] = rgbaData[4 * n + 1];
337  rgbData[3 * n + 2] = rgbaData[4 * n + 2];
338  }
339  return true;
340 }